/* ============================================================
   cards.css  -  how a card looks.

   A card is two boxes:
     .card       the outer box. It sets the size and is a "container".
     .card-face  the inner box you actually see.

   Everything inside is sized in "cqw" units (1% of the card's width),
   so the same design works big in the collection and small in your
   deck. To resize cards, just change the width.
   ============================================================ */

.card {
  font-family: var(--font); font-synthesis-weight: auto;   /* the page is pixel text; a card keeps its own type (its name and type are pixel) */
  --c1: #9aa2c8;          /* the card body (Normal type) */
  --c2: #565d84;          /* the frame */

  position: relative;
  width: var(--card-w, 100%);
  aspect-ratio: 5 / 7.4;
  container-type: inline-size;         /* lets children use cqw units */
  color: #fff;
  text-align: center;
  user-select: none;
  transition: transform 0.15s, filter 0.15s;
}
.card.type-fire   { --c1: #ff8f4d; --c2: #b8321a; }
.card.type-water  { --c1: #5cbcff; --c2: #1d58b8; }
.card.type-grass  { --c1: #72dc70; --c2: #257a38; }
.card.type-psychic { --c1: #d49aff; --c2: #7138a8; }
.card.type-electric { --c1: #ffe066; --c2: #b88a00; }
.card.type-ice { --c1: #a8ecff; --c2: #2a8cb8; }
.card.type-fighting { --c1: #f49a70; --c2: #a03420; }
.card.type-ground { --c1: #e8c878; --c2: #8a6430; }
.card.type-flying { --c1: #c8c0ff; --c2: #5a50b0; }
.card.type-dark { --c1: #a8907c; --c2: #3e2e26; }
/* status cards (enemies' junk) are a dull grey; an upgraded card's name is green, like StS's */
.card.status      { --c1: #8c8c94; --c2: #505058; }
.card.upgraded .card-name { color: #b8ff9c; text-shadow: 0 0 0.7cqw #06481a, 0 0 0.7cqw #06481a, 0 0 0.7cqw #06481a, 0 0.6cqw 1.2cqw rgba(0, 0, 0, 0.5); }
/* rarity lights the card's edge: a pale rim for a common, blue for an uncommon, gold (and a glow) for a rare */
.card { --edge: rgba(255, 255, 255, 0.55); }
.card:has(.card-rarity.uncommon) { --edge: #8fd0ff; }
.card:has(.card-rarity.rare) { --edge: #ffd34a; --halo: 0 0 4cqw rgba(255, 211, 74, 0.7); }

/* smooth, like the Pokédex (2026-10-12, the user's pick): a glossy gradient in the type's colours, lit at the top and
   shaded at the bottom. --ring is a highlight outside the edge (a picked card, a card you can pick) */
.card-face {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2.6cqw;
  padding: 4.5cqw 5cqw 5cqw;
  border-radius: 8cqw;
  background: linear-gradient(160deg, color-mix(in srgb, var(--c1) 60%, #fff) 0%, var(--c1) 38%, var(--c2) 100%);
  box-shadow: var(--ring, 0 0 0 0 transparent), var(--halo, 0 0 0 0 transparent), inset 0 0 0 1.4cqw var(--edge),
    inset 0 2cqw 4cqw rgba(255, 255, 255, 0.35), inset 0 -3cqw 5cqw rgba(0, 0, 0, 0.25), 0 2cqw 5cqw rgba(0, 0, 0, 0.5);
  transition: box-shadow 0.15s;
}

/* the PP cost: a lit gem in the type's colour, on the name's centre line */
.card-cost {
  position: absolute;
  top: 8cqw;
  left: 4.5cqw;
  width: 13cqw;
  height: 13cqw;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 28%, #fff 0 12%, color-mix(in srgb, var(--c1) 60%, #fff) 30%, var(--c2) 100%);
  box-shadow: 0 0 0 1cqw rgba(255, 255, 255, 0.85), 0 0 3cqw color-mix(in srgb, var(--c1) 80%, #fff), 0 1cqw 2cqw rgba(0, 0, 0, 0.4);
  color: #fff;
  text-shadow: 0 0.6cqw 1cqw rgba(0, 0, 0, 0.5);
  font-family: var(--font);
  font-weight: 900;
  font-size: 9cqw;
  line-height: 1;
}

/* every card keeps a two-line band for its name, so the art, type and text windows line up across a
   row whichever names wrap; it's padded the same both sides (room for the cost) to sit centred */
.card-name {
  width: 100%;
  flex: 0 0 auto;
  height: 20cqw;
  padding: 0 14cqw;
  display: grid;
  align-items: center;
  justify-items: center;
  font-family: var(--font);
  font-size: calc(9.5cqw * var(--name-fit, 1));
  font-weight: 900;
  line-height: 1.05;
  color: #fff;
  text-shadow: 0 0.6cqw 1.5cqw rgba(0, 0, 0, 0.45);
}
/* a frosted glass window; its shape says what kind of card it is: an Attack's comes to a point, a Skill's is square,
   a Power's is round (Slay the Spire's frames) */
.card-art {
  width: 100%;
  flex: 0 0 auto;
  height: 32cqw;
  display: grid;
  place-items: center;
  font-size: 24cqw;
  line-height: 1;
  border-radius: 5cqw;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.75), rgba(255, 255, 255, 0.35));
  box-shadow: inset 0 0 0 0.8cqw rgba(255, 255, 255, 0.8), inset 0 -2cqw 4cqw rgba(0, 0, 0, 0.12);
}
.card.kind-attack .card-art { clip-path: polygon(0 0, 100% 0, 100% 74%, 50% 100%, 0 74%); border-radius: 0; padding-bottom: 4cqw; }
.card.kind-power .card-art { width: 84%; border-radius: 50%; }
/* item art (cardSprite() in js/ui.js): the sprite's visible box (--bx/--by/--bw/--bh, in its 32px frame) scaled
   as big as fits --box-w x --box-h, whatever padding the file has, so every item fills the window the same way */
.card-art { --box-w: 64cqw; --box-h: 25cqw; }
.card:not(.small) .card-svg { --svg: 27cqw; }   /* the smooth art has its own margin, so it can take the window's height */
.sprite-fit {
  --k: min(calc(var(--box-w) / var(--bw)), calc(var(--box-h) / var(--bh)));
  position: relative;
  width: calc(var(--k) * var(--bw));
  height: calc(var(--k) * var(--bh));
  overflow: hidden;
  font-size: 21cqw;                    /* the emoji fallback, if the file is missing */
}
.card-svg {
  --svg: min(var(--box-w), calc(var(--box-h) * 1.12));
  height: var(--svg);
  width: var(--svg);
  overflow: visible;
  filter: drop-shadow(0 0.5cqw 0 rgba(0, 0, 0, 0.18));
}
.sprite-fit .item-sprite {
  position: absolute;
  left: calc(var(--k) * var(--bx) * -1);
  top: calc(var(--k) * var(--by) * -1);
  width: calc(var(--k) * 32);
  height: calc(var(--k) * 32);
}
.card-type {
  flex: 0 0 auto;
  padding: 0.8cqw 4cqw;
  border-radius: 10cqw;
  background: rgba(0, 0, 0, 0.22);
  font-family: var(--font);
  font-weight: 800;
  font-size: 6.4cqw;
  line-height: 1.2;
  color: #fff;
  white-space: nowrap;
}
.card-text {
  font-family: var(--font);
  font-size: calc(8.4cqw * var(--text-fit, 1));
  font-weight: 700;
  line-height: 1.22;
  padding: 2cqw 3cqw;
  border-radius: 4.5cqw;
  background: rgba(255, 255, 255, 0.92);
  box-shadow: inset 0 1cqw 2cqw rgba(0, 0, 0, 0.08);
  color: #22222c;
  width: 100%;
  flex: 1;
  display: grid;
  align-items: center;
}
.card-kw { font-weight: 900; color: #b05800; }

/* rarity, the TCG's way (makeCard()): a dot, a diamond or a star in the name band's right corner, mirroring the cost */
.card-rarity {
  position: absolute;
  top: 11cqw;
  right: 6cqw;
  width: 7cqw;
  height: 7cqw;
  filter: drop-shadow(0 0 0.6cqw rgba(0, 0, 0, 0.6)) drop-shadow(0 0.5cqw 1cqw rgba(0, 0, 0, 0.4));
}
.card-rarity::before { content: ''; position: absolute; inset: 0; }
.card-rarity.common::before { inset: 1cqw; border-radius: 50%; background: #f4f4fa; }
.card-rarity.uncommon::before { inset: 0.5cqw; rotate: 45deg; scale: 0.85; background: #a8d8ff; }
.card-rarity.rare { top: 10cqw; right: 5cqw; width: 9cqw; height: 9cqw; }
.card-rarity.rare::before {
  background: #f8d030;
  clip-path: polygon(50% 0, 62% 36%, 100% 38%, 70% 61%, 80% 98%, 50% 76%, 20% 98%, 30% 61%, 0 38%, 38% 36%);
}
/* a rare's shine sweeps across it every few seconds */
.card:has(.card-rarity.rare) .card-face::after {
  content: ''; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  background: linear-gradient(120deg, transparent 40%, rgba(255, 255, 255, 0.3) 50%, transparent 60%) no-repeat;
  background-size: 300% 100%;
  animation: rareSweep 4.5s ease-in-out infinite;
}
@keyframes rareSweep { 0% { background-position: 100% 0; } 40%, 100% { background-position: 0% 0; } }
@media (prefers-reduced-motion: reduce) { .card:has(.card-rarity.rare) .card-face::after { animation: none; background-position: 50% 0; } }
.card.small .card-rarity { top: 12cqw; right: 6.5cqw; }
.card.small .card-rarity.rare { top: 11cqw; right: 5.5cqw; }

/* Interactive cards lift up when you point at them */
.card[role="button"] { cursor: pointer; }
.card[role="button"]:hover { transform: translateY(-5px) scale(1.03); z-index: 2; }

/* Locked cards: greyed out with a message */
.card.locked { filter: grayscale(1) brightness(0.55); }
.lock-badge {
  position: absolute;
  inset: auto 6cqw 10cqw;
  padding: 3cqw 2cqw;
  border: 1cqw solid #181010;
  background: var(--win-bg);
  color: var(--win-ink);
  font-family: var(--pixel-font); font-synthesis-weight: none;
  font-size: 6.5cqw;
}
.card.locked .card-text { visibility: hidden; }

/* Badge showing how many copies are already in the deck */
.in-deck {
  position: absolute;
  top: -3cqw;
  right: -3cqw;
  padding: 1.5cqw 3cqw;
  border: 1.2cqw solid #181010;
  background: #fff8e0;
  color: #181010;
  font-family: var(--pixel-font); font-synthesis-weight: none;
  font-size: 9cqw;
  line-height: 1;
  z-index: 1;
}
.card.maxed { opacity: 0.55; }

/* Compact version used in the deck strip */
.card.small { aspect-ratio: 5 / 6.2; }
.card.small .card-face { padding: 5cqw 5cqw 6cqw; gap: 2cqw; }
.card.small .card-type,
.card.small .card-text { display: none; }
.card.small .card-name { font-size: calc(10.5cqw * var(--name-fit, 1)); height: 24cqw; padding: 0 16.5cqw; }
.card.small .card-art { height: auto; flex: 1; font-size: 30cqw; --box-w: 60cqw; --box-h: 50cqw; }
.card-cost.cheaper { background: radial-gradient(circle at 35% 28%, #fff 0 12%, #8ef0a0 30%, #189038 100%); }
.card-cost.dearer { background: radial-gradient(circle at 35% 28%, #fff 0 12%, #ff9a90 30%, #c02020 100%); }
.card.small .card-cost { top: 9.5cqw; left: 4cqw; width: 15cqw; height: 15cqw; font-size: 10.5cqw; }

/* ---------- cards in your battle hand ---------- */
.card.in-hand { --card-w: var(--hand-card-w); flex: 0 0 auto; touch-action: none; -webkit-touch-callout: none; user-select: none; -webkit-user-select: none; }
/* held in a fan (fanHand() in js/battle.js sets --fan, the offset from the middle): tilted, sinking towards the edges, overlapping.
   rotate/translate, not transform, so the hover lift and the deal animation stay separate */
.card.in-hand {
  rotate: calc((var(--fan, 0) + var(--shift, 0)) * var(--fan-tilt, 0deg));
  translate: var(--push, 0px) calc((var(--fan, 0) + var(--shift, 0)) * (var(--fan, 0) + var(--shift, 0)) * var(--fan-drop, 0px));
  transition: transform 0.15s, filter 0.15s, rotate 0.18s ease-out, translate 0.18s ease-out;
}
.card.in-hand + .card.in-hand { margin-left: calc(-1 * var(--overlap, 0px)); }
.card.in-hand:is(:hover:not(.unplayable), .selected) { rotate: 0deg; translate: 0; z-index: 2; }
.card.in-hand.unplayable { filter: grayscale(0.7) brightness(0.7); }
.card.in-hand.waiting, #hand.dealing .card { pointer-events: none; }
.card.in-hand:hover:not(.unplayable) { transform: translateY(-16px) scale(1.06); }

.card.deal { animation: deal 0.4s ease-out backwards; }   /* backwards, not both: holding the end state would block the hover lift */
@keyframes deal {
  from { opacity: 0; transform: translateY(80px) rotate(8deg) scale(0.8); }
  to   { opacity: 1; transform: none; }
}

/* Fighting's Follow-up: a card whose Follow-up would happen if played now glows orange (a pick's gold ring wins) */
.card.in-hand.follow-ready .card-face { --ring: 0 0 0 0.8cqw #fff3e0, 0 0 0 2.2cqw #ff9a50, 0 0 5cqw 1cqw rgba(255, 140, 60, 0.55); }

/* ---------- picking a card: the first tap lifts it out of the hand, the second plays it (an item blows up at the bottom middle) ---------- */
.card.in-hand.selected { transform: translateY(-10px); z-index: 2; }
.card.in-hand.selected .card-face { --ring: 0 0 0 1cqw #fff, 0 0 0 2.8cqw #f8d030, 0 0 6cqw 2cqw rgba(248, 208, 48, 0.7); }
/* a card is asking you to pick a card in your hand (discard / exhaust): they all glow and can be tapped */
.card.in-hand.choosable { cursor: pointer; }
.card.in-hand.choosable .card-face { --ring: 0 0 0 2.2cqw #f8f8f8, 0 0 5cqw 1cqw rgba(255, 255, 255, 0.6); }
.card-focus {
  position: fixed;
  inset: 0;
  z-index: 30;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  gap: 12px;
  padding: 0 16px calc(24px + env(safe-area-inset-bottom));
  background: rgba(8, 10, 24, 0.45);
}
.card.focus-card { --card-w: min(48vw, 205px); animation: focusIn 0.18s ease-out; touch-action: none; -webkit-touch-callout: none; user-select: none; -webkit-user-select: none; }
.card.focus-card[role="button"]:hover { transform: none; }
.card.focus-card.unplayable { filter: grayscale(0.6) brightness(0.8); }
.focus-hint {
  margin: 0;
  padding: 6px 12px;
  border: 3px solid #b8b8c8;
  background: var(--win-bg);
  color: var(--win-ink);
  box-shadow: 0 0 0 2px #303038, inset 0 0 0 2px #303038;
  font-family: var(--pixel-font); font-synthesis-weight: none;
  font-size: 0.8rem;
  text-align: center;
}
/* Fusion Flare / TM: the pile's cards laid out over the dimmed battle; a tap picks one (lifted, gold-rimmed) and shows
   its keyword boxes and the take button under the row, a second tap takes it */
.card-focus.pile-picking { justify-content: center; background: rgba(8, 10, 24, 0.7); }
.pile-pick { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; max-width: 760px; max-height: 55vh; overflow-y: auto; padding: 8px; touch-action: pan-y; }
.card.pile-card { --card-w: min(28vw, 130px); cursor: pointer; }
.card.pile-card:is(:hover, :focus-visible) { transform: translateY(-6px); }
.card.pile-card.picked { transform: translateY(-6px); outline: 3px solid var(--win-gold); outline-offset: 2px; }
.pile-below { display: flex; flex-direction: column; align-items: center; gap: 8px; width: min(92vw, 340px); }
.pile-below .card-tips { width: 100%; animation: tipsIn 0.2s ease-out backwards; }
@keyframes focusIn { from { transform: translateY(40px) scale(0.6); opacity: 0; } }
/* a picked hand card rises out of its own place (popFromHand() in js/battle.js), StS-style: no dimming,
   and the hand's copy hides so it reads as the same card lifting */
.card-focus.rise { display: block; padding: 0; background: none; }
.card-focus.rise > * { position: fixed; margin: 0; }
.card-focus.rise .card.focus-card { --card-w: min(38vw, 160px); animation: none; transform-origin: 50% 100%; }
.card-focus.rise .card.focus-card .card-face { --ring: 0 0 0 1cqw #fff, 0 0 0 2.8cqw #f8d030, 0 0 6cqw 2cqw rgba(248, 208, 48, 0.7); }
/* armed by a swipe up (initScrub() in js/battle.js): letting go plays it */
.card-focus.rise .card.focus-card.flinging { filter: brightness(1.15) drop-shadow(0 0 10px #f8e070); }
.card.in-hand.lifted { visibility: hidden; }
.card-focus.rise .focus-play { padding: 2px 3px; }
.card-focus.rise .focus-play .pp-pill { font-size: 0.6rem; padding: 4px 8px 3px 17px; }
.card-focus.rise .focus-play .pp-pill::before { left: 7px; }

/* ---------- deck views: tap a card to read it bigger (zoomCard() in js/ui.js); any tap closes it ---------- */
.card-zoom {
  position: fixed;
  inset: 0;
  z-index: 120;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  padding: 16px;
  background: rgba(8, 10, 24, 0.7);
  cursor: pointer;
}
.card.zoom-card { --card-w: min(72vw, 300px, 50vh); animation: focusIn 0.18s ease-out; }

/* ---------- keyword boxes (cardTips() in js/ui.js): StS's little windows beside a blown-up card ---------- */
.card-tips { display: flex; flex-direction: column; gap: 6px; width: 190px; cursor: default; }
.card-tip {
  padding: 6px 8px;
  border: 3px solid #b8b8c8;
  border-radius: var(--round-sm);
  background: var(--win-bg);
  color: var(--win-ink);
  box-shadow: 0 0 0 2px #303038, inset 0 0 0 2px #303038;
  font-size: 0.78rem;
  line-height: 1.3;
  text-align: left;
}
.card-tip-name { display: block; margin-bottom: 3px; color: var(--win-gold); font-family: var(--pixel-font); font-synthesis-weight: none; font-size: 0.72rem; font-weight: normal; }
/* beside the card on wide screens, under it on a phone */
.tip-row { display: flex; align-items: flex-start; justify-content: center; gap: 12px; }
/* the card stays centred, over its confirm button; the boxes hang off its right side instead of sharing the centring */
@media (min-width: 721px) {
  .tip-row { position: relative; }
  .tip-row .card-tips { position: absolute; left: calc(100% + 12px); top: 0; }
}
.tip-row .card-tips { animation: tipsIn 0.2s ease-out 0.1s backwards; }
@keyframes tipsIn { from { opacity: 0; transform: translateY(8px); } }
/* in battle the boxes are placed by placeTips() in js/battle.js, and taps go through them to the layer */
.card-focus.rise .card-tips { pointer-events: none; animation: tipsIn 0.2s ease-out 0.1s backwards; }
@media (max-width: 720px) {
  .tip-row { flex-direction: column; align-items: center; gap: 8px; }
  .tip-row .card-tips { width: min(100%, 340px); }
  :is(.card-focus, .card-zoom) .tip-row .card:is(.focus-card, .zoom-card) { --card-w: min(64vw, 260px, calc(50vh - var(--tips) * 5.5vh)); }
  .card-tip { padding: 4px 7px; font-size: 0.72rem; }
  .card-tip-name { display: inline; margin: 0 6px 0 0; font-size: 0.62rem; }
}
@media (prefers-reduced-motion: reduce) { .card-tips, .tip-row .card-tips { animation: none; } }

/* soft corners inside a card, in step with its 8cqw outer corners */
.lock-badge, .in-deck { border-radius: 3cqw; }

/* ---------- picking a card from your hand (exhaust / discard / keep / copy): the battle dims under the hand, a banner
   names the verb and the cards you can pick pulse in its colour, so it never reads as playing a card ---------- */
#battle-screen { --pick: #8878b8; }
#battle-screen[data-pick="discard"] { --pick: #4878d0; }
#battle-screen[data-pick="keep"] { --pick: #40a050; }
#battle-screen[data-pick="copy"] { --pick: #d0a020; }
#battle-screen.picking::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 20;
  background: rgba(8, 10, 24, 0.66);
  pointer-events: none;
  animation: pickDim 0.25s ease-out both;
}
#battle-screen.picking .hand { position: relative; z-index: 21; }
@keyframes pickDim { from { opacity: 0; } }
.pick-banner {
  position: fixed;
  left: 50%;
  top: 30%;
  z-index: 22;
  translate: -50% 0;
  display: grid;
  justify-items: center;
  gap: 6px;
  width: max-content;
  max-width: calc(100vw - 32px);
  padding: 12px 18px 10px;
  background: var(--win-bg);
  color: var(--win-ink);
  border: 4px solid var(--pick);
  border-radius: var(--round-sm);
  box-shadow: 0 0 0 3px #181010, 5px 5px 0 3px rgba(0, 0, 0, 0.45);
  font-family: var(--pixel-font);
  text-align: center;
  pointer-events: none;
  animation: pickBanner 0.4s ease-out both;
}
.pick-banner[hidden] { display: none; }
.pick-title { font-size: 1.15rem; letter-spacing: 0.04em; text-transform: uppercase; color: var(--pick); text-shadow: 2px 2px 0 #181010; }
.pick-line { font-size: 0.7rem; color: var(--win-muted); }
.pick-icon { font-size: 1.6rem; animation: pickPuff 1.2s ease-in-out infinite; }
@keyframes pickBanner { 0% { translate: -50% -40px; opacity: 0; } 70% { translate: -50% 6px; opacity: 1; } 100% { translate: -50% 0; } }
@keyframes pickPuff { 50% { translate: 0 -4px; scale: 1.15; } }
#battle-screen.picking .card.in-hand.choosable .card-face {
  --ring: 0 0 0 2.4cqw var(--pick), 0 0 5cqw 1cqw var(--pick);
  animation: pickGlow 1s steps(2) infinite;
}
#battle-screen.picking .card.in-hand:not(.choosable) { filter: grayscale(0.8) brightness(0.6); }
@keyframes pickGlow { 50% { filter: brightness(1.18); } }
.ds-btn.ds-play.pick-exhaust { --stripe-a: #8878b8; --stripe-b: #a090c8; --rim: #605090; }
.ds-btn.ds-play.pick-discard { --stripe-a: #4878d0; --stripe-b: #6890e0; --rim: #3058a8; }
.ds-btn.ds-play.pick-keep { --stripe-a: #40a050; --stripe-b: #60b868; --rim: #287838; }
.ds-btn.ds-play.pick-copy { --stripe-a: #d0a020; --stripe-b: #e0b840; --rim: #a07808; }

/* card trails (js/cardfx.js): a played card's clone arcs to where it acts and an exhausted one burns away; their
   particles are drawn on one low-res canvas over everything, in whole pixels */
.exhaust-fx { position: fixed; inset: 0; z-index: 130; pointer-events: none; }
.exhaust-fx .fly-ghost { will-change: transform, opacity; }
.fly-glow { position: absolute; inset: 0; border-radius: 8cqw; background: rgba(255, 255, 255, 0.45); box-shadow: 0 0 8px #a8d8ff; opacity: 0; pointer-events: none; }
.card-fx { position: fixed; inset: 0; width: 100vw; height: 100vh; z-index: 131; pointer-events: none; image-rendering: pixelated; }
.card-fx.clean { image-rendering: auto; }
/* a risen card glows in its type's colour (js/battle.js's renderFocus()); only its opacity moves, so nothing repaints */
.card-focus.rise .card.focus-card > .lift-glow { position: absolute; inset: -1cqw; z-index: -1; border-radius: 9cqw; pointer-events: none; box-shadow: 0 0 7cqw 3cqw var(--c1); opacity: 0.35; animation: liftGlow 1.1s ease-in-out infinite alternate; }
@keyframes liftGlow { to { opacity: 0.85; } }
.calm-fx .lift-glow, .no-battle-fx .lift-glow { animation: none; }
.pile.bump { animation: pileBump 0.35s ease-out; }
@keyframes pileBump { 40% { scale: 1.35; } }

/* keywords with a box beside the blown-up card, coloured in the card's text and on their box's name (colourTerms() in js/ui.js) */
.card-text .term { font-weight: 800; }
.term-key { color: #b05800; }
.term-burn { color: #c83810; }
.term-tide { color: #1d62c4; }
.term-seed { color: #2a7c2a; }
.term-debuff { color: #7a3aa8; }
.term-strength { color: #b8201c; }
.card-tip-name.term-key { color: var(--win-gold); }

/* a rare card shimmers where it's offered (rewards, the Mart): a gold sheen sweeps across it now and then */
.card.shimmer { filter: drop-shadow(0 0 1.5cqw rgba(255, 208, 64, 0.75)); }
.card.shimmer::after {
  content: ""; position: absolute; inset: 0; border-radius: 8cqw; pointer-events: none;
  background: linear-gradient(115deg, transparent 38%, rgba(255, 236, 150, 0.5) 46%, rgba(255, 255, 255, 0.85) 50%, rgba(255, 236, 150, 0.5) 54%, transparent 62%) no-repeat;
  background-size: 300% 100%;
  animation: cardShimmer 2.8s ease-in-out infinite;
}
@keyframes cardShimmer { 0% { background-position: 100% 0; } 55%, 100% { background-position: 0% 0; } }
@media (prefers-reduced-motion: reduce) { .card.shimmer::after { animation: none; background: none; } }
/* taking an upgraded card: green and gold sparks fly off its tile with a big + (upgradeBurst() in ui.js) */
.up-burst { position: fixed; z-index: 2000; width: 0; height: 0; pointer-events: none; }
.up-burst i { position: absolute; left: -4px; top: -4px; width: 8px; height: 8px; background: #58e070; box-shadow: 0 0 0 2px #1a6a30; animation: upSpark 0.7s ease-out forwards; }
.up-burst i.gold { background: #ffd84a; box-shadow: 0 0 0 2px #8a6000; }
@keyframes upSpark { from { transform: scale(1.4); } to { transform: translate(var(--dx), var(--dy)) scale(0.4); opacity: 0; } }
.up-burst b { position: absolute; font-family: var(--pixel-font); font-size: 3rem; color: #7dff8e; -webkit-text-stroke: 5px #145c28; paint-order: stroke fill; animation: upPlus 0.7s ease-out forwards; }
@keyframes upPlus { 0% { opacity: 0; transform: translate(-50%, -50%) scale(0.4); } 30% { opacity: 1; transform: translate(-50%, -50%) scale(1.3); } 100% { opacity: 0; transform: translate(-50%, -90%) scale(1); } }

/* PP Up's preview (markUpgrade() in js/ui.js): what the upgrade changes is the text itself, bigger, heavier and bright
   green with a dark rim (the user's call, 2026-10-08: no box), brighter than Leech Seed's green word; the blown-up card
   sits beside the card as it is now (.up-pair) */
.card-text .up-diff {
  color: #10c040; font-weight: 900; font-size: 1.22em; line-height: 1;
  text-shadow: -0.5px -0.5px 0 #0a4a18, 0.5px -0.5px 0 #0a4a18, -0.5px 0.5px 0 #0a4a18, 0.5px 0.5px 0 #0a4a18, 0 0 0.35em rgba(40, 230, 90, 0.55);
}
.up-pair { display: flex; align-items: center; justify-content: center; gap: 8px; }
.up-pair .card.up-before { --card-w: min(30vw, 150px); flex: none; filter: saturate(0.6) brightness(0.85); }
.up-arrow { flex: none; color: #8ef070; font-family: var(--pixel-font); font-size: 1.1rem; text-shadow: 2px 2px 0 #102010; }
.card-focus .up-pair .card.focus-card { --card-w: min(52vw, 240px, 45vh); flex: none; }
@media (max-width: 720px) {
  .card-focus .tip-row .up-pair .card.focus-card { --card-w: min(52vw, 240px, calc(50vh - var(--tips) * 5.5vh)); }
  .card-focus .tip-row .up-pair .card.up-before { --card-w: min(30vw, 150px, calc(29vh - var(--tips) * 3.2vh)); }
}

/* a Safari signature card whose shiny is yours (makeCard() in js/ui.js): the shiny Pokémon in its art window, cropped
   to its pose (--bx..--bh, in GIF px), and a ★ for its Sparkle; ★3 a glowing edge, ★4 sparkles over the art, ★5 a gold
   frame and foil (★2 is a burst when it's played, in battle.js) */
.card:not(.small) .sig-art { --box-h: 28cqw; --box-w: 58cqw; }
.sig-art { position: relative; overflow: hidden; }
.sig-fit {
  --gw: 1; --gh: 1; --bx: 0; --by: 0; --bw: 1; --bh: 1;
  --k: min(calc(var(--box-w) / var(--bw)), calc(var(--box-h) / var(--bh)));
  position: relative; width: calc(var(--k) * var(--bw)); height: calc(var(--k) * var(--bh));
  opacity: 0;
}
.sig-fit.ready { opacity: 1; }
.sig-fit img {
  position: absolute; max-width: none;
  left: calc(var(--k) * var(--bx) * -1); top: calc(var(--k) * var(--by) * -1);
  width: calc(var(--k) * var(--gw)); height: calc(var(--k) * var(--gh));
  filter: drop-shadow(0 0.5cqw 0 rgba(0, 0, 0, 0.18));
}
.card-sparkle {
  position: absolute; top: 11cqw; right: 3cqw;
  padding: 0.8cqw 1.8cqw 0.4cqw; border-radius: 3cqw;
  background: #fff; color: var(--c2);
  font-family: var(--pixel-font); font-synthesis-weight: none; font-size: 5.2cqw; line-height: 1.1;
  box-shadow: 0 0.6cqw 1.2cqw rgba(0, 0, 0, 0.35);
}
.card.sparkled { --edge: #8fd0ff; }
.card:is(.sparkle-3, .sparkle-4) { --edge: #b8f9ff; --halo: 0 0 4.5cqw rgba(184, 249, 255, 0.75); }
.card:is(.sparkle-3, .sparkle-4) .card-sparkle { background: #b8f9ff; color: #0b3a6a; }
.card.sparkle-5 { --edge: #ffd34a; --halo: 0 0 6cqw 1cqw rgba(255, 211, 74, 0.8); }
.card.sparkle-5 .card-sparkle { background: #ffd34a; color: #4a3000; }
.card.sparkle-5 .card-name { color: #ffe590; }
.card.sparkle-5 .card-face::after {
  content: ''; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  background: linear-gradient(115deg, transparent 38%, rgba(255, 255, 255, 0.4) 48%, rgba(255, 230, 150, 0.38) 52%, transparent 62%) no-repeat;
  background-size: 250% 100%;
  animation: sigFoil 3.2s linear infinite;
}
@keyframes sigFoil { 0% { background-position: 150% 0; } 100% { background-position: -50% 0; } }
.sig-twinkle { display: none; width: 6cqw; height: 6cqw; opacity: 0; animation: sigTwinkle 1.8s ease-in-out infinite; }
.card:is(.sparkle-4, .sparkle-5) .sig-twinkle { display: block; }
.sig-twinkle.t0 { left: 14%; top: 10%; }
.sig-twinkle.t1 { right: 14%; top: 22%; animation-delay: 0.6s; background: #ffd34a; }
.sig-twinkle.t2 { left: 32%; bottom: 14%; animation-delay: 1.2s; width: 4.5cqw; height: 4.5cqw; }
@keyframes sigTwinkle { 0%, 100% { opacity: 0; transform: scale(0.4); } 50% { opacity: 1; transform: scale(1); } }
:root.calm-fx .sig-twinkle { animation: none; opacity: 0.85; }
:root.calm-fx .card.sparkle-5 .card-face::after { animation: none; background-position: 50% 0; }
@media (prefers-reduced-motion: reduce) {
  .sig-twinkle { animation: none; opacity: 0.85; }
  .card.sparkle-5 .card-face::after { animation: none; background-position: 50% 0; }
}

/* the Safari's type hint on an attack in hand (markEdge() in js/battle.js): the type line turns green with a ▲ when it's
   super effective on the wild Pokémon, grey with a ▼ when it's resisted */
.card.edge-up .card-type { background: #23963a; box-shadow: 0 0 0 0.6cqw #9cf0a8; }
.card.edge-down .card-type { background: rgba(40, 40, 48, 0.62); color: #d4d4dc; }
.card-edge { font-weight: 900; }
.card.edge-up .card-edge { color: #eaffb0; }

/* foil decks (js/foil.js; the roadmap's Level 6-10 reward 6, 2026-10-23): a run whose starter was won on Trainer Level
   6-9 wears every card with a foil edge in that star's colour, Level 10 a rainbow edge and a holo sheen that follows
   --foil-x / --foil-y (the pointer or the tilt). The edge is a transparent border showing a second background, so the
   padding gives back its width; the rarity still shows on its gem. */
:root[data-foil] .card:not(.status) { --edge: transparent; }
:root[data-foil] .card:not(.status) .card-face {
  border: 1.4cqw solid transparent;
  padding: 3.1cqw 3.6cqw 3.6cqw;
  background: linear-gradient(160deg, color-mix(in srgb, var(--c1) 60%, #fff) 0%, var(--c1) 38%, var(--c2) 100%) padding-box,
    linear-gradient(calc(100deg + var(--foil-x, 0.5) * 70deg), var(--f1) 0%, var(--f2) 22%, var(--f3) 38%, var(--f2) 52%, var(--f1) 70%, var(--f3) 86%, var(--f2) 100%) border-box;
}
:root[data-foil] .card.small:not(.status) .card-face { padding: 3.6cqw 3.6cqw 4.6cqw; }
:root[data-foil="6"] { --f1: #6a0a1c; --f2: #e0284a; --f3: #ffd0d8; }
:root[data-foil="7"] { --f1: #084a26; --f2: #22b860; --f3: #d0ffe0; }
:root[data-foil="8"] { --f1: #0a2470; --f2: #2a6ae0; --f3: #d4e4ff; }
:root[data-foil="9"] { --f1: #401268; --f2: #9a48e0; --f3: #f0d8ff; }
:root[data-foil="10"] .card:not(.status) .card-face {
  background: linear-gradient(160deg, color-mix(in srgb, var(--c1) 60%, #fff) 0%, var(--c1) 38%, var(--c2) 100%) padding-box,
    linear-gradient(calc(100deg + var(--foil-x, 0.5) * 120deg), #ff5a7a, #ffb84a, #fff27a, #6ee8a0, #5ac8ff, #a87aff, #ff7ad8, #ff5a7a) border-box;
}
:root[data-foil="10"] .card:not(.status) .card-face::before {
  content: ''; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  background: linear-gradient(115deg, transparent 18%, rgba(255, 90, 140, 0.16) 30%, rgba(255, 230, 90, 0.16) 40%, rgba(110, 232, 160, 0.16) 50%,
    rgba(90, 200, 255, 0.16) 60%, rgba(170, 120, 255, 0.16) 70%, transparent 82%) no-repeat;
  background-size: 260% 260%;
  background-position: calc(var(--foil-x, 0.5) * 100%) calc(var(--foil-y, 0.5) * 100%);
}
