/* ==========================================================================
   cards.css - the collection.

   The card is the one thing the old app got right, so it survives whole:
   portrait, metal frame darkening with rarity, a face drawn from the name,
   foil that follows the finger. Around it: the rail, the filters, the
   packs, the stage the packs open on, and the doors to sealed sets.
   ========================================================================== */

/* ==================================================================== the card
   A collectible is an object: portrait, framed in metal, art in a window, a
   name plate, a rarity gem, and a back you turn over. A box with text in it is
   a website no matter what the text says. */
.tc{position:relative; aspect-ratio:5/7; perspective:1100px; -webkit-perspective:1100px;
  container-type:inline-size}
.tc-i{position:absolute; inset:0; transform-style:preserve-3d; -webkit-transform-style:preserve-3d;
  transition:transform .62s cubic-bezier(.3,1.3,.5,1)}
.tc.down .tc-i{transform:rotateY(180deg)}
.tc-f,.tc-b{position:absolute; inset:0; border-radius:11px; overflow:hidden;
  backface-visibility:hidden; -webkit-backface-visibility:hidden;
  box-shadow:0 2px 5px rgba(0,0,0,.3), 0 8px 20px rgba(0,0,0,.24)}
.tc-b{transform:rotateY(180deg)}
.tc-f{padding:5px; background:linear-gradient(155deg,var(--fa),var(--fb) 38%,var(--fc) 62%,var(--fb))}
.tc-pane{position:absolute; inset:5px; border-radius:7px; overflow:hidden; background:var(--pane);
  display:flex; flex-direction:column; box-shadow:0 0 0 1px rgba(0,0,0,.18) inset}
.tc-glyph{position:absolute; inset:0; display:flex; align-items:center; justify-content:center;
  font-size:30cqw; line-height:1; padding-bottom:4%;
  filter:drop-shadow(0 1px 0 rgba(255,255,255,.6)) drop-shadow(0 2px 3px rgba(0,0,0,.16))}
.tc.lg .tc-glyph{font-size:36cqw}
.tc-art{position:relative; flex:1 1 auto; min-height:0; overflow:hidden; color:var(--cink);
  background:radial-gradient(120% 90% at 50% 20%,var(--artA),var(--artB));
  border-top:1px solid rgba(0,0,0,.2); border-bottom:1px solid rgba(0,0,0,.2);
  box-shadow:0 0 14px rgba(0,0,0,.1) inset}
.tc-art svg{position:absolute; inset:0; width:100%; height:100%; display:block}
/* the engraved ground: struck in the card's own ink, well under the subject */
.tc-back{stroke:currentColor; stroke-width:2.2; fill:none; opacity:.17;
  stroke-linecap:round; stroke-linejoin:round; vector-effect:non-scaling-stroke}
.tc.lg .tc-back{stroke-width:1.6}
.tc.r2 .tc-back,.tc.r3 .tc-back{opacity:.22}
/* The Mandarin set puts the character itself in the window, at size. It is the
   most beautiful thing in the deck and it is also the actual lesson. */
.tc-han{position:absolute; inset:0; display:flex; align-items:center; justify-content:center;
  color:var(--cink); font-weight:600; line-height:1; padding:2px 4px 17%;
  font-size:30px; font-size:clamp(20px,34cqw,96px); opacity:.94; white-space:nowrap}
.tc-nm{flex:none; padding:5px 7px; font-family:"Bricolage Grotesque",sans-serif; font-weight:700;
  letter-spacing:-.015em; line-height:1.1; color:var(--plateInk);
  background:linear-gradient(180deg,var(--plateA),var(--plateB));
  font-size:clamp(8.5px,2.7vw,11.5px); overflow:hidden; text-wrap:balance;
  display:flex; align-items:center; min-height:26px}
.tc-nt{flex:none; padding:6px 8px 7px; font-size:10px; line-height:1.32; color:var(--plateInk2);
  background:linear-gradient(180deg,var(--plateB),var(--plateA)); display:none}
.tc.lg .tc-nm{font-size:17px; padding:9px 12px; min-height:0}
.tc.lg .tc-art{flex:0 0 70%}
.tc.lg .tc-nt{display:flex; align-items:flex-start; flex:1 1 auto; font-size:12.5px; padding:10px 12px 12px}
.tc-gem{position:absolute; right:5px; bottom:5px; width:13px; height:13px; z-index:4;
  border-radius:3px; transform:rotate(45deg); border:1px solid rgba(0,0,0,.32);
  background:linear-gradient(140deg,var(--fc),var(--fa)); box-shadow:0 1px 3px rgba(0,0,0,.4)}
.tc.lg .tc-gem{width:20px; height:20px}
.tc-cnt{position:absolute; left:5px; bottom:5px; z-index:4; font-family:"JetBrains Mono",monospace;
  font-size:9.5px; font-weight:800; padding:1px 5px; border-radius:5px;
  background:rgba(0,0,0,.55); color:#fff}
/* Unseen since it arrived. Every collection game needs this dot. */
.tc-new{position:absolute; left:4px; top:4px; z-index:5; width:9px; height:9px; border-radius:50%;
  background:var(--ember); box-shadow:0 0 0 2px rgba(0,0,0,.35), 0 0 9px var(--ember)}

.tc.r0{--fa:#9AA5A0; --fb:#C9D1CC; --fc:#7E8A85; --pane:#F4F6F3;
  --artA:#E7EBE6; --artB:#CFD6D0; --cink:#2B3531; --plateA:#EDF0EC; --plateB:#DFE4DF;
  --plateInk:#1E2724; --plateInk2:#4E5854}
.tc.r1{--fa:#3F6BE8; --fb:#8FA9F5; --fc:#2749A8; --pane:#F2F5FE;
  --artA:#DCE5FD; --artB:#B9C9F7; --cink:#16255C; --plateA:#E6ECFE; --plateB:#D3DDFA;
  --plateInk:#16255C; --plateInk2:#41548F}
.tc.r2{--fa:#D98B2B; --fb:#F2C77A; --fc:#A85F0E; --pane:#FEF7EC;
  --artA:#FBE9CC; --artB:#F3CE9B; --cink:#5A3407; --plateA:#FCEFDA; --plateB:#F7E2C2;
  --plateInk:#5A3407; --plateInk2:#8A6224}
.tc.r3{--fa:#C8A227; --fb:#FBEC9B; --fc:#8C6A0B; --pane:#FFFBEA;
  --artA:#FCF3CE; --artB:#F0DE94; --cink:#4C3A03; --plateA:#FDF6DB; --plateB:#F8EDBE;
  --plateInk:#4C3A03; --plateInk2:#7A6212}
.tc.r3 .tc-f{box-shadow:0 0 0 1px #E9CF63, 0 2px 6px rgba(0,0,0,.3), 0 0 22px rgba(226,186,60,.5)}

.tc-holo{position:absolute; inset:0; z-index:2; pointer-events:none; opacity:.5;
  mix-blend-mode:color-dodge;
  background:conic-gradient(from var(--ang,0deg) at 50% 45%,
    rgba(255,0,128,.34),rgba(255,200,0,.34),rgba(0,255,190,.34),
    rgba(80,120,255,.34),rgba(255,0,128,.34))}
.tc.r3 .tc-holo{opacity:.66}
.tc-glare{position:absolute; inset:0; z-index:2; pointer-events:none;
  background:linear-gradient(105deg,transparent 38%,rgba(255,255,255,.75) 48%,transparent 60%);
  transform:translateX(-130%)}
.tc.sweep .tc-glare{animation:glare 1.1s ease-out .1s 1}
@keyframes glare{to{transform:translateX(130%)}}
.tc-b{background:
    repeating-linear-gradient(45deg,rgba(255,255,255,.05) 0 7px,transparent 7px 14px),
    repeating-linear-gradient(-45deg,rgba(255,255,255,.05) 0 7px,transparent 7px 14px),
    linear-gradient(160deg,#1B3A6B,#0C1B33 55%,#16305A);
  border:1px solid rgba(255,255,255,.14)}
.tc-b::after{content:""; position:absolute; inset:9px; border-radius:5px;
  border:1px solid rgba(255,255,255,.22);
  background:radial-gradient(60% 40% at 50% 50%,rgba(255,255,255,.13),transparent 70%)}
.tc-mark{position:absolute; inset:0; display:flex; align-items:center; justify-content:center;
  z-index:2; font-family:"Bricolage Grotesque",sans-serif; font-weight:800; color:rgba(255,255,255,.5);
  font-size:min(9vw,28px); letter-spacing:-.04em}
/* A card he has not found is a sealed back with its rarity on it. The grid is
   not a filing cabinet because the pips differ and the rare ones glow - what
   is withheld is which card, not how much is left. */
/* One deck, one back: every sealed card wears the same navy, because three
   different backs would be three different decks. Rarity shows in the pip and
   the edge, which is enough to want the rare one without knowing it. */
.tc.hid .tc-b{border-color:var(--pipc,rgba(255,255,255,.2))}
.tc.hid .tc-mark{color:var(--pipc,rgba(255,255,255,.32)); opacity:.42}
.tc.hid .tc-b::after{border-color:var(--pipc,rgba(255,255,255,.22)); opacity:.5}
.tc-pip{position:absolute; left:0; right:0; bottom:8px; z-index:3; text-align:center;
  font-size:8px; font-weight:800; letter-spacing:.14em; text-transform:uppercase;
  color:var(--pipc,rgba(255,255,255,.55))}
.tc.lg .tc-pip{bottom:15px; font-size:11px; letter-spacing:.18em}
.tc.hid.r0{--pipc:#9FB4C9}
.tc.hid.r1{--pipc:#93B0FF}
.tc.hid.r2{--pipc:#F5CE86}
.tc.hid.r2 .tc-b{box-shadow:0 0 0 1px rgba(245,206,134,.45), 0 0 16px rgba(242,199,122,.3) inset}

/* A trophy he has not claimed still shows its face, drained: it is a goal, and
   a goal you are not allowed to read is not a goal. */
.tc.miss .tc-f{filter:saturate(.12) brightness(.62) contrast(.9)}
.tc.miss .tc-pane{opacity:.86}
.tc.miss .tc-nm{color:var(--plateInk2)}
.tc.miss::after{content:""; position:absolute; inset:0; border-radius:11px; z-index:3;
  pointer-events:none; background:color-mix(in srgb,var(--bg) 34%,transparent);
  box-shadow:0 0 0 1px color-mix(in srgb,var(--ink) 8%,transparent) inset}
.tc.miss.lg::after{background:color-mix(in srgb,var(--bg) 22%,transparent)}

/* ============================================================== the collection
   Was a 16,856-pixel scroll of face-down cards. Now: one set at a time, chosen
   from a rail that stays on screen, with a progress ring you can read at a
   glance and a filter that answers the only two questions you ever have —
   what am I missing, and what is nearly done. */
/* Sticky and transparent meant the page scrolled visibly through the gaps
   between the pills, which reads as a rendering fault rather than a rail. */
/* sticks to the top of the scroller, which is now the screen itself rather
   than the window - the HUD sits outside it and no longer has to be cleared */
.rail{position:sticky; top:0; z-index:20; margin:0 -14px;
  padding:9px 14px 10px;
  display:flex; gap:7px; overflow-x:auto; scrollbar-width:none;
  -webkit-overflow-scrolling:touch; scroll-snap-type:x proximity;
  background:var(--bg);
  box-shadow:0 10px 12px -10px rgba(0,0,0,.1), 0 1px 0 var(--edge);
  }
.rail::-webkit-scrollbar{display:none}
.rail button{flex:none; display:flex; align-items:center; gap:7px; padding:8px 13px;
  min-height:44px; border-radius:99px; border:3px solid var(--cardLine2);
  background:var(--card); color:var(--cardInk2); font:inherit; font-size:13.5px;
  font-weight:800; font-family:"Bricolage Grotesque",system-ui,sans-serif; cursor:pointer;
  white-space:nowrap; box-shadow:0 2px 0 var(--edge)}
.rail button[aria-current="true"]{color:var(--goldInk); border-color:var(--goldEdge);
  background:var(--gold);
  background:linear-gradient(150deg,var(--goldSoft),var(--panel) 70%)}
.rail button:active{transform:scale(.95)}
.rail .rg{flex:none; width:26px; height:26px}
.rail .rg circle{fill:none; stroke-width:4}
.rail .rg .bg{stroke:var(--line2)}
.rail .rg .fg{stroke:var(--violet); stroke-linecap:round; transition:stroke-dasharray .6s var(--tap)}
.rail button[aria-current="true"] .rg .fg{stroke:var(--gold)}
.rail .rg.done .fg{stroke:var(--jade)}
.rail .lock{opacity:.55}

.sethead{display:flex; align-items:flex-start; gap:12px; margin:14px 0 4px}
.sethead .big{font-family:"JetBrains Mono",monospace; font-size:30px; font-weight:800;
  letter-spacing:-.04em; line-height:1; flex:none}
.sethead .big small{display:block; font-family:"Instrument Sans",sans-serif; font-size:9.5px;
  letter-spacing:.12em; text-transform:uppercase; color:var(--ink3); font-weight:500; margin-top:5px}
.sethead .bd{flex:1; min-width:0}
.sethead .bd h3{font-size:19px}
.sethead .bd p{margin:3px 0 0; font-size:13px; color:var(--ink3)}

.filters{display:flex; gap:6px; margin:12px 0 2px; overflow-x:auto; scrollbar-width:none;
  padding-bottom:2px}
.filters::-webkit-scrollbar{display:none}
.filters button{flex:1 0 auto; white-space:nowrap; padding:10px 9px; min-height:46px; border-radius:14px;
  border:3px solid var(--cardLine2); background:var(--card); color:var(--cardInk2);
  font:inherit; font-size:13.5px; font-weight:800; cursor:pointer;
  box-shadow:0 2px 0 var(--edge)}
.filters button[aria-pressed="true"]{color:var(--ink); border-color:var(--line2);
  background:var(--panel2)}

.binder{display:grid; grid-template-columns:repeat(3,1fr); gap:9px; margin:12px 0 4px;
  container-type:inline-size}
@media (min-width:520px){.binder{grid-template-columns:repeat(4,1fr)}}
.binder .tc{cursor:pointer; transition:transform .12s var(--tap)}
.binder .tc:active{transform:scale(.95)}
.empty{text-align:center; padding:34px 16px; color:var(--ink3); font-size:14px}

.door{display:flex; align-items:center; gap:13px; padding:15px 16px; margin:11px 0;
  border-radius:var(--r); border:1px dashed var(--line2); background:var(--sunk)}
.door .lk{flex:none; width:40px; height:40px; border-radius:12px; display:flex; align-items:center;
  justify-content:center; background:var(--panel); border:1px solid var(--line2); color:var(--ink3)}
.door .bd{flex:1; min-width:0}
.door .bd b{display:block; font-family:"Bricolage Grotesque",sans-serif; font-weight:700;
  font-size:16px; color:var(--ink2)}
.door .bd span{display:block; font-size:12.5px; color:var(--ink3); line-height:1.3; margin-top:2px}
.door .at{flex:none; font-family:"JetBrains Mono",monospace; font-size:10px; letter-spacing:.1em;
  text-transform:uppercase; color:var(--ink3); text-align:right; max-width:92px; line-height:1.3}

/* ==================================================================== packs */
.pk{position:relative; width:100%; max-width:190px; margin:14px auto 4px; aspect-ratio:3/4;
  border-radius:11px; cursor:pointer; overflow:hidden; border:none; padding:0; display:block;
  background:linear-gradient(150deg,#2A3F86,#5C7BD8 28%,#1B2C63 55%,#4A66C4 78%,#22356F);
  box-shadow:0 8px 24px rgba(0,0,0,.42), 0 0 0 1px rgba(255,255,255,.16) inset;
  color:#fff; font-family:"Bricolage Grotesque",sans-serif;
  transition:transform .12s var(--tap)}
.pk.big{background:linear-gradient(150deg,#6B4A0E,#E0B54B 28%,#4E360A 55%,#C79A34 78%,#5A3F0C)}
.pk-strip{position:absolute; top:0; left:0; right:0; height:20%;
  border-bottom:2px dashed rgba(255,255,255,.45);
  background:linear-gradient(180deg,rgba(255,255,255,.22),rgba(255,255,255,.04))}
.pk-body{position:absolute; inset:20% 0 0; display:flex; flex-direction:column; align-items:center;
  justify-content:center; gap:5px; text-align:center; padding:8px 14px}
.pk-ttl{font-weight:800; font-size:15px; letter-spacing:-.02em; line-height:1.1;
  text-shadow:0 1px 3px rgba(0,0,0,.45)}
.pk-sub{font-family:"Instrument Sans",sans-serif; font-weight:500; font-size:11px; opacity:.86;
  line-height:1.25}
.pk-n{position:absolute; top:22%; right:9px; font-family:"JetBrains Mono",monospace; font-size:11px;
  font-weight:800; background:rgba(0,0,0,.42); padding:2px 7px; border-radius:20px}
.pk-sheen{position:absolute; inset:-30% -60%; pointer-events:none;
  background:linear-gradient(100deg,transparent 40%,rgba(255,255,255,.4) 50%,transparent 60%);
  animation:pksheen 3.4s ease-in-out infinite}
@keyframes pksheen{0%{transform:translateX(-60%)}55%,100%{transform:translateX(60%)}}
.pk:active{transform:scale(.975)}
.pk.tear .pk-strip{animation:tear .42s ease-in forwards}
@keyframes tear{to{transform:translateY(-130%) rotate(-7deg); opacity:0}}
.pk.tear{animation:pkgo .5s ease-in .18s forwards}
@keyframes pkgo{to{transform:scale(1.15); opacity:0}}

/* ================================================================= the stage */
#stage{position:fixed; inset:0; z-index:120; display:none;
  background:radial-gradient(80% 55% at 50% 38%,#1B2942,#050810 72%);
  padding:max(18px,env(safe-area-inset-top)) 18px calc(18px + env(safe-area-inset-bottom));
  flex-direction:column; align-items:center; justify-content:center; gap:14px;
  overscroll-behavior:contain}
#stage.on{display:flex; animation:fadein .28s ease-out both}
@keyframes fadein{from{opacity:0}to{opacity:1}}
#stage .rays{position:absolute; inset:0; pointer-events:none; opacity:0; z-index:0;
  --rc:rgba(255,255,255,.09); --rc2:rgba(255,255,255,.07);
  background:conic-gradient(from 0deg at 50% 42%,transparent 0 12deg,var(--rc) 12deg 18deg,
    transparent 18deg 30deg,var(--rc2) 30deg 34deg,transparent 34deg 60deg);
  animation:spin 26s linear infinite}
#stage.burst2 .rays{--rc:rgba(245,196,81,.26); --rc2:rgba(245,196,81,.16);
  animation:spin 26s linear infinite, raysburst .8s ease-out both}
#stage.burst3 .rays{--rc:rgba(255,225,130,.4); --rc2:rgba(255,225,130,.22);
  animation:spin 26s linear infinite, raysburst 1s ease-out both}
@keyframes raysburst{0%{filter:brightness(2.6) saturate(1.4)} 100%{filter:none}}
#stage.lit .rays{opacity:1; transition:opacity .5s}
#stage .step{position:relative; z-index:2; font-family:"JetBrains Mono",monospace; font-size:12px;
  letter-spacing:.16em; text-transform:uppercase; color:rgba(255,255,255,.62); min-height:16px}
/* The arena is where the pack sits, and where the stack rises out of it. */
#stage .arena{position:relative; z-index:2; width:min(66vw,250px); max-height:56vh; aspect-ratio:5/7;
  container-type:inline-size}
#stage .arena .pk{position:absolute; inset:0; width:100%; max-width:none; margin:0; aspect-ratio:auto;
  z-index:3}
#stage .arena .pk.tear{animation:pkdrop .55s ease-in .1s forwards; pointer-events:none}
@keyframes pkdrop{to{transform:translateY(72px) scale(.92); opacity:0}}
#stage .stack{position:absolute; inset:0; z-index:2; opacity:0;
  transform:translateY(48px) scale(.94);
  transition:opacity .5s var(--tap), transform .6s var(--pop)}
#stage .stack.up{opacity:1; transform:none}
#stage .stack .tc{position:absolute; inset:0}
#stage .flash{position:absolute; inset:0; z-index:3; pointer-events:none; background:#fff; opacity:0}
#stage .flash.go{animation:flash .34s ease-out both}
#stage .flash.gold{background:radial-gradient(circle at 50% 40%,#FFF3C4,#FFD35C 42%,#fff 100%)}
@keyframes flash{0%{opacity:0} 35%{opacity:.86} 100%{opacity:0}}

/* the card's own moments: dealt, lifted, teased, turned, landed, gone */
#stage .tc.deal{animation:dealin .38s var(--pop) both}
@keyframes dealin{from{opacity:0; transform:translateY(18px) scale(.96)}}
#stage .tc .tc-i{transition-duration:var(--flipd,.62s)}
#stage .tc.lift{transform:translateY(-12px) scale(1.04); transition:transform .3s var(--pop)}
#stage .tc.lift .tc-f,#stage .tc.lift .tc-b{box-shadow:0 10px 18px rgba(0,0,0,.45), 0 26px 48px rgba(0,0,0,.4)}
#stage .tc.tease2 .tc-b{--tz:rgba(245,196,81,.95); animation:tease .46s ease-in-out both}
#stage .tc.tease3 .tc-b{--tz:rgba(255,232,150,1); animation:tease .64s ease-in-out both}
@keyframes tease{0%{box-shadow:0 0 0 0 transparent}
  60%{box-shadow:0 0 0 3px var(--tz), 0 0 30px 8px var(--tz)}
  100%{box-shadow:0 0 0 2px var(--tz), 0 0 20px 5px var(--tz)}}
#stage .tc.land{animation:landing .52s var(--pop) both}
@keyframes landing{0%{transform:translateY(-12px) scale(1.04)} 55%{transform:translateY(0) scale(1.07)} 100%{transform:none}}
#stage .tc.fly{animation:flyaway .38s ease-in both; pointer-events:none}
@keyframes flyaway{to{transform:translateY(44vh) scale(.22); opacity:0}}

/* the pull so far, on the table */
#stage .tray{position:relative; z-index:2; display:flex; gap:6px; justify-content:center; flex-wrap:wrap;
  width:min(84vw,330px)}
#stage .tray:empty{display:none}
#stage .tray .tc{width:44px; flex:none; pointer-events:none; container-type:inline-size}
#stage .tray .tc.pop{animation:traypop .42s var(--pop) both}
@keyframes traypop{from{opacity:0; transform:translateY(-34px) scale(.4)}}
#stage.scored .tray .tc{width:58px}
@media (prefers-reduced-motion:reduce){
  #stage .tc.deal,#stage .tc.land,#stage .tc.fly,#stage .tray .tc.pop,#stage .flash.go,
  #stage .tc.tease2 .tc-b,#stage .tc.tease3 .tc-b,#stage .rays{animation:none}
  #stage .tc.lift{transform:none}
  #stage .stack{transition:none}
}
#stage .under{position:relative; z-index:2; width:min(66vw,250px); display:flex; gap:8px}
#stage .under button{flex:1; min-height:48px; border-radius:13px; font-weight:700; font:inherit;
  font-size:14.5px; cursor:pointer; border:1px solid rgba(255,255,255,.28);
  background:rgba(255,255,255,.1); color:#fff}
#stage .under button.pri{background:linear-gradient(180deg,#FFE38A,#F2B735 60%,#D89412);
  color:#3A2A05; border-color:#C99417; font-weight:800}
#stage .dots{position:relative; z-index:2; display:flex; gap:6px}
#stage .dots i{width:7px; height:7px; border-radius:50%; background:rgba(255,255,255,.24)}
#stage .dots i.on{background:#fff}
#stage .dots i.hi{background:#F5C451; box-shadow:0 0 8px #F5C451}
#stage .ghost{position:absolute; inset:0; border-radius:11px;
  background:
    repeating-linear-gradient(45deg,rgba(255,255,255,.05) 0 7px,transparent 7px 14px),
    linear-gradient(160deg,#1B3A6B,#0C1B33 55%,#16305A);
  border:1px solid rgba(255,255,255,.14); box-shadow:0 6px 18px rgba(0,0,0,.4);
  transform:translateY(calc(var(--k) * 5px)) rotate(calc((var(--k) - 1) * 1.7deg)) scale(calc(1 - var(--k) * .018));
  opacity:calc(1 - var(--k) * .16)}
.burst{position:absolute; inset:0; z-index:4; pointer-events:none}
.burst i{position:absolute; left:50%; top:46%; width:5px; height:5px; border-radius:50%;
  background:#FFD86B; opacity:0; animation:spark .95s ease-out forwards}
@keyframes spark{0%{opacity:1; transform:translate(0,0) scale(1)}
  100%{opacity:0; transform:translate(var(--dx),var(--dy)) scale(.25)}}
.score{position:relative; z-index:2; text-align:center; color:#fff; animation:rise .5s ease-out both}
.score .big{font-family:"JetBrains Mono",monospace; font-variant-numeric:tabular-nums;
  font-size:31px; font-weight:800; letter-spacing:-.03em; color:#8FE3B4}
.score .sm{font-size:13px; color:rgba(255,255,255,.7); margin-top:3px}
.score .shard{margin-top:8px; font-family:"JetBrains Mono",monospace; font-size:14px;
  font-weight:700; color:#7FE6C0}
@keyframes rise{from{opacity:0; transform:translateY(12px)}to{opacity:1; transform:none}}
.lvlup{position:relative; z-index:2; font-family:"Bricolage Grotesque",sans-serif; font-weight:800;
  font-size:21px; color:#F5C451; text-align:center; animation:pop .5s var(--pop) both}
@keyframes pop{from{opacity:0; transform:scale(.6)}to{opacity:1; transform:none}}

/* ============================================================== card detail */
#sheet{position:fixed; inset:0; z-index:110; display:none; align-items:center; justify-content:center;
  flex-direction:column; gap:16px; padding:24px;
  background:rgba(4,7,12,.9); backdrop-filter:blur(8px); -webkit-backdrop-filter:blur(8px)}
#sheet.on{display:flex; animation:fadein .2s ease-out both}
#sheet .slot{width:min(70vw,262px); aspect-ratio:5/7; position:relative; container-type:inline-size}
#sheet .slot .tc{position:absolute; inset:0}
#sheet .meta{color:rgba(255,255,255,.75); text-align:center; font-size:13.5px; max-width:290px}
/* .fine is a light-ground colour; on the dark sheet it was ink on ink. */
#sheet .fine{color:rgba(255,255,255,.62); max-width:300px; font-size:13px; line-height:1.5}
#sheet .acts{display:flex; gap:9px}
#sheet button{min-height:48px; padding:0 22px; border-radius:13px; font-weight:700; font:inherit;
  font-size:14.5px; cursor:pointer; border:1px solid rgba(255,255,255,.3);
  background:rgba(255,255,255,.11); color:#fff}
#sheet button.pri{background:linear-gradient(180deg,#5CE8B5,#3FD9A0 60%,#22A87A); color:#05231A;
  border-color:#2FBF8C; font-weight:800}

/* ================================================================== the shop
   The sink. Duplicates stop being dead weight and start being the thing that
   finishes a set. */
.wares{display:grid; gap:10px; margin:12px 0}
.ware{display:flex; align-items:center; gap:13px; padding:14px; border-radius:var(--r);
  border:1px solid var(--line); background:linear-gradient(150deg,var(--panel),var(--panel2));
  width:100%; text-align:left; cursor:pointer; font:inherit; color:var(--ink); min-height:74px;
  transition:transform .12s var(--tap)}
.ware:active{transform:scale(.985)}
.ware[disabled]{opacity:.45; pointer-events:none}
.ware .ic{flex:none; width:44px; height:44px; border-radius:13px; display:flex; align-items:center;
  justify-content:center; background:var(--sunk); border:1px solid var(--line2); color:var(--jade)}
.ware .bd{flex:1; min-width:0}
.ware .bd b{display:block; font-family:"Bricolage Grotesque",sans-serif; font-weight:700; font-size:16px}
.ware .bd span{display:block; font-size:12.5px; color:var(--ink3); line-height:1.3; margin-top:1px}
.ware .cost{flex:none; display:flex; align-items:center; gap:4px; font-family:"JetBrains Mono",monospace;
  font-size:15px; font-weight:800; color:var(--jade)}
.ware .cost svg{width:15px; height:15px}

/* ---------------------------------------------------- the long game
   The locked sets were always a progression track; they were just never drawn
   as one. Seven gates do not fit across a phone, so the ladder scrolls. */
.season{margin:22px 0 0; padding:15px; border-radius:var(--r2);
  border:1px solid color-mix(in srgb,var(--violet) 42%,transparent);
  background:linear-gradient(150deg,var(--violetSoft),var(--panel) 72%)}
.season .top{display:flex; align-items:baseline; gap:10px}
.season .top b{font-family:"Bricolage Grotesque",sans-serif; font-weight:800; font-size:17px; flex:1}
.season .top span{font-family:"JetBrains Mono",monospace; font-size:11px; color:var(--ink2); flex:none}
.season p{margin:7px 0 0; font-size:12.5px; color:var(--ink3)}
.nodes{display:flex; gap:7px; margin-top:13px; overflow-x:auto; scrollbar-width:none;
  -webkit-overflow-scrolling:touch; margin-inline:-4px; padding-inline:4px}
.nodes::-webkit-scrollbar{display:none}
.node{flex:0 0 62px; text-align:center; min-width:0}
.node .d{height:44px; border-radius:13px; border:1px solid var(--line2); background:var(--sunk);
  display:flex; align-items:center; justify-content:center; font-family:"JetBrains Mono",monospace;
  font-size:12px; font-weight:800; color:var(--ink3)}
.node.got .d{border-color:var(--gold); color:var(--goldInk);
  background:radial-gradient(70% 70% at 35% 25%,var(--gold2),var(--gold) 62%,#C08D12)}
.node.next .d{border-color:var(--violet); color:var(--violetInk);
  box-shadow:0 0 0 3px color-mix(in srgb,var(--violet) 16%,transparent)}
.node .l{font-size:9px; letter-spacing:.07em; text-transform:uppercase; color:var(--ink3);
  margin-top:5px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap}

/* a lived card: the side quest was done in the world, not on the screen */
/* A lived card is one he went and did. Foil whatever the rarity, and a
   stamp with the date on it - the card changing is the reward. */
.tc.lived .tc-f{box-shadow:0 0 0 1.5px #F2C94C, 0 2px 5px rgba(0,0,0,.3), 0 8px 20px rgba(0,0,0,.24),
  0 0 16px rgba(242,201,76,.45)}
.tc.lived .tc-holo{opacity:.42}
.tc-stamp{position:absolute; right:-5px; top:10px; z-index:6; transform:rotate(8deg);
  background:linear-gradient(180deg,#FFE38A,#F2B735); color:#4A3200; border:1.5px solid #B9840C;
  border-radius:6px; padding:2px 6px 2px 7px; text-align:center; line-height:1.05;
  box-shadow:0 1px 0 rgba(0,0,0,.25), 0 3px 8px rgba(0,0,0,.25)}
.tc-stamp b{display:block; font:900 8.5px/1 "Bricolage Grotesque",sans-serif; letter-spacing:.14em;
  text-transform:uppercase}
.tc-stamp i{display:block; font:700 6.5px/1.2 "JetBrains Mono",monospace; font-style:normal;
  opacity:.8; margin-top:1px}
.tc.lg .tc-stamp{right:-8px; top:16px; padding:4px 10px 4px 11px; border-radius:8px}
.tc.lg .tc-stamp b{font-size:12px}
.tc.lg .tc-stamp i{font-size:9px}

/* the ask a held card carries, on its sheet */
#sheet .try{max-width:290px; text-align:center; font-family:"Nunito",sans-serif;
  font-weight:700; font-size:13.5px; line-height:1.45; color:#FFE9AE;
  background:rgba(255,200,0,.12); border:1px solid rgba(255,200,0,.35);
  border-radius:13px; padding:10px 14px; text-wrap:balance}
#sheet .try b{font-weight:900; color:#FFD35C; margin-right:6px}
#sheet .try.done{color:#C9F3DE; background:rgba(63,217,160,.12);
  border-color:rgba(63,217,160,.4)}
#sheet .try.done b{color:#5CE8B5}
#sheet .try .doit{display:block; width:100%; margin-top:11px; min-height:48px; border-radius:13px;
  font:inherit; font-weight:800; font-size:14.5px; cursor:pointer;
  background:linear-gradient(180deg,#FFE38A,#F2B735 60%,#D89412); color:#3A2A05;
  border:1px solid #C99417; box-shadow:0 3px 0 #A87A0E}
#sheet .try .doit:active{transform:translateY(2px); box-shadow:0 1px 0 #A87A0E}

/* the deck is finished, so deal another one */
.newseason{border-color:#F3D9A0; background:var(--flameSoft); text-align:center}
.newseason .sn{font-family:"JetBrains Mono",monospace; font-size:10px; letter-spacing:.16em;
  text-transform:uppercase; color:var(--ink3)}
.newseason h3{margin:6px 0 0; font-size:19px}
.newseason p{margin:8px 0 0; font-size:13.5px; color:var(--ink2); line-height:1.45}
.seasonbar{display:flex; align-items:baseline; gap:10px; flex-wrap:wrap; margin:10px 0 2px;
  padding:9px 13px; border-radius:14px; background:var(--card2); border:2px solid var(--edge)}
.seasonbar b{font-family:"Bricolage Grotesque",sans-serif; font-weight:800; font-size:15px;
  letter-spacing:-.02em}
.seasonbar span{font-size:12px; color:var(--ink3)}

/* =============================================================== do & inspire
   The two faces that are not collected. Same bones as a collectible so the
   stage does not know the difference; different clothes so he does. */
.tc.kd{--fa:#1F2937; --fb:#4B5563; --fc:#111827; --pane:#0F172A}
.tc.kd .tc-pane{color:#F8FAFC; padding:9px 9px 8px; justify-content:flex-start}
.tc.kd .tc-kind{font:800 8px/1 "JetBrains Mono",monospace; letter-spacing:.16em; text-transform:uppercase;
  color:#FFD35C; margin-bottom:8px}
.tc.kd .tc-kind i{font-style:normal; color:rgba(255,255,255,.55); margin-left:6px; letter-spacing:.1em}
.tc.kd .tc-verb{font:800 12.5px/1.15 "Bricolage Grotesque",sans-serif; letter-spacing:-.01em; text-wrap:balance}
.tc.kd .tc-det{margin-top:6px; font:600 8.5px/1.35 "Nunito",sans-serif; color:rgba(255,255,255,.66)}
.tc.kd .tc-mk{position:absolute; right:8px; bottom:8px; width:26px; height:26px; border-radius:9px;
  display:flex; align-items:center; justify-content:center; color:#0F172A; background:#FFD35C}
.tc.kd.s2 .tc-kind{color:#8FE3B4} .tc.kd.s2 .tc-mk{background:#8FE3B4}
.tc.kd.s3 .tc-kind{color:#C7B2FF} .tc.kd.s3 .tc-mk{background:#C7B2FF}
.tc.kd.lg .tc-pane{padding:16px 16px 14px}
.tc.kd.lg .tc-kind{font-size:10.5px; margin-bottom:14px}
.tc.kd.lg .tc-verb{font-size:22px}
.tc.kd.lg .tc-det{font-size:13.5px; margin-top:10px}
.tc.kd.lg .tc-mk{width:40px; height:40px; border-radius:13px; right:14px; bottom:14px}
.tc.kd .tc-b .tc-pip,.tc.ki .tc-b .tc-pip{color:#FFD35C}

.tc.ki{--fa:#E8DCC0; --fb:#F7EFDD; --fc:#C9B78F; --pane:#FBF7EE}
.tc.ki .tc-pane{color:#3B3A36; padding:9px 9px 8px; justify-content:flex-start}
.tc.ki .tc-kind{font:800 8px/1 "JetBrains Mono",monospace; letter-spacing:.16em; text-transform:uppercase;
  color:#8A6B1E}
.tc.ki .tc-mark{font:900 38px/0.8 "Bricolage Grotesque",serif; color:#D9C48A; margin:8px 0 2px; height:24px}
/* the pin is a block, not a glyph in a text line, or it lands on the title */
.tc.ki.k-place .tc-mark{color:#3F8F06; height:20px; margin:8px 0 4px; display:flex; align-items:flex-end}
.tc.ki.k-place .tc-mark svg{display:block; width:18px; height:18px}
.tc.ki.lg.k-place .tc-mark{height:30px; margin:14px 0 6px}
.tc.ki.lg.k-place .tc-mark svg{width:28px; height:28px}
/* a line set in the middle of the page reads as meant; at the top it reads
   as a form with the rest left blank */
.tc.ki.lg .tc-pane{justify-content:center}
.tc.ki.lg .tc-kind{position:absolute; top:16px; left:16px}
.tc.ki .tc-ttl{font:800 12px/1.15 "Bricolage Grotesque",sans-serif; letter-spacing:-.01em; text-wrap:balance}
.tc.ki .tc-body{margin-top:6px; font:600 8.5px/1.35 "Nunito",sans-serif; color:#6F6D63}
.tc.ki.lg .tc-pane{padding:16px 16px 14px}
.tc.ki.lg .tc-kind{font-size:10.5px}
.tc.ki.lg .tc-mark{font-size:64px; height:40px; margin:14px 0 6px}
.tc.ki.lg .tc-ttl{font-size:21px}
.tc.ki.lg .tc-body{font-size:13.5px; margin-top:10px}

/* the hand, on Cards */
.hand{display:grid; gap:9px}
.hc{display:grid; grid-template-columns:78px 1fr; gap:12px; align-items:start;
  background:var(--card); border:1.5px solid var(--edge); border-bottom-width:3px;
  border-radius:18px; padding:11px}
.hc .tc{width:78px; container-type:inline-size}
.hc .hcb b{display:block; font-size:15px; font-weight:800; letter-spacing:-.01em; line-height:1.2}
.hc .hcb > span{display:block; margin-top:3px; font-size:12.5px; color:var(--ink2); line-height:1.4}
.hc .hca{display:flex; gap:7px; margin-top:9px; flex-wrap:wrap}
.hc .hca .btn{padding:9px 12px; min-height:40px; font-size:12.5px; flex:1 1 auto}
.kept{display:grid; gap:7px}
.kp{background:var(--card2); border:1.5px solid var(--edge); border-left:4px solid #D9C48A;
  border-radius:12px; padding:9px 12px}
.kp.k-place{border-left-color:var(--green)}
.kp.k-idea{border-left-color:var(--gold)}
.kp b{display:block; font-size:13.5px; font-weight:800}
.kp span{display:block; margin-top:2px; font-size:12px; color:var(--ink2); line-height:1.4}
.score .sm.hand{color:#FFD35C; margin-top:5px}
/* Small faces - the hand and the stage tray - show the kind and the title.
   The row beside them carries the full text; on a 78px card the verb was
   wrapping under the tick and the second line was cut mid-word. */
.tc.kd:not(.lg) .tc-det,.tc.ki:not(.lg) .tc-body{display:none}
.tc.kd:not(.lg) .tc-pane{padding-bottom:28px}
.tc.kd:not(.lg) .tc-mk{width:18px; height:18px; border-radius:6px; right:6px; bottom:6px}
.tc.kd:not(.lg) .tc-mk svg{width:13px; height:13px}
.tc.ki:not(.lg) .tc-mark{height:16px; margin:5px 0 3px}
.tc.ki:not(.lg).k-place .tc-mark{height:16px}
.tc.ki:not(.lg).k-place .tc-mark svg{width:14px; height:14px}
/* At thumbnail size a long verb wrapped to five lines and ran under the tick;
   three lines and an ellipsis, and the row beside it has the rest. The pin on
   a small place card sat on its own label, and the label already says place. */
.tc.kd:not(.lg) .tc-verb{font-size:11px; display:-webkit-box; -webkit-line-clamp:3;
  -webkit-box-orient:vertical; overflow:hidden}
.tc.ki:not(.lg).k-place .tc-mark{display:none}

/* ================================================================= textures
   A rarity you can feel with your thumb. --px, --py and --ang come from
   tilt(), so every layer here moves as the card is turned in the hand:
   common is matte, uncommon carries a specular band, rare refracts, gold is
   foil with a sparkle where the light is. At rest they sit at centre. */
.tc-fx{position:absolute; inset:0; z-index:2; pointer-events:none; border-radius:7px}
.tc.r0 .tc-fx{opacity:.5; mix-blend-mode:multiply;
  background:repeating-linear-gradient(0deg,rgba(0,0,0,.035) 0 1px,transparent 1px 3px)}
.tc.r1 .tc-fx{opacity:.75; mix-blend-mode:screen;
  background:linear-gradient(calc(62deg + var(--px,.5) * 46deg),
    transparent calc(var(--px,.5) * 100% - 34%), rgba(255,255,255,.62) calc(var(--px,.5) * 100%),
    transparent calc(var(--px,.5) * 100% + 34%))}
.tc.r2 .tc-fx{opacity:.58; mix-blend-mode:color-dodge; filter:saturate(1.35);
  background:
    repeating-linear-gradient(calc(112deg + var(--px,.5) * 36deg),
      rgba(255,255,255,.16) 0 2px, transparent 2px 7px),
    conic-gradient(from var(--ang,170deg) at calc(var(--px,.5) * 100%) calc(var(--py,.5) * 100%),
      #ff6ec7,#ffd36e,#6effb3,#6ec7ff,#c86eff,#ff6ec7)}
.tc.r3 .tc-fx{opacity:.82; mix-blend-mode:overlay;
  background:
    radial-gradient(circle at calc(var(--px,.5) * 100%) calc(var(--py,.5) * 100%),
      rgba(255,255,255,.85), transparent 38%),
    repeating-radial-gradient(circle at 28% 22%, rgba(255,255,255,.2) 0 1px, transparent 1px 6px),
    linear-gradient(calc(58deg + var(--px,.5) * 54deg),
      #B8860B 0%, #FFE38A 24%, #C9A227 50%, #FFF1B8 76%, #B8860B 100%)}
/* the same layer on a Do or Inspire face is paper: a whisper of grain */
.tc.kd .tc-fx{opacity:.35; mix-blend-mode:screen;
  background:repeating-linear-gradient(0deg,rgba(255,255,255,.05) 0 1px,transparent 1px 3px)}
.tc.ki .tc-fx{opacity:.5; mix-blend-mode:multiply;
  background:repeating-linear-gradient(90deg,rgba(0,0,0,.03) 0 1px,transparent 1px 4px)}
/* lived: the foil edge stays, and the holo is a soft wash rather than a second rainbow */
.tc.lived .tc-holo{opacity:.3}
/* the rarity, said on the plate as a texture would be on a real card */
.tc-gem::after{content:""; position:absolute; inset:0; border-radius:inherit;
  background:linear-gradient(135deg,rgba(255,255,255,.7),transparent 55%)}

/* ==================================================== the face stays hidden
   On iOS, layers with a blend mode inside a 3D flip escape backface culling:
   the rare texture, the art, the new dot and the gem all showed through the
   back of a face-down card. So while a card is down, everything on the face
   is invisible outright - and on the turn it stays invisible until the
   half-way point, which is exactly when the face comes round. */
.tc-pane{isolation:isolate}
.tc .tc-f > *{transition:visibility 0s linear calc(var(--flipd,.62s) * .5)}
.tc.down .tc-f > *{visibility:hidden; transition-delay:0s}
.tc.down .tc-fx,.tc.down .tc-holo,.tc.down .tc-glare{display:none}

/* Thumbnails - in the tray and beside a hand row - are pictures, not
   labels. "Labra tunn" and "Chan Jewe" were not helping anyone. */
#stage .tray .tc .tc-nm,#stage .tray .tc .tc-nt,#stage .tray .tc .tc-cnt,
.hc .tc .tc-nm,.hc .tc .tc-nt,
#stage .tray .tc.kd .tc-verb,#stage .tray .tc.kd .tc-det,
#stage .tray .tc.ki .tc-ttl,#stage .tray .tc.ki .tc-body,#stage .tray .tc.ki .tc-mark{display:none}
#stage .tray .tc .tc-art{border-top:0}
#stage .tray .tc.kd .tc-pane,#stage .tray .tc.ki .tc-pane{justify-content:center; align-items:center}
#stage .tray .tc.kd .tc-mk{position:static; width:22px; height:22px; border-radius:7px}
#stage .tray .tc .tc-kind{margin:0; font-size:7px}

/* A row that has just been asked for, briefly ringed. */
.hc.pulse{animation:hcpulse .9s var(--pop)}
@keyframes hcpulse{0%,100%{box-shadow:none}30%{box-shadow:0 0 0 4px var(--goldSoft), 0 0 0 6px var(--gold)}}

