:root {
  --bg: #0b0e14; --ink: #eef1f6; --mute: #8a93a3; --line: #232a38;
  --r1: #c5f2dc; --r2: #b8cff2; --r3: #c3a9ef; --r4: #dd6fa5; --r5: #f0a04f; --r6: #fbe364; --r7: #8a3dff;   /* C UC R SR UR L, and the Secret */
  --serif: 'Gloock', Georgia, serif;
  --mono: 'DM Mono', ui-monospace, monospace;
  --rainbow: hsl(2 100% 72%), hsl(40 100% 68%), hsl(64 100% 66%), hsl(140 90% 68%), hsl(186 100% 70%), hsl(228 100% 76%), hsl(284 100% 76%), hsl(2 100% 72%);
}
* { box-sizing: border-box; margin: 0; }
[hidden] { display: none !important; }
html, body { height: 100%; }
body {
  background: radial-gradient(120% 80% at 50% 0%, #161c2a 0%, var(--bg) 60%);
  color: var(--ink); font: 16px/1.5 'DM Sans', system-ui, sans-serif;
  overflow: hidden; -webkit-tap-highlight-color: transparent; user-select: none;
}
/* phone: header / main / tab bar. From 720px the same nav becomes a left sidebar under the header. */
#app { height: 100dvh; display: grid; grid-template: auto 1fr auto / minmax(0, 1fr); position: relative; z-index: 2; }
#nav { grid-row: 3; display: flex; justify-content: center; gap: 4px; padding: 6px 12px calc(6px + env(safe-area-inset-bottom)); border-top: 1px solid var(--line); }
#nav button {
  flex: 1; max-width: 200px; display: flex; flex-direction: column; align-items: center; gap: 2px; padding: 8px;
  border: 0; border-radius: 10px; background: none; color: var(--mute); font: 500 12px 'DM Sans', sans-serif; cursor: pointer;
}
/* five tabs on a 320px phone: a label never breaks in two ("Trade / up" made its tab taller than the others), it gives up its side padding first */
@media (max-width: 719px) { #nav { gap: 2px; padding-inline: 6px; } #nav button { padding: 8px 2px; white-space: nowrap; min-width: 0; } }
@media (max-width: 359px) { #nav button { font-size: 11px; } }
#nav button:hover { color: var(--ink); }
/* cards that came in and have not been looked at yet: a count on the Collection tab, beside its icon */
#nav button { position: relative; }
#nav button[data-new]::after { content: attr(data-new); position: absolute; top: 3px; left: calc(50% + 5px); min-width: 17px; height: 17px; padding: 0 5px; border-radius: 999px;
  background: #4db8ff; color: #0b0e14; font: 700 10px/17px 'DM Sans', sans-serif; font-variant-numeric: tabular-nums; }
#nav button[aria-current] { color: var(--ink); background: #ffffff0f; }
#nav svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linejoin: round; stroke-linecap: round; }
@media (min-width: 720px) {
  #app { grid-template: auto 1fr / auto minmax(0, 1fr); }
  header { grid-column: 1 / -1; }
  main { grid-area: 2 / 2; }
  #nav { grid-area: 2 / 1; width: 190px; flex-direction: column; justify-content: flex-start; padding: 12px; border-top: 0; border-right: 1px solid var(--line); }
  #nav button { flex: none; max-width: none; flex-direction: row; gap: 10px; padding: 10px 12px; font-size: 15px; }
  #nav button[data-new]::after { position: static; margin-left: auto; }
}
header { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 16px; padding: 14px 16px; white-space: nowrap; font-size: 14px; }
/* the logo: the plaque, a picture shot from web/logo-lab.html (lab-archive/export-logo.mjs), three times the size it is shown at. The header gives up some of its padding for it */
.logo { height: 44px; width: auto; margin: -6px auto -6px -4px; pointer-events: none; -webkit-touch-callout: none; }
/* desktop: the plaque is as wide as the sidebar allows and sits in the middle of it (the sidebar is 190px, the header's own padding 16px) */
@media (min-width: 720px) { .logo { height: 80px; margin: -4px auto -4px calc((190px - 147px) / 2 - 16px); } .logo:has(+ .mode:not([hidden])) { margin-right: 12px; } }   /* mock: the red button sits right after the logo and takes over the push to the right */
/* mock mode: a big red button, so nobody mistakes the mock for the real game, and nobody stays stuck in it: it is the way out.
   A phone has no room for it beside the logo: it takes a row of its own, the whole width, under the header's */
.mode { display: flex; align-items: center; justify-content: center; gap: 8px; order: 1; flex: 1 0 100%; margin-top: 6px; padding: 10px 16px; border: 0; border-radius: 10px; background: #c8323f; color: #fff; font: 700 14px 'DM Sans', sans-serif; cursor: pointer; box-shadow: 0 4px 16px #c8323f66; }
.mode[hidden] { display: none; }
@media (min-width: 720px) { .mode { order: 0; flex: none; margin: 0 auto 0 -8px; } }
.mode:hover, .mode:focus-visible { background: #e04452; outline: none; }
.mode svg { width: 12px; height: 12px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; }
/* main clips the show (sliding hand, rays, dim, flash, embers): nothing may paint over the sidebar or tab bar */
main { flex: 1; min-height: 0; display: grid; position: relative; overflow: hidden; }
main > section { position: relative; z-index: 1; }
/* desktop: instead of a hard cut at the sidebar, the show keeps a small margin and fades out (same on the right, for balance).
   Phones have no sidebar: cards simply leave by the screen edge. */
@media (min-width: 720px) {
  #play, #trade.forging, .dim, .flash, #fx {
    -webkit-mask: linear-gradient(90deg, #0000 14px, #000 110px, #000 calc(100% - 110px), #0000 calc(100% - 14px));
            mask: linear-gradient(90deg, #0000 14px, #000 110px, #000 calc(100% - 110px), #0000 calc(100% - 14px));
  }
}
section { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 16px; padding: 16px; min-height: 0; }

.btn {
  font: 700 16px 'DM Sans', sans-serif; color: var(--bg); background: var(--ink);
  border: 0; border-radius: 999px; padding: 14px 28px; min-width: 260px; cursor: pointer;
}
/* a button's words are never selected, even on the pages whose text can be: a double tap (Select, "Tap again") highlights nothing */
button { -webkit-user-select: none; user-select: none; }
.btn:hover { background: #fff; }
.btn:disabled { opacity: .4; cursor: default; }
.btn:disabled:hover { background: var(--ink); }
.btn.ghost { background: none; color: var(--ink); box-shadow: inset 0 0 0 1.5px var(--line); }
.link { background: none; border: 0; color: var(--mute); font: inherit; text-decoration: underline; cursor: pointer; }
:focus-visible { outline: 2px solid var(--r3); outline-offset: 3px; }
.hint, .save { color: var(--mute); font-size: 14px; text-align: center; }
/* "Share this pack", over the table (app.js, note()). It floats: the stage never moves for it, and a tap beside the button still
   goes to the table under it. */
.table-note { position: absolute; z-index: 25; top: 10px; left: 0; right: 0; padding: 0 16px; pointer-events: none; color: var(--ink); font-size: 15px; text-align: center; text-wrap: balance; text-shadow: 0 1px 8px #000c; }
.table-note .btn { pointer-events: auto; display: inline-flex; align-items: center; justify-content: center; gap: 9px; min-width: 0; padding: 12px 24px; font-size: 15.5px; background: #0b0d12d9; box-shadow: inset 0 0 0 1.5px #eef1f699; }
.table-note .btn .ic { width: 18px; height: 18px; }
.table-note .btn:hover { background: #1b1f2ae6; }
/* Share on a card's sheet: top left, across from Close, filled with the card's own colour. Nobody should have to look for it. */
#shareCard { position: absolute; top: 12px; left: 14px; z-index: 1; display: inline-flex; align-items: center; gap: 8px; padding: 9px 20px 9px 16px; border: 0; border-radius: 999px;
  background: var(--c); color: #0b0e14; font: 700 15px 'DM Sans', sans-serif; cursor: pointer; box-shadow: 0 4px 14px #0007; transition: filter .15s, translate .06s; }
#shareCard:hover { filter: brightness(1.1); } #shareCard:active { translate: 0 1px; }
#shareCard .ic { width: 17px; height: 17px; flex: none; fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
/* the offers: ten packs now, OR Premium. Only on an empty table, never for guests (they have no account to buy on). Designed in web/shop-lab.html (round 7, B3) */
.offers { display: grid; gap: 16px; width: min(100%, 400px); }
#play.shop { overflow-y: auto; justify-content: flex-start; scrollbar-width: none; }   /* the offers are tall: on a small screen the page scrolls rather than squeeze them */
#play.shop > :first-child { margin-top: auto; } #play.shop > :last-child { margin-bottom: auto; }
/* what scrolls out fades out: without this the header cut the timer with a hard line as the page went up. The fades exist only on the side there is more to see (.up / .down, set on scroll) */
#play.shop { --ft: 0px; --fb: 0px; -webkit-mask: linear-gradient(#0000, #000 var(--ft), #000 calc(100% - var(--fb)), #0000); mask: linear-gradient(#0000, #000 var(--ft), #000 calc(100% - var(--fb)), #0000); }
#play.shop.up { --ft: 44px; } #play.shop.down { --fb: 44px; }
@media (min-width: 720px) {   /* desktop keeps its fade at the sidebar's edge as well */
  #play.shop { -webkit-mask: linear-gradient(90deg, #0000 14px, #000 110px, #000 calc(100% - 110px), #0000 calc(100% - 14px)), linear-gradient(#0000, #000 var(--ft), #000 calc(100% - var(--fb)), #0000); -webkit-mask-composite: source-in;
    mask: linear-gradient(90deg, #0000 14px, #000 110px, #000 calc(100% - 110px), #0000 calc(100% - 14px)), linear-gradient(#0000, #000 var(--ft), #000 calc(100% - var(--fb)), #0000); mask-composite: intersect; }
}
body.guest #play.shop { -webkit-mask: none; mask: none; }
#play.shop .stage.empty { height: calc(var(--cw) * .5); flex: none; } #play.shop .wait.on { scale: .84; }
body.guest #play.shop { overflow: visible; justify-content: space-evenly; } body.guest #play.shop .stage.empty { height: calc(var(--cw) * .62); } body.guest #play.shop .wait.on { scale: 1; }
/* a small pack, flat: the ink, the two crimps. It peeks over the gold button and runs down the lanes of the Premium card */
.mp { --w: 50px; --b0: #fff0a8; --b1: #ffa53d; --b2: #e6408f; --b3: #6a35e0; --b4: #131b52; width: var(--w); aspect-ratio: 5/8; flex: none; position: relative; container-type: inline-size; border-radius: calc(var(--w) * .035); overflow: hidden;
  background: radial-gradient(95% 62% at 50% 40%, var(--b0), var(--b1) 20%, var(--b2) 46%, var(--b3) 72%, var(--b4)); box-shadow: 0 6px 14px #000a, inset 0 0 0 1px #ffffff26; }
.mp::before, .mp::after { content: ''; position: absolute; left: 0; right: 0; height: 9cqw; background: repeating-linear-gradient(90deg, #0006 0 2cqw, #ffffff38 2cqw 4cqw), linear-gradient(90deg, var(--r1), var(--r2), var(--r3), var(--r4), var(--r5), var(--r6), var(--r5), var(--r4), var(--r3), var(--r2), var(--r1)); }
.mp::before { top: 0; } .mp::after { bottom: 0; }
.mp.lagoon { --b0: #fff6c0; --b1: #4dedc4; --b2: #1c9fe0; --b3: #1d3fb0; --b4: #0c1a4a; } .mp.ember { --b0: #fff3b0; --b1: #ffb347; --b2: #f0522e; --b3: #9c1f3c; --b4: #3a0c1c; }
.mp.jade { --b0: #fbffc2; --b1: #b6f06a; --b2: #2fbf8f; --b3: #0f6f78; --b4: #06303a; } .mp.eclipse { --b0: #ffe9a0; --b1: #e09a2c; --b2: #5a2a12; --b3: #07080c; --b4: #000; }
.mp.sun { --b0: #fffde0; --b1: #ffd21f; --b2: #ff9d00; --b3: #b85300; --b4: #4a1f00; } .mp.violet { --b0: #f6e6ff; --b1: #d48bff; --b2: #9146ff; --b3: #4b1fa8; --b4: #1d0a4a; }
/* ten packs now: one gold button, five real packs standing behind its top edge. Each pack is its own element showing one cell of ONE picture
   (packs-peek.webp, made by lab-archive/make-pack-peek.py from shots of the real pack): under the mouse they rise one after the other and the fan opens.
   Their box is cut at the bottom only, 18px behind the button, and has room above: nothing is clipped at the top. Only translate and rotate move. */
.refill-wrap { position: relative; margin-top: 56px; }
.refill-packs { position: absolute; z-index: 0; left: 0; right: 0; bottom: calc(100% - 18px); height: 120px; overflow: hidden; display: flex; justify-content: center; align-items: flex-end; pointer-events: none; }
.refill-packs i { --d: calc(var(--i) - 2); flex: none; width: 56px; height: 78px; margin: 0 -9px; background: url(packs-peek.webp) calc(var(--i) * -56px) 0 / 280px 78px no-repeat; z-index: calc(3 - max(var(--d), -1 * var(--d)));
  transform-origin: 50% 140%; rotate: calc(var(--d) * 7deg); translate: 0 calc(12px + var(--d) * var(--d) * 3px);
  transition: translate .4s cubic-bezier(.3, 1.6, .5, 1), rotate .4s cubic-bezier(.3, 1.6, .5, 1); transition-delay: calc(var(--i) * 35ms); }
.refill-wrap:hover .refill-packs i, .refill-wrap:focus-within .refill-packs i { rotate: calc(var(--d) * 11deg); translate: 0 calc(-2px + var(--d) * var(--d) * 2px); }
.refill { position: relative; z-index: 1; width: 100%; display: block; padding: 18px 20px; border: 0; border-radius: 20px; cursor: pointer; color: #2a1a02; font: 700 18px/1 'DM Sans', sans-serif;
  background: linear-gradient(100deg, #d1901c, #fbe364 30%, #fff7c4 48%, #fbe364 66%, #d1901c); box-shadow: 0 10px 30px #fbe36430, inset 0 -3px 0 #a06f12, inset 0 2px 0 #fff7c4; transition: scale .15s, filter .2s; }
.refill b { font: 400 30px/1 var(--serif); font-variant-numeric: tabular-nums; } .refill i { font-style: normal; margin-left: 6px; padding-left: 14px; border-left: 1.5px solid #2a1a0244; font-variant-numeric: tabular-nums; }
.refill:hover { filter: brightness(1.06); } .refill:active { scale: .97; } .refill:disabled { cursor: default; }
.or { display: flex; align-items: center; gap: 12px; color: var(--mute); font: 500 11px/1 var(--mono); letter-spacing: .24em; text-transform: uppercase; }
.or::before, .or::after { content: ''; flex: 1; height: 1px; background: var(--line); }
.or:has(+ [hidden]) { display: none; }                  /* a subscriber has no Premium card under it */
/* a purchase on its way to Stripe: the button keeps its place, its content fades and a gold spinner turns in its middle */
[data-buy].busy { position: relative; opacity: 1; cursor: progress; }
[data-buy].busy > * { opacity: .18; }
.link[data-buy].busy { color: #0000; text-decoration-color: #0000; }
[data-buy].busy::after { content: ''; position: absolute; inset: 0; margin: auto; width: 18px; height: 18px; border-radius: 50%; translate: none; rotate: none; background: none;
  border: 2px solid #ffffff33; border-top-color: var(--r6); animation: busy-spin .7s linear infinite; }
@keyframes busy-spin { to { rotate: 1turn; } }
/* Premium: the ×2, the race (your packs and Premium's run down their lanes and queue up: you are full at 10, Premium goes on), the table You / Premium, the price, the free packs */
.offer { display: grid; gap: 16px; padding: 18px 16px; text-align: left; cursor: pointer; font: inherit; color: var(--ink); border-radius: 20px; border: 1px solid #fbe36455;
  background: radial-gradient(80% 90% at 0% 0%, #fbe36422, #0000 70%), #ffffff06; transition: border-color .2s; }
.offer:hover { border-color: #fbe364aa; } .offer:disabled { cursor: default; }
.p-top { display: flex; align-items: center; gap: 10px; }
.p-top b { font: 400 46px/.9 var(--serif); letter-spacing: -.04em; color: transparent; background: linear-gradient(100deg, #fff7c4, #fbe364 30%, #d1901c 55%, #fff7c4 70%, #fbe364); -webkit-background-clip: text; background-clip: text; filter: drop-shadow(0 2px 0 #7a5410) drop-shadow(0 6px 10px #000a); }
.p-top em { font: 500 12px var(--mono); font-style: normal; letter-spacing: .16em; text-transform: uppercase; color: var(--r6); }
.qlanes { display: grid; gap: 9px; }
.qlane { display: grid; grid-template-columns: 78px 1fr 30px; align-items: center; gap: 8px; font: 500 11px/1.35 var(--mono); letter-spacing: .08em; text-transform: uppercase; color: var(--mute); }
.qlane u { text-decoration: none; display: grid; white-space: nowrap; } .qlane u small { display: flex; align-items: center; gap: 4px; font-size: 10px; letter-spacing: .02em; text-transform: none; color: #6b7485; }
.qlane u svg { width: 11px; height: 11px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; }
.qtrack { position: relative; justify-self: end; width: 100%; height: 32px; border-radius: 999px; background: #0b0e1499; box-shadow: inset 0 0 0 1px #ffffff10; overflow: hidden; }
.qtrack::before { content: ''; position: absolute; left: 12px; right: 12px; top: 50%; border-top: 2px dotted #ffffff14; }
.qtrack .mp { --w: 14px; position: absolute; top: 5px; right: calc(5px + var(--i) * var(--sx, 9px)); opacity: 0; box-shadow: 2px 0 4px #0009; } .qtrack .mp.in { opacity: 1; }
.qlane > b { display: grid; justify-items: end; font: 400 21px/1 var(--serif); letter-spacing: 0; color: var(--ink); font-variant-numeric: tabular-nums; }
.qlane > b::after { content: 'max'; font: 500 8.5px/1.2 var(--mono); letter-spacing: .1em; color: var(--mute); visibility: hidden; } .qlane.full > b::after { visibility: visible; }
.qlane.gold, .qlane.gold > b { color: var(--r6); } .qlane.gold u small { color: #a08f45; } .qlane.gold .qtrack { box-shadow: inset 0 0 0 1px #fbe36440; }
.bt { display: grid; font-size: 14.5px; position: relative; }
.bt::before { content: ''; position: absolute; top: 0; bottom: 0; right: 0; width: 84px; border-radius: 12px; background: #fbe36414; box-shadow: inset 0 0 0 1px #fbe36440; }
.bt > span { position: relative; display: grid; grid-template-columns: 1fr 70px 84px; align-items: baseline; padding: 7px 0 7px 2px; border-top: 1px solid #ffffff12; }
.bt > .h { border-top: 0; padding: 9px 0 3px 2px; font: 500 10px/1 var(--mono); letter-spacing: .12em; text-transform: uppercase; color: var(--mute); } .bt > .h + span { border-top: 0; }
.bt u { text-decoration: none; } .bt s { text-align: center; color: #6b7485; font: 500 13px var(--mono); } .bt .h s { text-decoration: none; font: inherit; color: inherit; }
.bt b { text-align: center; font: 400 20px/1 var(--serif); color: var(--r6); white-space: nowrap; } .bt .h b { font: inherit; }
.cta { display: block; padding: 15px 16px; border-radius: 16px; font: 700 16px/1 'DM Sans', sans-serif; font-variant-numeric: tabular-nums; color: #0b0e14; background: linear-gradient(#fff, #d5dbe8); box-shadow: 0 8px 22px #0008, inset 0 -3px 0 #9aa3b8, inset 0 2px 0 #fff; transition: scale .15s; }
.cta i { font-style: normal; padding-left: 12px; border-left: 1.5px solid #0000002e; } .cta small { font-weight: 500; font-size: 12px; } .offer:active .cta { scale: .98; }
.gift { display: grid; grid-template-columns: auto 1fr; align-items: center; gap: 10px; padding: 0 10px 0 8px; min-height: 54px; margin-top: 12px; border-radius: 14px; background: linear-gradient(100deg, #fbe3642e, #fbe3640a); box-shadow: inset 0 0 0 1px #fbe36455; }
.gift img { width: 92px; height: auto; margin: -20px 0 -2px; align-self: end; filter: drop-shadow(0 4px 6px #0008); pointer-events: none; }
.gift b { font: 400 21.5px/1 var(--serif); color: var(--r6); white-space: nowrap; }
.refill > span, .cta > span { display: flex; align-items: center; justify-content: center; gap: 12px; transition: opacity .15s; }
.refill[data-buy].busy > span { opacity: 0; }
.refill[data-buy].busy::after { width: 22px; height: 22px; border: 2.5px solid #2a1a0230; border-top-color: #2a1a02; }
.offer[data-buy].busy::after { content: none; }
.offer[data-buy].busy > * { opacity: .5; } .offer[data-buy].busy > .cta { opacity: 1; position: relative; }
.offer.busy .cta > span { opacity: 0; }
.offer.busy .cta::after { content: ''; position: absolute; inset: 0; margin: auto; width: 20px; height: 20px; border-radius: 50%; border: 2.5px solid #0b0e1426; border-top-color: #0b0e14; animation: busy-spin .7s linear infinite; }
@media (max-width: 359px) { .gift b { font-size: 18px; } .gift img { width: 76px; } .bt > span { grid-template-columns: 1fr 62px 74px; } .bt::before { width: 74px; } }
.guest .offers { display: none; }
/* guests: Friends and Profile are the gate alone: a message, the Google button and the email form, as on the login screen */
.gate { display: none; --col: min(100%, 360px); }
.guest .gate { display: grid; justify-items: center; gap: 12px; text-align: center; width: 100%; }
.gate > .btn { width: var(--col); min-width: 0; }
.gate .email-auth { text-align: left; }
.guest #friends > :not(h2, .gate), .guest #profile > :not(.gate) { display: none; }
#pfPremium { font-size: 14px; color: var(--mute); }
#pfPremium b { color: var(--r6); }
.stage.empty { height: calc(var(--cw) * .62); }        /* nothing but the timer on it: the room goes to the offers */
#ask, #account { margin: auto; width: min(420px, calc(100vw - 32px)); padding: 28px; border: 1px solid var(--line); border-radius: 18px; background: #11151e; color: var(--ink); box-shadow: 0 30px 80px #000c; text-align: center; }
#ask::backdrop, #account::backdrop { background: #000000d0; }
#account[open] { display: grid; gap: 14px; }
#account h2 { font: 26px/1.1 var(--serif); }
#account .email-auth { text-align: left; }
#ask form { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; }
#ask p { width: 100%; margin-bottom: 12px; text-wrap: pretty; }
#ask .btn { min-width: 0; padding: 12px 22px; font-size: 15px; }

/* the way to an account (the account dialog, the gates of Friends and Profile) is one column, as wide as the email form: --col */
.auth-separator { display: flex; align-items: center; gap: 12px; width: var(--col); color: var(--mute); font-size: 12px; text-transform: uppercase; }
.auth-separator::before, .auth-separator::after { content: ''; flex: 1; height: 1px; background: var(--line); }
.email-auth { display: grid; gap: 12px; width: var(--col); }
.email-auth label { display: grid; gap: 5px; color: var(--mute); font-size: 13px; }
.email-auth input {
  width: 100%; border: 1px solid var(--line); border-radius: 10px; padding: 12px 14px;
  color: var(--ink); background: #ffffff08; font: inherit; user-select: text;
}
.email-auth input::placeholder { color: #687184; }
.email-auth .btn { min-width: 0; padding: 12px 16px; }
.email-auth [role=status] { margin: 0; color: var(--r1); font-size: 13px; }

/* wallet */
.coin { width: 1.25em; height: 1.25em; flex: none; vertical-align: -.27em; pointer-events: none; -webkit-touch-callout: none; }
.coins { display: inline-flex; align-items: center; gap: 5px; color: var(--r6); font-weight: 700; font-variant-numeric: tabular-nums; position: relative; }
.coin-gain { position: absolute; top: 100%; right: 0; white-space: nowrap; font-size: 15px; color: #fff6c9; text-shadow: 0 0 10px #fbe36499, 0 1px 3px #000c; pointer-events: none; }

/* pack: a body plus a top strip in two pieces, so it can really be torn. --p = tear progress 0..1
   .pack-print  everything printed on the foil, flattened. It exists three times at full size: .pack-body below the zigzag,
                .pack-top.a the torn strip, .pack-top.b the strip still attached
   .pack-fl     floats: real elements at their own translateZ, so a tilt pulls the artwork apart
   Sizes are in cqw (1cqw = 1% of the pack width). No filter on .pack itself: a filter would flatten the floats. */
:root { --cw: min(68vw, 300px, 42dvh); }
/* A phone spends some 280px on the header, the tab bar, the hint and the margins; the stage is 1.4 cards tall and the wings hang a
   little under it. On a short screen (an SE, or any phone once Safari's bars are up) 42dvh left no room: the fan covered the hint. */
@media (max-width: 719px) { :root { --cw: min(68vw, 300px, max(150px, (100dvh - 280px) / 1.5)); } }
@property --drift { syntax: '<number>'; inherits: false; initial-value: 0; }
.pack {
  --p: 0; --gx: 50; --gy: 50; --cut: 19.2cqw;   /* the cut sits at 12% of the height */
  --b0: #fff0a8; --b1: #ffa53d; --b2: #e6408f; --b3: #6a35e0; --b4: #131b52; --deep: #1c0f52;
  width: calc(var(--cw) * .78); aspect-ratio: 5/8; position: relative; cursor: pointer; container-type: inline-size;
  touch-action: manipulation; will-change: transform; transform-style: preserve-3d;
}
/* Every pack is printed in one of seven inks, drawn at random when it is made. Rarely, it comes out as the negative of that ink: the artwork is a radial ladder from a light core
   (--b0) to a night rim (--b4), --deep is the shade its gilt letters cast. Aurora is the default above. */
.pack[data-look="lagoon"]  { --b0: #fff6c0; --b1: #4dedc4; --b2: #1c9fe0; --b3: #1d3fb0; --b4: #0a1238; --deep: #06234a; }
.pack[data-look="ember"]   { --b0: #fff3b0; --b1: #ffb347; --b2: #f0522e; --b3: #9c1f3c; --b4: #2a0a1e; --deep: #3a0a18; }
.pack[data-look="jade"]    { --b0: #fbffc2; --b1: #b6f06a; --b2: #2fbf8f; --b3: #0f6f78; --b4: #062a3a; --deep: #05303a; }
.pack[data-look="eclipse"] { --b0: #ffe9a0; --b1: #e09a2c; --b2: #5a2a12; --b3: #1a1220; --b4: #07080c; --deep: #000; }
.pack[data-look="eclipse"] .pp-foil { opacity: .8; }
.pack[data-look="sun"]     { --b0: #fffde0; --b1: #ffd21f; --b2: #ff9d00; --b3: #b85300; --b4: #2e1200; --deep: #4a2400; }
.pack[data-look="violet"]  { --b0: #f6e6ff; --b1: #d48bff; --b2: #9146ff; --b3: #4b1fa8; --b4: #140a3c; --deep: #1d0f55; }
/* The rare one: a pack as the photographic negative of the ink it drew. Night at the core, a pale rim, the gold gone to steel
   blue. The filter goes on each printed piece, never on the pack itself (that would flatten its depth); the seal and the tear's
   light stay true. */
.pack.negative :is(.pack-print, .pack-coin > *, .pack-name, .pack-chip, .pack-fan i) { filter: invert(1); }
.pack.negative .pack-aura { filter: invert(1); }
/* the foil never sits still, even when nobody touches the pack. The clock is not inherited: it runs on the elements that read it,
   all started in the same frame, so the three prints stay in step across the cut */
.pack :is(.pp-foil, .pp-glit, .pp-crimp, .pack-coin b, .pack-name b, .pack-one) { animation: pk-drift 9s linear infinite; }
@keyframes pk-drift { to { --drift: 100; } }
/* On a phone the drift ticks 30 times a second, not 60 or 120. --drift is a custom property: the browser cannot hand it to the
   compositor, so every new value is a style pass, a repaint and a new raster of the foil (blend and filters), the glitter's two
   masks, the crimps, the coin's face and the gilt name, and WebKit does all of that on the CPU. A step is two thirds of a pixel
   of a slow shimmer: it cannot be seen, and it halves (or quarters, at 120 Hz) the hero's standing cost. */
.flat .pack :is(.pp-foil, .pp-glit, .pp-crimp, .pack-coin b, .pack-name b, .pack-one) { animation-timing-function: steps(270); }
.pack > * { position: absolute; }
/* here the filter is wanted: it flattens the floats, a spent pack is a dead, flat thing */
.pack.empty { filter: grayscale(1) brightness(.5); cursor: default; }
.pack.empty, .pack.empty * { animation-play-state: paused !important; }
.pack.empty :is(.pack-aura, .pack-sparks, .pack-orbit) { display: none; }

/* under the pack: its shadow, a coloured breath on the table, and three dark sheets of thickness */
/* Both are soft by construction, not by filter: blur() on a layer that moves or breathes is run again by the GPU every frame
   (a seventh of the whole table's GPU time, for two smudges). The shadow's stops are the profile of the old blurred ellipse
   (an 8.8cqw half-height under a 5cqw gaussian); the aura already was a smooth gradient and only needed its falloff let out. */
.pack-shadow { inset: auto -20% -19.25%; height: 23.5%; opacity: .6; transform: translateZ(-12cqw); pointer-events: none;
  background: radial-gradient(closest-side, #000000eb 0, #000000cf 23%, #00000080 47%, #0000003d 73%, #0000 100%); }
.pack-aura { inset: -18%; border-radius: 50%; transform: translateZ(-14cqw); pointer-events: none; opacity: .75;
  background: radial-gradient(closest-side, color-mix(in srgb, var(--b1) 66%, #0000), color-mix(in srgb, var(--b2) 38%, #0000) 45%, color-mix(in srgb, var(--b2) 9%, #0000) 66%, #0000 82%);
  animation: pk-breathe 3.6s ease-in-out infinite alternate; }
@keyframes pk-breathe { from { opacity: .45; scale: .92; } to { opacity: .9; scale: 1.06; } }
.pack-ply { inset: var(--cut) 0 4px; border-radius: 0 0 1.2cqw 1.2cqw; background: color-mix(in srgb, var(--b4) 70%, #000); transform: translateZ(calc(var(--i) * -.9cqw)); }

.pack-print { inset: 0; border-radius: 1.2cqw; overflow: hidden; color: #fff; }
.pack-print > * { position: absolute; inset: 0; pointer-events: none; }
/* the artwork is the rarity ladder, seen from inside: legendary gold at the core, then UR orange, SR pink, R violet, night at the rim */
.pp-base { background: radial-gradient(105% 68% at 50% 38%, var(--b0) 0, var(--b1) 24%, var(--b2) 46%, var(--b3) 70%, var(--b4) 100%); }
/* right and bottom back to auto, one by one: "inset: auto !important" took left and top with it, and the three of them sat on the
   pouch's top left corner instead of behind the coin */
.pp-rays, .pp-ros, .pp-halo { right: auto; bottom: auto; left: 50%; top: 61cqw; translate: -50% -50%; aspect-ratio: 1; }
/* 180cqw, not more: the mask lets nothing through past 90cqw from the centre, and a turning layer costs its full square (at 300cqw,
   on a phone at 3x, a 1800px texture and its mask, for the 36% of it that showed) */
.pp-rays { width: 180cqw; animation: pk-spin 46s linear infinite;
  background: repeating-conic-gradient(#fff0 0 8deg, #ffffff3d 8.5deg 12.5deg, #fff0 13deg 22deg);
  -webkit-mask: radial-gradient(closest-side, #000 0, #000a 43.33%, #0000 100%); mask: radial-gradient(closest-side, #000 0, #000a 43.33%, #0000 100%); }
.pp-ros { width: 150cqw; opacity: .5; mix-blend-mode: soft-light; animation: pk-spin 90s linear infinite reverse; background: #fff;
  -webkit-mask: var(--rosette-lg) center / contain no-repeat; mask: var(--rosette-lg) center / contain no-repeat; }
.pp-halo { width: 96cqw; background: radial-gradient(closest-side, #fffffff2, #fff8 30%, #fff0 70%); animation: pk-pulse 2.8s ease-in-out infinite alternate; }
@keyframes pk-spin { to { rotate: 1turn; } }
@keyframes pk-pulse { from { opacity: .55; scale: .9; } to { opacity: 1; scale: 1.08; } }
/* holo: a spectrum cut by diffraction lines. It rides the tilt (--gx) and drifts on its own (--drift). The spectrum's period is
   100cqw * sin(115deg) / 2, so a drift of one pack width is exactly two periods and the loop has no seam. */
.pp-foil { mix-blend-mode: color-dodge; opacity: .42; filter: brightness(.62) contrast(1.35) saturate(1.4);
  background-image:
    repeating-linear-gradient(115deg, #3a3a3a 0, #6e6e6e .5cqw, #d8d8d8 .8cqw, #6e6e6e 1.1cqw, #3a3a3a 1.7cqw),
    repeating-linear-gradient(115deg, hsl(2 100% 70%) 0, hsl(45 100% 66%) 6.5cqw, hsl(120 90% 66%) 13cqw, hsl(186 100% 68%) 19.5cqw, hsl(228 100% 74%) 26cqw, hsl(290 100% 74%) 32.5cqw, hsl(330 100% 72%) 39cqw, hsl(2 100% 70%) 45.32cqw);
  background-blend-mode: multiply;
  background-position: calc(var(--gx) * -.9cqw) 0, calc(var(--drift) * 1cqw + var(--gx) * 1.4cqw) 0; }
/* glitter: two sparse noise masks, one fixed, one moving. A flake lights only where they overlap, so it twinkles */
.pp-glit { opacity: .9; background: linear-gradient(120deg, #fff, #fff3b8, #fff, #c8f0ff, #fff);
  -webkit-mask: var(--noise-a) 0 0 / 52cqw, var(--noise-b) calc(var(--drift) * .52cqw + var(--gx) * .3cqw) calc(var(--gy) * .3cqw) / 52cqw; -webkit-mask-composite: source-in;
  mask: var(--noise-a) 0 0 / 52cqw, var(--noise-b) calc(var(--drift) * .52cqw + var(--gx) * .3cqw) calc(var(--gy) * .3cqw) / 52cqw; mask-composite: intersect; }
/* a lamp passes over the pouch every few seconds */
/* The band is a sheet 2.2 packs wide that slides, not a background that is repositioned: a transform is animated by the compositor
   alone, a background-position repaints the pouch-sized layer on the main thread at every frame of the pass. Same band, same path
   (it was background-size 220%, position 170% -> -70%, which is this sheet going from -2.04 to +0.84 pack widths). */
.pp-sweep { mix-blend-mode: soft-light; }
.pp-sweep::before { content: ''; position: absolute; inset: 0 auto 0 0; width: 220%; background: linear-gradient(105deg, #fff0 42%, #ffffffa8 50%, #fff0 58%);
  transform: translateX(-92.727%); animation: pk-sweep 4.6s cubic-bezier(.5, 0, .3, 1) infinite; }
@keyframes pk-sweep { 0%, 35% { transform: translateX(-92.727%); } 80%, 100% { transform: translateX(38.182%); } }
/* heat-sealed ends: ridges over a strip of the six rarity colours */
.pp-crimp { inset: 0 0 auto !important; height: 10cqw;
  background: repeating-linear-gradient(90deg, #0006 0 1.1cqw, #ffffff2e 1.1cqw 2.2cqw), linear-gradient(#fff5, #0000 35%, #0003),
    linear-gradient(90deg, var(--r1), var(--r2), var(--r3), var(--r4), var(--r5), var(--r6), var(--r5), var(--r4), var(--r3), var(--r2), var(--r1)) calc(var(--gx) * 1cqw + var(--drift) * 2cqw) 0 / 200cqw 100%;
  box-shadow: 0 .4cqw 0 #0005, 0 .8cqw 0 #ffffff40; }
.pp-crimp.b { inset: auto 0 0 !important; box-shadow: 0 -.4cqw 0 #0005, 0 -.8cqw 0 #ffffff40; }
/* the pouch is a pillow: dark at the seams, a soft bar of light that slides with the tilt */
.pp-shade { background: linear-gradient(90deg, #0009, #0000 9%, #0000 91%, #000a),
    linear-gradient(100deg, #fff0 calc(var(--gx) * 1% - 26%), #ffffff50 calc(var(--gx) * 1%), #fff0 calc(var(--gx) * 1% + 26%)),
    radial-gradient(120% 50% at 50% 118%, color-mix(in srgb, var(--deep) 92%, #0000), #0000 70%); }

/* the cut is a zigzag: body and strip carry complementary teeth, so the closed pack shows a faint pre-cut line. Both ends are pinked. */
.pack-body {
  --m: conic-gradient(from 135deg at 50% 0, #000 90deg, #0000 0) 0 var(--cut) / 12px 6px repeat-x,
    linear-gradient(#000 0 0) 0 calc(var(--cut) + 5.5px) / 100% calc(100% - var(--cut) - 9px) no-repeat,
    conic-gradient(from -45deg at 50% 100%, #000 90deg, #0000 0) 0 100% / 8px 4px repeat-x;
  -webkit-mask: var(--m); mask: var(--m); }
.pack-top {
  --m: conic-gradient(from 135deg at 50% 0, #0000 90deg, #000 0) 0 var(--cut) / 12px 6px repeat-x,
    linear-gradient(#000 0 0) 0 3.5px / 100% calc(var(--cut) - 3px) no-repeat,
    conic-gradient(from 135deg at 50% 0, #000 90deg, #0000 0) 0 0 / 8px 4px repeat-x;
  -webkit-mask: var(--m); mask: var(--m); }
/* the strip is mostly crimp: it skips the costly layers. Not the rays and the rosette any more: now that they turn about the coin they
   reach the cut, and a strip without them read as a plain band across the top of the pouch (a black one on a Mega noir). The strips
   are clipped to their teeth, so that is two slivers more to draw. A phone still skips them: every layer there is memory */
.pack-top :is(.pp-glit, .pp-sweep, .pp-halo) { display: none; }
.lean .pack-top :is(.pp-rays, .pp-ros) { display: none; }
/* .a = the torn part, hinged at the tear point and peeling up; .b = what is still attached. */
/* Both strips carry the whole print, the mask only shows its top 12%. The clip stops at the strip's teeth too: a mask hides what is
   under it but the GPU still blends it, foil and all, over the full pouch; a clip is never drawn. Nothing visible changes. */
.pack-top { --strip: calc(100% - var(--cut) - 8px); }
.pack-top.a { clip-path: inset(-60% calc((1 - var(--p)) * 100%) var(--strip) -60%); transform-origin: calc(var(--p) * 100%) var(--cut); transform: rotate(calc(var(--p) * 20deg)); }
.pack-top.b { clip-path: inset(0 0 var(--strip) calc(var(--p) * 100%)); }
.pack-glow {
  left: 0; top: var(--cut); width: calc(var(--p) * 100%); height: 46%; translate: 0 -50%;
  background: radial-gradient(closest-side, #fff6d8, #ffc83d88 40%, transparent); filter: blur(8px);
  opacity: calc(var(--p) * 1.2); pointer-events: none; transform-origin: 50% 50%;
  transition: scale .5s cubic-bezier(.2, 1.5, .4, 1), opacity .6s;
}
.pack.open .pack-glow { scale: 1.3 2.2; }
/* The rip is called done at 97%: without this, the last 3% of the strip stays on the open pack as a small bar at its top right
   while the rest tumbles away. Once open, the torn piece takes the whole strip with it. */
.pack.open .pack-top.b { display: none; }
.pack.open .pack-top.a { clip-path: inset(-60% 0 var(--strip) -60%); }

/* floats. The coin is a real object: six gold discs give it a rim you can see when it rocks, the face is an engraved rosette
   under a sheen that never stops turning (--drift), and the W is struck into it */
.pack-fl { pointer-events: none; backface-visibility: hidden; -webkit-backface-visibility: hidden; }
/* how far it may rock: the edge swings back by radius x sin(angle), and the rim is 3.75cqw deep behind the face. At 22 degrees and 10cqw up,
   the far edge ended 3.5cqw INSIDE the pouch and was cut off along a straight line. 14 degrees at 13cqw leaves it 3cqw clear */
.pack-coin { left: 50%; top: 61cqw; width: 0; height: 0; transform-style: preserve-3d; transform: translateZ(13cqw); animation: pk-rock 5.2s ease-in-out infinite alternate; }
@keyframes pk-rock { from { rotate: y -14deg; } to { rotate: y 14deg; } }
.pack-coin > * { position: absolute; width: 52cqw; aspect-ratio: 1; left: -26cqw; top: -26cqw; border-radius: 50%; backface-visibility: hidden; -webkit-backface-visibility: hidden; }
.pack-coin i { background: linear-gradient(90deg, #6b470c, #f3d572 30%, #fff3bd 50%, #c28a1e 70%, #6b470c); transform: translateZ(calc(var(--i) * -.75cqw)); }
.pack-coin i:last-of-type { box-shadow: 0 3cqw 6cqw #000a; }
.pack-coin b { display: grid; place-items: center; font: 400 31cqw/1 var(--serif); color: #8a5a10; text-shadow: 0 -.35cqw 0 #fff6c4, 0 .45cqw 0 #5e3c08, 0 .9cqw 1.4cqw #3d2603aa;
  background: conic-gradient(from calc(var(--gx) * 3.6deg + var(--drift) * 3.6deg), #b9831a, #fff3bd, #e2b443, #a06f12, #fbe364, #fff8d6, #c9962b, #8a5a10, #f3d572, #b9831a);
  box-shadow: inset 0 0 0 1.1cqw #fbe364, inset 0 0 0 1.6cqw #7a5410, inset 0 0 0 2.6cqw #f3d572, inset 0 0 0 3cqw #7a541088, inset 0 -2cqw 4cqw #5e3c0877, inset 0 2cqw 4cqw #fff6c488; }
.pack-coin b::before { content: ''; position: absolute; inset: 3.4cqw; border-radius: 50%; background: #6b470c; opacity: .55;
  -webkit-mask: var(--rosette) center / contain no-repeat; mask: var(--rosette) center / contain no-repeat; }
.pack-coin b::after { content: ''; position: absolute; inset: 0; border-radius: 50%; mix-blend-mode: soft-light;
  background: linear-gradient(112deg, #fff0 calc(var(--gx) * 1% - 28%), #fffffff0 calc(var(--gx) * 1%), #fff0 calc(var(--gx) * 1% + 28%)); }
/* the name: gilt letters with a real extrusion (stacked shadows), the gold runs with the light and the drift */
.pack-name { left: 0; right: 0; top: 91cqw; text-align: center; transform: translateZ(16cqw); font: 23.5cqw/.9 var(--serif); letter-spacing: -.01em; }
.pack-name span { display: block; color: #fff; text-shadow: 0 .35cqw 0 #d9d2ee, 0 .7cqw 0 #a99bd6, 0 1.05cqw 0 var(--deep), 0 1.4cqw 0 var(--deep), 0 2.4cqw 3.4cqw #000c; }
.pack-name b, .pack-one { display: block; font-weight: 400; color: transparent; -webkit-background-clip: text; background-clip: text;
  background-image: linear-gradient(100deg, #fff7c4, #fbe364 22%, #d1901c 42%, #fff7c4 50%, #fbe364 62%, #d1901c 82%, #fff7c4);
  background-size: 200% 100%; background-position: calc(var(--gx) * 1.2% + var(--drift) * 2%) 0;
  filter: drop-shadow(0 .35cqw 0 #8a5a10) drop-shadow(0 .7cqw 0 #5e3c08) drop-shadow(0 1.05cqw 0 var(--deep)) drop-shadow(0 2.2cqw 2.4cqw #000b); }
.pack-chip { left: 50%; top: 137.5cqw; translate: -50% 0; transform: translateZ(11cqw); padding: 1.7cqw 4.4cqw; border-radius: 99cqw; white-space: nowrap;
  font-weight: 700; font-size: 4.2cqw; line-height: 1; letter-spacing: .24em; text-transform: uppercase; color: var(--r6); background: #0b0e14e6;
  box-shadow: inset 0 0 0 max(1px, .3cqw) var(--r6), 0 1.4cqw 3cqw #0009; }
/* sparks: the nearest plane, some overhang the pouch. Four-point stars, each on its own clock */
.pack-sparks { inset: -6%; transform: translateZ(22cqw); }
.pack-sparks i { position: absolute; left: var(--x); top: var(--y); width: var(--s); aspect-ratio: 1; background: radial-gradient(closest-side, #fff, #fff6b0 45%, #fff0 70%);
  clip-path: polygon(50% 0, 58% 42%, 100% 50%, 58% 58%, 50% 100%, 42% 58%, 0 50%, 42% 42%); animation: pk-twinkle var(--t) ease-in-out infinite; animation-delay: var(--d); }
@keyframes pk-twinkle { 0%, 100% { scale: .2; opacity: 0; rotate: 0deg; } 50% { scale: 1; opacity: 1; rotate: 45deg; } }

/* ======================================================================================
   MEGA: ten cards. One pack in twenty (SQL 0025), seen on the table before it is opened, so it has to read as an event from across
   the room: a tenth bigger (app.js, MEGA_SIZE) and twice as thick, a larger coin, faster and denser rays, a louder aura, two orbs
   circling it in real 3D (they pass behind the foil and come back in front), more sparks. Same pouch, same tear, and nothing floats
   above the cut. It wears one of five designs (data-mega), over any of the seven inks:
   ten     the coin is the zero of a gilt 10
   gold    a gold bar: the ink only shows through a porthole behind the coin
   noir    black label: gold engraving on matt black, the ink is the glow
   hand    ten card backs fanned out behind the coin
   prism   pearl foil: the ink is a pastel at the seams, the rainbow does the work
   .pp-art is one more printed layer, empty unless a design draws on it.
   ====================================================================================== */
.pp-art { display: none; }
.pack.mega .pack-aura { inset: -32%; opacity: 1; animation-duration: 2.2s; background: radial-gradient(closest-side, #fbe364bf, color-mix(in srgb, var(--b2) 55%, #0000) 42%, color-mix(in srgb, var(--b2) 12%, #0000) 62%, #0000 80%); }
.pack.mega .pp-rays { animation-duration: 18s; background: repeating-conic-gradient(#fff0 0 6deg, #ffffff5c 6.5deg 10.5deg, #fff0 11deg 18deg); }
.pack.mega .pp-foil { opacity: .6; }
.pack.mega .pack-coin { top: 57cqw; scale: 1.12; }
.pack.mega :is(.pp-rays, .pp-ros, .pp-halo) { top: 57cqw; }
.pack.mega .pack-name { top: 90cqw; }
.pack.mega .pack-name b { font-size: 24.5cqw; text-transform: uppercase; letter-spacing: .03em; }
.pack.mega .pack-name span { font-size: 10.5cqw; margin-top: 2.2cqw; letter-spacing: .02em; }
.pack.mega .pack-chip { color: #0b0e14; background: linear-gradient(100deg, #fbe364, #fff6c4 45%, #e2b443); box-shadow: inset 0 0 0 max(1px, .3cqw) #fff8d6, 0 1.4cqw 3cqw #0009; }
/* orbit: three nested turns. The ring turns about the pouch's vertical axis, the arm pushes the orb out, the orb turns back to face you.
   Transforms only: the compositor carries them, on a phone too */
.pack-orbit { left: 50%; top: 52%; width: 0; height: 0; pointer-events: none; transform-style: preserve-3d; transform: rotateZ(var(--tilt)) rotateX(-10deg); }
.pack-orbit i, .pack-orbit u { position: absolute; transform-style: preserve-3d; }
.pack-orbit i { animation: pk-orbit var(--t) linear infinite; animation-delay: var(--d); }
.pack-orbit u { transform: translateX(74cqw); }
.pack-orbit b { position: absolute; left: -5cqw; top: -5cqw; width: 10cqw; aspect-ratio: 1; border-radius: 50%; animation: pk-orbit var(--t) linear infinite reverse; animation-delay: var(--d);
  background: radial-gradient(closest-side, #fff 0, #fff 14%, var(--oc) 34%, color-mix(in srgb, var(--oc) 40%, #0000) 58%, #0000 72%); }
@keyframes pk-orbit { to { rotate: y 1turn; } }
.pack.open .pack-orbit { display: none; }

/* ---- ten ---- */
.mega[data-mega="ten"] .pack-coin { left: 66cqw; top: 58cqw; scale: 1; }
.mega[data-mega="ten"] :is(.pp-rays, .pp-ros, .pp-halo) { top: 58cqw; }
.mega[data-mega="ten"] .pp-halo { width: 118cqw; }
.pack-one { left: 5cqw; top: 58cqw; width: 34cqw; translate: 0 -50%; transform: translateZ(13cqw); text-align: center; font: 74cqw/1 var(--serif);
  filter: drop-shadow(0 .5cqw 0 #8a5a10) drop-shadow(0 1cqw 0 #5e3c08) drop-shadow(0 2.6cqw 2.6cqw #000b); }
.pack.negative .pack-one { filter: invert(1) drop-shadow(0 .5cqw 0 #a57510) drop-shadow(0 2.2cqw 2.4cqw #fff4); }
.mega[data-mega="ten"] .pack-name { top: 93cqw; }
.mega[data-mega="ten"] .pack-name b { font-size: 21cqw; }

/* ---- gold ---- */
.mega[data-mega="gold"] .pp-base { background:
  radial-gradient(circle at 50% 58cqw, var(--b0) 0, var(--b0) 19cqw, var(--b1) 25cqw, var(--b2) 30cqw, var(--b3) 34cqw, var(--b4) 37cqw, #0000 37.3cqw),
  repeating-linear-gradient(0deg, #ffffff1c 0 .25cqw, #00000014 .25cqw .5cqw),
  linear-gradient(100deg, #8a5a10 calc(var(--gx) * .6% - 60%), #e9c558 calc(var(--gx) * .6% - 25%), #fff3bd calc(var(--gx) * .6% + 5%), #c9962b calc(var(--gx) * .6% + 40%), #f3d572 calc(var(--gx) * .6% + 75%), #8a5a10 calc(var(--gx) * .6% + 120%)); }
.mega[data-mega="gold"] :is(.pp-rays, .pp-ros, .pp-halo) { top: 58cqw; }
.mega[data-mega="gold"] .pp-rays { width: 74cqw; border-radius: 50%; -webkit-mask: none; mask: none; }
.mega[data-mega="gold"] .pp-halo { width: 66cqw; }
.mega[data-mega="gold"] .pack-coin { top: 58cqw; scale: .9; }
.mega[data-mega="gold"] .pp-ros { opacity: .75; }
.mega[data-mega="gold"] .pp-foil { opacity: .22; }
.mega[data-mega="gold"] .pp-art { display: block; inset: auto; left: 50%; top: 58cqw; width: 77cqw; aspect-ratio: 1; translate: -50% -50%; border-radius: 50%;
  box-shadow: inset 0 0 0 1.1cqw #fbe364, inset 0 0 0 1.7cqw #7a5410, inset 0 0 0 2.9cqw #f3d572, inset 0 0 0 3.3cqw #5e3c08, inset 0 2cqw 5cqw 3cqw #000a, 0 .7cqw 0 #fff6c4aa, 0 -.6cqw 0 #5e3c0888; }
.mega[data-mega="gold"] .pack-name { top: 98cqw; transform: translateZ(4cqw); }          /* struck into the bar: it barely floats */
.mega[data-mega="gold"] .pack-name b { font-size: 22cqw; background-image: linear-gradient(100deg, #5e3c08, #8a5a10 22%, #3d2603 42%, #6b470c 50%, #8a5a10 62%, #3d2603 82%, #5e3c08);
  filter: drop-shadow(0 .35cqw 0 #fff6c4d0) drop-shadow(0 -.25cqw 0 #3d2603aa); }
.mega[data-mega="gold"] .pack-name span { font-size: 9.5cqw; margin-top: 1.6cqw; color: #4a2f06; text-shadow: 0 .3cqw 0 #fff6c4b0; }
.mega:is([data-mega="gold"], [data-mega="prism"]) .pack-chip { color: var(--r6); background: #0b0e14e6; box-shadow: inset 0 0 0 max(1px, .3cqw) var(--r6), 0 1.4cqw 3cqw #0009; }

/* ---- noir ---- */
.mega[data-mega="noir"] .pp-base { background: radial-gradient(90% 60% at 50% 36%, color-mix(in srgb, var(--b3) 40%, #0b0c10) 0, #0b0c10 60%, #050608 100%); }
.mega[data-mega="noir"] .pp-rays { background: repeating-conic-gradient(#0000 0 6deg, color-mix(in srgb, var(--b1) 38%, #0000) 6.5deg 10.5deg, #0000 11deg 18deg); }
.mega[data-mega="noir"] .pp-ros { mix-blend-mode: normal; opacity: .62; background: conic-gradient(#b9831a, #fff3bd, #e2b443, #8a5a10, #fbe364, #fff8d6, #c9962b, #8a5a10, #f3d572, #b9831a); }
.mega[data-mega="noir"] .pp-halo { width: 124cqw; background: radial-gradient(closest-side, color-mix(in srgb, var(--b0) 92%, #0000), color-mix(in srgb, var(--b1) 72%, #0000) 26%, color-mix(in srgb, var(--b2) 42%, #0000) 50%, #0000 72%); }
html:not(.lean) .mega[data-mega="noir"] .pack-top .pp-halo { display: block; }   /* the glow is this pouch's colour: without it the strip is a black band */
.mega[data-mega="noir"] .pp-crimp { background: repeating-linear-gradient(90deg, #0006 0 1.1cqw, #ffffff2e 1.1cqw 2.2cqw), linear-gradient(#fff5, #0000 35%, #0003),
  linear-gradient(90deg, #8a5a10, #fbe364, #fff3bd, #c9962b, #6b470c, #c9962b, #fff3bd, #fbe364, #8a5a10) calc(var(--gx) * 1cqw + var(--drift) * 2cqw) 0 / 200cqw 100%; }
.mega[data-mega="noir"] .pp-art { display: block; inset: 25cqw 5cqw 14.5cqw; border-radius: 1.6cqw; box-shadow: inset 0 0 0 .35cqw #c9962b, inset 0 0 0 1.3cqw #0000, inset 0 0 0 1.5cqw #c9962b70; }
.mega[data-mega="noir"] .pack-orbit { --oc: var(--b1) !important; }
.mega[data-mega="noir"] .pack-orbit + .pack-orbit { --oc: var(--b2) !important; }
.mega[data-mega="noir"] .pack-aura { background: radial-gradient(closest-side, color-mix(in srgb, var(--b1) 80%, #0000), color-mix(in srgb, var(--b2) 55%, #0000) 42%, color-mix(in srgb, var(--b2) 12%, #0000) 62%, #0000 80%); }

/* ---- hand ---- */
/* the coin rocks: its edge swings back by radius x sin(angle), rim and all, and would go through the cards. Here it rocks 12 degrees and
   floats a little higher (its edge never comes nearer the pouch than 5.8cqw), and the hand stays low (4.2cqw at most). Not higher than
   that: a tilt would slide the coin right off the middle of the hand */
.mega[data-mega="hand"] .pack-coin { top: 68cqw; scale: 1; transform: translateZ(15cqw); animation-name: pk-rock-soft; }
@keyframes pk-rock-soft { from { rotate: y -12deg; } to { rotate: y 12deg; } }
.mega[data-mega="hand"] :is(.pp-rays, .pp-ros, .pp-halo) { top: 68cqw; }
.pack-fan { left: 50%; top: 68cqw; width: 0; height: 0; transform-style: preserve-3d; transform: translateZ(1cqw); }
/* one card back, the game's: matt black, a gold line, the medallion. Each one a step nearer than the one before, so a tilt opens the hand */
.pack-fan i { position: absolute; left: -9.5cqw; top: -44cqw; width: 19cqw; height: 26cqw; border-radius: 1.7cqw; transform-origin: 50% 44cqw;
  transform: rotate(var(--a)) translateZ(calc(var(--n) * .35cqw)); animation: pk-fan 4.4s ease-in-out infinite alternate; backface-visibility: hidden; -webkit-backface-visibility: hidden;
  background: radial-gradient(circle at 50% 38%, #0000 0 2.7cqw, #c9a66b 2.8cqw 3.2cqw, #0000 3.3cqw), radial-gradient(120% 90% at 50% 35%, #262830, #0b0c0f 72%);
  box-shadow: inset 0 0 0 .4cqw #0b0c0f, inset 0 0 0 .75cqw #c9a66bd0, 0 .5cqw 1.6cqw #000b; }
@keyframes pk-fan { from { rotate: calc(var(--a) * -.1); } to { rotate: 0deg; } }
.mega[data-mega="hand"] .pack-name { top: 96cqw; }
.mega[data-mega="hand"] .pack-name b { font-size: 21.5cqw; }
.mega[data-mega="hand"] .pack-name span { font-size: 9.5cqw; margin-top: 1.6cqw; }

/* ---- prism ---- */
.mega[data-mega="prism"] .pp-base { background: radial-gradient(105% 68% at 50% 36%, #fff 0, #f7f5ff 26%, color-mix(in srgb, var(--b1) 30%, #f0eef8) 50%, color-mix(in srgb, var(--b2) 45%, #dcdaea) 74%, color-mix(in srgb, var(--b3) 70%, #9d9ab8) 100%); }
.mega[data-mega="prism"] .pp-rays { background: repeating-conic-gradient(#0000 0 6deg, color-mix(in srgb, var(--b2) 34%, #0000) 6.5deg 10.5deg, #0000 11deg 18deg); }
.mega[data-mega="prism"] .pp-ros { mix-blend-mode: normal; opacity: .38; background: var(--b3); }
.mega[data-mega="prism"] .pp-foil { mix-blend-mode: overlay; opacity: .75; filter: saturate(1.6) brightness(1.9) contrast(1.1); }   /* dodge burns a pale foil white: overlay keeps the pastels */
/* a gold engine turning behind the coin: a still gradient under the rosette mask, turned by the compositor */
.pack-engine { left: 50%; top: 57cqw; width: 84cqw; aspect-ratio: 1; translate: -50% -50%; transform: translateZ(1.5cqw); animation: pk-spin 24s linear infinite;
  background: conic-gradient(#b9831a, #fff3bd, #fbe364, #8a5a10, #fbe364, #fff8d6, #c9962b, #b9831a);
  -webkit-mask: var(--rosette-lg) center / contain no-repeat; mask: var(--rosette-lg) center / contain no-repeat; }
.mega[data-mega="prism"] .pack-name b { background-image: linear-gradient(100deg, var(--b4), var(--b3) 22%, var(--b2) 42%, var(--b4) 50%, var(--b3) 62%, var(--b2) 82%, var(--b4));
  filter: drop-shadow(0 .35cqw 0 #fff) drop-shadow(0 .7cqw 0 #d9d2ee) drop-shadow(0 2cqw 2.4cqw #0006); }
.mega[data-mega="prism"] .pack-name span { color: var(--b4); text-shadow: 0 .3cqw 0 #fff, 0 1.6cqw 2.4cqw #0004; }
@media (prefers-reduced-motion: reduce) { .pack, .pack *, .pp-sweep::before { animation: none !important; } }

/* The stock on the table. One hero pack in front, the others a hand of packs opening behind it on both sides: the wings.
   Every pack sits on a .seat and the springs move the seat, never the pack: the pack is a size container (its artwork is drawn
   in cqw), so touching its own style, even just its transform, makes the browser re-resolve its sixty-odd descendants. */
.seat { width: calc(var(--cw) * .78); position: relative; transform-style: preserve-3d; will-change: transform; transition: opacity .3s; }
.seat .pack { width: 100%; will-change: auto; }
/* A pack of the wings LOOKS like the hero (same foil, glitter, rays, coin) but is frozen and flat: no clock runs in it, its light
   never changes, so it is painted once into one texture and from then on only moved. Frozen means "in the pose the clocks start
   from", or waking would jump: the halo sits where pk-pulse begins, and the coin is not stopped but paused, rim and all, so it
   rocks on from where it was. Only what lives outside the pouch or only exists in motion is off. */
.pack.mini { transform-style: flat; }
.pack.mini, .pack.mini :not(.pack-coin) { animation: none !important; }
.pack.mini .pack-coin { animation-play-state: paused !important; }
.pack.mini .pp-halo { opacity: .55; scale: .9; }
.pack.mini :is(.pack-name, .pack-chip, .pack-one, .pack-engine) { transform: none; backface-visibility: visible; -webkit-backface-visibility: visible; }
.pack.mini :is(.pp-sweep, .pack-aura, .pack-sparks, .pack-shadow, .pack-ply, .pack-top.a, .pack-glow, .pack-medal, .pack-orbit) { display: none; }
/* The shade of a pack further back is not paint: a black veil cut to the pouch's pinked outline, on its own layer, whose opacity
   the compositor fades. .pack-flash is its white twin, put on a pack for the third of a second after it lands, then thrown away. */
.pack-flash { background: #fff !important; transition: none !important; }
.pack-dim, .pack-flash { inset: 0; border-radius: 1.2cqw; background: #000; opacity: 0; will-change: opacity; transition: opacity .35s; pointer-events: none;
  --m: conic-gradient(from 135deg at 50% 0, #000 90deg, #0000 0) 0 0 / 8px 4px repeat-x, linear-gradient(#000 0 0) 0 3.5px / 100% calc(100% - 7px) no-repeat,
    conic-gradient(from -45deg at 50% 100%, #000 90deg, #0000 0) 0 100% / 8px 4px repeat-x;
  -webkit-mask: var(--m); mask: var(--m); }
/* The seal, struck on the hero's corner and riding it in 3D: how many packs, the time to the next one, and around them a ring that
   fills as that time runs out. The ring glides: app.js reads the time left off the deadline, to the millisecond, and moves the
   ring ten times a second, a twentieth of a pixel of arc at a time. It used to be told once a second and tweened there by a
   transition on --prog: a custom property can only be animated on the main thread, so that was a style pass and a repaint of the
   seal on every frame, for as long as a timer ran. Same glide, a tenth of the work. --prog does not inherit: only the ring reads it.
   The tear wipes the seal, and a pack leaving the front hands it over at once. */
@property --prog { syntax: '<number>'; inherits: false; initial-value: 0; }
.pack-medal { right: -14cqw; top: 2cqw; width: 43cqw; aspect-ratio: 1; border-radius: 50%; display: grid; place-content: center; justify-items: center; gap: 1.2cqw; transform: translateZ(26cqw); pointer-events: none;
  transition: opacity .15s; box-shadow: 0 2cqw 7cqw #000b; opacity: calc(1 - var(--p) * 5);
  background: conic-gradient(#b9831a 0, var(--r6) calc(var(--prog) * 1turn - 40deg), #fff8d6 calc(var(--prog) * 1turn), #2a3246 0); }
.pack-medal::before { content: ''; position: absolute; inset: 2.4cqw; border-radius: 50%; background: radial-gradient(circle at 35% 30%, #1b2232, #0b0e14); }
.pack.unsealed .pack-medal { opacity: 0; }
.pack-medal b { position: relative; font: 400 18cqw/1 var(--serif); color: var(--r6); font-variant-numeric: tabular-nums; }
.pack-medal b::before { content: '×'; font-size: 9cqw; color: var(--mute); margin-right: .5cqw; }
.pack-medal em { position: relative; font: 500 6.4cqw/1 var(--mono); font-style: normal; color: var(--ink); letter-spacing: .04em; font-variant-numeric: tabular-nums; }
/* Nothing left: just the seal, in the middle, exactly as the packs wear it (x0, the time left, the ring), only larger. */
.wait { position: relative; width: calc(var(--cw) * .5); aspect-ratio: 1; border-radius: 50%; display: grid; place-content: center; justify-items: center; gap: calc(var(--cw) * .014); opacity: 0; scale: .8; pointer-events: none;
  transition: opacity .3s, scale .45s cubic-bezier(.2, 1.5, .4, 1); box-shadow: 0 10px 34px #000a;
  background: conic-gradient(#b9831a 0, var(--r6) calc(var(--prog) * 1turn - 40deg), #fff8d6 calc(var(--prog) * 1turn), #2a3246 0); }
.wait::before { content: ''; position: absolute; inset: 5.5%; border-radius: 50%; background: radial-gradient(circle at 35% 30%, #1b2232, #0b0e14); }
.wait b { position: relative; font: 400 calc(var(--cw) * .209)/1 var(--serif); color: var(--r6); font-variant-numeric: tabular-nums; }
.wait b::before { content: '×'; font-size: calc(var(--cw) * .105); color: var(--mute); margin-right: calc(var(--cw) * .006); }
.wait em { position: relative; font: 500 calc(var(--cw) * .0745)/1 var(--mono); font-style: normal; color: var(--ink); letter-spacing: .04em; font-variant-numeric: tabular-nums; }
.wait.on { opacity: 1; scale: 1; }

/* card: .inner is driven every frame by the spring engine in app.js (transform, --px/--py/--hyp light, --dark shade).
   Every card is a banknote of knowledge: engraved border, serial number, a seal struck in the rarity's metal, and a foil
   whose complexity grows with the rarity. The rarer the card, the deeper its layer stack.
   .c-print  clipped, flattened: border engraving, panel, art (slides against the tilt), foil, glitter, glare
   .c-front  unclipped floats: title plate, text, value chip, star, seal. Each sits at its own translateZ.
   A card is .live once a spring body drives it (table, detail sheet, forge). Grid cards are static: they keep the print, the frame,
   the seal and the layout, and skip everything that costs a layer or a blend (3D, foil, glitter, grain, embers). */
@property --flow { syntax: '<number>'; inherits: false; initial-value: 0; }
@property --spin { syntax: '<angle>'; inherits: false; initial-value: 0deg; }
.card { --c: var(--r1); width: var(--cw); aspect-ratio: 5/7; position: relative; z-index: 1; container-type: inline-size;
  --thick: 1.6cqw; --depth: 1.6cqw; --z-text: .6cqw; --z-plate: 1.5cqw; --z-chip: 2.5cqw; --z-seal: 3cqw; }
.card.r2 { --c: var(--r2); --depth: 2.4cqw; --z-text: 1cqw;   --z-plate: 2.5cqw; --z-chip: 4cqw;  --z-seal: 5cqw; }
.card.r3 { --c: var(--r3); --depth: 3.4cqw; --z-text: 1.5cqw; --z-plate: 4cqw;   --z-chip: 6cqw;  --z-seal: 7.5cqw; }
.card.r4 { --c: var(--r4); --depth: 4.4cqw; --z-text: 2cqw;   --z-plate: 5.5cqw; --z-chip: 8cqw;  --z-seal: 10cqw; }
.card.r5 { --c: var(--r5); --depth: 6cqw;   --z-text: 3cqw;   --z-plate: 8cqw;   --z-chip: 11cqw; --z-seal: 14cqw; }
.card.r6 { --c: var(--r6); --depth: 8cqw;   --z-text: 4cqw;   --z-plate: 11cqw;  --z-chip: 15cqw; --z-seal: 19cqw; }
.card[data-glow="2"] { --glow: var(--r2); --spread: 18px; }
.card[data-glow="3"] { --glow: var(--r3); --spread: 34px; }
.card[data-glow="4"] { --glow: var(--r4); --spread: 50px; }
.card[data-glow="5"] { --glow: var(--r5); --spread: 75px; }
.card[data-glow="6"] { --glow: var(--r6); --spread: 110px; }
.card[data-glow="7"] { --glow: var(--r7); --spread: 150px; }
/* ...and the moment the climb dies and the waves start, the gold of its back has turned violet: nothing of a Secret is anyone else's */
.card[data-glow="7"] .bk-band { background: #8a5cf0; } .card[data-glow="7"] .bk-line { box-shadow: inset 0 0 0 max(1px, .35cqw) #8a5cf0a6; }
.card[data-glow="7"] .bk-ros { background: conic-gradient(from calc(var(--gx) * -3.6deg), #2a0a5e, #8a3dff, #efe2ff, #6a2ee0, #2a0a5e, #8a3dff, #efe2ff, #6a2ee0, #2a0a5e); }
.card[data-glow="7"] .bk-w { color: #b9a3e6; }
.inner { --px: 0; --py: 0; --hyp: 0; --dark: 0; position: absolute; inset: 0; transform-style: preserve-3d; transform: rotateY(180deg); will-change: transform; }
.flipped .inner { transform: none; }
/* the print's light wants 0..100 across the face; the engine's own --gx overshoots on purpose (the pack uses it), so it is rebuilt here */
.face, .back { --gx: calc(50 + var(--px) * 50); --gy: calc(50 + var(--py) * 50); position: absolute; inset: 0; backface-visibility: hidden; -webkit-backface-visibility: hidden; }
/* What the card throws around itself (the rarity glow, and its shadow on the table) is cast by one empty sheet inside the card,
   not by the two faces. The glow changes colour and width at every step of a reveal's build-up, and as part of a face's own
   box-shadow each of those frames repainted the whole face-down back under it: the engraved band, the big rosette mask, the
   glare. The sheet has nothing to repaint but the shadow itself. Both shadows are outer ones, so nothing of the sheet shows inside
   the card's outline, whichever side it is seen from; glow over shadow, the order they always had. */
.c-print, .back { border-radius: 5cqw; overflow: hidden; box-shadow: inset 0 0 0 1px #ffffff1f; }
.c-glow { position: absolute; inset: 0; border-radius: 5cqw; pointer-events: none; box-shadow: 0 0 var(--spread, 0) var(--glow, transparent), 0 20px 40px -10px #000c; transition: box-shadow .35s; }
.live .c-glow { transform: translateZ(calc(var(--thick) / -2)); }

/* thickness: five sheets of card stock, a dark core between two papers, like a real playing card seen edge-on */
.c-edge { display: none; }
.live .c-edge, .live .c-edge i { display: block; position: absolute; inset: 0; transform-style: preserve-3d; }
.live .c-edge i { border-radius: 5cqw; background: #cfc8b8; transform: translateZ(calc(var(--i) * var(--thick) / -6)); }
.live .c-edge i:nth-child(3) { background: #1a2130; }
.card.r6.live .c-edge i { background: #d8b24a; } .card.r6.live .c-edge i:nth-child(3) { background: #7a5c16; }

/* back: matte black note, gold engraving, W medallion */
.back { transform: rotateY(180deg); display: grid; place-items: center; background: radial-gradient(120% 90% at 50% 35%, #191a1f, #0b0c0f 70%); }
.live .back { transform: translateZ(calc(var(--thick) * -1)) rotateY(180deg); }
.back > * { grid-area: 1 / 1; pointer-events: none; }
.bk-band { position: absolute; inset: 0; background: #b99a5e; opacity: .28; -webkit-mask: var(--wave) 0 0 / 9cqw 2.4cqw; mask: var(--wave) 0 0 / 9cqw 2.4cqw; }
.bk-core { position: absolute; inset: 5.4cqw; border-radius: 1.8cqw; background: radial-gradient(120% 90% at 50% 35%, #17181d, #0b0c0f 70%); }
.bk-line { position: absolute; inset: 3.4cqw; border-radius: 2.6cqw; box-shadow: inset 0 0 0 max(1px, .35cqw) #b99a5ea6; }
.bk-ros, .bk-w { position: relative; }               /* in-flow boxes paint under positioned siblings otherwise */
.bk-ros { width: 78cqw; aspect-ratio: 1; opacity: .8; background: conic-gradient(from calc(var(--gx) * -3.6deg), #6d4c0f, #fbe364, #fff6c9, #d29a2a, #6d4c0f, #fbe364, #fff6c9, #d29a2a, #6d4c0f);
  -webkit-mask: var(--rosette-lg) center / contain no-repeat; mask: var(--rosette-lg) center / contain no-repeat; }
.bk-w { width: 30cqw; aspect-ratio: 1; border-radius: 50%; display: grid; place-items: center; font: 400 18cqw/1 var(--serif); color: #8d8466;
  text-shadow: 0 -1px 0 #ffffff26, 0 .6cqw 1cqw #000; background: radial-gradient(circle at 50% 30%, #1d1e24, #0e0f12);
  box-shadow: inset 0 0 0 max(1px, .3cqw) #b99a5e99, 0 0 0 1.4cqw #0b0c0f, 0 0 0 1.7cqw #b99a5e55; }
.bk-glare { position: absolute; inset: 0; mix-blend-mode: overlay; opacity: calc(.25 + var(--hyp) * .5);
  background: radial-gradient(farthest-corner circle at calc(100% - var(--gx) * 1%) calc(var(--gy) * 1%), #ffffffd0, #ffffff40 18%, #00000060 80%); }
.bk-shade { position: absolute; inset: 0; background: #000; opacity: var(--dark); }

/* ---------- the print ---------- */
.face { color: var(--ink); }
.live .face, .live .c-front { transform-style: preserve-3d; }
.live .face *, .live .c-edge i { backface-visibility: hidden; -webkit-backface-visibility: hidden; }
.c-print { position: absolute; inset: 0; background: #0d1118; }
.c-print > * { position: absolute; inset: 0; pointer-events: none; }
/* engraved border: woven sine lines in the rarity ink, only visible between the card edge and the panel */
.c-ring { background: var(--c); opacity: .5; -webkit-mask: var(--wave) 0 0 / 9cqw 2.4cqw; mask: var(--wave) 0 0 / 9cqw 2.4cqw; }
.c-panel { inset: 3cqw !important; border-radius: 2.8cqw;
  background: radial-gradient(130% 70% at 50% 0, color-mix(in srgb, var(--c) 20%, #10141d), #0d1017 78%);
  box-shadow: inset 0 0 0 max(1px, .3cqw) color-mix(in srgb, var(--c) 55%, transparent), 0 0 0 .8cqw #0d1118; }
/* the art is a window: sunk, bevelled, and the picture slides against the tilt as if it sat behind the card */
.art { inset: 4.6cqw 4.6cqw auto !important; height: 62cqw; border-radius: 2cqw; overflow: hidden; background: #1a2130; }
.art img, .art .pix { width: 100%; height: 100%; display: block; object-fit: cover; object-position: 50% 22%; }
.live .art img, .live .art .pix { scale: 1.22; translate: calc(var(--ix, 0) * -1 * var(--depth)) calc(var(--iy, 0) * -1 * var(--depth)); }   /* --ix/--iy: the tilt, written on the picture every frame (app.js) */
.art img, .art .pix { transition: opacity .35s; }     /* a grid's pictures fade in as they arrive (fadeImages) */
.art::after { content: ''; position: absolute; inset: 0; border-radius: inherit; box-shadow: inset 0 0 0 1px #ffffff26, inset 0 2.4cqw 5cqw #000b, inset 0 -1cqw 3cqw #0006; }
/* streamer mode: an explicit picture is swapped for its pixelated copy (cardEl draws it) */
.art .pix { display: none; image-rendering: pixelated; }
.streamer .card[data-nsfw] .art img { display: none; }
.streamer .card[data-nsfw] .art .pix { display: block; }
/* rosette watermark behind the text, SR only */
.c-mark { display: none; inset: auto -14cqw -22cqw auto !important; width: 84cqw; aspect-ratio: 1; opacity: .16;
  background: conic-gradient(from calc(var(--gx) * 3.6deg), var(--c), #fff, var(--c), #fff, var(--c));
  -webkit-mask: var(--rosette-lg) center / contain no-repeat; mask: var(--rosette-lg) center / contain no-repeat; }
.card.r4 .c-mark { display: block; }
.c-scrim { display: none; background: linear-gradient(#0000 36%, #070a10b8 58%, #070a10f2 82%); }
.c-glare { opacity: calc(.28 + var(--hyp) * .6); mix-blend-mode: overlay;
  background: radial-gradient(farthest-corner circle at calc(var(--gx) * 1%) calc(var(--gy) * 1%), #fffffff0, #ffffff66 16%, #00000052 78%); }
.c-shade { background: #000; opacity: var(--dark); }
/* static cards carry no blend at all: no glare, no grain, no foil */
.c-foil, .c-wash, .c-glit, .c-grain, .card:not(.live) .c-glare { display: none; }
.live .c-grain { display: block; background: var(--grain) 0 0 / 40cqw; mix-blend-mode: overlay; opacity: .34; }
.card.r5.live .c-grain, .card.r6.live .c-grain { opacity: .14; }

/* ---------- foil ladder, live cards only. Dodge blending: the foil only catches where the print is light, like the real thing ---------- */
/* UC: a satin band, nothing more */
.card.r2.live .c-foil { display: block; mix-blend-mode: soft-light; opacity: calc(.55 + var(--hyp) * .45);
  background: linear-gradient(112deg, #0000 32%, #e2ecff88 46%, #fff 50%, #e2ecff88 54%, #0000 68%) calc(var(--gx) * 1.5% - 25%) 0 / 300% 100%; }
/* R and SR carry no foil on the picture. Every rainbow laid over a Wikipedia photograph looked cheap (26 were tried in
   web/card-lab.html): a photograph is not drawn for a foil, colour poured on it fights it. The photograph stays clean and the card
   itself is the precious thing, in the tier's own colour: light for the Rare, metal for the Super Rare. Cheaper than the foils
   they replace, too: those were dodge passes with a filter each, these are plain gradients, one blend and (SR) one small shadow. */
.card:is(.r3, .r4) { --m0: color-mix(in srgb, var(--c) 24%, #06080d); --m1: color-mix(in srgb, var(--c) 82%, #2a2140); --m2: color-mix(in srgb, var(--c) 28%, #fff); }   /* the tier's metal: shadow, body, shine */
/* SR · Chrome: the frame is a wide raised band of polished metal (a bright lip outside, a shadow inside) that comes right up to the
   picture, the engraving is cut into it, and its reflections run round it as the card turns. Grid cards wear the same metal,
   still: a gradient costs nothing. What needs a blend (the light on the metal, the pane of glass) is for the live card. */
.card.r4 .c-ring { opacity: 1; border-radius: 5cqw; -webkit-mask: none; mask: none;
  background: conic-gradient(from calc(var(--gx) * 3.6deg + var(--gy) * 1.8deg), var(--m0), var(--m1) 8%, var(--m2) 14%, var(--m1) 20%, var(--m0) 34%, var(--m0) 50%, var(--m1) 58%, var(--m2) 64%, var(--m1) 70%, var(--m0) 84%, var(--m0));
  box-shadow: inset 0 0 0 max(1px, .3cqw) color-mix(in srgb, var(--m2) 75%, transparent), inset 0 0 1.4cqw #000a; }
.card.r4 .c-ring::after { content: ''; position: absolute; inset: 0; background: #05070b; opacity: .55; -webkit-mask: var(--wave) 0 0 / 9cqw 2.4cqw; mask: var(--wave) 0 0 / 9cqw 2.4cqw; }
.card.r4 .c-panel { inset: 4.2cqw !important; border-radius: 2.2cqw; box-shadow: inset 0 0 0 max(1px, .35cqw) var(--m1), inset 0 .5cqw 0 #ffffff14, 0 0 0 .8cqw #0d1118; }
.card.r4 .art::after { box-shadow: inset 0 0 0 max(1px, .45cqw) var(--m1), inset 0 0 0 .7cqw #000a, inset 0 2.4cqw 5cqw #000b, inset 0 -1cqw 3cqw #0006; }
.card.r4 .c-plate { box-shadow: inset 0 0 0 max(1px, .3cqw) var(--m1), inset 0 .45cqw 0 color-mix(in srgb, var(--m2) 55%, transparent),
  calc(var(--px) * -2cqw) calc(var(--py) * -2cqw + 1.6cqw) 3.4cqw #000b; }
/* the light on the metal: the frame band alone (padding + xor), brighter where the light is */
.card.r4.live .c-glit { display: block; padding: 4.2cqw; border-radius: 5cqw; mix-blend-mode: overlay; opacity: calc(.55 + var(--hyp) * .45);
  background: radial-gradient(circle at calc(var(--gx) * 1%) calc(var(--gy) * 1%), #fff, #fff0 48%);
  -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 exclude, linear-gradient(#000 0 0); }
/* a pane of glass over the picture: one soft band of white that slides with the light. No colour */
.card.r4.live .c-foil { display: block; inset: 4.6cqw 4.6cqw auto !important; height: 62cqw; border-radius: 2cqw; opacity: calc(.7 + var(--hyp) * .3);
  background: linear-gradient(112deg, #0000 40%, #ffffff26 47%, #ffffff5c 50%, #ffffff26 53%, #0000 60%) calc(var(--gx) * 1%) 0 / 300% 100%; }
/* R · Neon, the soft one: the engraving is lit from inside. Only the lines are lit (border, panel, window, title plate, seal);
   the live card adds a thin halo round the border and a faint pool of the tier's light that follows the tilt. The lines are
   drawn by ::before so that the halo, a filter on their parent, comes after the mask (a filter on the masked element itself
   is applied before its mask, and shows nothing). */
.card.r3 .c-ring { opacity: .6; background: none; -webkit-mask: none; mask: none; }
.card.r3 .c-ring::before { content: ''; position: absolute; inset: 0; background: var(--m2); -webkit-mask: var(--wave) 0 0 / 9cqw 2.4cqw; mask: var(--wave) 0 0 / 9cqw 2.4cqw; }
.card.r3.live .c-ring { opacity: calc(.6 + var(--hyp) * .25); filter: drop-shadow(0 0 .5cqw var(--c)); }
.card.r3 .c-panel { box-shadow: inset 0 0 0 max(1px, .3cqw) color-mix(in srgb, var(--c) 80%, #fff), 0 0 0 .8cqw #0d1118; }
.card.r3 .art::after { box-shadow: inset 0 0 0 max(1px, .3cqw) color-mix(in srgb, var(--c) 80%, #fff), inset 0 2.4cqw 5cqw #000b, inset 0 -1cqw 3cqw #0006; }
.card.r3 .c-plate { box-shadow: inset 0 0 0 max(1px, .25cqw) color-mix(in srgb, var(--c) 70%, #fff), calc(var(--px) * -2cqw) calc(var(--py) * -2cqw + 1.6cqw) 3.4cqw #000b; }
.card.r3 .c-seal { box-shadow: inset 0 0 0 max(1px, .3cqw) var(--m2), 0 0 3cqw var(--c), calc(var(--px) * -2.4cqw) calc(var(--py) * -2.4cqw + 1.6cqw) 3cqw #000c; }
.card.r3.live .c-glit { display: block; mix-blend-mode: screen; opacity: calc(.12 + var(--hyp) * .25);
  background: radial-gradient(circle at calc(var(--gx) * 1%) calc(var(--gy) * 1%), color-mix(in srgb, var(--c) 70%, transparent), #0000 58%); }
/* UR: full art under an iridescent wash, no lines: big soft colour fields that roll with the tilt */
.card.r5.live .c-foil { display: block; mix-blend-mode: color-dodge; opacity: calc(.24 + var(--hyp) * .44); filter: brightness(.75) contrast(1.35) saturate(1.5);
  background-image: radial-gradient(farthest-corner circle at calc(var(--gx) * 1%) calc(var(--gy) * 1%), #fff 0, #7a7a7a 40%, #111 95%), linear-gradient(128deg, var(--rainbow));
  background-blend-mode: multiply; background-size: 100% 100%, 320% 320%;
  background-position: 0 0, calc(var(--gx) * 1.8%) calc(var(--gy) * 1.8%); }
/* L: the living card, the only tier that moves on its own. Two clocks run on it: --flow (0..100, the prism drifts one card width,
   seamlessly: its period is 100cqw * sin(115deg) / 2) and --spin (a light runs round the gold frame). A lined gold prism rolls over the picture, and embers rise in front of everything. */
/* the clocks are not inherited: each runs on the element that reads it, so a tick restyles three elements, not the whole card */
.card.r6.live :is(.c-foil, .c-glit) { animation: c-flow 7s linear infinite; }
.card.r6.live .c-panel { animation: c-spin 4.5s linear infinite; }
@keyframes c-flow { to { --flow: 100; } }
@keyframes c-spin { to { --spin: 360deg; } }
.card.r6.live .c-foil { display: block; mix-blend-mode: color-dodge; opacity: calc(.62 + var(--hyp) * .38); filter: brightness(.72) contrast(1.45) saturate(1.35);
  background-image: repeating-linear-gradient(115deg, #2e2e2e 0, #6a6a6a .5cqw, #e2e2e2 .8cqw, #6a6a6a 1.1cqw, #2e2e2e 1.7cqw),
    repeating-linear-gradient(115deg, #ffd76a 0, #fff6cf 6.5cqw, #ff9d5c 13cqw, #ffd1ec 19.5cqw, #fffbe8 26cqw, #ffc14d 32.5cqw, #ff8fb1 39cqw, #ffd76a 45.32cqw);
  background-blend-mode: multiply;
  background-position: calc(var(--gx) * -.9cqw) 0, calc(var(--flow) * 1cqw + var(--gx) * 1.6cqw) 0;
  -webkit-mask: radial-gradient(58% 44% at 50% 35%, #0000 34%, #000 100%); mask: radial-gradient(58% 44% at 50% 35%, #0000 34%, #000 100%); }
.card.r6.live .c-wash { display: block; mix-blend-mode: soft-light; opacity: calc(.45 + var(--hyp) * .4);
  background: linear-gradient(112deg, #0000 calc(var(--gx) * 1% - 34%), #ffdf8a calc(var(--gx) * 1%), #0000 calc(var(--gx) * 1% + 34%)); }
/* glitter: two sparse noise masks, one fixed, one riding the tilt. A flake lights only where they overlap, so it twinkles.
   Third mask: full strength on the picture, faint over the text so it stays readable */
.card.r5.live .c-glit, .card.r6.live .c-glit { display: block; opacity: calc(.2 + var(--hyp) * .5);
  background: linear-gradient(120deg, #fff, #ffe9a8, #fff, #bfe9ff, #fff, #ffd1f0, #fff) calc(var(--gx) * 1%) 0 / 200% 100%;
  -webkit-mask: var(--noise-a) 0 0 / 46cqw, var(--noise-b) calc(var(--flow) * .52cqw + var(--gx) * .22cqw) calc(var(--gy) * .22cqw) / 52cqw, linear-gradient(#000 48%, #0004 64%); -webkit-mask-composite: source-in, source-in;
  mask: var(--noise-a) 0 0 / 46cqw, var(--noise-b) calc(var(--flow) * .52cqw + var(--gx) * .22cqw) calc(var(--gy) * .22cqw) / 52cqw, linear-gradient(#000 48%, #0004 64%); mask-composite: intersect, intersect; }
.card.r6.live .c-glit { opacity: calc(.42 + var(--hyp) * .4); }

/* ---------- floats ---------- */
.c-front { position: absolute; inset: 0; display: flex; flex-direction: column; padding: 0 7.5cqw 5cqw; pointer-events: none; }
.c-gap { flex: none; height: 58.5cqw; }
.c-plate { flex: none; margin: 0 -2.6cqw; padding: 3cqw 4cqw 3.3cqw; border-radius: 2.2cqw; background: linear-gradient(#161b28f7, #0e121bf7);
  box-shadow: inset 0 0 0 max(1px, .25cqw) color-mix(in srgb, var(--c) 42%, #ffffff14), inset 0 .3cqw 0 #ffffff1a,
    calc(var(--px) * -2cqw) calc(var(--py) * -2cqw + 1.6cqw) 3.4cqw #000b; }
.c-plate h3 { font: 400 7.5cqw/1.08 var(--serif); text-wrap: balance; letter-spacing: -.005em;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.face .sub { font-size: 3.9cqw; line-height: 1.25; color: color-mix(in srgb, var(--c) 55%, #dfe5ee); margin-top: 1.1cqw;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.face .sub:empty { display: none; }
.face .ext { flex: 1; min-height: 0; overflow: hidden; margin-top: 3.2cqw; font-size: 3.75cqw; line-height: 1.42; color: #c9d0dc;
  -webkit-mask: linear-gradient(#000 calc(100% - 7cqw), #0000); mask: linear-gradient(#000 calc(100% - 7cqw), #0000); }
.face .ext:empty { visibility: hidden; }
/* footer: the rarity and, right beside it, whatever a shelf appends (the ×n of the Collection). The serial runs underneath. */
.face footer { flex: none; height: 12.5cqw; display: grid; grid-template-columns: auto 1fr; align-content: end; align-items: baseline; gap: 1.1cqw 2cqw;
  font-size: 3.5cqw; line-height: 1; color: var(--mute); font-variant-numeric: tabular-nums; }
.rar { font-weight: 700; letter-spacing: .16em; text-transform: uppercase; color: var(--c); }
.c-serial { grid-row: 2; grid-column: 1 / -1; font: 400 3.1cqw/1 var(--mono); letter-spacing: .04em; white-space: nowrap; }
.c-serial b { font-weight: 500; color: #c9d0dc; }
/* value chip: the denomination. Market value = views / 10, same maths as worth() */
.c-chip { position: absolute; left: 6.6cqw; top: 6.6cqw; height: 7.4cqw; padding: 0 2.6cqw 0 1.4cqw; border-radius: 4cqw; display: flex; align-items: center; gap: 1.2cqw;
  font: 500 3.7cqw/1 var(--mono); color: #0b0e14; background: var(--c);
  box-shadow: inset 0 .3cqw 0 #ffffff80, calc(var(--px) * -1.6cqw) calc(var(--py) * -1.6cqw + 1.2cqw) 2.4cqw #0009; }
.c-chip .coin { width: 5.6cqw; height: 5.6cqw; vertical-align: -.5cqw; }
/* the star is a button: the padding is its touch target */
.star { position: absolute; right: 3.4cqw; top: 3.4cqw; z-index: 1; width: 14cqw; height: 14cqw; padding: 3.3cqw; display: grid; place-items: center; border: 0; background: none; cursor: pointer; pointer-events: auto; }
.star svg { width: 100%; display: block; fill: none; stroke: #f0dcae; stroke-width: 1.7; stroke-linejoin: round; filter: drop-shadow(0 .4cqw .8cqw #000a); }
.star[aria-pressed="true"] svg { fill: #f0dcae; }
.tiers .fav { --c: #f0dcae; }
.tiers .new { --c: #4db8ff; }
.tiers .dupes { --c: var(--ink); }
/* security seal: a guilloché rosette struck in the rarity's own metal. One colour per tier, dark to light around the dial,
   and the dial turns with the light. Commons carry no seal: the absence is the tell. */
.c-seal { position: absolute; right: 5.4cqw; bottom: 4.6cqw; width: 17cqw; aspect-ratio: 1; border-radius: 50%; display: grid; place-items: center; background: #0c0f16;
  box-shadow: inset 0 0 0 max(1px, .3cqw) color-mix(in srgb, var(--c) 60%, transparent), calc(var(--px) * -2.4cqw) calc(var(--py) * -2.4cqw + 1.6cqw) 3cqw #000c; }
.c-seal::before { content: ''; position: absolute; inset: .8cqw; border-radius: 50%;
  --lo: color-mix(in srgb, var(--c) 38%, #05070b); --hi: color-mix(in srgb, var(--c) 45%, #fff);
  background: conic-gradient(from calc(var(--gx) * 3.6deg + var(--gy) * 1.8deg), var(--lo), var(--c), var(--hi), var(--c), var(--lo), var(--c), var(--hi), var(--c), var(--lo));
  -webkit-mask: var(--rosette) center / contain no-repeat; mask: var(--rosette) center / contain no-repeat; }
.c-seal span { position: relative; width: 8.2cqw; aspect-ratio: 1; border-radius: 50%; display: grid; place-items: center; background: #0c0f16;
  font: 400 4.3cqw/1 var(--serif); color: var(--c); box-shadow: 0 0 0 max(1px, .25cqw) color-mix(in srgb, var(--c) 50%, transparent); }
/* live: every float takes its own height. They ease into it, so a card arriving in hand lifts its layers as it lands. */
:is(.c-plate, .face .ext, .face footer, .c-chip, .star, .c-seal) { transition: transform .45s cubic-bezier(.2, .9, .3, 1); }
.live .c-plate { transform: translateZ(var(--z-plate)); }
.live .ext, .live .face footer { transform: translateZ(var(--z-text)); }
.live :is(.c-chip, .star) { transform: translateZ(var(--z-chip)); }
.live .c-seal { transform: translateZ(var(--z-seal)); }

/* ---------- UR + L: full-bleed art, the panel becomes a hairline, the title leaves its plate ---------- */
.card:is(.r5, .r6) .c-ring { display: none; }
.card.r5 .c-panel { z-index: 1; background: none; inset: 2.6cqw !important; box-shadow: inset 0 0 0 max(1px, .3cqw) color-mix(in srgb, var(--c) 70%, transparent); }
/* L: a thick gold band, and on a live card a light runs round it */
.card.r6 .c-panel { z-index: 1; inset: 2cqw !important; padding: .9cqw; border-radius: 3.4cqw; box-shadow: none;
  background: conic-gradient(from var(--spin), #6b470c, #c9962b 8%, #fff8d6 14%, #fbe364 20%, #6b470c 34%, #8a5a10 50%, #c9962b 58%, #fff8d6 64%, #fbe364 70%, #6b470c 84%, #6b470c);
  -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 exclude, linear-gradient(#000 0 0); }
.card.r6 .c-print { box-shadow: inset 0 0 0 1px #fbe36480, inset 0 0 7cqw #fbe36440; }
.card:is(.r5, .r6) .art { inset: 0 !important; height: auto; border-radius: 0; }
.card:is(.r5, .r6) .art::after { box-shadow: none; }
.card:is(.r5, .r6) .c-scrim { display: block; }
.card:is(.r5, .r6) .c-gap { flex: 1; height: auto; }
.card:is(.r5, .r6) .c-plate { background: none; box-shadow: none; padding: 0 2.6cqw; text-shadow: 0 .5cqw 2.6cqw #000, 0 0 1cqw #000a; }
.card:is(.r5, .r6) .c-plate h3 { font-size: 9.4cqw; }
.card:is(.r5, .r6) .sub { font-size: 4.1cqw; }
.card:is(.r5, .r6) .ext { flex: none; margin-top: 2.6cqw; display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; -webkit-mask: none; mask: none; text-shadow: 0 .3cqw 1.6cqw #000; color: #dfe4ec; }
.card:is(.r5, .r6) footer { height: 17.5cqw; }        /* clears the seal: the last text line never runs under it */
/* gilt title: the gold runs across the letters with the light */
.card.r6 .c-plate h3 { background: linear-gradient(100deg, #fff6c9, #fbe364 28%, #c98f1f 50%, #fff6c9 72%, #fbe364) calc(var(--gx) * 1.4%) 0 / 240% 100%;
  -webkit-background-clip: text; background-clip: text; color: transparent; text-shadow: none; filter: drop-shadow(0 .5cqw 1.6cqw #000c); }
/* The Legendary's picture is one sharp print sliding behind the frame, like every other tier, only deeper (--depth). It used to be
   two copies of the picture, a blurred dark one and a sharp oval floating above: tilted, they slid apart into a ghost image. */
/* embers: the nearest plane, overhanging the frame. Three sparse grids of different pitch, each rising a whole number of its own
   tiles per loop: reads as random, loops without a seam. They fade at the ends of their climb and leave the text block alone. */
.sparks { display: none; }
.card.r6.live .sparks { display: block; position: absolute; inset: -8%; transform: translateZ(24cqw); pointer-events: none; animation: c-embers 9s linear infinite;
  background:
    radial-gradient(circle, #fff 0 .45cqw, #fbe364aa .55cqw, #0000 1.7cqw) 0 0 / 41cqw 54cqw,
    radial-gradient(circle, #fff6c4 0 .3cqw, #ffb84daa .4cqw, #0000 1.2cqw) 17cqw 20cqw / 29cqw 36cqw,
    radial-gradient(circle, #fff 0 .22cqw, #fbe36488 .3cqw, #0000 .9cqw) 9cqw 40cqw / 23cqw 27cqw;
  -webkit-mask: linear-gradient(#0000, #000 22%, #000 74%, #0000), radial-gradient(44% 24% at 50% 70%, #0000 70%, #000 100%); -webkit-mask-composite: source-in;
  mask: linear-gradient(#0000, #000 22%, #000 74%, #0000), radial-gradient(44% 24% at 50% 70%, #0000 70%, #000 100%); mask-composite: intersect; }
@keyframes c-embers { to { background-position: 0 -108cqw, 17cqw -88cqw, 9cqw -68cqw; } }
@media (prefers-reduced-motion: reduce) { .card.r6.live :is(.c-foil, .c-glit, .c-panel, .sparks) { animation: none; } }
/* S, the Secret: black and deep violet. It stands on a Legendary's dress (cardEl gives it both classes, r6 and r7) and changes
   what makes it one. Its picture lies in the dark under a veil, and the light of the tilt is a lantern carried across it (.c-wash:
   a hole in the veil, where the foil shows too). Over the picture an engraved seal turns slowly, like a spell being held. */
.card.r7 { --c: var(--r7); }
.card.r7.live .c-edge i { background: #3a0a78; } .card.r7.live .c-edge i:nth-child(3) { background: #12031f; }
.card.r6.r7 .c-panel { background: conic-gradient(from var(--spin), #0b0218, #3a0a78 8%, #efe2ff 14%, #8a3dff 20%, #0b0218 34%, #1d0640 50%, #3a0a78 58%, #efe2ff 64%, #8a3dff 70%, #0b0218 84%, #0b0218); }
.card.r6.r7 .c-print { background: #07010f; box-shadow: inset 0 0 0 1px #8a3dff80, inset 0 0 9cqw #5a1fd060; }
.card.r6.r7 .c-plate h3 { background: linear-gradient(100deg, #fff, #d9c2ff 28%, #8a3dff 50%, #fff 72%, #d9c2ff) calc(var(--gx) * 1.4%) 0 / 240% 100%; -webkit-background-clip: text; background-clip: text; }
/* The picture is no picture, it is a planet: the whole globe, hanging in the great seal as in its orbit, over a field of stars.
   --orb: where it hangs and how wide (the seal's centre). It has an atmosphere (the glow of its own outline), a day and a night
   side that follow the tilt (.c-wash: the light is its sun, with a glint where it strikes), and a foil that runs over its surface
   only (.c-foil). The three are discs over black: they need no mask cut to the globe, black takes no shade and no foil. */
.card.r7 { --orb: 78cqw; --orb-x: calc(50cqw - var(--orb) / 2); --orb-y: calc(49cqw - var(--orb) / 2); --seal: calc(var(--orb) * 1.79); }   /* the seal is wider than the card: it runs off its edges */
.card.r6.r7 .c-scrim { background: linear-gradient(#0000 58%, #07010fd9 76%, #07010f 92%); }
/* the stars: three grids of one dot a tile, of pitches that share nothing, so that no pattern shows (as the Legendary's embers) */
.card.r6.r7 .art { background: radial-gradient(80cqw 80cqw at 50cqw 49cqw, #3a0a7870, #0000 70%),
    radial-gradient(circle, #fff 0 .16cqw, #0000 .42cqw) 3cqw 2cqw / 23cqw 31cqw, radial-gradient(circle, #d9c2ff 0 .24cqw, #0000 .6cqw) 9cqw 13cqw / 37cqw 29cqw,
    radial-gradient(circle, #ffffffb3 0 .1cqw, #0000 .3cqw) 13cqw 5cqw / 17cqw 19cqw, #07010f; }
.card.r6.r7 .art img { position: absolute; left: var(--orb-x); top: var(--orb-y); width: var(--orb); height: var(--orb); object-fit: contain; object-position: center;
  scale: 1; translate: none; filter: drop-shadow(0 0 2.2cqw #a772ffd9) drop-shadow(0 0 8cqw #5a1fd0b3); }
.card.r6.r7 :is(.c-wash, .c-foil) { inset: var(--orb-y) auto auto var(--orb-x) !important; width: var(--orb); height: var(--orb); border-radius: 50%; }
.card.r6.r7 .c-wash { display: block; mix-blend-mode: normal; opacity: 1;
  background: radial-gradient(circle at calc(var(--gx) * .7% + 8%) calc(var(--gy) * .7% + 4%), #ffffff4d 0, #fff0 16%),
    radial-gradient(circle at calc(var(--gx) * .7% + 8%) calc(var(--gy) * .7% + 4%), #0000 34%, #0d0320b8 60%, #05010cf5 86%); }
.card.r6.r7.live .c-foil { -webkit-mask: radial-gradient(circle, #000 58%, #0000 70%); mask: radial-gradient(circle, #000 58%, #0000 70%); }
/* Its ring, Saturn's: a band engraved with the letters of the world's scripts (--ring, generated in app.js), a real tilted plane
   in the card's 3D scene. Two copies turn in step (cardEl): the far half lies under the planet, dim; the near half is a float of
   the face, the highest of all (its edge comes 55cqw out of the card) and wider than the card, so it swings out past the edges
   when the card leans. Each copy is cut in half on the ring's own plane, and only what is inside the cut turns: a plain rotation
   of one picture, which the compositor does alone. 66deg: the player's tilt adds up to 19, and past 90 a plane shows its back. */
.orbit { position: absolute; left: 50cqw; top: 49cqw; width: 0; height: 0; pointer-events: none; transform: rotate(-16deg) rotateX(66deg); }
.orbit b { position: absolute; left: -61cqw; top: -61cqw; width: 122cqw; height: 122cqw; clip-path: inset(50% 0 0 0); }
.orbit.far b { clip-path: inset(0 0 50% 0); opacity: .45; }
.orbit u { display: block; width: 100%; height: 100%; background: var(--ring) center / contain no-repeat; }
.card.live:not(.aside) .orbit u { animation: spin 70s linear infinite; }
@media (prefers-reduced-motion: reduce) { .card.live .orbit u { animation: none; } }
.card.r6.r7 .c-mark { display: block; z-index: 1; inset: calc(49cqw - var(--seal) / 2) auto auto calc(50cqw - var(--seal) / 2) !important; width: var(--seal); opacity: .42; mix-blend-mode: screen;   /* above the veil: the seal glows in the dark */
  background: conic-gradient(from calc(var(--gx) * 3.6deg), #8a3dff, #efe2ff, #3a0a78, #8a3dff, #efe2ff, #3a0a78, #8a3dff); }
.card.r7.live .c-mark { animation: spin 40s linear infinite; }
/* Sober, because rare: no band round it, no seal in the corner, no value, no description, no text, no views. The great seal, the
   name, the word Secret, and which of the hundred copies this one is. */
.card.r6.r7 :is(.c-panel, .sub, .ext, .c-chip, .c-seal) { display: none; }
.card.r6.r7 footer { height: 14cqw; }
.card.r6.r7 .rar { letter-spacing: .3em; }
.card.r6.r7 .c-serial { font-size: 4.2cqw; letter-spacing: .08em; color: #b9a3e6; } .card.r6.r7 .c-serial b { color: #fff; font-weight: 600; }
.card.r6.r7.live .c-foil { background-image: repeating-linear-gradient(115deg, #2e2e2e 0, #6a6a6a .5cqw, #e2e2e2 .8cqw, #6a6a6a 1.1cqw, #2e2e2e 1.7cqw),
    repeating-linear-gradient(115deg, #8a3dff 0, #efe2ff 6.5cqw, #3a0a78 13cqw, #c7a2ff 19.5cqw, #12042a 26cqw, #6a2ee0 32.5cqw, #f4b8ff 39cqw, #8a3dff 45.32cqw); }
.card.r6.r7.live .c-glit { background: linear-gradient(120deg, #fff, #d9c2ff, #fff, #8a3dff, #fff, #f4b8ff, #fff) calc(var(--gx) * 1%) 0 / 200% 100%; }
.card.r6.r7.live .sparks { background:
    radial-gradient(circle, #fff 0 .45cqw, #8a3dffaa .55cqw, #0000 1.7cqw) 0 0 / 41cqw 54cqw,
    radial-gradient(circle, #efe2ff 0 .3cqw, #b07dffaa .4cqw, #0000 1.2cqw) 17cqw 20cqw / 29cqw 36cqw,
    radial-gradient(circle, #fff 0 .22cqw, #8a3dff88 .3cqw, #0000 .9cqw) 9cqw 40cqw / 23cqw 27cqw; }
@media (prefers-reduced-motion: reduce) { .card.r7.live .c-mark { animation: none; } }

/* Side cards of the hand (.aside, set by layout() in app.js): small, dimmed, never tilted. They go flat and drop everything that costs
   a layer, a blend or a clock; one veil shades the whole card. Only the card in hand pays for the show. */
.c-veil { display: none; position: absolute; inset: 0; border-radius: 5cqw; background: #000; opacity: var(--dark); pointer-events: none; }
.card.live.aside .c-veil { display: block; }
.card.live.aside :is(.c-edge, .c-foil, .c-wash, .c-glit, .c-grain, .c-glare, .c-shade, .sparks) { display: none !important; }
.card.live.aside :is(.face, .c-front) { transform-style: flat; }
.card.live.aside :is(.c-plate, .ext, footer, .c-chip, .star, .c-seal) { transform: none; }
/* A side card's picture stops sliding but keeps its framing (the 1.22 zoom): dropping it made every picture jump as cards changed places. */
.card.live.aside .art :is(img, .pix) { translate: none; }
.card.live.aside :is(.c-foil, .c-glit, .c-panel) { animation: none; }
.card.r3.live.aside .c-ring { filter: none; }

/* .flat (set on <html> by app.js: phones, and Safari everywhere): the face is one flat sheet. Every float used to be a layer of
   its own a pixel or two above the print, and WebKit orders the layers of a 3D scene whole, by depth: the idle sway alone put the
   print in front of the text, then of the title plate, for half of every cycle. They blinked. Flat, nothing is left to order: the
   face paints in document order. The card keeps its thickness, its back and its flip (all full-size sheets, which no ordering can
   get wrong), and its depth still reads: the art slides behind its window and the shadows of the floats move with the light. */
.flat .card.live :is(.face, .c-front) { transform-style: flat; }
.flat .card.live :is(.c-plate, .ext, footer, .c-chip, .star, .c-seal) { transform: none; }
.flat .card.r6.live .sparks { transform: none; }
.flat .live .face * { backface-visibility: visible; -webkit-backface-visibility: visible; }   /* no layer per element: the flat face hides its own back */

/* small cards (summary grid): slightly larger type. Tiny cards (phone collection, crowded summary): art, a two-line title, seal */
@container (max-width: 250px) { .c-plate h3 { font-size: 7.9cqw; } .face .sub { font-size: 4.4cqw; } .face .ext { font-size: 4.3cqw; line-height: 1.34; } }
@container (max-width: 190px) {
  .face .sub, .face .ext, .c-serial, .c-chip, .c-mark { display: none !important; }
  .art { height: 96cqw; } .c-gap { height: 91cqw; }     /* the picture takes the room the text gave up */
  .c-plate h3, .card:is(.r5, .r6) .c-plate h3 { font-size: 9.6cqw; }
  .face footer, .card:is(.r5, .r6) footer { height: 15cqw; font-size: 5cqw; } .rar { letter-spacing: .1em; }
  .c-seal { width: 22cqw; } .c-seal span { width: 11cqw; font-size: 6cqw; }
  .star { width: 17cqw; height: 17cqw; padding: 3cqw; right: 2cqw; top: 2cqw; }
}

/* stage */
#play { cursor: pointer; justify-content: space-evenly; touch-action: pan-y; }
/* On a phone some hints take one line and some two. The room for two is always kept: otherwise the stage moved up and down a few
   pixels each time the words changed, in the middle of a tear or a flip, and every layer on it was laid out and painted again. */
.stage { position: relative; display: grid; place-items: center; width: var(--cw); height: calc(var(--cw) * 1.4); }
.stage > * { grid-area: 1 / 1; }
.rays {
  position: absolute; left: 50%; top: 50%; translate: -50% -50%;
  width: 190vmin; height: 190vmin; pointer-events: none; opacity: 0; scale: .3;
  /* Out of a big reveal the rays are not just transparent, they are not there: invisible, they still were a turning, masked layer
     larger than the screen (5 million pixels on a phone) that the compositor carried through every frame of the whole game. */
  visibility: hidden; animation-play-state: paused;
  transition: opacity .6s, scale 1.1s cubic-bezier(.2, 1.4, .4, 1), visibility 0s .6s;
  background: repeating-conic-gradient(var(--ray) 0 7deg, transparent 7deg 20deg);
  -webkit-mask: radial-gradient(circle, #000 0, transparent 60%); mask: radial-gradient(circle, #000 0, transparent 60%);
  animation: spin 18s linear infinite;
}
.stage[data-rays] .rays { visibility: visible; animation-play-state: running; transition-delay: 0s; }
.stage[data-rays="4"] .rays { --ray: var(--r4); opacity: .1; scale: 1; }
.stage[data-rays="5"] .rays { --ray: var(--r5); opacity: .2; scale: 1; }
.stage[data-rays="6"] .rays { --ray: var(--r6); opacity: .4; scale: 1; }
/* A Secret has no rays behind it. It stands in front of a great engraved seal that turns slowly, the one on its own face grown
   to the size of the table, while rings of light close in on the card from the dark, one after the other (--rip: the rings are one
   repeating gradient whose stops slide inward by a period, so the loop has no seam). */
@property --rip { syntax: '<number>'; inherits: false; initial-value: 0; }
.stage[data-rays="7"] .rays { opacity: 1; scale: 1; background: none; -webkit-mask: none; mask: none; animation: none; }
.stage[data-rays="7"] .rays::before, .stage[data-rays="7"] .rays::after { content: ''; position: absolute; }
.stage[data-rays="7"] .rays::before { inset: 17%; opacity: .55; animation: spin 70s linear infinite reverse;
  background: conic-gradient(#8a3dff, #efe2ff, #3a0a78, #8a3dff, #efe2ff, #3a0a78, #8a3dff);
  -webkit-mask: var(--rosette-lg) center / contain no-repeat; mask: var(--rosette-lg) center / contain no-repeat; }
.stage[data-rays="7"] .rays::after { inset: 0; animation: rip 4.5s linear infinite;
  background: repeating-radial-gradient(circle, #0000 calc(var(--rip) * 1vmin), #8a3dff59 calc(var(--rip) * 1vmin + 1.5vmin), #0000 calc(var(--rip) * 1vmin + 5vmin), #0000 calc(var(--rip) * 1vmin + 24vmin));
  -webkit-mask: radial-gradient(circle, #000 12%, #0000 52%); mask: radial-gradient(circle, #000 12%, #0000 52%); }
@keyframes rip { from { --rip: 24; } to { --rip: 0; } }
.lean .stage[data-rays="7"] .rays::after, .lean .stage[data-rays="7"] .rays::before { animation: none; }   /* a phone: the rings repaint a layer larger than its screen, they stand still */
@media (prefers-reduced-motion: reduce) { .stage[data-rays="7"] .rays::before, .stage[data-rays="7"] .rays::after { animation: none; } }
/* The waves a Secret sends out while it waits for its tap (app.js, secretHold): round ones, one a heartbeat, born just inside
   the card's outline. Scale and opacity only, and each is thrown away as soon as it has faded. */
.pulse { position: absolute; left: 50%; top: 50%; width: calc(var(--cw) * 1.1); aspect-ratio: 1; translate: -50% -50%; border-radius: 50%; pointer-events: none;
  border: 2px solid #b07dff; box-shadow: 0 0 34px 4px var(--r7), inset 0 0 30px #8a3dff80; }
@keyframes spin { to { transform: rotate(1turn); } }
/* the five card boxes overlap at the centre: only the visible, transformed faces take clicks */
.stage .card { pointer-events: none; }
.stage .inner { pointer-events: auto; }
#fx { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 4; pointer-events: none; }

.dim { position: absolute; inset: 0; background: #000; opacity: 0; transition: opacity .5s; pointer-events: none; z-index: 0; }
.flash { position: absolute; inset: 0; background: #fff8e0; opacity: 0; pointer-events: none; z-index: 5; }

#collection, #all, #trade, #friends, #swap, #profile { overflow-y: auto; justify-content: flex-start; user-select: text; }
:is(#collection, #all, #trade, #friends, #swap, #profile) h2 { font: 30px/1.1 var(--serif); margin-top: 8px; }
/* collection: a real column grid, as many columns as fit (3 on phones). Tap a card for its detail sheet. */
:is(#collection, #all, #trade, #profile) .grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 12px; width: 100%; margin: 0; }
:is(#collection, #all, #trade, #profile) .grid :is(.card, .skel) { width: auto; }
/* All cards shows a card of yours exactly as the Collection does (its star, its copies in the footer). A card you do not own has
   no star to give; nor have the cards of someone else's profile. */
.card.missing .star, #profile .star { display: none; }
/* collection: a card fresh from a pack glows under a NEW tag until the pointer passes over it, as in Hearthstone. Both pieces are
   always there and only fade (opacity: no repaint); the halo is a static shadow whose opacity breathes, never an animated box-shadow. */
#colGrid .card::before { content: ''; position: absolute; inset: 0; z-index: -1; border-radius: 5cqw; pointer-events: none; opacity: 0; transition: opacity .45s;
  box-shadow: 0 0 0 max(2px, 1.3cqw) #bfe6ff, 0 0 5cqw 1.5cqw #4db8ff, 0 0 14cqw 3cqw #4db8ff80; }
#colGrid .card::after { content: 'NEW'; position: absolute; left: 50%; top: -3.5cqw; z-index: 4; translate: -50% 0; pointer-events: none; opacity: 0; transition: opacity .3s, translate .3s;
  padding: 1cqw 5cqw; border-radius: 999px; background: #4db8ff; border: max(2px, 1cqw) solid var(--bg); color: #0b0e14;
  font-weight: 800; font-size: max(10px, 6.5cqw); line-height: 1.3; letter-spacing: .14em; text-indent: .14em; }
#colGrid .card.fresh::before { opacity: 1; animation: fresh-pulse 1.4s ease-in-out infinite alternate; }
#colGrid .card.fresh::after { opacity: 1; }
#colGrid .card:not(.fresh)::after { translate: -50% -3cqw; }
@keyframes fresh-pulse { from { opacity: .45; } }
.search { width: min(100%, 420px); padding: 10px 16px; border: 1px solid var(--line); border-radius: 999px; background: #ffffff0a; color: var(--ink); font: 15px 'DM Sans', sans-serif; }
.search::placeholder { color: var(--mute); }
.search:focus-visible { outline: 2px solid var(--r6); outline-offset: 2px; }
:is(#colGrid, #allGrid, #profGrid) > .hint { grid-column: 1 / -1; padding: 40px 0; }
/* pages: ‹ 1 … 4 5 6 … 200 › */
.pager { flex: none; display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 4px; padding-bottom: 8px; }
.pager button { min-width: 38px; height: 38px; padding: 0 10px; border: 0; border-radius: 999px; background: #ffffff0f; color: var(--mute); font: 500 14px 'DM Sans', sans-serif; font-variant-numeric: tabular-nums; cursor: pointer; }
.pager button:hover:not(:disabled) { color: var(--ink); }
.pager button[aria-current] { background: var(--ink); color: #0b0e14; font-weight: 700; cursor: default; }
.pager button:disabled { opacity: .3; cursor: default; }
.pager span { color: var(--mute); padding: 0 4px; }
.grid .inner { will-change: auto; }   /* static cards: no compositor layer per card */
.grid { display: flex; flex-wrap: wrap; justify-content: center; gap: 14px; max-width: 1300px; margin: auto 0; padding: 12px 0; }
.grid .card[data-glow] { --spread: 22px; }
.grid .card { width: min(44vw, 236px); animation: cards-in .28s ease-out both; }
/* loading: skeleton cards in the grid's own layout, drawn to the card's own measures (in cqw, like .art and .c-seal): the picture,
   two title lines, the rarity line, the seal's gold ring. A gold-tinted light crosses the grid as one wave (--i staggers it).
   Everything drawn is background layers of ::before; only the light (a transform on ::after) ever moves. */
.skel {
  width: min(44vw, 236px); aspect-ratio: 5/7; position: relative; overflow: hidden; container-type: inline-size; border-radius: 5% / 3.57%;   /* the card's 5cqw corners */
  background: linear-gradient(165deg, #1c2333, #10141d 55%, #0c0f16); box-shadow: inset 0 0 0 1px #ffffff17, inset 0 1px 0 #ffffff1f, 0 6px 18px #0006;
  animation: cards-in .28s ease-out both; animation-delay: calc(var(--i) * 18ms);
}
.skel::before {
  content: ''; position: absolute; inset: 0;
  background:
    radial-gradient(circle closest-side, #0c0f16 56%, #fbe36466 60%, #fbe36466 78%, #0000 82%) right 5.4cqw bottom 4.6cqw / 17cqw 17cqw no-repeat,
    linear-gradient(#fbe36433, #fbe36433) left 6cqw bottom 9cqw / 26cqw 3.4cqw no-repeat,
    linear-gradient(#ffffff24, #ffffff24) left 6cqw top 76cqw / 58cqw 7.5cqw no-repeat,
    linear-gradient(#ffffff17, #ffffff17) left 6cqw top 87cqw / 40cqw 7.5cqw no-repeat,
    linear-gradient(140deg, #2a344a, #1a2130 60%, #141a26) left 4.6cqw top 4.6cqw / 90.8cqw 62cqw no-repeat;
}
.skel::after { content: ''; position: absolute; inset: -20% -60%; translate: -100% 0; rotate: 12deg;
  background: linear-gradient(90deg, #0000 35%, #fbe36414 44%, #ffffff2e 50%, #fbe36414 56%, #0000 65%);
  animation: skel-sweep 1.7s cubic-bezier(.4, 0, .2, 1) infinite; animation-delay: calc(var(--i) * 55ms); }
#pkGrid .skel { width: auto; }
.skel-status { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
/* a grid's pictures fade in one by one as they arrive (fadeImages) */
.grid .art img.coming { opacity: 0; }
@keyframes skel-sweep { 60%, 100% { translate: 100% 0; } }   /* crosses, then rests: the wave reads as one light, not a flicker */
@media (max-width: 719px) { :is(#collection, #all, #trade, #profile) .grid { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; } }
@keyframes cards-in { from { opacity: 0; transform: translateY(10px) scale(.97); } }

/* trade up: the collection grid as a picker. The slots and the button sit above it and stay in view: the grid scrolls behind them.
   top: -16px is the section's padding, so no card shows above the bar. */
.tiers { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px; }
.tiers button { border: 0; border-radius: 999px; padding: 6px 14px; background: #ffffff0f; color: var(--mute); font: 500 14px 'DM Sans', sans-serif; font-variant-numeric: tabular-nums; cursor: pointer; }
.tiers button:hover { color: var(--ink); }
.tiers button[aria-pressed="true"] { background: var(--c); color: #0b0e14; font-weight: 700; }
#picks { flex: none; }
#picks > .hint { grid-column: 1 / -1; padding: 40px 0; }
/* copies: how many you own, then how many of them are in the slots. A card with every copy in steps back. */
#picks .card::after {
  content: '×' attr(data-own); position: absolute; left: 50%; top: 3.2cqw; translate: -50% 0; z-index: 4; pointer-events: none; white-space: nowrap;
  padding: .6cqw 4.5cqw; border-radius: 999px; background: #0b0e14d9; color: var(--ink); font-weight: 700; font-size: 8cqw; line-height: 1.3; font-variant-numeric: tabular-nums;
}
#picks .card[data-n]::after { content: attr(data-n) '/' attr(data-own); background: var(--c); color: #0b0e14; box-shadow: 0 2px 12px #000a; }
#picks .card[data-n] .inner { outline: 3px solid var(--c); outline-offset: 2px; border-radius: 5cqw; }
#picks .card[data-full] .inner { opacity: .4; }
.bar {
  position: sticky; top: -16px; z-index: 6; flex: none; display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 10px 24px;
  padding: 12px 16px; border: 1px solid var(--line); border-radius: 16px; background: #0b0e14f4; font-size: 14px; user-select: none;
}
/* the 10 slots in one row, on phones too (small ones: the bar is on top of the cards and must stay short). Tap one to take it back. */
.slots { display: grid; grid-template-columns: repeat(10, minmax(0, 68px)); gap: 8px; flex: 0 1 752px; }
.slots > * { aspect-ratio: 5/7; width: 100%; border-radius: 5px; border: 1.5px dashed var(--line); background: #ffffff08; }
.slots > img { border: 2px solid var(--c); object-fit: cover; object-position: 50% 20%; cursor: pointer; }
.slots > img.in { animation: slot-in .3s var(--d, 0ms) both; }
@keyframes slot-in { from { scale: 0; opacity: 0; } 60% { scale: 1.2; } }
.ctl { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 8px 16px; white-space: nowrap; }
.bar .btn { min-width: 0; padding: 10px 22px; font-size: 15px; font-variant-numeric: tabular-nums; }
@media (max-width: 719px) { .bar { padding: 10px; } .slots { gap: 4px; } .slots > * { border-radius: 3px; } .bar .btn { padding: 10px 16px; } }
/* thumbnails in flight, above everything: a tapped card hopping into its slot, or the 10 of the sacrifice ring.
   --heat 0..1: the ring burns to white before it collapses. */
.ash {
  position: fixed; z-index: 30; width: 60px; height: 84px; object-fit: cover; object-position: 50% 20%; border-radius: 6px; border: 2px solid var(--c); pointer-events: none;
  filter: brightness(calc(1 + var(--heat, 0) * 3)) saturate(calc(1 - var(--heat, 0) * .8)); box-shadow: 0 0 calc(var(--heat, 0) * 34px) var(--hot, transparent);
}
.shock { width: 40%; aspect-ratio: 1; border-radius: 50%; border: 3px solid var(--c); box-shadow: 0 0 30px var(--c), inset 0 0 30px var(--c); pointer-events: none; }
#forgeHint { min-height: 1.5em; }
#forge { display: none; }
#trade.forging { justify-content: center; overflow: hidden; cursor: pointer; }
#trade.forging > * { display: none; }
#trade.forging > #forge { display: flex; flex: 1; width: 100%; flex-direction: column; align-items: center; justify-content: space-evenly; }

/* swap: a live trade with a friend, one window in the way of World of Warcraft's (designed in web/trade-lab.html). Two halves side by
   side with slots, the cards under the window (at its right on a computer), one Trade button; a half turns green when its player
   says Trade, and two green halves are the trade. The section is the window: it does not scroll as a page, its parts do. */
#swap { padding: 0; overflow: hidden; align-items: stretch; justify-content: stretch; gap: 0; }
#swap.waiting :is(.tl-halves, .tl-tray, .tl-go) { display: none; }
#swap.waiting .tl-act { margin-top: 20px; }
#swap.done .tl-half { border-color: var(--ok); background: #4fd08a1c; }
#swap.done :is(.tl-tray, .tl-slots) { pointer-events: none; }
#swap .tl-top .btn { flex: none; }
.tl { --ok: #4fd08a; --warn: #ffb547; position: relative; flex: 1; min-height: 0; width: min(100%, 1280px); margin: 0 auto; box-sizing: border-box; display: flex; flex-direction: column; gap: 10px; padding: 12px; overflow: hidden auto; scrollbar-width: none; user-select: none; }
.tl-top { display: flex; align-items: center; gap: 10px; flex: none; }
#swap .tl-top h2 { font: 19px/1.1 var(--serif); margin: 0; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.tl-halves { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 8px; flex: none; position: relative; }
.tl-half { position: relative; display: flex; flex-direction: column; gap: 8px; min-width: 0; padding: 9px; border: 1.5px solid var(--line); border-radius: 14px; background: #10151fd9;
  transition: border-color .18s, background-color .18s; }
.tl-half.ok { border-color: var(--ok); background: #4fd08a1c; }
.tl-half::after { content: ''; position: absolute; inset: 0; border-radius: inherit; pointer-events: none; opacity: 0; background: linear-gradient(100deg, transparent 35%, #4fd08a66 50%, transparent 65%) 100% 0 / 300% 100% no-repeat; }
.tl-half.ok::after { animation: tl-sheen .55s ease-out; }   /* a green light crosses the half once, inside its own box */
@keyframes tl-sheen { 0% { opacity: 1; background-position: 100% 0; } 100% { opacity: 0; background-position: 0 0; } }
.tl-head { display: flex; align-items: center; gap: 6px; min-height: 22px; }
.tl-head b { font-weight: 700; font-size: 14.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.tl-head em { margin-left: auto; font: 700 11px/1 'DM Sans', sans-serif; letter-spacing: .08em; text-transform: uppercase; font-style: normal; color: var(--ok); white-space: nowrap; opacity: 0; scale: .6; transition: opacity .15s, scale .25s cubic-bezier(.2, 1.6, .4, 1); }
.tl-half.ok .tl-head em { opacity: 1; scale: 1; }
.tl-money { display: flex; align-items: center; gap: 6px; min-height: 32px; font-size: 13px; color: var(--mute); }
.tl-money .coin { width: 17px; height: 17px; flex: none; }
.tl-money input { width: 100%; min-width: 0; flex: 1; padding: 5px 8px; border: 1px solid var(--line); border-radius: 8px; background: #0b0e14; outline: 0; color: var(--r6); font: 700 15px/1.2 'DM Sans', sans-serif; -moz-appearance: textfield; appearance: textfield; }
.tl-money input::-webkit-outer-spin-button, .tl-money input::-webkit-inner-spin-button { -webkit-appearance: none; }
.tl-money input:focus { border-color: var(--r6); }
.tl-money input::placeholder { color: #fbe36466; }
.tl-money output { color: var(--r6); font: 700 15px/1.2 'DM Sans', sans-serif; }
.tl-money output.bump { animation: tl-pop .3s; }
/* six slots in sight; a seventh card brings a new row and the half scrolls (its height is set by paintSide(): two rows and the top of the third).
   The padding keeps the ×n and the − from being cut by the scroll box. */
.tl-slots { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; padding: 6px 5px; margin: -6px -5px; overflow: hidden auto; scrollbar-width: none; overscroll-behavior: contain; }
.tl-slot { position: relative; aspect-ratio: 5/7; border-radius: 5% / 3.57%; background: #080a10; box-shadow: inset 0 2px 6px #000c, inset 0 0 0 1px #232a38; container-type: inline-size; }
.tl-half.ok .tl-slot { box-shadow: inset 0 2px 6px #000c, inset 0 0 0 1px #4fd08a80; }
.tl-me .tl-slot.next::before { content: '+'; position: absolute; inset: 0; display: grid; place-items: center; font: 300 34cqw/1 'DM Sans', sans-serif; color: #3a4458; }
.tl-slot .card { --cw: 100cqw; position: absolute; inset: 0; cursor: pointer; }
.tl .card .star { display: none; }
.tl .card { cursor: pointer; }
.tl-slot[data-x]::after { content: '×' attr(data-x); position: absolute; left: 50%; top: -4px; translate: -50% 0; z-index: 5; pointer-events: none; padding: 1px 7px; border-radius: 999px; background: #eef1f6; color: #0b0e14; font: 800 11px/1.5 'DM Sans', sans-serif; box-shadow: 0 2px 6px #0009; }
.tl-slot.pop::after { animation: tl-pop .3s; }
.tl-me .tl-slot:has(.card)::before { content: '−'; position: absolute; right: -4px; bottom: -4px; z-index: 6; width: 20px; height: 20px; border-radius: 50%; display: grid; place-items: center; background: #1c2331; border: 1px solid #3a4458; color: var(--ink); font: 700 14px/1 'DM Sans', sans-serif; pointer-events: none; }
.tl-slot.changed { animation: tl-warn .5s 3; }
@keyframes tl-warn { 50% { box-shadow: 0 0 0 3px var(--warn), 0 0 18px #ffb54799; } }
@keyframes tl-pop { 40% { scale: 1.35; } }
.tl-foot { display: flex; justify-content: flex-end; }
.tl-worth { display: flex; align-items: center; gap: 4px; white-space: nowrap; font-size: 12.5px; color: var(--mute); min-height: 19px; }
.tl-worth .coin { width: 13px; height: 13px; }

/* the cards, right under the window. Two tabs: yours (a tap puts one in) and the friend's (to search what to ask for, a tap shows it big) */
.tl-tray { flex: 1 1 0; min-height: 132px; display: flex; flex-direction: column; gap: 8px; padding: 9px; border: 1px solid var(--line); border-radius: 14px; background: #0d111a; }
.tl-trayhead { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; flex: none; }
.tl-tabs { display: flex; flex: 1 1 100%; border: 1px solid var(--line); border-radius: 10px; overflow: hidden; }
.tl-tabs button { flex: 1; min-width: 0; border: 0; background: none; padding: 7px 8px; font-size: 13.5px; font-weight: 700; color: var(--mute); cursor: pointer; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tl-tabs button + button { border-left: 1px solid var(--line); }
.tl-tabs button[aria-pressed="true"] { background: #1a2130; color: var(--ink); }
.tl-trayhead input { flex: 1; min-width: 0; padding: 6px 12px; border: 1px solid var(--line); border-radius: 999px; background: #0b0e14; outline: 0; color: var(--ink); font: 13.5px 'DM Sans', sans-serif; }   /* a field does not take the page's colour: left alone it typed black on black */
.tl-trayhead input::placeholder { color: var(--mute); }
.tl-trayhead input:focus { border-color: #3a4458; }
/* favourites: the cards a player starred carry a gold star, in both tabs; the chip keeps only those (the server already says it: profile_cards() hands `liked`) */
.tl-fav { flex: none; border: 1px solid var(--line); border-radius: 999px; background: #0b0e14; padding: 5px 11px; font-size: 13px; color: var(--mute); cursor: pointer; white-space: nowrap; }
.tl-fav b { color: var(--r6); font-weight: 400; margin-right: 4px; }
.tl-fav[aria-pressed="true"] { border-color: var(--r6); color: var(--ink); background: #fbe36414; }
.tl-star { position: absolute; left: -3px; top: -4px; z-index: 5; pointer-events: none; width: 17px; height: 17px; border-radius: 50%; display: grid; place-items: center; background: #1c2331; border: 1px solid #fbe36480; color: var(--r6); font: 10px/1 'DM Sans', sans-serif; font-style: normal; }
.tl-cards { flex: 1; min-height: 0; overflow: hidden auto; scrollbar-width: thin; scrollbar-color: #232a38 transparent; display: grid; grid-template-columns: repeat(auto-fill, minmax(var(--tw, 58px), 1fr)); gap: 8px 7px; align-content: start; padding: 5px 2px 2px; }
.tl-cards .tl-c { position: relative; aspect-ratio: 5/7; container-type: inline-size; transition: opacity .15s; }
.tl-cards .tl-c .card { --cw: 100cqw; position: absolute; inset: 0; }
.tl-cards .tl-c[data-left]::after { content: '×' attr(data-left); position: absolute; left: 50%; top: -5px; translate: -50% 0; z-index: 5; pointer-events: none; padding: 0 6px; border-radius: 999px; background: #1c2331; border: 1px solid #3a4458; font: 700 10.5px/1.5 'DM Sans', sans-serif; }
.tl-cards .tl-c.fresh::before { content: 'NEW'; position: absolute; right: -3px; bottom: -3px; z-index: 5; pointer-events: none; padding: 0 5px; border-radius: 5px; background: var(--ok); color: #04301a; font: 800 9.5px/1.6 'DM Sans', sans-serif; letter-spacing: .06em; }
.tl-cards .tl-c.out { opacity: .25; pointer-events: none; }
.tl-cards .tl-c.offered { outline: 2px solid var(--r6); outline-offset: 1px; border-radius: 5% / 3.57%; }   /* in the friend's cards: what he has put in the trade */
.tl-cards .hint { grid-column: 1 / -1; color: var(--mute); font-size: 13px; padding: 14px 4px; }

/* the one button */
.tl-act { flex: none; display: grid; gap: 7px; justify-items: stretch; text-align: center; }
.tl-status { font-size: 13.5px; color: var(--mute); min-height: 20px; }
.tl-status.hot { color: var(--ok); } .tl-status.warn { color: var(--warn); }
.tl-go { display: flex; align-items: center; justify-content: center; gap: 10px; height: 54px; border: 0; border-radius: 14px; cursor: pointer; white-space: nowrap;
  font: 800 15px/1 'DM Sans', sans-serif; letter-spacing: .08em; text-transform: uppercase; color: #3b2700; text-shadow: 0 1px 0 #ffffff80;
  background: linear-gradient(#fff3b0, #fbe364 48%, #dba41c); box-shadow: inset 0 1px 0 #ffffffa6, inset 0 -2px 0 #0000002e, 0 4px 0 #8a5d08, 0 10px 22px #000a;
  transition: translate .06s, box-shadow .06s, filter .15s, opacity .15s; }
.tl-go:hover { filter: brightness(1.08); } .tl-go:active { translate: 0 3px; box-shadow: inset 0 1px 0 #ffffffa6, 0 1px 0 #8a5d08, 0 3px 8px #000a; }
.tl-go:disabled { opacity: .4; cursor: default; filter: saturate(.5); }
.tl-go.ok { color: #04301a; text-shadow: 0 1px 0 #ffffff66; background: linear-gradient(#b9f5d4, #4fd08a 48%, #27a565); box-shadow: inset 0 1px 0 #ffffffa6, inset 0 -2px 0 #0000002e, 0 4px 0 #136b3c, 0 10px 22px #000a; }
.tl-go small { font: 500 11.5px/1 'DM Sans', sans-serif; letter-spacing: .02em; text-transform: none; opacity: .75; }

/* a phone: no room for the word next to a long pseudo, the tick alone in a green disc */
@media (max-width: 999px) {
  .tl .tl-head em span { display: none; }
  .tl .tl-head em { width: 20px; height: 20px; border-radius: 50%; display: grid; place-items: center; background: var(--ok); color: #04301a; font-size: 13px; flex: none; }
}
/* a computer: the window on the left, the cards open on the right like bags */
@media (min-width: 1000px) {
  .tl { display: grid; grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr); grid-template-rows: auto 1fr auto; gap: 12px 16px; padding: 18px; overflow: hidden; }
  .tl .tl-top { grid-column: 1 / -1; }
  .tl .tl-halves { align-self: start; gap: 12px; }
  .tl .tl-half { padding: 14px; gap: 10px; }
  .tl .tl-slots { gap: 9px; }
  .tl .tl-tray { grid-column: 2; grid-row: 2 / 4; --tw: 92px; min-height: 0; padding: 12px; }
  .tl .tl-act { grid-column: 1; grid-row: 3; align-self: end; }
  #swap .tl-top h2 { font-size: 26px; }
}
.tl-fly { position: fixed; z-index: 99; pointer-events: none; left: 0; top: 0; transform-origin: 0 0; }
.tl-flash { position: absolute; inset: 0; z-index: 20; pointer-events: none; background: radial-gradient(circle at 50% 30%, #ffffffb0, #4fd08a44 40%, transparent 70%); opacity: 0; }
/* the Collection's selection: the grid as a picker (n/own on a picked card, a second tap lets it go), its bar stuck to the bottom */
#collection:is(.selling, .unselling) #colGrid .card::after { content: '×' attr(data-own); opacity: 1; translate: -50% 0; top: 3.2cqw; padding: .6cqw 4.5cqw; border: 0; border-radius: 999px; background: #0b0e14d9; color: var(--ink);
  font-weight: 700; font-size: 8cqw; line-height: 1.3; letter-spacing: 0; text-indent: 0; font-variant-numeric: tabular-nums; }
#collection:is(.selling, .unselling) #colGrid .card[data-n]::after { content: attr(data-n) '/' attr(data-own); background: var(--c); color: #0b0e14; box-shadow: 0 2px 12px #000a; }
/* leaving the selection: the pill fades out as a pill, never as a NEW (the tag takes its text back once it is gone) */
#collection.unselling #colGrid .card::after { opacity: 0; }
#collection.selling #colGrid .card[data-n] .inner { outline: 3px solid var(--c); outline-offset: 2px; border-radius: 5cqw; }
#collection.selling #colGrid .card[data-full] .inner { opacity: .45; }
#collection.selling .star { display: none; }
#sellBar { top: auto; bottom: -16px; margin-top: auto; width: min(100%, 900px); gap: 10px 20px; }
#sellInfo { display: inline-flex; align-items: center; gap: 5px; font-size: 15px; font-variant-numeric: tabular-nums; }
#sellInfo b { color: var(--r6); }
#sellInfo .coin { width: 1em; height: 1em; color: var(--r6); }
#sellBar .ctl { gap: 8px; }
/* the tools over the grid: the search takes the room, Select stands at its right, both one height and one corner radius */
.col-tools { display: flex; align-items: stretch; gap: 8px; width: min(100%, 520px); flex: none; }
.col-tools .search { flex: 1; min-width: 0; width: auto; border-radius: 9px; }
#collection #sellMode { height: auto; min-height: 40px; padding: 0 16px; font-size: 12.5px; flex: none; }
#collection #sellMode[aria-pressed="true"] { --top: #fff3b0; --mid: #fbe364; --bot: #dba41c; --lip: #8a5d08; --txt: #3b2700; --hi: #ffffffa6; --ts: #ffffff80; }
#sellBar #sellGo { height: 38px; padding: 0 22px; font-size: 13px; }
/* a phone: what is picked and Disenchant on one line, the three small ones under it */
@media (max-width: 719px) {
  #sellBar { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 8px; padding: 10px; }
  #sellInfo { grid-area: 1 / 1; }
  #sellBar #sellGo { grid-area: 1 / 2; }
  #sellBar .ctl { grid-area: 2 / 1 / 3 / 3; display: grid; grid-template-columns: 1.5fr 1fr 1fr; gap: 6px; }
  #sellBar .ctl .btn { width: 100%; height: 30px; padding: 0; font-size: 10.5px; letter-spacing: .05em; }
}
body:has(#swap:not([hidden])) #detail .actions { display: none; }   /* a card looked at during a trade: to read, not to disenchant */

/* detail sheet: native <dialog>. The rarity identity is the card itself, live, with its glow; the panel and the
   backdrop only borrow its colour. Desktop: card left, numbers right. Phone: stacked. */
#detail {
  --c: var(--r1); margin: auto; width: min(780px, calc(100vw - 24px)); max-height: calc(100dvh - 24px); overflow-y: auto;
  border: 1px solid color-mix(in srgb, var(--c) 45%, #ffffff1f); border-radius: 18px; padding: 64px 36px 40px; color: var(--ink); user-select: text;   /* 64px: the top row is Share and Close */
  background: linear-gradient(color-mix(in srgb, var(--c) 30%, #11151e), color-mix(in srgb, var(--c) 10%, #11151e));
  box-shadow: 0 0 var(--halo, 0) -20px var(--c), 0 30px 80px #000c;   /* the sheet only glows from Rare up, like the reveal */
  scrollbar-width: none;                               /* a tilted card overhangs its box and a useless scrollbar flickered in and out; a short screen still scrolls */
}
#detail::-webkit-scrollbar { display: none; }
#detail[open] { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 40px; align-items: center; }
#detail.r2 { --c: var(--r2); } #detail.r3 { --c: var(--r3); --halo: 50px; } #detail.r4 { --c: var(--r4); --halo: 70px; } #detail.r5 { --c: var(--r5); --halo: 90px; } #detail.r6 { --c: var(--r6); --halo: 120px; } #detail.r7 { --c: var(--r7); --halo: 140px; }
#detail::backdrop { background: radial-gradient(circle at 50% 45%, color-mix(in srgb, var(--c, #000) 22%, #000000d9), #000000e6 75%); }
#detail .close { position: absolute; top: 12px; right: 14px; z-index: 1; color: var(--ink); background: #0006; border-radius: 999px; padding: 4px 12px; text-decoration: none; font-size: 14px; }
#detailCard { align-self: start; }   /* the card hangs from the top of the sheet, not centred against the text */
#detailCard .card { width: min(60vw, 280px, 50dvh); }
#detailCard .card[data-glow] { --spread: 36px; }
/* Never write "+ *" or "~ *": a sibling combinator whose subject is the bare universal selector makes the browser restyle the
   whole parent subtree whenever any element with a following sibling is added or removed anywhere. With ten packs on the table,
   taking one node off the stage cost 44 ms of style recalc instead of 0.3 (the torn wrapper, a spark, the dust speck...). */
#detailBody > :not(:first-child) { margin-top: 14px; }
.pill { display: inline-block; padding: 3px 12px; border-radius: 999px; background: var(--c); color: #0b0e14; font-size: 12px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; }
@media (max-width: 719px) {
  #detail { padding: 64px 20px 24px; }
  #detail[open] { grid-template-columns: minmax(0, 1fr); gap: 28px; justify-items: center; }
  #detailBody { width: 100%; }
}
#detailBody h2 { font: 28px/1.1 var(--serif); text-wrap: balance; }
#detailBody .sub { margin-top: 4px; color: color-mix(in srgb, var(--c) 35%, var(--ink)); }
#detailBody dl { display: grid; grid-template-columns: repeat(auto-fit, minmax(110px, 1fr)); gap: 12px; padding: 12px 0; border-block: 1px solid #ffffff1f; }
#detailBody dt { font-size: 12px; color: var(--mute); }
#detailBody dd { font-weight: 700; font-variant-numeric: tabular-nums; }
#detailBody .worth { color: var(--r6); display: flex; align-items: center; gap: 6px; }
/* coin icon: the value is a currency amount, not a score */
#detailBody .worth svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
#detailBody p { font-size: 15px; color: #c9d0dc; }
#detailBody a { display: inline-block; color: var(--ink); }
.actions { display: grid; gap: 10px; }
.actions .btn { min-width: 0; width: 100%; }
.actions .btn.ghost { box-shadow: inset 0 0 0 1.5px color-mix(in srgb, var(--c) 45%, var(--line)); }
.actions .btn .coin, .bar .btn .coin { margin: 0 3px 0 4px; }
.actions .btn.ghost:hover { background: #ffffff12; }
:is(.actions, .bar) .btn[data-armed] { background: #5a1f28; color: #ffd9d9; box-shadow: none; }
#detailBody .actions .hint { text-align: left; font-size: 13px; color: var(--mute); }
.grid .card { cursor: pointer; }

.toast.ok { background: #14261c; color: #b6f0cf; border-color: #2a5a3e; }
.toast { position: fixed; left: 50%; bottom: 24px; translate: -50% 0; z-index: 9; background: #2a1518; color: #ffb4b4; border: 1px solid #5a2a30; padding: 10px 16px; border-radius: 10px; font-size: 14px; }

@media (prefers-reduced-motion: reduce) {
  .rays, .skel, .skel::after, .grid .card, #colGrid .card.fresh::before { animation: none; }
}

/* friends: pick a pseudo, add by pseudo, answer requests. A friend's name opens their profile. */
#addForm { display: flex; align-items: center; gap: 8px; width: min(100%, 560px); padding: 0 14px; box-sizing: border-box; }   /* as wide as the list, its button in line with the lines' buttons */
#addForm label { flex-basis: 100%; }
#addForm .search { flex: 1; min-width: 0; }
/* Friends, a friend's profile options, the trade and its notice: game buttons, not SaaS slabs (Yan). Small, in relief: a gradient
   face, a light rim on top, a darker lip under it that the button sinks into when pressed. Three faces and no more:
   slate = every ordinary action, light (.main) = the one main action of a form or a line, gold (.gold) = trading, and only trading
   (Trade, Join, Ready). No red, no green: a colour that appears nowhere else in the game does not belong on a button.
   Never a pill, never a ghost, never a bare text link. */
:is(#addForm, #addList, #friendList, #pfFriend, #pfRefer, #invite, #swap, #bellMenu, #collection) .btn {
  --top: #566279; --mid: #3a4357; --bot: #2a3142; --lip: #10141d; --txt: #eef1f6; --hi: #ffffff33; --ts: #00000080;
  min-width: 0; width: auto; height: 34px; padding: 0 14px; border: 0; border-radius: 9px; display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  font: 800 12px/1 'DM Sans', sans-serif; letter-spacing: .08em; text-transform: uppercase; white-space: nowrap; color: var(--txt); text-shadow: 0 1px 0 var(--ts);
  background: linear-gradient(var(--top), var(--mid) 48%, var(--bot));
  box-shadow: inset 0 1px 0 var(--hi), inset 0 -2px 0 #0000002e, 0 3px 0 var(--lip), 0 6px 12px #0009;
  transition: translate .06s, box-shadow .06s, filter .15s; cursor: pointer;
}
:is(#addForm, #addList, #friendList, #pfFriend, #pfRefer, #invite, #swap, #bellMenu, #collection) .btn:hover { filter: brightness(1.12); background: linear-gradient(var(--top), var(--mid) 48%, var(--bot)); }
:is(#addForm, #addList, #friendList, #pfFriend, #pfRefer, #invite, #swap, #bellMenu, #collection) .btn:active { translate: 0 2px; box-shadow: inset 0 1px 0 var(--hi), inset 0 -1px 0 #0000002e, 0 1px 0 var(--lip), 0 2px 5px #0009; }
:is(#addForm, #addList, #friendList, #pfFriend, #pfRefer, #invite, #swap, #bellMenu, #collection) .btn:disabled { filter: grayscale(.7); translate: none; }
:is(#addForm, #addList, #friendList, #pfFriend, #pfRefer, #invite, #swap, #bellMenu, #collection) .btn.main { --top: #ffffff; --mid: #e6eaf2; --bot: #b9c1d1; --lip: #5d6678; --txt: #10141d; --hi: #ffffff; --ts: #ffffff99; }
:is(#addForm, #addList, #friendList, #pfFriend, #pfRefer, #invite, #swap, #bellMenu, #collection) .btn.gold { --top: #fff3b0; --mid: #fbe364; --bot: #dba41c; --lip: #8a5d08; --txt: #3b2700; --hi: #ffffffa6; --ts: #ffffff80; }
.btn svg.ic { width: 16px; height: 16px; flex: none; fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
#addForm .search { border-radius: 9px; }
/* one size per place */
#addForm .btn { width: 192px; flex: none; }   /* the two button columns of the list, as one */
#invite .btn { height: 30px; padding: 0 11px; font-size: 11px; }

/* a friend's line. Every line is the same grid, whatever its state: portrait, name (and what is going on under it), then two
   button slots of one width, so the buttons stand in two straight columns down the list. A line with one button keeps the right slot. */
:is(#friendList, #addList) li:not(.hint) { display: grid; grid-template-columns: 40px minmax(0, 1fr) auto; align-items: center; gap: 12px; }
:is(#friendList, #addList) .fr-who { grid-column: 1 / 3; display: grid; grid-template-columns: 40px minmax(0, 1fr); align-items: center; gap: inherit; min-width: 0; padding: 0; border: 0; background: none; color: var(--ink); font: inherit; text-align: left; }
button.fr-who { cursor: pointer; }
button.fr-who:hover b { text-decoration: underline; }
.fr-who > span:last-child { display: grid; gap: 2px; min-width: 0; }
.fr-who b { font-size: 16px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fr-who .hint { text-align: left; font-size: 13px; line-height: 1.25; }
.me-av.fr-av { width: 40px; font-size: 19px; }
:is(#friendList, #addList) .fr-acts { display: grid; grid-template-columns: repeat(2, 92px); gap: 8px; }
:is(#friendList, #addList) .fr-acts > :only-child { grid-column: 2; }
:is(#friendList, #addList) .fr-acts .btn { width: 100%; padding: 0; }
@media (max-width: 719px) { #addForm { padding: 0 10px; } #addForm .btn { width: 146px; } :is(#friendList, #addList) .fr-acts { grid-template-columns: repeat(2, 70px); gap: 6px; } :is(#friendList, #addList) .fr-acts .btn { font-size: 10.5px; letter-spacing: .04em; gap: 4px; } :is(#friendList, #addList) .btn svg.ic { width: 13px; height: 13px; }
  :is(#friendList, #addList) li:not(.hint) { grid-template-columns: 34px minmax(0, 1fr) auto; gap: 8px; padding: 10px; } :is(#friendList, #addList) .fr-who { grid-template-columns: 34px minmax(0, 1fr); } .me-av.fr-av { width: 34px; font-size: 16px; } .fr-who b { font-size: 15px; } }
/* a friend's profile: the two buttons sit under the pseudo, centred like it, the same size */
#pfFriend { display: grid; grid-template-columns: repeat(2, 112px); justify-content: center; gap: 10px; margin-top: 14px; }
#pfFriend .btn { width: 100%; padding: 0; }
/* the bell, top right between the coins and the profile: the bare icon, no box around it; a red count on it when something waits.
   Its list borrows the friend lines' buttons. */
.bell { position: relative; width: 32px; height: 32px; flex: none; display: grid; place-items: center; padding: 0; border: 0; background: none; color: var(--mute); cursor: pointer; }
.bell:hover, .bell[data-n] { color: var(--ink); }
.bell svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; }
.bell[data-n]::after { content: attr(data-n); position: absolute; top: -2px; right: -3px; min-width: 16px; height: 16px; padding: 0 4px; box-sizing: border-box; border-radius: 8px; background: #ff4d4d; color: #fff; font: 700 10px/16px 'DM Sans', sans-serif; box-shadow: 0 0 0 2px var(--bg); }
.bell[data-n] svg { animation: bell-ring 2.4s ease-in-out infinite; transform-origin: 50% 10%; }
@keyframes bell-ring { 0%, 70%, 100% { rotate: 0deg; } 76% { rotate: 14deg; } 82% { rotate: -12deg; } 88% { rotate: 8deg; } 94% { rotate: -4deg; } }
#bellMenu { width: min(340px, calc(100vw - 16px)); padding: 12px; box-sizing: border-box; }
#bellMenu h3 { font: 500 12px var(--mono); letter-spacing: .08em; text-transform: uppercase; color: var(--mute); margin: 2px 4px 10px; }
#bellList { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
#bellList li:not(.hint) { display: grid; gap: 10px; padding: 12px; border-radius: 12px; background: #ffffff08; font-size: 14px; white-space: normal; }
#bellList .fr-acts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
#bellList .fr-acts .btn { width: 100%; }
#bellList li.hint { padding: 14px 4px; }
@media (prefers-reduced-motion: reduce) { .bell[data-n] svg { animation: none; } }
/* someone is calling: the red dot (the Friends tab, the friend's line, the notice) and the notice itself, under the header */
.dot { display: inline-block; flex: none; width: 9px; height: 9px; margin-right: 6px; border-radius: 50%; background: #ff4d4d; animation: dot-pulse 1.2s ease-out infinite; }
@keyframes dot-pulse { from { box-shadow: 0 0 0 0 #ff4d4dcc; } to { box-shadow: 0 0 0 9px #ff4d4d00; } }
#nav button[data-alert]::before { content: ''; position: absolute; top: 4px; left: calc(50% + 8px); width: 10px; height: 10px; border-radius: 50%; background: #ff4d4d; box-shadow: 0 0 0 2px var(--bg); }
@media (min-width: 720px) { #nav button[data-alert]::before { position: static; order: 2; margin-left: auto; } }
#invite { position: fixed; top: calc(env(safe-area-inset-top) + 64px); left: 50%; translate: -50% 0; z-index: 9; display: flex; align-items: center; gap: 10px; max-width: calc(100vw - 24px);
  padding: 8px 10px 8px 16px; border: 1px solid var(--line); border-radius: 12px; background: #1a2030; box-shadow: 0 10px 30px #000a; font-size: 14px; white-space: nowrap; animation: invite-in .35s ease-out both; }
body:has(#friends:not([hidden])) #invite, body:has(#bellMenu:popover-open) #invite { display: none; }   /* on Friends the friend's own line says it, with its Join; under the open bell its list does */
#inviteText { overflow: hidden; text-overflow: ellipsis; }
#invite .dot { margin-right: 0; }
@media (max-width: 719px) { #invite { top: calc(env(safe-area-inset-top) + 100px); } }   /* a phone's header is two lines high */
@keyframes invite-in { from { opacity: 0; translate: -50% -12px; } }
@media (prefers-reduced-motion: reduce) { .dot, #invite { animation: none; } }
:is(#friendList, #addList) { list-style: none; padding: 0; display: grid; gap: 8px; width: min(100%, 560px); }
:is(#friendList, #addList) li { display: flex; align-items: center; justify-content: space-between; gap: 8px 12px; flex-wrap: wrap; padding: 12px 14px; border-radius: 14px; background: #ffffff08; }
:is(#friendList, #addList) li.hint { background: none; justify-content: center; }
:is(#friendList, #addList) li.head { justify-content: flex-start; padding: 8px 14px 0; font-size: 12px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; }   /* the name of a list, while the players found and the friends both show */
:is(#friendList, #addList) li > span { display: flex; align-items: center; gap: 12px; }
:is(#friendList, #addList) [data-act="view"] { color: var(--ink); font-weight: 700; }

/* header: your avatar and pseudo, top right like Steam. Opens your profile. */
.me { display: inline-flex; align-items: center; gap: 8px; padding: 3px 12px 3px 3px; border: 0; border-radius: 999px; background: #ffffff0f; color: var(--ink); font: 500 14px 'DM Sans', sans-serif; cursor: pointer; }
.me:hover, .me[aria-current] { background: #ffffff21; }
.me-caret { width: 12px; height: 12px; fill: none; stroke: var(--mute); stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; transition: rotate .2s; }
.me.open .me-caret { rotate: 180deg; }
/* the account menu: placed under the button by app.js (no CSS anchor positioning in every browser yet) */
.menu { position: fixed; inset: auto; margin: 0; min-width: 220px; padding: 6px; border: 1px solid var(--line); border-radius: 14px; background: #11151ef2; color: var(--ink);
  box-shadow: 0 18px 50px #000b; backdrop-filter: blur(12px); }
.menu:popover-open { display: grid; animation: menu-in .14s ease-out; }
.menu button { display: flex; align-items: center; justify-content: space-between; gap: 24px; padding: 10px 12px; border: 0; border-radius: 9px; background: none; color: inherit; font: 500 14px 'DM Sans', sans-serif; text-align: left; cursor: pointer; }
.menu button:hover, .menu button:focus-visible { background: #ffffff12; outline: none; }
.menu em { font: 500 12px var(--mono); font-style: normal; letter-spacing: .06em; text-transform: uppercase; color: var(--mute); }
.menu [aria-checked="true"] em { color: var(--r6); }
.menu #signout { margin-top: 6px; border-top: 1px solid var(--line); border-radius: 0 0 9px 9px; padding-top: 12px; color: #ffb4b4; }
.menu #leave { color: #ffb4b4; }                        /* the way out of test mode: red, as Sign out is */
@keyframes menu-in { from { opacity: 0; translate: 0 -6px; } }
.btn.with-logo { display: inline-flex; align-items: center; justify-content: center; gap: 12px; }
.btn .g { width: 20px; height: 20px; flex: none; }
.me-av { display: grid; place-items: center; flex: none; background: #232a38 center / cover no-repeat; font-family: var(--serif); color: var(--mute); }
.me-av { width: 26px; aspect-ratio: 1; border-radius: 50%; font-size: 14px; }
[data-img] { color: transparent !important; }                  /* the monogram waits under the picture */
.streamer [data-img][data-nsfw] { background-image: none !important; color: var(--mute) !important; }

/* profile: two columns. Left, sticky: the signature card (live, like in the detail sheet), name, stats. Right: showcases,
   then the collection. On phones it all stacks, the card centred on top. */
#profile { overflow-x: hidden; }                              /* a tilting card must never add a sideways scrollbar */
.pf { width: 100%; max-width: 1100px; display: grid; grid-template-columns: 270px minmax(0, 1fr); grid-template-rows: auto auto 1fr;
  grid-template-areas: "back back" "side shows" "side coll"; gap: 16px 28px; align-items: start; }
#profBack { grid-area: back; justify-self: start; }
/* The side stays in view while the collection scrolls, and it is often taller than the page (the signature card, the invitation, the
   stats, the completion): it scrolls on its own then, under the mouse, instead of showing its foot only once the whole collection
   has gone by. 100cqh is the height of #profile, the page's scroller (a size container for that one reason), whatever the header's. */
#profile { container-type: size; }
.pf-side { grid-area: side; position: sticky; top: 0; max-height: 100cqh; overflow-y: auto; overscroll-behavior: auto; scrollbar-width: none; display: grid; gap: 16px; padding: 8px 14px 0; margin: 0 -14px; }   /* a scroller cuts what sticks out of it: 14px of room on each side for the signature card's glow and tilt */
.pf-sig { display: grid; justify-items: center; gap: 8px; }
.pf-sig .card { width: min(100%, 250px); cursor: pointer; }
.pf-sig .card[data-glow] { --spread: 30px; }
/* round icon buttons for your own profile: rename, swap the signature card */
.pf-edit { width: 36px; height: 36px; flex: none; display: grid; place-items: center; padding: 0; border: 1px solid var(--line); border-radius: 50%;
  background: #1b2130e6; color: var(--ink); cursor: pointer; box-shadow: 0 4px 14px #0008; transition: background .15s, scale .15s; }
.pf-edit:hover { background: #2a3246; scale: 1.08; }
.pf-edit svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
/* on the card's top right corner: the card is min(100%, 250px) wide and centred in .pf-sig */
.pf-sig { position: relative; }
.pf-sig-edit { position: absolute; top: -12px; left: calc(50% + min(50%, 125px) - 24px); z-index: 3; }
.pf-name { display: flex; align-items: center; justify-content: center; gap: 8px; }
.pf-name[hidden] { display: none; }
.pf-name .pf-edit { width: 30px; height: 30px; box-shadow: none; }
.pf-name .pf-edit svg { width: 15px; height: 15px; }
.pf-name-form { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 8px; }
.pf-name-form[hidden] { display: none; }
.pf-name-form .search { width: 100%; text-align: center; font-size: 18px; }
.pf-name-hint { width: 100%; margin: 0; font-size: 12px; color: var(--mute); }
.pf-name-hint.err { color: #ff6b7d; }
.pf-none { width: min(100%, 250px); aspect-ratio: 5/7; display: grid; place-items: center; align-content: center; gap: 10px; padding: 20px; text-align: center;
  border: 1.5px dashed var(--line); border-radius: 14px; background: #ffffff05; color: var(--mute); font: 15px 'DM Sans', sans-serif; }
.pf-none b { font: 72px/1 var(--serif); color: var(--ink); }
button.pf-none { cursor: pointer; }
button.pf-none:hover { border-color: var(--mute); color: var(--ink); }
.pf-id { text-align: center; min-width: 0; }
#profile .pf-id h2 { font: 34px/1.1 var(--serif); margin: 0; overflow-wrap: anywhere; }
.pf-id p { color: var(--mute); font-size: 14px; margin-top: 4px; }
.pf-shows { grid-area: shows; display: grid; gap: 16px; min-width: 0; padding-top: 8px; }
.pf-coll { grid-area: coll; }
.panel { display: flex; flex-direction: column; align-items: center; gap: 12px; min-width: 0; padding: 16px; border: 1px solid var(--line); border-radius: 14px; background: #0b0e14b3; }
#profile .panel h3 { align-self: stretch; font: 700 12px 'DM Sans', sans-serif; letter-spacing: .14em; text-transform: uppercase; color: var(--mute); }
.pf-sh { align-self: stretch; display: flex; align-items: baseline; gap: 14px; }
.pf-sh h3 { flex: 1; min-width: 0; overflow-wrap: anywhere; }
#profile .pf-sh h3 { font: 20px/1.2 var(--serif); letter-spacing: 0; text-transform: none; color: var(--ink); }
.pf-sh .link { font-size: 13px; }
#profile .pf-show { grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 10px; padding: 0; }
.pf-slot { aspect-ratio: 5/7; border: 1.5px dashed var(--line); border-radius: 10px; background: #ffffff05; color: var(--mute); font-size: 26px; cursor: pointer; }
.pf-slot:hover { color: var(--ink); border-color: var(--mute); }
.pf-new { justify-self: center; min-width: 0; padding: 10px 22px; font-size: 15px; }
.pf-shows > .hint { padding: 8px 0; }
#pfStats { align-items: stretch; }
/* your invitation and your bank (app.js, referrals): the buttons take the panel's width */
#pfRefer { align-items: stretch; }
#pfRefer .hint { text-align: left; text-wrap: pretty; }
#pfRefer dl { margin: 0; }
#pfRefer .btn { width: 100%; height: 38px; }
/* the bank: a pile of packs that is the button. The packs are the shop's (packs-peek.webp, five real packs side by side, cut short of
   their foot): rows from the floor up (--r), the floor row in front, each pack its own picture (--k) and its own lean (--rz). Every
   row hides the foot of the row behind it, and the gold plate with the count hides the floor row's. Sizes are in cqw: the pile is
   as wide as its panel, whatever the screen. Under the mouse the pile breathes; released (.gone), the packs take off one after the
   other. Only translate, rotate and opacity move. */
.bank { --w: 22cqw; --h: calc(var(--w) * 1.393); container-type: inline-size; display: grid; justify-items: center; padding: 0; border: 0; background: none; color: var(--ink); font: inherit; cursor: pointer; }
.bank:disabled { cursor: default; }
.bank-pile { display: grid; justify-items: center; padding-top: 6cqw; }
.bank-pile span { display: flex; justify-content: center; margin-top: calc(var(--w) * .68 - var(--h)); z-index: calc(6 - var(--r)); }
.bank-pile span:first-child { margin-top: 0; }
.bank-pile i { flex: none; width: var(--w); height: var(--h); margin: 0 -4cqw; background: url(packs-peek.webp) calc(var(--k) * var(--w) * -1) 0 / calc(var(--w) * 5) 100% no-repeat; filter: drop-shadow(0 3px 5px #000a);
  transform-origin: 50% 120%; rotate: var(--rz); transition: translate .35s cubic-bezier(.3, 1.6, .5, 1), rotate .35s, opacity .3s; transition-delay: calc(var(--i) * 18ms); }
.bank:hover:enabled .bank-pile i, .bank:focus-visible .bank-pile i { translate: 0 -5px; rotate: calc(var(--rz) * 1.7); }
.bank.gone .bank-pile i { translate: 0 -300px; rotate: calc(var(--rz) * 5); opacity: 0; transition-duration: .45s; transition-timing-function: cubic-bezier(.5, 0, .9, .4); }
.bank-plate { position: relative; z-index: 7; width: 100%; margin-top: -5cqw; padding: 10px 8px; border-radius: 12px; color: #2a1a02; font: 700 13px/1.2 'DM Sans', sans-serif; text-wrap: balance;
  background: linear-gradient(100deg, #d1901c, #fbe364 30%, #fff7c4 48%, #fbe364 66%, #d1901c); box-shadow: 0 8px 24px #fbe36430, inset 0 -3px 0 #a06f12, inset 0 2px 0 #fff7c4; transition: filter .2s; }
.bank-plate b { display: block; font: 400 34px/1 var(--serif); font-variant-numeric: tabular-nums; }
.bank:hover:enabled .bank-plate { filter: brightness(1.06); }
.bank-go { margin-top: 8px; font-size: 12px; color: var(--mute); }
/* an empty bank: what filling it takes. Five of the table's own packs (app.js packEl()) held as a hand, --d from -2 to 2: each step
   from the middle is further out, lower, more turned and further back, as on the table. The hand turns on itself as one piece; the
   front pack has its full look and its seal struck "+5", a third bigger than on the table: it is the message here. */
.bank-hero { padding: 26px 0 10px; perspective: 700px; background: radial-gradient(70% 60% at 50% 55%, #fbe36426, #0000 70%); }
.bank-fan { position: relative; width: 100%; aspect-ratio: 1.5; transform-style: preserve-3d; animation: bank-turn 3.6s ease-in-out infinite alternate; }
.bank-fan .pack { --a: max(var(--d), -1 * var(--d)); position: absolute; left: 31%; top: 0; width: 38%; cursor: default; z-index: calc(3 - var(--a));
  transform: translate3d(calc(var(--d) * 34%), calc(var(--a) * var(--a) * 3.5%), calc(var(--a) * -14px)) rotate(calc(var(--d) * 9deg)); filter: brightness(calc(1 - var(--a) * .12)); }
.bank-fan .pack-medal b::before { content: none; }     /* "+5", not "×5" */
.bank-fan .pack-medal { scale: 1.3; right: -22cqw; top: -4cqw; }
.bank-fan .pack-medal b { color: #fbe364; }
@keyframes bank-turn { from { transform: rotateY(-20deg) rotateX(6deg); } to { transform: rotateY(20deg) rotateX(6deg); } }
.bank-pitch { font-size: 14px; line-height: 1.45; color: var(--mute); text-align: center; text-wrap: balance; }
.bank-pitch b { color: #fbe364; font-weight: 800; }
.bank-pitch b:first-child { display: block; margin-bottom: 2px; font: 400 30px/1.1 var(--serif); text-align: center; text-shadow: 0 2px 14px #fbe36455; }
@media (prefers-reduced-motion: reduce) { .bank-pile i { transition: none; } .bank-fan { animation: none; transform: rotateY(-14deg) rotateX(6deg); } }
.pf-side dl { display: grid; gap: 10px; margin-bottom: 8px; }
.pf-side dl div { display: flex; justify-content: space-between; gap: 12px; font-size: 14px; }
.pf-side dt { color: var(--mute); }
.pf-side dd { font-weight: 700; font-variant-numeric: tabular-nums; display: inline-flex; align-items: center; gap: 4px; }
.pf-side .worth { color: var(--r6); }
.pf-bar { display: grid; grid-template-columns: 1fr auto; gap: 4px; font-size: 13px; }
.pf-bar span { color: var(--c); font-weight: 500; }
.pf-bar b { color: var(--mute); font-weight: 400; font-variant-numeric: tabular-nums; }
.pf-bar i { grid-column: 1 / -1; height: 6px; border-radius: 3px; background: linear-gradient(90deg, var(--c) calc(var(--p) * 100%), #ffffff14 0); }
@media (max-width: 899px) {
  .pf { grid-template-columns: minmax(0, 1fr); grid-template-areas: "back" "side" "shows" "coll"; }
  .pf-side { position: static; max-height: none; overflow: visible; padding: 8px 0 0; margin: 0; }
  .pf-sig .card, .pf-none { width: min(64vw, 250px); }
}
@media (max-width: 599px) {
  #profile .pf-show { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
}
}

/* detail sheet: which showcases hold this card, and whether it is your profile background */
.showto { display: grid; gap: 6px; }
.showto > span { color: var(--mute); font-size: 13px; }
.showto .tiers { justify-content: flex-start; }

/* showcase picker: a sheet over the profile, your collection as a grid; picked cards get their order number */
#picker { margin: auto; width: min(960px, calc(100vw - 32px)); max-height: calc(100dvh - 48px); padding: 0; border: 1px solid var(--line); border-radius: 18px;
  background: #121722; color: var(--ink); overflow: hidden; }
#picker[open] { display: grid; grid-template-rows: auto auto minmax(0, 1fr); }
#picker::backdrop { background: #000000d0; }
.pk-head { display: flex; align-items: center; gap: 14px; padding: 16px 20px 10px; }
.pk-head h2 { flex: 1; min-width: 0; font: 24px/1.2 var(--serif); overflow-wrap: anywhere; }
.pk-head .btn { min-width: 0; padding: 10px 24px; font-size: 15px; }
#pkSearch { justify-self: center; margin: 0 20px 6px; }
#pkGrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 10px; margin: 0; padding: 8px 20px 20px; overflow-y: auto; max-width: none; }
#pkGrid .card { width: auto; cursor: pointer; }
#pkGrid .card:not([data-pick]) .inner { filter: brightness(.6); transition: filter .2s; }
#pkGrid .card:not([data-pick]):hover .inner { filter: none; }
#pkGrid .card[data-pick]::after {
  content: attr(data-pick); position: absolute; z-index: 4; top: -2cqw; right: -2cqw; width: 17cqw; aspect-ratio: 1; display: grid; place-items: center;
  border-radius: 50%; background: var(--r6); color: #0b0e14; font-weight: 800; font-size: max(11px, 8cqw); box-shadow: 0 0 0 max(2px, 1cqw) #121722; pointer-events: none;
}
#pkGrid .star { display: none; }
#pkGrid > .hint { grid-column: 1 / -1; padding: 30px 0; }
@media (max-width: 599px) { #pkGrid { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; padding: 8px 12px 16px; } .pk-head { flex-wrap: wrap; } }

/* Phones (.flat): the front card's face is drawn while the card still lies face down. A face turned away is never rasterised, so its
   first paint (a megapixel at 3x, picture and all) used to land in the middle of the flip, as a stutter. Told it may be seen from
   behind, it is painted ahead of time; the opaque back in front of it hides it until the turn. */
.flat .card.live:is(.dress, .ready, :not(.aside)) .face { backface-visibility: visible; -webkit-backface-visibility: visible; }
/* the torn wrapper falling away: a dead thing, no clocks, no glow */
.pack.spent, .pack.spent * { animation-play-state: paused !important; }
.pack.spent :is(.pack-aura, .pack-sparks, .pack-shadow, .pack-orbit) { display: none; }

/* Phones (.lean, set by app.js). Safari on an iPhone paints on the CPU at 3x: a pack at rest ran at 40 frames a second because its
   foil, glitter, crimps, coin and name were repainted thirty times a second by the drift clock. On a phone those stand still (the
   pack still floats, its rays turn, its halo breathes, its coin rocks, its sparks twinkle: all of that is free, it only moves
   layers). The packs of the wings wear the plain print, and a card drops its grain and its five sheets of thickness. */
.lean .pack :is(.pp-foil, .pp-glit, .pp-crimp, .pack-coin b, .pack-name b, .pack-one), .lean .card.live :is(.c-foil, .c-glit, .c-panel) { animation: none !important; }
.lean .pack.mini :is(.pp-foil, .pp-glit, .pp-rays, .pp-ros, .pp-halo) { display: none; }
.lean .card :is(.c-grain, .c-edge) { display: none !important; }

/* ?cut=... (app.js): one cost off at a time, to find on a real phone what the lag is made of. Diagnosis only, never shipped on. */
.cut-drift .pack *, .cut-drift .card.live :is(.c-foil, .c-glit, .c-panel) { animation-name: none !important; }
.cut-drift .pack .pack-coin { animation-name: pk-rock !important; }
.cut-foil :is(.pp-foil, .c-foil, .c-wash) { display: none !important; }
.cut-glit :is(.pp-glit, .c-glit) { display: none !important; }
.cut-rays :is(.pp-rays, .pp-ros, .pp-halo) { display: none !important; }
.cut-coin .pack-coin { animation: none !important; } .cut-coin .pack-coin i { display: none !important; }
.cut-sparks :is(.pack-sparks, .card .sparks) { display: none !important; }
.cut-aura :is(.pack-aura, .pack-shadow) { display: none !important; }
.cut-wings .seat:has(.pack.mini) { display: none !important; }
.cut-grain .c-grain { display: none !important; }
.cut-glare :is(.c-glare, .bk-glare) { display: none !important; }
.cut-fx #fx { display: none !important; }
.cut-glow .c-glow { display: none !important; }
.cut-art .art :is(img, .pix) { display: none !important; }
.cut-back .back > * { display: none !important; }

