/* ui/UpgradeCard — contract: ./UpgradeCard.spec.md. Tokens from ui/Theme. */

.sp-card {
  --rarity: var(--sp-rarity-common);
  position: relative;
  display: flex;
  flex-direction: column;
  margin: 0;
  color: var(--sp-text);
  font: inherit;
  text-align: left;
  background: var(--sp-space-1);
  background: linear-gradient(
    180deg,
    color-mix(in oklab, var(--rarity) 11%, var(--sp-space-1)) 0%,
    var(--sp-space-1) 58%
  );
  border: 1px solid color-mix(in oklab, var(--rarity) 36%, transparent);
  border-radius: var(--sp-radius);
}

.sp-card[data-rarity="rare"] { --rarity: var(--sp-rarity-rare); }
.sp-card[data-rarity="epic"] { --rarity: var(--sp-rarity-epic); }
.sp-card[data-rarity="legendary"] { --rarity: var(--sp-rarity-legendary); }

button.sp-card {
  cursor: pointer;
  transition:
    transform var(--sp-dur-fast) var(--sp-ease-out),
    border-color var(--sp-dur) var(--sp-ease-out),
    box-shadow var(--sp-dur) var(--sp-ease-out);
}

button.sp-card:hover,
button.sp-card:focus-visible {
  transform: translateY(-3px);
  border-color: var(--rarity);
  box-shadow: 0 16px 40px -18px color-mix(in oklab, var(--rarity) 70%, transparent);
}

button.sp-card:active {
  transform: translateY(0);
}

/* Epic and legendary earn a little more presence. */
.sp-card[data-rarity="epic"] {
  box-shadow: 0 0 28px -14px var(--rarity);
}

.sp-card[data-rarity="legendary"] {
  box-shadow: 0 0 36px -12px color-mix(in oklab, var(--rarity) 80%, transparent);
}

/* A slow light sweep around the legendary border. */
.sp-card[data-rarity="legendary"]::after {
  content: "";
  position: absolute;
  inset: -1px;
  padding: 1px;
  border-radius: inherit;
  background: linear-gradient(115deg, transparent 38%, var(--rarity) 50%, transparent 62%) 0 0 / 300% 100%;
  -webkit-mask: linear-gradient(black, black) content-box, linear-gradient(black, black);
  -webkit-mask-composite: xor;
  mask: linear-gradient(black, black) content-box exclude, linear-gradient(black, black);
  animation: sp-card-sheen 3.6s linear infinite;
  pointer-events: none;
}

@keyframes sp-card-sheen {
  from { background-position: 100% 0; }
  to { background-position: 0% 0; }
}

/* ------------------------------------------------------------ pieces --- */

/* Everything inside is a span (valid in a <button>); make them blocks by
   default at zero specificity so the class rules below can override freely. */
:where(.sp-card) > span,
:where(.sp-card__top) > span {
  display: block;
}

.sp-card__pips {
  display: inline-flex;
  gap: 4px;
  flex: none;
}

.sp-card__pip {
  display: block;
  width: 7px;
  height: 7px;
  border: 1px solid var(--rarity);
  border-radius: 1.5px;
  transform: rotate(45deg);
  opacity: 0.55;
}

.sp-card__pip[data-filled] {
  background: var(--rarity);
  opacity: 1;
}

.sp-card__top {
  display: flex;
  align-items: center;
  gap: 10px;
}

.sp-card__rarity {
  font-size: 11px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--rarity);
}

.sp-card__hotkey {
  flex: none;
  margin-left: auto;
}

.sp-card__category {
  font-size: 11px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--sp-text-faint);
}

.sp-card__name {
  font-weight: 600;
  line-height: 1.15;
  letter-spacing: 0.01em;
}

.sp-card__desc {
  color: var(--sp-text-dim);
}

.sp-card__stacks {
  font: 600 11px/1 var(--sp-font-mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--sp-text-faint);
}

.sp-card__stacks[data-new] {
  color: var(--sp-accent-2);
}

/* The change list: what taking it changes, a bullet a line, coloured by
   whether it helps; the sign in the text says it either way. */
.sp-card__changes {
  display: flex;
  flex-direction: column;
  gap: 3px;
  margin: 12px 0 0;
  padding: 0;
  list-style: none;
}

.sp-card__change {
  position: relative;
  padding-left: 12px;
  font: 500 12.5px/1.35 var(--sp-font);
  color: var(--sp-text);
}

.sp-card__change::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.55em;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--sp-accent-2);
}

.sp-card__change[data-good="false"] { color: var(--sp-text-dim); }
.sp-card__change[data-good="false"]::before { background: var(--sp-warn, var(--sp-accent)); }

/* The before-and-after rows. A monospace column on the right so the numbers of
   three cards side by side line up and can be read down rather than across. */
.sp-card__effects {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-top: 12px;
}

.sp-card__effect {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  font: 500 12px/1.3 var(--sp-font);
  color: var(--sp-text-faint);
}

.sp-card__effect-label {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.sp-card__effect-value {
  display: flex;
  align-items: baseline;
  gap: 5px;
  flex: none;
  font-family: var(--sp-font-mono);
  font-variant-numeric: tabular-nums;
}

.sp-card__effect-from { color: var(--sp-text-faint); }
.sp-card__effect-arrow { color: var(--sp-text-faint); }

/* Up is not always good and down is not always bad -- a form that trades reach
   for weight shows one of each, and that pair is the whole decision -- so the
   colours say direction, not verdict. */
.sp-card__effect[data-up="true"] .sp-card__effect-to { color: var(--sp-accent-2); }
.sp-card__effect[data-up="false"] .sp-card__effect-to { color: var(--sp-warn, var(--sp-accent)); }

/* Build tags. A held chip is lit and carries a check mark, so "held" is never
   colour alone. The synergy badge is a reading aid only: a tag match gives no
   gameplay bonus (see the spec). */
.sp-card__tags {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
}

.sp-card__tag {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 8px;
  font: 600 11px/1.2 var(--sp-font-ui);
  letter-spacing: 0.04em;
  color: var(--sp-text-faint);
  border: 1px solid var(--sp-line);
  border-radius: 999px;
}

.sp-card__tag[data-held="true"] {
  color: var(--sp-text);
  background: color-mix(in oklab, var(--sp-accent-2) 18%, transparent);
  border-color: color-mix(in oklab, var(--sp-accent-2) 70%, transparent);
}

.sp-card__tag-check {
  color: var(--sp-accent-2);
}

/* Resonance (game/Resonance): what taking the card does to a tag's count. Lit
   when it reaches a tier; gold for the second. */
.sp-card__resonance {
  font: 600 12px/1.35 var(--sp-font-ui);
  color: var(--sp-text-dim);
}
.sp-card__resonance[data-reaches="1"] { color: var(--sp-accent-2); }
.sp-card__resonance[data-reaches="2"] { color: var(--sp-rarity-legendary); }

.sp-card__synergy {
  margin-left: auto;
  padding: 3px 8px;
  font: 700 10px/1.2 var(--sp-font-ui);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--sp-space-0);
  background: var(--sp-accent-2);
  border-radius: var(--sp-radius-sm);
  animation: sp-card-synergy 2.4s ease-in-out infinite;
}

@keyframes sp-card-synergy {
  50% { box-shadow: 0 0 14px -2px var(--sp-accent-2); }
}

/* -------------------------------------------------------------- full --- */

.sp-card--full {
  gap: 0;
  padding: 20px 20px 18px;
}

.sp-card--full .sp-card__category { margin-top: 26px; }
.sp-card--full .sp-card__name { margin-top: 8px; font-size: 22px; }
.sp-card--full .sp-card__desc { margin-top: 14px; font-size: 14px; line-height: 1.5; }
.sp-card--full .sp-card__effects { flex: 1; margin-top: 16px; }
.sp-card--full .sp-card__effect { font-size: 13px; }
.sp-card--full .sp-card__tags { margin-top: 16px; }
.sp-card--full .sp-card__stacks { margin-top: 22px; padding-top: 14px; border-top: 1px solid var(--sp-line); }

/* ----------------------------------------------------------- compact --- */

/* One elastic part, and it is the name. Everything else on the row is exactly
   as wide as it has to be, so a tray narrower than the row would like shortens
   the name and never the word that says what kind of upgrade this is. The row
   may be narrower than its own contents want (min-width: 0); the parent laying
   it out has to bound its track — ui/Hud claim 133 is that half. */
.sp-card--compact {
  flex-direction: row;
  align-items: center;
  gap: 10px;
  width: 100%;
  min-width: 0;
  padding: 9px 12px;
  background: var(--sp-glass);
  border-radius: 9px;
  backdrop-filter: blur(8px);
}

.sp-card--compact .sp-card__name {
  min-width: 0;
  font-size: 14px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.sp-card--compact .sp-card__category {
  flex: none;
  margin-left: auto;
  padding-left: 8px;
  font-size: 10px;
  letter-spacing: 0.08em; /* ПАССИВНАЯ, PASYWNA: the name keeps the room the spacing took */
  white-space: nowrap;
}

.sp-card--compact .sp-card__hotkey {
  margin-left: 0;
}

.sp-card--compact:hover,
.sp-card--compact:focus-visible {
  transform: translateX(-3px);
}

/* A narrow viewport: ui/Hud stacks at 860px and the tray becomes half of it —
   224px at 520 × 800 to hold a keycap, four pips, a name and a category. So
   the row loses its air the way the full card does below 520px tall, and the
   name keeps about nine characters instead of five. Compact only: the
   selection screen's card is untouched here. */
@media (max-width: 860px) {
  .sp-card--compact { gap: 8px; padding: 8px 10px; }
  .sp-card--compact .sp-card__name { font-size: 13px; }
  .sp-card--compact .sp-card__pips { gap: 3px; }
  .sp-card--compact .sp-card__category { padding-left: 8px; letter-spacing: 0.1em; }
}

/* A landscape phone: the full card is the whole screen's height budget, so it
   keeps its shape and loses its air. The compact card in the HUD tray is
   sized by width, above. */
@media (max-height: 520px) {
  .sp-card--full { padding: 10px 12px 9px; }
  .sp-card--full .sp-card__category { margin-top: 10px; }
  .sp-card--full .sp-card__name { margin-top: 4px; font-size: 16px; }
  .sp-card--full .sp-card__desc { margin-top: 6px; font-size: 12px; line-height: 1.45; }
  .sp-card--full .sp-card__stacks { margin-top: 10px; padding-top: 7px; }
  .sp-card--full .sp-card__tags { margin-top: 8px; gap: 4px; }
  .sp-card--full .sp-card__tag { padding: 2px 6px; font-size: 10px; }
  .sp-card--full .sp-card__rarity,
  .sp-card--full .sp-card__category { font-size: 10px; }
}

/* ------------------------------------------------------------- touch --- */

/* The selection card under a thumb. There is no keycap on touch, so the stack
   status takes the keycap's corner of the top row instead of a row of its own,
   and the card's air goes: the offer, all of it, has to fit one screen of a
   phone, because a card you have to scroll to is a card you do not pick. */
.sp-card--full[data-touch="true"] .sp-card__stacks {
  position: absolute;
  top: 10px;
  right: 12px;
  margin: 0;
  padding: 0;
  border: 0;
}

.sp-card--full[data-touch="true"] .sp-card__top { padding-right: 76px; }

/* A phone held upright: the offer stacks, one card above the next, in about
   600px. The sentence gives way first (two lines, then an ellipsis); the name,
   the rarity and the effect rows, which are what the choice is made on, stay. */
@media (orientation: portrait) and (max-width: 560px) {
  .sp-card--full[data-touch="true"] { padding: 10px 12px; }
  .sp-card--full[data-touch="true"] .sp-card__category { margin-top: 7px; font-size: 10px; }
  .sp-card--full[data-touch="true"] .sp-card__name { margin-top: 3px; font-size: 17px; }
  .sp-card--full[data-touch="true"] .sp-card__desc {
    display: -webkit-box;
    margin-top: 4px;
    overflow: hidden;
    font-size: 12.5px;
    line-height: 1.35;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
  }
  .sp-card--full[data-touch="true"] .sp-card__effects { margin-top: 6px; gap: 1px; }
  .sp-card--full[data-touch="true"] .sp-card__effect { font-size: 12px; }
  /* The change list keeps its first four lines: three cards share the screen. */
  .sp-card--full[data-touch="true"] .sp-card__changes { margin-top: 6px; gap: 1px; }
  .sp-card--full[data-touch="true"] .sp-card__change { font-size: 12px; }
  .sp-card--full[data-touch="true"] .sp-card__change:nth-child(n + 5) { display: none; }
  .sp-card--full[data-touch="true"] .sp-card__tags { margin-top: 6px; gap: 4px; }
  .sp-card--full[data-touch="true"] .sp-card__tag { padding: 1px 6px; font-size: 11px; }
}

/* A phone on its side: three cards abreast in about 250px of height. The
   max-height chunk above already took the air; the sentence is held to three
   lines so one wordy card cannot set the height of all three. */
@media (max-height: 520px) {
  .sp-card--full[data-touch="true"] .sp-card__desc {
    display: -webkit-box;
    overflow: hidden;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3;
    line-clamp: 3;
  }
  .sp-card--full[data-touch="true"] .sp-card__effects { margin-top: 6px; gap: 1px; }
  .sp-card--full[data-touch="true"] .sp-card__effect { font-size: 11.5px; }
}

/* The synergy glow is decoration; without motion it is simply a lit badge. */
@media (prefers-reduced-motion: reduce) {
  .sp-card__synergy { animation: none; }
}
