/* THE card-tile system (grid, flip, foil shine, captions) — ONE source.
   Consumed by BOTH the finelux.co generator (app/site.py inlines it at
   generate time) and the storefront home (linked directly). Editing here
   changes both — that is the point (no drifting twins). */
  /* Capped so a wide row holds 3 cards (then 2 centered below); wraps to 2 then
     1 as the viewport narrows. 1010px seats FOUR 210px cards + three 56px gaps
     (Chris, Sep 2: "max at four cards wide instead of just 3"). */
  .grid { display:flex; flex-wrap:wrap; justify-content:center; gap:52px 56px; max-width:1010px; margin:0 auto; }
  /* width, corner radius, aspect-ratio (--ar) and card-back logo (--ph) are set
     per-card inline. Real-world scale (Yu-Gi-Oh narrower/near-square, others round
     like Magic). The fixed --ar gives each card its real size instantly so the page
     never collapses or jumps while images load; a game card-back (logo watermark on
     a dark card) shows until the real image fades in on top. AR = the scan ratio, so
     object-fit:cover fills with no crop. The fixed-height .slot bottom-aligns cards
     on a common baseline so the captions below all line up. */
  a.card { max-width:100%; text-decoration:none; color:var(--txt); text-align:center; }
  .slot { height:296px; display:flex; align-items:flex-end; perspective:900px; }
  /* transparent perspective host for the flip. NOT preserve-3d — the flipper is the
     single 3D context so backface culling stays reliable; the cursor tilt still works
     because it renders in .slot's perspective. Dark back + placeholder live on faces. */
  .cardimg { position:relative; width:100%; aspect-ratio:var(--ar, .716); border-radius:12px;
    transition:transform .4s ease, box-shadow .3s ease;
    perspective:900px; box-shadow:0 18px 36px rgba(0,0,0,.55); will-change:transform; }
  .card:hover .cardimg { box-shadow:0 26px 50px rgba(0,0,0,.65); }
  /* flip layer: single-faced cards just hold the front; .dfc cards rotate to the back on hover */
  .flip3d { position:absolute; inset:0; z-index:1; border-radius:inherit; transform-style:preserve-3d;
    transition:transform .7s ease-in-out; }
  .card.dfc:hover .flip3d { transform:rotateY(180deg); }
  /* Reliable face-swap: flip which face is visible at the 90 deg midpoint (card is
     edge-on there, so the instant opacity swap is unseen). Independent of backface
     culling, which some browsers ignore once effects are stacked. */
  .card.dfc .face { transition:opacity 0s linear .35s; }
  .card.dfc .face.back { opacity:0; }
  .card.dfc:hover .face.front { opacity:0; }
  .card.dfc:hover .face.back { opacity:1; }
  /* each face is a flat, clipped, opaque plane holding its own back-colour, placeholder
     logo, image + sheen — so nothing shows through and the sheen can't intersect it */
  .face { position:absolute; inset:0; border-radius:inherit; background:#1c1a17;
    backface-visibility:hidden; -webkit-backface-visibility:hidden; }
  .face::before { content:''; position:absolute; inset:0; z-index:0; border-radius:inherit;
    background:var(--ph) center/70% auto no-repeat; opacity:.15; }
  .face.back { transform:rotateY(180deg); }
  .cimg { position:absolute; inset:0; z-index:1; width:100%; height:100%; object-fit:cover;
    display:block; border-radius:inherit; opacity:0; transition:opacity .4s ease; }
  .cimg.ld { opacity:1; }
  /* a sideways-printed card (Palworld) is rotated 90deg clockwise so it
     fills the portrait tile like every other card — width and height are
     swapped against the tile's aspect ratio, then spun about the centre
     (Chris, Sep 3) */
  .cimg.sideways { inset:auto; left:50%; top:50%;
    width:calc(100% / var(--ar, .716)); height:calc(100% * var(--ar, .716));
    transform:translate(-50%,-50%) rotate(90deg); }
  /* Foil-only sheen: a white glare at the cursor plus a holographic band that
     shifts as the pointer moves. Positions are driven by the script below. */
  .shine { position:absolute; inset:0; pointer-events:none; border-radius:inherit; z-index:2;
    opacity:0; transition:opacity .3s ease; mix-blend-mode:color-dodge;
    background:
      radial-gradient(circle at var(--mx,50%) var(--my,50%),
        rgba(255,255,255,.6) 0%, rgba(255,255,255,.14) 22%, rgba(255,255,255,0) 46%),
      linear-gradient(var(--ang,115deg), transparent 36%, rgba(255,228,170,.38) 46%,
        rgba(170,224,255,.32) 52%, rgba(255,170,228,.30) 58%, transparent 68%);
    background-size:100% 100%, 230% 230%;
    background-position:0 0, var(--lx,50%) var(--ly,50%); }
  /* half strength (Chris, 2026-10-17: "halve the opacity of the standard foil shine", for
     mana and step-and-compleat too, which are foil cards like any other) */
  .card.foilcard.loaded:hover .shine { opacity:.5; }
  /* GILDED FOIL (Chris, 2026-10-14, Sword of Wealth and Power BIG 064): a gold plane over
     the picture, masked to the card's gilding (--gm, a black-and-white mask from
     store/gild.py), so solid gold shows only there and catches the light as the card
     tilts. The highlight and the band follow the same cursor variables as the sheen.
     Hidden until the mask has loaded (.gl), so the picture shows meanwhile and a tile is
     never bare gold. */
  .gild { position:absolute; inset:0; z-index:2; border-radius:inherit; pointer-events:none;
    opacity:0; transition:opacity .4s ease;
    -webkit-mask-image:var(--gm); mask-image:var(--gm);
    -webkit-mask-size:100% 100%; mask-size:100% 100%;
    -webkit-mask-repeat:no-repeat; mask-repeat:no-repeat;
    /* mirror gold, matched to photos of the card (Oct 14): deep amber in shadow, a blazing
       pale-yellow band where the light hits, and a hot spot under the cursor */
    background:
      radial-gradient(circle at var(--mx,50%) var(--my,50%),
        rgba(255,255,255,.95) 0%, rgba(255,250,215,.55) 10%, rgba(255,255,255,0) 34%),
      linear-gradient(var(--ang,115deg), #6e4c0f 0%, #b8871d 14%, #f4cf3f 27%, #fff6c0 36%,
        #ffe27a 42%, #d9a627 52%, #8c6414 62%, #e9c24a 76%, #fff1b0 84%, #b8871d 92%,
        #6e4c0f 100%);
    background-size:100% 100%, 240% 240%;
    background-position:0 0, var(--lx,50%) var(--ly,50%); }
  .card.gilded.gl .gild { opacity:1; }
  /* FOIL OVERLAYS (Chris, 2026-10-17): a pattern across the whole card that only shows when
     the card is tilted into the light, and faintly even then. One plane; the picture comes
     from the tile's foil-<kind> class: "mana" is the Mana Foil's lattice of circled mana
     symbols cut from his artboard (white where the card shines: the field and the space
     inside each ring, the ring and glyph dull), "compleat" the Step-and-Compleat foil's
     Phyrexian symbols (his PNG, white where it shines), "chocobo" the Final Fantasy Chocobo
     Track foil's tracks (his PNG, the same way). --mf is the tilt script's 0..1 for
     how far into the band the pointer has tilted the card, and the plane never passes .16.
     Bump a picture's ?v= when its file changes: static files are cached a week. */
  .foilplane { position:absolute; inset:0; z-index:2; border-radius:inherit; pointer-events:none;
    opacity:0; transition:opacity .3s ease; mix-blend-mode:screen;
    background:center/100% 100% no-repeat; }
  .card.foil-mana .foilplane { background-image:url(foil/manafoil.svg?v=3); }
  .card.foil-compleat .foilplane { background-image:url(foil/stepandcompleat.png?v=1); }
  .card.foil-chocobo .foilplane { background-image:url(foil/chocobo.png?v=1); }
  /* while the pointer is on the card the plane tracks the tilt INSTANTLY: a transition here
     restarts on every mousemove and never climbs until the pointer stops (Chris, Oct 17:
     "not showing the new layer until you stop moving the mouse"); the fade is for leaving */
  .card.foil-mana.loaded:hover .foilplane, .card.foil-compleat.loaded:hover .foilplane {
    opacity:calc(var(--mf, 0) * .16); transition:none; }
  /* the chocobo tracks at twice the strength (Chris, Oct 17: "double the highest opacity") */
  .card.foil-chocobo.loaded:hover .foilplane {
    opacity:calc(var(--mf, 0) * .32); transition:none; }
  .card.foil-mana .shine, .card.foil-compleat .shine, .card.foil-chocobo .shine { z-index:3; }
  .card.gilded .shine { z-index:3; }
  /* on a gilded card the gold carries the shine: the foil sheen at half strength
     (Chris, 2026-10-14: "the non-gold shine was 50% less bright") */
  .card.gilded.foilcard.loaded:hover .shine { opacity:.5; }
  .cname { font-family:'Cormorant Garamond',serif; font-size:21px; margin-top:16px; }
  .ver { font-size:10px; letter-spacing:2px; text-transform:uppercase; color:var(--muted); margin-top:3px; }
  .foil { display:inline-block; margin-top:7px; font-size:9px; letter-spacing:2px; text-transform:uppercase;
    color:#1c160a; background:linear-gradient(180deg,#e6cf95,#c8a44f); padding:2px 9px; border-radius:10px; font-weight:600; }
  .set { font-family:'Cormorant Garamond',serif; font-style:italic; font-size:13px; color:var(--muted); margin-top:7px; }
  .price { font-family:'Cormorant Garamond',serif; font-size:26px; margin-top:8px; }
  .price sup { font-size:.55em; top:-.6em; }
  .empty { text-align:center; color:var(--muted); }
