/* WINGED — the shell around the match: title screen, collection, settings,
   card detail. The board itself lives in index.html; this is everything that
   makes it feel like a game you launched rather than a page you loaded. */

/* ---------------- title screen ---------------- */
#title{position:fixed;inset:0;z-index:150;display:none;flex-direction:column;align-items:center;justify-content:center;
  padding:24px;overflow:hidden;background:#05080b}
#title.on{display:flex}
#title .tbg{position:absolute;inset:-2%;background:#05080b center/cover no-repeat;
  background-image:var(--board,none);filter:saturate(.9);
  animation:tdrift 38s ease-in-out infinite alternate}
@keyframes tdrift{0%{transform:scale(1.06) translate(-1%,0)}100%{transform:scale(1.14) translate(1%,-1.5%)}}
#title .tveil{position:absolute;inset:0;
  background:radial-gradient(ellipse at 50% 42%,rgba(4,7,10,.24),rgba(3,5,8,.9) 72%),
             linear-gradient(180deg,rgba(3,5,8,.78),rgba(3,5,8,.35) 34%,rgba(3,5,8,.92))}
#title .tinner{position:relative;z-index:2;display:flex;flex-direction:column;align-items:center;gap:6px;max-width:520px;width:100%}

.wordmark{font-size:clamp(46px,9vw,86px);letter-spacing:clamp(10px,2.4vw,22px);font-weight:normal;margin:0 0 0 clamp(10px,2.4vw,22px);
  background:linear-gradient(180deg,#fff8e2,var(--gold-l) 26%,var(--gold) 54%,#9d7526 78%,#6d4f18);
  -webkit-background-clip:text;background-clip:text;color:transparent;
  filter:drop-shadow(0 4px 18px rgba(0,0,0,.95)) drop-shadow(0 0 34px rgba(224,185,95,.28));
  line-height:1.05;text-align:center}
.wordrule{display:flex;align-items:center;gap:11px;width:min(340px,86%);margin:2px 0 4px;opacity:.9}
.wordrule::before,.wordrule::after{content:"";flex:1;height:1px;background:linear-gradient(90deg,transparent,var(--gold-d),var(--gold),var(--gold-d),transparent)}
.wordrule i{width:7px;height:7px;transform:rotate(45deg);background:linear-gradient(135deg,var(--gold-l),var(--gold-d));box-shadow:0 0 10px rgba(224,185,95,.7)}
.tagline{font-size:clamp(11px,1.5vw,13px);letter-spacing:5px;opacity:.5;text-transform:uppercase;margin-bottom:22px;text-align:center}

.tmenu{display:flex;flex-direction:column;gap:9px;width:min(310px,84%)}
.tbtn{position:relative;display:flex;align-items:center;gap:12px;width:100%;padding:13px 18px;border-radius:10px;cursor:pointer;
  font-family:inherit;font-size:15px;letter-spacing:2.5px;text-align:left;color:var(--cream);font-weight:normal;text-shadow:0 1px 3px rgba(0,0,0,.9);
  background:linear-gradient(180deg,rgba(28,40,50,.9),rgba(12,19,26,.94));
  border:1px solid rgba(224,185,95,.3);box-shadow:0 5px 18px rgba(0,0,0,.6),inset 0 1px 0 rgba(255,255,255,.07);
  transition:transform .13s,border-color .13s,box-shadow .13s}
.tbtn .ic{font-size:18px;width:22px;text-align:center;flex:none;filter:drop-shadow(0 2px 3px rgba(0,0,0,.8))}
.tbtn:hover{transform:translateX(4px);border-color:var(--gold);box-shadow:0 0 22px rgba(224,185,95,.22),0 5px 18px rgba(0,0,0,.6)}
.tbtn.primary{padding:16px 18px;font-size:17px;letter-spacing:4px;color:#241a05;font-weight:bold;text-shadow:0 1px 0 rgba(255,255,255,.28);
  background:linear-gradient(180deg,#fbeec2,var(--gold) 46%,#9b7327);border-color:var(--gold-l);
  box-shadow:0 0 26px rgba(224,185,95,.34),0 6px 20px rgba(0,0,0,.7),inset 0 1px 0 rgba(255,255,255,.6)}
.tbtn.primary .ic{filter:none}
/* A refused entry says WHY, on the button. `disabled` alone reads as broken —
   and the one thing a player needs here (sign in / you are offline) is exactly
   what a greyed-out button cannot tell them. See design/pvp/README.md §4b. */
.tbtn:disabled{cursor:default;opacity:.6;filter:grayscale(.4);border-style:dashed}
.tbtn:disabled:hover{transform:none;border-color:rgba(224,185,95,.3);box-shadow:0 5px 18px rgba(0,0,0,.6),inset 0 1px 0 rgba(255,255,255,.07)}
.tbtn-why{margin-left:auto;font-style:normal;font-size:10.5px;letter-spacing:.9px;opacity:.8;text-transform:none;white-space:nowrap}
.tbtn-why:empty{display:none}
.tfoot{margin-top:20px;display:flex;align-items:center;gap:10px;font-size:11px;opacity:.45;letter-spacing:1px}
.tacct{margin-top:14px;display:flex;align-items:center;gap:9px;font-size:12px;padding:8px 14px;border-radius:9px;
  background:rgba(8,13,18,.7);border:1px solid rgba(224,185,95,.16)}
.tacct b{color:var(--gold-l);font-weight:normal}
.tacct .lk{color:var(--gold);cursor:pointer;text-decoration:underline;text-underline-offset:2px}

/* ---------------- generic full screen (collection / settings) ---------------- */
.screen{position:fixed;inset:0;z-index:155;display:none;flex-direction:column;background:rgba(4,7,10,.97)}
.screen.on{display:flex}
.screen .shead{display:flex;align-items:center;gap:14px;padding:11px 18px;flex:none;
  background:linear-gradient(180deg,rgba(10,15,20,.96),rgba(8,12,16,.72));border-bottom:1px solid var(--line)}
.screen .shead h2{margin:0;font-size:15px;letter-spacing:5px;font-weight:normal;
  background:linear-gradient(180deg,var(--gold-l),var(--gold) 50%,#a57d2c);-webkit-background-clip:text;background-clip:text;color:transparent}
.screen .shead .sp{margin-left:auto;display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.screen .sbody{flex:1 1 auto;min-height:0;overflow-y:auto;padding:16px 18px 26px}
.screen .sbody::-webkit-scrollbar{width:8px}
.screen .sbody::-webkit-scrollbar-thumb{background:#3a4b57;border-radius:4px}

/* ---------------- rarity ----------------
   ONE palette, used by the collection border, the filter chips, the tally and
   the inspector. Rarity in WINGED says who you are looking at, never how strong
   the card is — Common is the land, Uncommon is an animal, Rare is somebody.
   The ladder, the per-card reasoning and the measurements live at the top of
   menu.js.

   Every rung carries a SHAPE as well as a colour (● ◆ ★ ✦ ✹) and a letter
   (C U R FA SR), for the same reason the board carries redundant shape cues
   further down this file: colour alone is not an accessible cue. */
:root{
  --r-common:#8d9aa5;   --r-common-d:#39434c;
  --r-uncommon:#dfeaf2; --r-uncommon-d:#5d6f7d;
  --r-rare:#f2cd6e;     --r-rare-d:#8a6a25;
  --r-fullart:#d29bf5;  --r-fullart-d:#5b2c78;
  --r-secret:#ffe9a8;   --r-secret-d:#7a5a12;
}
.r-common{--rc:var(--r-common);--rcd:var(--r-common-d)}
.r-uncommon{--rc:var(--r-uncommon);--rcd:var(--r-uncommon-d)}
.r-rare{--rc:var(--r-rare);--rcd:var(--r-rare-d)}
.r-fullart{--rc:var(--r-fullart);--rcd:var(--r-fullart-d)}
.r-secret{--rc:var(--r-secret);--rcd:var(--r-secret-d)}
.ccount .ctal span,.chip.rchip{color:var(--rc)}

/* ---------------- collection ---------------- */
.cfilters{display:flex;gap:7px;flex-wrap:wrap;align-items:center;margin-bottom:14px}
.chip{padding:5px 12px;border-radius:20px;font-size:11.5px;letter-spacing:.6px;cursor:pointer;
  background:rgba(20,30,38,.85);border:1px solid rgba(224,185,95,.2);color:var(--cream);transition:.13s}
.chip:hover{border-color:var(--gold)}
.chip.on{background:linear-gradient(180deg,var(--gold-l),var(--gold));color:#241a05;font-weight:bold;border-color:var(--gold-l)}
.chip.rchip{border-color:color-mix(in srgb,var(--rc) 45%,transparent)}
.chip.rchip:hover{border-color:var(--rc)}
.chip.rchip.on{background:linear-gradient(180deg,var(--rc),var(--rcd));color:#0b1016;border-color:var(--rc);text-shadow:0 1px 0 rgba(255,255,255,.25)}
.ccount{margin-left:auto;font-size:11.5px;opacity:.62;display:flex;align-items:center;gap:10px}
.ccount .ctal{display:flex;gap:9px;font-size:11.5px;letter-spacing:.4px}
.cgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(132px,1fr));gap:13px}

/* ---------------- rarity legend ----------------
   Michael: "I dont get the rarrity (C, R, U in the grid) somehow it makes no
   sence." He was right twice over. The ladder was never stated anywhere a
   player could read it — and the rule it stated was "how much of the set's
   identity the image carries", a judgement invisible from outside the source
   file, which no player could derive, predict or check.

   Both halves are now fixed. The rungs were re-derived onto a rule a player can
   apply to a card they have never seen (menu.js has the argument and the
   numbers), and this prints it. The one sentence — "Common is the land,
   Uncommon is an animal, Rare is somebody" — sits in the TOGGLE, so it is read
   even when the panel is folded, which is its default on a phone. The body
   splits the ladder by its TWO AXES, because "C U R" and "FA SR" being
   independent scales rather than one five-step ladder is the part that makes
   the whole thing click. Collapsible, and it remembers. */
.rlegend{margin:0 0 15px;border-radius:11px;overflow:hidden;
  background:linear-gradient(180deg,rgba(16,24,32,.85),rgba(10,16,22,.72));
  border:1px solid rgba(224,185,95,.16)}
.rltoggle{display:flex;align-items:center;gap:9px;width:100%;padding:9px 13px;cursor:pointer;
  font-family:inherit;font-size:12px;letter-spacing:1.1px;color:var(--gold-l);text-align:left;
  background:none;border:0}
.rltoggle:hover{background:rgba(224,185,95,.06)}
/* The whole ladder in one sentence, and it lives in the toggle so it is on
   screen even when the legend is folded — which is the default on a phone.
   Set larger than the surrounding chrome: if a player reads one line on this
   screen, this is the line it has to be. */
.rltoggle .rlrule{font-size:14.5px;letter-spacing:.2px;line-height:1.35;text-align:left;
  color:var(--gold-l);padding:2px 0}
@media (max-width:760px){ .rltoggle .rlrule{font-size:12.5px} }
.rltoggle .rlq{font-style:normal;width:16px;height:16px;border-radius:50%;flex:none;display:grid;place-items:center;
  font-size:11px;font-weight:bold;background:linear-gradient(180deg,var(--gold-l),var(--gold));color:#241a05}
.rltoggle .rlchev{margin-left:auto;font-style:normal;opacity:.6;transition:transform .16s}
.rlegend.shut .rltoggle .rlchev{transform:rotate(-90deg)}
.rlegend.shut .rlbody{display:none}
.rlbody{padding:2px 13px 13px;display:flex;flex-wrap:wrap;gap:13px 26px}
.rlnote{flex:1 0 100%;margin:0 0 2px;font-size:11.5px;line-height:1.55;opacity:.74}
.rlnote b{color:var(--gold-l);font-weight:normal}
.rlcol{flex:1 1 250px;min-width:0}
.rlcol h4{margin:0 0 7px;font-size:10px;letter-spacing:2px;text-transform:uppercase;
  font-weight:normal;color:var(--gold-l);opacity:.85}
.rlcol h4 span{display:block;margin-top:3px;letter-spacing:.3px;text-transform:none;
  font-size:10.5px;opacity:.6;color:var(--cream)}
.rlcol ul{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:6px}
.rlcol li{display:grid;grid-template-columns:14px 22px minmax(62px,auto) 1fr;align-items:baseline;gap:8px;font-size:11.5px}
.rlcol .rlmark{font-style:normal;color:var(--rc);text-align:center}
.rlcol .rlshort{font-size:9.5px;font-weight:bold;text-align:center;border-radius:4px;padding:1px 0;color:#0b1016;
  background:linear-gradient(180deg,var(--rc),var(--rcd));text-shadow:0 1px 0 rgba(255,255,255,.28)}
.rlcol .rlname{color:var(--rc)}
.rlcol .rlblurb{opacity:.62;line-height:1.45}
@media (max-width:760px){
  .rlcol li{grid-template-columns:14px 22px 1fr;row-gap:1px}
  .rlcol .rlblurb{grid-column:3/-1}
}

/* The border IS the rarity — same job the printed keyline does. Kind moved to
   the small tag below, because a collection screen exists to show rarity. */
.ccard{position:relative;cursor:pointer;border-radius:10px;overflow:hidden;transition:transform .15s,box-shadow .15s;
  background:linear-gradient(160deg,var(--rcd),var(--rc) 34%,#ffffff 50%,var(--rc) 62%,var(--rcd));padding:2.5px;
  box-shadow:0 5px 16px rgba(0,0,0,.7)}
.ccard.r-common{background:linear-gradient(160deg,#333c45,#7d8b96 40%,#aab6c0 50%,#69757f 60%,#2c343c)}
.ccard:hover{transform:translateY(-5px) scale(1.03);
  box-shadow:0 0 22px color-mix(in srgb,var(--rc) 45%,transparent),0 10px 24px rgba(0,0,0,.8)}
.ccard .ci{border-radius:8px;overflow:hidden;background:#0e151b}

/* rarity stamp, top-right: mark + letter, so it reads without colour */
.ccard .crar{position:absolute;top:-4px;right:-4px;z-index:4;display:flex;align-items:center;gap:3px;
  padding:2px 7px 2px 5px;border-radius:0 9px 0 10px;font-size:9.5px;font-weight:bold;letter-spacing:.6px;
  background:linear-gradient(180deg,var(--rc),var(--rcd));color:#0b1016;text-shadow:0 1px 0 rgba(255,255,255,.3);
  box-shadow:0 2px 7px rgba(0,0,0,.85)}
.ccard .crar i{font-style:normal;font-size:8.5px;line-height:1}
/* The chase tag: this card ALSO exists as a Full Art / Secret Rare.
   It rides the TOP of the art, inset past the cost bubble on the left and the
   rarity stamp on the right. It started at the bottom and collided with the
   Wings/Roots chips — on Loam Digger and Thunder Falcon the ribbon sat right
   through them and neither was readable. */
.ccard .cprem{position:absolute;left:25px;right:33px;top:3px;z-index:4;text-align:center;
  font-size:8px;font-weight:bold;letter-spacing:.5px;padding:2px 0;border-radius:3px;color:#150b20;
  background:linear-gradient(90deg,transparent,var(--r-fullart) 22%,#fff 50%,var(--r-fullart) 78%,transparent);
  text-shadow:0 1px 0 rgba(255,255,255,.4);white-space:nowrap;overflow:hidden}
.ccard .cprem.p-secret{color:#1d1406;
  background:linear-gradient(90deg,transparent,var(--r-secret) 18%,#fff 50%,var(--r-secret) 82%,transparent)}
.ccard.has-secret{box-shadow:0 0 18px rgba(255,233,168,.34),0 5px 16px rgba(0,0,0,.7)}
/* A travelling sheen so a chase card catches the eye while scrolling.
   Calibrated three times before anyone measured it, and all three calibrations
   were beside the point, because the band was never moving at all.

   WHY THIS IS A TRANSFORM AND NOT A BACKGROUND — the actual bug, measured.
   The sheen used to be a gradient inside a background 300% of the tile wide,
   slid with `background-position`. The shared rule set `background-size:300%
   100%`; the two per-tier rules under it then set `background:` — the
   SHORTHAND — which silently resets every background longhand it does not
   mention, `background-size` included, back to `auto`. For a linear-gradient
   `auto` means "exactly the element's size", and a percentage
   background-position resolves to (containerWidth − imageWidth) × pct, i.e.
   0 × pct = 0px at EVERY percentage. Measured on build 0.9.14: driving the
   animation by hand moved the computed position 190% → 50% → −90% while the
   painted pixels stayed byte-identical. The band was nailed to the tile. That
   is precisely what Michael kept reporting as a static shimmer, and it was
   never his eyes.

   The same shorthand reset had killed `.fafoil.fa-lite::after` further down,
   which is why Full Art never shimmered anywhere. The Secret Rare detail foil
   survived for one accidental reason: it re-declares `background-size` AFTER
   its shorthand, in the same rule.

   A bar moved with `translateX` cannot fail that way — there is no shorthand
   that can reset a transform — and it rides the compositor instead of
   repainting every chase tile on every frame. The geometry is shared with the
   detail-view sheen below, so there is now ONE sheen mechanism in this file.

   A glint reads as a glint when it is roughly a sixth of the tile wide and
   there are frames with no band at all, so the bar is 26% of the tile with a
   soft-edged core and travels clear off both edges. Bright in the middle,
   tinted at the edges — pure white looks like a rendering artefact, a
   warm-to-cool shift looks like light on foil. */
.ccard.has-secret::after,.ccard.has-fullart::after,#cardview .fasheen{
  content:"";position:absolute;top:-6%;bottom:-6%;left:0;width:26%;
  pointer-events:none;transform:translateX(-200%) skewX(-16deg);
  will-change:transform;animation:rsheen 2s linear infinite}
.ccard.has-secret::after,.ccard.has-fullart::after{z-index:5}
.ccard.has-secret::after{
  background:linear-gradient(90deg,transparent,
    color-mix(in srgb,var(--r-secret) 62%,transparent) 30%,rgba(255,255,255,.72) 50%,
    color-mix(in srgb,#9fd8ff 58%,transparent) 70%,transparent)}
/* Full Art gets the same language one rung quieter, so the two chase tiers are
   distinguishable at a glance instead of only by their ribbon. */
.ccard.has-fullart::after{animation-duration:2.4s;
  background:linear-gradient(90deg,transparent,
    color-mix(in srgb,var(--r-fullart) 60%,transparent) 30%,rgba(255,255,255,.5) 50%,
    color-mix(in srgb,var(--r-fullart) 60%,transparent) 70%,transparent)}
/* Reduce motion is already a setting; honour it here rather than inventing one.
   The bar is parked mid-tile — at its start position it sits off the edge, so
   `animation:none` alone would have hidden the treatment entirely. */
.ccard.still::after{animation:none;transform:translateX(145%) skewX(-16deg);opacity:.5}
@keyframes rsheen{from{transform:translateX(-200%) skewX(-16deg)}
                  to{transform:translateX(490%) skewX(-16deg)}}
/* 38% down, not centred — see the note on `.being .art` in index.html.
   Same anchor as the print renderer, so a card looks the same on the table
   and on screen. */
.ccard .cart{display:block;width:100%;height:104px;object-fit:cover;object-position:center 38%;background:#0e151b}
/* The name plate keeps the KIND colour — gold Being, blue Gale, green Guard —
   now that the border has been handed over to rarity. */
.ccard .cnm{font-size:10px;text-align:center;padding:5px 6px;line-height:1.2;min-height:28px;display:flex;align-items:center;justify-content:center;
  background:linear-gradient(180deg,#4a3a17,#241b09);color:var(--gold-l);text-shadow:0 1px 2px #000}
.ccard.gale .cnm{background:linear-gradient(180deg,#24384a,#111c26)}
.ccard.gd .cnm{background:linear-gradient(180deg,#1f4227,#0e2213)}
.ccard .cco{position:absolute;top:-5px;left:-5px;width:29px;height:29px;display:grid;place-items:center;z-index:3;
  background:radial-gradient(circle at 36% 28%,#d5f4ff,#39a9e0 52%,#11445f);border-radius:50%;
  font-size:13.5px;font-weight:bold;color:#fff;text-shadow:0 1px 2px #000;box-shadow:0 2px 7px rgba(0,0,0,.85)}
.ccard .cst{position:absolute;right:4px;bottom:32px;display:flex;gap:3px;z-index:3}
.ccard .cst span{font-size:10px;font-weight:bold;padding:1px 5px;border-radius:7px;box-shadow:0 2px 5px rgba(0,0,0,.8)}
.ccard .cst .w{background:linear-gradient(180deg,#bfe3f8,#3f7fa5);color:#06222f}
.ccard .cst .r{background:linear-gradient(180deg,#d8edb5,#4d7a2c);color:#0f2408}

/* ---------------- card detail (also the touch inspector) ---------------- */
#cardview{position:fixed;inset:0;z-index:170;display:none;align-items:center;justify-content:center;padding:20px;
  background:rgba(3,5,8,.9);backdrop-filter:blur(5px)}
#cardview.on{display:flex}
#cardview .cv{width:min(330px,92vw);border-radius:15px;padding:3px;position:relative;
  background:linear-gradient(160deg,var(--rcd),var(--rc) 34%,#ffffff 50%,var(--rc) 62%,var(--rcd));
  box-shadow:0 26px 70px rgba(0,0,0,.9);animation:cvin .2s cubic-bezier(.2,1.3,.5,1)}
#cardview .cv.r-common{background:linear-gradient(160deg,#333c45,#7d8b96 40%,#aab6c0 50%,#69757f 60%,#2c343c)}
@keyframes cvin{0%{opacity:0;transform:scale(.9) translateY(14px)}100%{opacity:1;transform:none}}
#cardview .cvi{border-radius:12px;overflow:hidden;background:#0e151b}
#cardview .cvart{height:min(248px,34vh);background:#0e151b center 38%/cover no-repeat}
#cardview .cvband{background:linear-gradient(180deg,#4a3a17,#241b09);border-top:1px solid rgba(240,225,180,.4);
  padding:9px 12px;text-align:center;font-size:16px;color:var(--gold-l);text-shadow:0 1px 3px #000}
/* Kind still tints the name band, matching the collection tile, now that the
   border round the whole card has been handed over to rarity. */
#cardview .cv.gale .cvband{background:linear-gradient(180deg,#24384a,#111c26)}
#cardview .cv.gd .cvband{background:linear-gradient(180deg,#1f4227,#0e2213)}
#cardview .cvtype{font-size:9.5px;letter-spacing:2.5px;opacity:.55;margin-top:2px}
#cardview .cvtx{padding:12px 15px 15px;font-size:13px;line-height:1.6;text-align:center;min-height:56px}
#cardview .cvkw{display:flex;gap:6px;justify-content:center;flex-wrap:wrap;padding:0 12px 12px}
#cardview .cvkw span{font-size:10px;letter-spacing:1px;padding:2px 9px;border-radius:9px;
  background:linear-gradient(180deg,var(--gold-l),var(--gold));color:#241a05;font-weight:bold}
#cardview .cvcost{position:absolute;top:-13px;left:-13px;width:46px;height:46px;display:grid;place-items:center;z-index:3;
  background:radial-gradient(circle at 36% 28%,#d5f4ff,#39a9e0 52%,#11445f);border-radius:50%;
  font-size:21px;font-weight:bold;color:#fff;text-shadow:0 2px 3px #000;box-shadow:0 4px 12px rgba(0,0,0,.9)}
#cardview .cvpair{display:flex;justify-content:center;gap:16px;padding:0 0 14px}
#cardview .cvpair div{text-align:center}
#cardview .cvpair b{display:block;font-size:24px;line-height:1.1}
#cardview .cvpair i{font-style:normal;font-size:9.5px;letter-spacing:2px;opacity:.6}
#cardview .cvpair .w b{color:#9fd4f2}
#cardview .cvpair .r b{color:#c3e08f}
#cardview .cvclose{position:absolute;top:-13px;right:-13px;width:34px;height:34px;border-radius:50%;cursor:pointer;
  display:grid;place-items:center;font-size:17px;z-index:6;color:var(--cream);
  background:linear-gradient(180deg,#2f3f4b,#161f27);border:1px solid rgba(224,185,95,.4);box-shadow:0 4px 12px rgba(0,0,0,.9)}

/* --- rarity row on the standard printing --- */
#cardview .cvrar{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:8px 13px 4px}
#cardview .rpill{display:inline-flex;align-items:center;gap:5px;font-size:10px;font-weight:bold;letter-spacing:1.3px;
  text-transform:uppercase;padding:3px 10px;border-radius:11px;color:#0b1016;
  background:linear-gradient(180deg,var(--rc),var(--rcd));text-shadow:0 1px 0 rgba(255,255,255,.28)}
#cardview .rpill .rgem{width:9px;height:9px;transform:rotate(45deg);border-radius:1px;
  background:linear-gradient(135deg,#fff,var(--rcd));box-shadow:0 0 4px rgba(0,0,0,.5)}
#cardview .cvnum{font-size:9.5px;letter-spacing:1.6px;opacity:.62;font-variant-numeric:tabular-nums}
#cardview .cvnum em{font-style:normal;margin-left:7px;color:var(--rc);opacity:.95;font-weight:bold}

/* --- the swap button: a chase card you have to ASK to see ---
   The button and its note hang below the card, so the centring container has
   to be told they exist — otherwise the note falls off the bottom edge, which
   it did at 844 × 420 (a phone held landscape). */
#cardview .cv.has-swap{margin-bottom:88px}
#cardview .faswap{position:absolute;left:0;right:0;bottom:-46px;margin:0 auto;width:max-content;cursor:pointer;
  font-family:inherit;font-size:12px;letter-spacing:1.6px;padding:8px 18px;border-radius:10px;color:#241a05;
  background:linear-gradient(180deg,#fbeec2,var(--gold) 46%,#9b7327);border:1px solid var(--gold-l);
  box-shadow:0 6px 18px rgba(0,0,0,.75);transition:transform .13s,box-shadow .13s}
#cardview .faswap:hover{transform:translateY(-2px);box-shadow:0 0 20px rgba(224,185,95,.45),0 6px 18px rgba(0,0,0,.75)}
#cardview .fanote{position:absolute;left:-30px;right:-30px;bottom:-72px;text-align:center;
  font-size:10.5px;letter-spacing:.6px;opacity:.5;color:var(--cream)}

/* --- FULL ART: the frame gets out of the way ----------------------------
   Deliberately the same content in the same order as the standard printing —
   name, type, collector row, keywords, text, stats — because a Full Art is the
   SAME CARD and must not send anyone hunting for a number in a new place. What
   changes is that the art runs to all four edges of the panel and everything
   floats on top of it. This is print/make-cards.py's render_premium() on
   screen; the two were built to match. */
/* The premium card is a fixed 63.5:88.9 rectangle, so unlike the standard
   view — whose art panel is capped at 34vh and shrinks — its height follows
   its width. `54vh` is that ratio worked backwards (0.714 × 1.4 ≈ 1), and it
   is what keeps the card on screen in landscape on a phone. */
#cardview .cv.prem{padding:2px;width:min(330px,92vw,54vh);
  background:linear-gradient(160deg,var(--rcd),var(--rc) 40%,#fff 50%,var(--rc) 60%,var(--rcd))}
/* The panel is its own container, and every text size below is expressed in
   `cqw` — a share of the CARD's width, not the viewport's. The card can be
   capped by 54vh (see above), and when it is, viewport-based type does not
   follow it down: measured at a 374 × 367 viewport the card came out 198 px
   wide and the collector row wrapped "SECRET RARE" onto a second line while
   the name still rendered at its full 23 px. The px value on each rule is the
   fallback for anything without container query units. */
#cardview .cv.prem .cvi.fai{position:relative;border-radius:13px;overflow:hidden;background:#0b1016;
  aspect-ratio:63.5/88.9;container-type:inline-size}
/* The copy count on a collection tile. Two characters that say "you may play
   one of these"; it can never read ×3, because MAX_COPIES is 2 and there is no
   third slot to grant one into. */
#collection .ccard .ccop{position:absolute;left:4px;bottom:30px;z-index:2;
  font:600 11px/1 ui-monospace,SFMono-Regular,Menlo,monospace;letter-spacing:.02em;
  color:#dfe8f2;background:rgba(8,12,18,.78);border:1px solid rgba(190,210,235,.25);
  border-radius:5px;padding:2px 4px}
#collection .ccard.unowned .ccop{display:none}
#cardview .faart{position:absolute;inset:0;background:#0b1016 center 42%/cover no-repeat}
/* the scrim is what replaces the frame's job of separating art from text */
#cardview .fascrim{position:absolute;inset:0;
  background:radial-gradient(ellipse at 50% 34%,transparent 34%,rgba(2,5,9,.66) 100%),
             linear-gradient(180deg,rgba(3,6,10,.5) 0%,transparent 22%,transparent 40%,rgba(3,6,10,.82) 62%,rgba(2,4,7,.96) 100%)}
#cardview .fabody{position:absolute;left:0;right:0;bottom:0;padding:0 4cqw 4cqw;text-align:center;z-index:3}
#cardview .faname{font-size:23px;font-size:clamp(14px,7.2cqw,25px);line-height:1.15;color:#fdf3d8;
  text-shadow:0 2px 5px #000,0 0 22px rgba(0,0,0,.9)}
#cardview .cv.prem .cvtype{font-size:9.5px;font-size:clamp(7px,2.9cqw,10px);letter-spacing:.28em;
  opacity:.72;margin-top:3px;text-shadow:0 1px 3px #000}
#cardview .cv.prem .cvnum{margin-top:5px;opacity:.82;text-shadow:0 1px 3px #000;white-space:nowrap;
  font-size:9.5px;font-size:clamp(6.5px,2.85cqw,9.5px);letter-spacing:.13em}
#cardview .cv.prem .cvnum em{margin-left:.6em}
#cardview .cv.prem .cvkw{padding:3cqw 0 0}
#cardview .cv.prem .cvtx{padding:3cqw 1cqw 1cqw;min-height:0;text-shadow:0 1px 4px #000;
  font-size:13px;font-size:clamp(9px,3.9cqw,13px)}
#cardview .cv.prem .cvpair{padding:2.5cqw 0 0}
#cardview .cv.prem .cvpair b{text-shadow:0 2px 5px #000;font-size:24px;font-size:clamp(15px,7.3cqw,24px)}
#cardview .cv.prem .cvpair i{font-size:9.5px;font-size:clamp(6.5px,2.85cqw,9.5px);white-space:nowrap;letter-spacing:.18em}

/* --- SECRET RARE: above Full Art. Prismatic foil + a slow drifting glint,
   which is the closest a screen gets to tilting a foil card under a lamp. */
#cardview .cv.r-secret.prem{box-shadow:0 0 46px rgba(255,225,150,.36),0 26px 70px rgba(0,0,0,.95)}
/* `screen` at .4 was wrong for the same reason the print foil was wrong: it
   lightens EVERYTHING, and the Crest Watcher owl came out flat green. `overlay`
   keeps the painting's own light and dark and pushes colour through it, which
   is what foil actually does. */
/* TIMING IS THE WHOLE THING HERE, and the first version got it wrong. The hue
   layer drifted its background-position over 9s with ease-in-out, which spends
   most of the cycle nearly stationary — Michael reported the card as simply not
   shimmering, and he was right: at that speed it reads as a coloured overlay,
   not as light moving. Foil reads as foil when a bright band CROSSES the card
   at a speed the eye can follow: linear, never eased.

   Corrected once more after Michael called the whole card sluggish, and the
   culprit was the hue wash, not the band. `alternate` means the 5s was really a
   10s round trip, and a wash that takes ten seconds to cross does not read as
   slow motion — it reads as a stationary tint. Halved to 3.2s (6.4s round trip),
   which is about the tempo of turning a card in your hand. The band came down
   with it, to 1.8s, so a glint is a glint and not a searchlight. */
#cardview .fafoil{position:absolute;inset:0;z-index:2;pointer-events:none;
  mix-blend-mode:overlay;opacity:.68;
  background:linear-gradient(115deg,#ff5f8f,#ffd76a 16%,#7dffb0 33%,#5fd0ff 50%,#a98cff 66%,#ff7ad9 83%,#ff5f8f);
  background-size:260% 260%;animation:rfoil 3.2s linear infinite alternate}
/* The specular sweep — the bit that reads as tilting the card under a lamp.
   IT IS A SIBLING OF .fafoil, NOT ITS CHILD, and that is deliberate. It used
   to be `.fafoil::after`, which put it inside a group that is composited at
   `mix-blend-mode:overlay` and — on Full Art — `opacity:.3`. Overlay against a
   dark painting is very nearly a no-op: overlay(0.15, 0.96) = 0.29, then 30%
   of the way from 0.15 to that is 0.19, a ~4% luminance lift on a card that is
   mostly forest shadow. Michael reported the Full Art foil as invisible and it
   effectively was. Blended `screen` straight onto the art it survives on dark
   and light alike, which is what a specular highlight does in the world.
   Geometry and keyframes are shared with the collection tile above. */
/* AND IT MUST NOT EAT THE RAINBOW. Moving the sweep out of the overlay group
   fixed its visibility and immediately cost something else, which is what
   Michael meant by "the gradient was nicer when it only worked on the Secret
   Rare" — the rainbow never changed, the thing sitting on top of it did.
   `screen` at .6 white is a desaturator: screen(c,.6) floors every channel at
   .6, so wherever the bar sits the prismatic layer's separation collapses
   toward white, and .16 flanks spanning 44% of the bar meant it sat over much of
   the card much of the time. Peak down to .34, flanks to .05, bright core pulled
   in to 40%–60%: the highlight still reads on dark art, the colour under it
   stays colour. */
#cardview .fasheen{z-index:3;mix-blend-mode:screen;animation-duration:1.8s;
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.05) 28%,
    rgba(255,255,255,.16) 40%,rgba(255,255,255,.34) 50%,rgba(255,255,255,.16) 60%,
    rgba(255,255,255,.05) 72%,transparent)}
/* Three layers at coprime sizes. Two layers at 74/43 px drew a visible
   rectangular lattice on the first proof — it read as a texture bug, not glitter. */
#cardview .fastars{position:absolute;inset:0;z-index:2;pointer-events:none;
  background-image:radial-gradient(circle,#fff 0 .9px,transparent 1.4px),
                   radial-gradient(circle,#fff 0 .7px,transparent 1.2px),
                   radial-gradient(circle,#fff 0 1.2px,transparent 1.7px);
  background-size:97px 89px,61px 67px,143px 131px;
  background-position:11px 7px,38px 41px,73px 96px;
  animation:rtwinkle 2.4s ease-in-out infinite alternate}
@keyframes rfoil{0%{background-position:0% 50%}100%{background-position:100% 50%}}
@keyframes rtwinkle{0%{opacity:.3}100%{opacity:.72}}
/* Full Art gets the foil too — Michael asked for it, and he is right: a Full
   Art card with no light on it is just a big picture. One rung quieter than
   Secret: the hue wash is dialled back and there is no sparkle scatter, so the
   two treatments still read as different objects rather than the same effect.
   The SHEEN, though, is the part that has to be plainly visible on both — it is
   the whole reason Michael asked — so it is only slightly softer, not hidden. */
#cardview .fafoil.fa-lite{opacity:.38}
   Its peak comes down with Secret's but not as far — .36, against a hue wash of
   only .38 there is far less colour for the bar to bleach, and this is the tier
   where the sheen going quiet once already read as "no foil at all". */
#cardview .fasheen.fa-lite{animation-duration:2.2s;
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.05) 28%,
    rgba(255,255,255,.17) 40%,rgba(255,255,255,.36) 50%,rgba(255,255,255,.17) 60%,
    rgba(255,255,255,.05) 72%,transparent)}
#cardview .cv.still .fafoil,#cardview .cv.still .fastars{animation:none}
#cardview .cv.still .fasheen{animation:none;transform:translateX(145%) skewX(-16deg);opacity:.5}

/* ---------------- settings ---------------- */
.setgrid{display:flex;flex-direction:column;gap:16px;max-width:520px}
.setrow{display:flex;align-items:center;gap:14px;padding:12px 15px;border-radius:10px;
  background:rgba(14,21,28,.8);border:1px solid rgba(224,185,95,.14)}
.setrow .lab{flex:1;min-width:0}
.setrow .lab b{display:block;font-size:13.5px;color:var(--gold-l);font-weight:normal}
.setrow .lab span{display:block;font-size:11px;opacity:.6;margin-top:2px;line-height:1.4}
.setrow input[type=range]{width:130px;accent-color:var(--gold)}
.setrow select{min-width:118px}
.swi{position:relative;width:46px;height:25px;border-radius:14px;cursor:pointer;flex:none;
  background:#1b2831;border:1px solid rgba(224,185,95,.25);transition:.16s}
.swi::after{content:"";position:absolute;top:2px;left:2px;width:19px;height:19px;border-radius:50%;
  background:linear-gradient(180deg,#8c9aa4,#5a6870);transition:.16s}
.swi.on{background:linear-gradient(180deg,var(--gold),#9b7327);border-color:var(--gold-l)}
.swi.on::after{left:23px;background:linear-gradient(180deg,#fff8e2,var(--gold-l))}

/* ---------------- colour-blind cues ----------------
   The board codes everything by colour: green = you can act, red = you can
   attack it. These add a redundant SHAPE so the information survives without
   colour vision. Always on — they read as rank pips, not as an aid. */
.being.able::before,.being.target::before{position:absolute;top:-7px;left:-6px;z-index:6;
  width:17px;height:17px;border-radius:50%;display:grid;place-items:center;
  font-size:10px;font-weight:bold;line-height:1;box-shadow:0 2px 6px rgba(0,0,0,.9)}
.being.able::before{content:"▲";background:linear-gradient(180deg,#8ce087,#2f7a2c);color:#04240a}
.being.target::before{content:"✕";background:linear-gradient(180deg,#f0776a,#8e2b20);color:#fff}
.hero.target .hitchip::before{content:"✕ ";}
.card.playable .plate::after{content:"▲";position:absolute;top:-6px;right:-6px;z-index:5;
  width:17px;height:17px;border-radius:50%;display:grid;place-items:center;font-size:10px;font-weight:bold;
  background:linear-gradient(180deg,#8ce087,#2f7a2c);color:#04240a;box-shadow:0 2px 6px rgba(0,0,0,.9)}

/* ---------------- versus / match intro ---------------- */
#versus{position:fixed;inset:0;z-index:160;display:none;align-items:center;justify-content:center;
  background:rgba(3,5,8,.93);backdrop-filter:blur(3px)}
#versus.on{display:flex}
#versus .vrow{display:flex;align-items:center;gap:clamp(18px,6vw,64px);animation:vin .45s ease}
@keyframes vin{0%{opacity:0}100%{opacity:1}}
#versus .vside{display:flex;flex-direction:column;align-items:center;gap:9px;width:clamp(110px,26vw,190px)}
#versus .vside.a{animation:vleft .55s cubic-bezier(.2,1.2,.4,1)}
#versus .vside.b{animation:vright .55s cubic-bezier(.2,1.2,.4,1)}
@keyframes vleft{0%{transform:translateX(-60px);opacity:0}100%{transform:none;opacity:1}}
@keyframes vright{0%{transform:translateX(60px);opacity:0}100%{transform:none;opacity:1}}
#versus .vpor{width:clamp(92px,20vw,142px);height:clamp(92px,20vw,142px);border-radius:50%;
  background:#16222c center/cover no-repeat;
  box-shadow:0 0 0 3px var(--gold-d),0 0 0 6px rgba(0,0,0,.6),0 12px 36px rgba(0,0,0,.9)}
#versus .vside.you .vpor{box-shadow:0 0 0 3px var(--you),0 0 0 6px rgba(0,0,0,.6),0 0 40px rgba(95,182,212,.4),0 12px 36px rgba(0,0,0,.9)}
#versus .vside.them .vpor{box-shadow:0 0 0 3px var(--them),0 0 0 6px rgba(0,0,0,.6),0 0 40px rgba(212,112,95,.4),0 12px 36px rgba(0,0,0,.9)}
#versus .vnm{font-size:clamp(12px,1.7vw,15px);color:var(--gold-l);text-align:center;line-height:1.3}
#versus .vfac{font-size:10px;letter-spacing:2.5px;opacity:.55}
#versus .vs{font-size:clamp(26px,5vw,44px);letter-spacing:5px;
  background:linear-gradient(180deg,var(--gold-l),var(--gold) 50%,#8a6a25);-webkit-background-clip:text;background-clip:text;color:transparent;
  filter:drop-shadow(0 3px 12px rgba(0,0,0,.9));animation:vspop .6s cubic-bezier(.2,1.5,.4,1)}
@keyframes vspop{0%{transform:scale(2.4);opacity:0}60%{transform:scale(.92)}100%{transform:none;opacity:1}}
#versus .vflip{position:absolute;bottom:12%;left:0;right:0;text-align:center;font-size:13px;opacity:0;
  color:var(--gold-l);letter-spacing:1.5px;animation:vfade .4s ease .75s forwards}
@keyframes vfade{to{opacity:.92}}

@media (max-width:760px){
  .cgrid{grid-template-columns:repeat(auto-fill,minmax(108px,1fr));gap:10px}
  .ccard .cart{height:84px}
  /* 108 px tile minus the cost bubble and the rarity stamp leaves ~50 px */
  .ccard .cprem{left:22px;right:29px;font-size:7px;letter-spacing:0}
  /* the premium card needs no breakpoint — its type is sized in `cqw` */
  .screen .sbody{padding:12px 12px 22px}
  .screen .shead{padding:9px 12px;gap:9px}
  .screen .shead h2{font-size:13px;letter-spacing:3px}
  .tbtn{padding:12px 15px;font-size:14px}
  .tbtn.primary{padding:14px 15px;font-size:15.5px}
}

/* Keyboard focus was completely invisible across the shell. */
.tbtn:focus-visible,.chip:focus-visible,.ccard:focus-visible,button:focus-visible,
select:focus-visible,input:focus-visible,.swi:focus-visible{
  outline:3px solid var(--gold);outline-offset:2px;border-radius:8px}
@media (max-width:760px){.ccard .cart{height:84px}}

/* ---- a card you do not own yet -------------------------------------------
   GREY, PRESENT, COUNTABLE — never absent and never a padlock.
   Absent is fatal: you cannot want what is not on screen, and a grid that
   changes size destroys spatial memory (Skyfall is in the same place every
   time, or it is a new screen every time). The padlock is already spoken for:
   this game uses it for ACCESS you do not have — the DECK and COLLECTION
   buttons while signed out, and Skyholds 2/3/4 on the campaign map. A card is
   not access; it is a thing you have or have not.
   Desaturation is the house style for exactly this: a card in hand you cannot
   afford is dimmed and labelled "needs 3 Breeze", present and obviously
   yours-later.

   TWO THINGS THIS DELIBERATELY DOES NOT DO, both measured after doing them:
   1. It does not use ::after. `.ccard.has-fullart::after` IS THE SHEEN — an
      element gets one ::after, so an overlay here silently fought the foil on
      exactly the 25 Full Art and 6 Secret Rare tiles that are the best reason
      to open this screen. The dim is an inset shadow on the frame instead.
   2. It does not position the route line absolutely. `.cnm` is in flow, so an
      absolutely-positioned strip at bottom:0 lands on top of the card's name:
      measured 2.4px on a framed tile and 17.4px on a Full Art one, on all 158
      unowned tiles. It sits in flow, and it is rendered EMPTY on owned tiles so
      every tile in the grid keeps the same height and the rows stay level. */
.ccard.unowned .cart{filter:grayscale(1) brightness(.55)}
.ccard.unowned{box-shadow:inset 0 0 0 999px rgba(9,13,19,.34)}
.ccard.unowned .cco,.ccard.unowned .cst{opacity:.5}
/* The route out. "A collection that shows you a card and not the way to get it
   is a taunt." — design/economy/OWNERSHIP-VERDICT-first-hour.md §4 */
.cget{min-height:13px;padding:1px 5px 2px;font-size:9px;line-height:1.25;
  text-align:center;letter-spacing:.2px;color:#9fb0c2}
.ccard.unowned .cget{color:#cdd8e4}
.cget b{color:#e9c96b;font-weight:600}
.ccount .cown{font-variant-numeric:tabular-nums;color:#e9c96b;opacity:.95}
