/* 공용 카드 컴포넌트 — renderCard(shared/card.js)와 짝. 플테와 랜딩이 같이 쓴다.
   화면별 크기 조정은 각 화면 CSS(client/css/playtest.css, landing/landing.css)에서 폭만 바꾼다 — 안쪽은 카드 폭(cqw) 비례.

   카드 — 질서와 붕괴. 바깥은 모든 카드가 같은 직사각형, 바탕의 결정 격자가 방향을 말한다:
   치유 = 가지런한 격자(구축), 공격 = 깨져 흩어진 파편(파괴).
   원소 = 격자·바탕의 색, 위력 = 한가운데 고정 숫자, 2층 효과 = 아래 한 줄 그림 아이콘. 카드 위 글자는 없다.
   상전이 카드 = 윗부분 효과 기호 줄 + 상전이 전선 (아래 "상전이 카드" 절, card.js phaseLayers). */
.card-comp, .mini-card {
  --cc: #8f8a80;
  container-type: inline-size;
  position: relative; flex-shrink: 0; overflow: hidden;
  aspect-ratio: 5 / 7; height: auto; padding: 0;
  border-radius: 4px;
  border: 1px solid color-mix(in srgb, var(--cc) 38%, #3a362f);
  background:
    radial-gradient(ellipse 90% 60% at 50% 51%, color-mix(in srgb, var(--cc) 16%, transparent), transparent 75%),
    linear-gradient(180deg, color-mix(in srgb, var(--cc) 9%, #16140f), #0f0e0b);
  --side: 0 0 transparent;   /* 옆 빛 (강한 · 폭발 번짐) — 아래 상태별 그림자도 이 값을 앞에 단다 */
  box-shadow: var(--side), 0 6px 16px rgba(0,0,0,.5);
  transition: transform .22s cubic-bezier(.3,.7,.3,1), border-color .2s, box-shadow .2s, opacity .2s;
}
.card-comp { width: 130px; }
.mini-card { width: 86px; }

/* 방향 = 카드 전체의 명도. 한 학파는 한 원소라 덱 화면에서 색은 아무것도 가르지 못한다 — 실눈 떠도 갈려야 한다.
   공격 = 원소빛으로 꽉 찬 밝은 카드 · 치유 = 거의 검은 바탕에 가는 선(성기고 맑다) */
.cf-attack {
  border-color: color-mix(in srgb, var(--cc) 58%, #3a362f);
  background:
    radial-gradient(ellipse 85% 66% at 50% 50%, color-mix(in srgb, var(--cc) 34%, transparent), transparent 82%),
    linear-gradient(180deg, color-mix(in srgb, var(--cc) 20%, #1a1712), #12100c);
}
.cf-heal { border-color: color-mix(in srgb, var(--cc) 22%, #26231d); background: linear-gradient(180deg, #0e0d0b, #090807); }

/* 격자 — 공격 = 원소빛으로 찬 파편 덩어리, 치유 = 채움 없는 가는 선과 마디 */
.card-lattice { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.lt-body { fill: none; stroke: color-mix(in srgb, var(--cc) 75%, #efe6d6); stroke-width: .8; stroke-linejoin: round; }
.lt-cell  { stroke-opacity: .2; }
.lt-shard { stroke-opacity: .5; fill: var(--cc); fill-opacity: .3; }   /* 종이빛을 섞으면 물·바람·무속성이 회색으로 바래 원소가 안 읽힌다 */
.lt-node  { fill: color-mix(in srgb, var(--cc) 60%, #f4ecdd); opacity: .45; }
.cf-attack .lt-shard { fill-opacity: .58; stroke-opacity: .85; }
.cf-attack .lt-body  { filter: drop-shadow(0 0 1.5px color-mix(in srgb, var(--cc) 80%, transparent)); }
.cf-heal .lt-cell    { stroke-opacity: .3; }

/* 안쪽 테 — 치유는 이어지고 모서리에 마디, 공격은 토막 나 어긋난다 (card.js rimSvg) */
.lt-rim  { fill: none; stroke: color-mix(in srgb, var(--cc) 55%, #efe6d6); stroke-opacity: .42; stroke-width: 1; stroke-linecap: round; stroke-linejoin: round; }
.lt-rim-node { fill: color-mix(in srgb, var(--cc) 50%, #f4ecdd); opacity: .6; }
.lt-tick { fill: none; stroke: rgba(236,228,214,.28); stroke-width: 1; }
.cf-heal .lt-rim { stroke-opacity: .55; }

/* 숫자 층 — SVG. 획의 실제 중심이 격자 중심(카드 높이 47.9%)에 온다 (card.js cardNumSvg) */
.card-num, .card-num-fx { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; }
/* 움직이는 겹은 제 겹(합성 레이어)으로 — 알갱이가 움직여도 아래 격자 · 숫자의 필터를 다시 칠하지 않는다. 화면 밖(.fx-off)이면 겹도 놓는다 */
.card-num-fx, .ph-flow, .ph-spill { will-change: transform; }
.fx-off :is(.card-num-fx, .ph-flow, .ph-spill) { will-change: auto; }
/* 화면에 들어와 처음 꺼낸 빛은 스며든다 (card.js fx-lazy). 끝값은 적지 않는다 — 원래 투명도로 돌아간다 */
.fx-wake { animation: fx-wake .45s ease-out backwards; }
@keyframes fx-wake { from { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .fx-wake { animation: none; } }
.reduce-motion .fx-wake { animation: none; }
.fx-off :is(.cfx-mote, .cfx-ring, .ph-mote, .ph-shard, .ph-front path) { animation-play-state: paused !important; }
.cn-power {
  font-family: var(--font-display); font-weight: 600;
  fill: color-mix(in srgb, var(--cc) 35%, #f6efe2);
  filter: drop-shadow(0 0 1px #0b0a08) drop-shadow(0 0 2.5px #0b0a08) drop-shadow(0 0 8px color-mix(in srgb, var(--cc) 70%, transparent));
}
.cn-stab { font-family: var(--font-display); font-weight: 700; fill: color-mix(in srgb, var(--cc) 35%, #f6efe2); opacity: .8; filter: drop-shadow(0 0 1px #0b0a08); }
/* 응축 — 0 흩어짐: 뿌옇고 입자가 새어 나감 · 2 모임: 또렷 · 3 응축: 흰 속 + 획 중심으로 좁혀 드는 고리 */
.cfx-0 .cn-power { opacity: .78; filter: blur(.4px) drop-shadow(0 0 2.5px #0b0a08) drop-shadow(0 0 10px color-mix(in srgb, var(--cc) 70%, transparent)); }
.cfx-mote { fill: color-mix(in srgb, var(--cc) 45%, #f6efe2); animation: cfx-leak 2.8s ease-out infinite; animation-delay: var(--d); }
@keyframes cfx-leak { 0% { transform: translate(0, 0); opacity: .8; } 100% { transform: translate(var(--dx), var(--dy)); opacity: 0; } }
.cfx-2 .cn-power { filter: drop-shadow(0 0 1px #0b0a08) drop-shadow(0 0 2px color-mix(in srgb, var(--cc) 80%, #fff)) drop-shadow(0 0 7px color-mix(in srgb, var(--cc) 90%, transparent)); }
.cfx-3 .cn-power { fill: color-mix(in srgb, var(--cc) 18%, #fffaf0);
  filter: drop-shadow(0 0 1px #fff) drop-shadow(0 0 3px color-mix(in srgb, var(--cc) 90%, #fff)) drop-shadow(0 0 9px var(--cc)); }
.cfx-ring { fill: none; stroke: color-mix(in srgb, var(--cc) 55%, #f6efe2); stroke-width: 1; vector-effect: non-scaling-stroke;
  transform-box: fill-box; transform-origin: center; animation: cfx-gather 2.2s ease-in infinite; }
@keyframes cfx-gather { 0% { transform: scale(1.7); opacity: 0; } 60% { opacity: .6; } 100% { transform: scale(.85); opacity: 0; } }

/* 옆 빛 — 번짐은 맞은 결정의 양옆 이웃에 흔적을 남긴다. 강한(원소 흔적 1) · 폭발(원소 흔적 2) 번짐 카드는 왼쪽 · 오른쪽 테두리로만 원소빛이 샌다.
   사방 빛(= 고른 카드)과 겹치지 않게 위아래로는 새지 않는다: 그림자를 흐림만큼 안으로 줄였다가 옆으로만 민다. 가까이 진하게 + 멀리 옅게, 움직이지 않는다 */
:is(.card-comp, .mini-card):has(.mod-spread-2, .mod-spread-3) {
  --sa: color-mix(in srgb, var(--cc) 75%, transparent); --sb: color-mix(in srgb, var(--cc) 40%, transparent);
  --side: -7px 0 8px -7px var(--sa), 7px 0 8px -7px var(--sa), -14px 0 14px -12px var(--sb), 14px 0 14px -12px var(--sb);
}
:is(.card-comp, .mini-card):has(.mod-spread-3) { --sa: color-mix(in srgb, var(--cc) 95%, transparent); --sb: color-mix(in srgb, var(--cc) 60%, transparent); }

/* 2층 아이콘 — 아래 한 줄, 그림만 */
.card-comp .card-tags, .mini-card .mini-card-stats {
  position: absolute; left: 6%; right: 6%; bottom: 7%; margin: 0; min-height: 0;
  display: flex; justify-content: center; gap: 7cqw;
}
.card-tag.mod-hr, .card-tag.mod-spread, .card-tag.mod-echo, .card-tag.mini {
  display: inline-flex; padding: 0; border: none; border-radius: 0; background: none; line-height: 0;
  color: rgba(239,230,214,.9); filter: drop-shadow(0 0 2px #0b0a08);
}
.card-tag svg { width: 19cqw; height: 19cqw; overflow: visible; }

/* 바탕 주문 (project plan/261017_basic_spells.md, 목업 E1) — 원소가 없는 마력이라 색이 없다(백금).
   채움 없이 선만 남은 빈 결정을 한 단계 가라앉혀, 직접 만든 카드가 앞에 서게 한다. 모두 정지 그림 */
:is(.card-comp, .mini-card).basic { --cc: #d4d0c6 !important; border-color: rgba(212,208,198,.24);
  background: linear-gradient(180deg, #0e0e0d, #0a0a09); box-shadow: 0 4px 10px rgba(0,0,0,.45); }
:is(.card-comp, .mini-card).basic .lt-shard { fill-opacity: 0; stroke-opacity: .7; }
:is(.card-comp, .mini-card).basic .lt-body { stroke: #d9d6ce; stroke-width: .7; filter: none; }
:is(.card-comp, .mini-card).basic .card-lattice { opacity: .6; }
:is(.card-comp, .mini-card).basic .cn-power { fill: #dcd9d2; filter: drop-shadow(0 0 1px #0b0a08) drop-shadow(0 0 2.5px #0b0a08); }
:is(.card-comp, .mini-card).basic .cn-stab { opacity: .6; }

/* 고르기 — 종이빛 테두리 + 떠오름 */
.card-comp.selectable { cursor: pointer; }
.card-comp.selectable:hover { transform: translateY(-4px); border-color: color-mix(in srgb, var(--cc) 60%, #efe6d6); }
.card-comp.selected {
  transform: translateY(-10px); border-color: #f0e9d9;
  box-shadow: var(--side), 0 0 0 1px rgba(240,233,217,.55), 0 0 18px rgba(240,233,217,.16), 0 12px 26px rgba(0,0,0,.6);
}
.mini-card:hover { transform: translateY(-4px); border-color: color-mix(in srgb, var(--cc) 60%, #efe6d6); box-shadow: var(--side), 0 10px 24px rgba(0,0,0,.55); }

/* 방향 표식 — 돋보기 뒷면 · 기록 등 글자 옆. 공격 ▸(밖으로) · 치유 ○(아묾) */
.dir-mark::before { content: ''; display: inline-block; flex-shrink: 0; box-sizing: border-box; }
.dir-attack::before  { width: 6px; height: 7px; background: currentColor; clip-path: polygon(0 0, 100% 50%, 0 100%); }
.dir-heal::before    { width: 6px; height: 6px; border: 1.3px solid currentColor; border-radius: 50%; }


/* 응축(글자 숫자용) — 돋보기 뒷면의 숫자. 카드 앞면의 응축은 위 .cfx-* (SVG) */
.mini-card-num { display: inline-block; }
.card-power.cond-0, .card-power.cond-3, .mini-card-num.cond-0, .mini-card-num.cond-3 { position: relative; display: inline-block; }
.cond-0 {
  opacity: .72; filter: blur(.4px);
  text-shadow: 0 0 .5em currentColor, 0 0 1.1em color-mix(in srgb, currentColor 45%, transparent);
}
.cond-2 { opacity: 1; text-shadow: 0 0 .22em currentColor, 0 0 .45em currentColor; }
.cond-3 { opacity: 1; filter: brightness(1.2) saturate(1.2); text-shadow: 0 0 .04em rgba(255,255,255,.75), 0 0 .12em currentColor, 0 0 .26em currentColor, 0 0 .5em currentColor; }
.cond-0::after, .cond-3::before { content: ''; position: absolute; pointer-events: none; border-radius: 50%; }
.cond-0::after {
  inset: -.3em -.45em;
  background:
    radial-gradient(circle at 12% 28%, currentColor 0 .04em, transparent .07em),
    radial-gradient(circle at 88% 22%, currentColor 0 .035em, transparent .065em),
    radial-gradient(circle at 80% 82%, currentColor 0 .045em, transparent .075em),
    radial-gradient(circle at 18% 78%, currentColor 0 .035em, transparent .065em),
    radial-gradient(circle at 50% 4%, currentColor 0 .03em, transparent .06em);
  animation: pt-cond-leak 2.8s ease-out infinite;
}
.cond-3::before {
  left: 50%; top: 50%; width: 1em; height: 1em; margin: -.5em 0 0 -.5em;
  border: 1px solid currentColor;
  animation: pt-cond-gather 2.2s ease-in infinite;
}
@keyframes pt-cond-leak {
  0%   { transform: scale(.75); opacity: .75; }
  100% { transform: scale(1.45); opacity: 0; }
}
@keyframes pt-cond-gather {
  0%   { transform: scale(1.7); opacity: 0; }
  60%  { opacity: .55; }
  100% { transform: scale(.85); opacity: 0; }
}


@media (prefers-reduced-motion: reduce) {
  .cfx-ring, .cfx-mote { animation: none !important; }
  .cond-0::after { animation: none; transform: scale(1.1); opacity: .45; }
  .cond-3::before { animation: none; transform: scale(1.05); opacity: .35; }
}
.reduce-motion .cfx-ring, .reduce-motion .cfx-mote { animation: none !important; }
.reduce-motion .cond-0::after { animation: none; transform: scale(1.1); opacity: .45; }
.reduce-motion .cond-3::before { animation: none; transform: scale(1.05); opacity: .35; }


/* ═══ 상전이 카드 (card.js phaseLayers) ═══════════════════════════════
   1~3단계 = 윗부분 흰 기호 줄 + 위쪽 상전이 전선 · 4단계 = 위아래 전선 · 5단계 = 테 빛 · 마력 흐름 · 틀 밖 파편
   교차 카드(.ph-x)만 호버할 때 한 번 흐려졌다 번쩍한다 */
.ph-band, .ph-alt, .ph-front, .ph-top, .ph-flow, .ph-spill { position: absolute; inset: 0; pointer-events: none; }
.ph-top, .ph-front, .ph-flow, .ph-spill { width: 100%; height: 100%; overflow: visible; }
.ph-alt { display: none; }
/* 윗부분 기호 — 2층 아이콘과 같은 흰 선 · 같은 그림자 */
.ph-top { color: rgba(239,230,214,.92); filter: drop-shadow(0 0 1px #0b0a08) drop-shadow(0 0 2.5px #0b0a08); }
.ph-g { transform-box: fill-box; transform-origin: center; }
.ph-g.on { animation: ph-pulse .6s ease-out; }
@keyframes ph-pulse { 40% { transform: scale(1.32); filter: drop-shadow(0 0 4px #fff); } }
/* 상전이 전선 — 위쪽 띠에서 격자가 반대 상태로 넘어간다. 4 · 5단계는 아래쪽 띠도 */
.ph-band { clip-path: polygon(0 0, 100% 0, 100% 24%, 88% 26.8%, 75% 24.6%, 62% 27.6%, 50% 25.2%, 38% 27.4%, 25% 24.8%, 12% 27%, 0 24.4%); }
.ph-band.ph-band2 { clip-path: polygon(0 75.6%, 12% 73%, 25% 75.2%, 38% 72.6%, 50% 74.8%, 62% 72.4%, 75% 75.4%, 88% 73.2%, 100% 76%, 100% 100%, 0 100%); }
.ph-card > .card-lattice { clip-path: polygon(0 24.4%, 12% 27%, 25% 24.8%, 38% 27.4%, 50% 25.2%, 62% 27.6%, 75% 24.6%, 88% 26.8%, 100% 24%, 100% 100%, 0 100%); }
:is(.ph-deep-4, .ph-deep-5) > .card-lattice { clip-path: polygon(0 24.4%, 12% 27%, 25% 24.8%, 38% 27.4%, 50% 25.2%, 62% 27.6%, 75% 24.6%, 88% 26.8%, 100% 24%,
  100% 76%, 88% 73.2%, 75% 75.4%, 62% 72.4%, 50% 74.8%, 38% 72.6%, 25% 75.2%, 12% 73%, 0 75.6%); }
.ph-front path { fill: none; stroke: color-mix(in srgb, var(--cc) 40%, #fff6e6); stroke-width: 1; stroke-linejoin: round; opacity: .55;
  filter: drop-shadow(0 0 1.5px var(--cc)) drop-shadow(0 0 4px color-mix(in srgb, var(--cc) 70%, transparent)); }
:is(.ph-deep-4, .ph-deep-5) .ph-front path { opacity: .9; stroke-width: 1.3; animation: ph-front-breathe 4.5s ease-in-out infinite; }
@keyframes ph-front-breathe { 50% { opacity: .5; } }
/* 5단계 — 테두리 안팎의 원소빛, 마력 흐름, 틀 밖 파편 (이 카드만 틀을 넘는다) */
:is(.card-comp, .mini-card).ph-deep-5 {
  overflow: visible;
  border-color: color-mix(in srgb, var(--cc) 55%, #f4ecdd);
  box-shadow: var(--side), inset 0 0 0 1px color-mix(in srgb, var(--cc) 55%, transparent), inset 0 0 22px color-mix(in srgb, var(--cc) 45%, transparent),
    0 0 22px color-mix(in srgb, var(--cc) 35%, transparent), 0 6px 16px rgba(0,0,0,.5);
}
/* 알갱이 = 반지름 두 배의 원에 방사 그라데이션(card.js phaseFlowSvg) — 속 절반은 알갱이 색, 바깥 절반은 원소빛이 옅어지는 번짐. filter 없음 */
.ph-mote { opacity: 0; }
.ph-mg-core { stop-color: color-mix(in srgb, var(--cc) 35%, #fffaf0); }
.ph-mg-edge { stop-color: var(--cc); }
.ph-flow-in .ph-mote  { animation: ph-in  var(--t) cubic-bezier(.5,0,.9,.6) var(--d) infinite; }
.ph-flow-out .ph-mote { animation: ph-out var(--t) cubic-bezier(.1,.4,.5,1) var(--d) infinite; }
@keyframes ph-in  { 0% { transform: translate(var(--dx), var(--dy)); opacity: 0; } 25% { opacity: .9; } 100% { transform: translate(0, 0); opacity: 0; } }
@keyframes ph-out { 0% { transform: translate(0, 0); opacity: 0; } 15% { opacity: .95; } 100% { transform: translate(var(--dx), var(--dy)); opacity: 0; } }
.ph-spill { z-index: 2; }
.ph-shard { opacity: 0; transform-box: fill-box; transform-origin: center; }
.ph-shard-core { fill: var(--cc); fill-opacity: .75; stroke: color-mix(in srgb, var(--cc) 40%, #fff6e6); stroke-width: .5; stroke-linejoin: round; }
/* 번짐 — filter 대신 같은 꼴의 굵고 옅은 테 */
.ph-shard-glow { fill: none; stroke: var(--cc); stroke-width: 2.6; stroke-opacity: .35; stroke-linejoin: round; }
.ph-spill-out .ph-shard { animation: ph-leak 3.6s cubic-bezier(.15,.5,.4,1) var(--d) infinite; }
.ph-spill-in .ph-shard  { animation: ph-return 3.6s cubic-bezier(.6,0,.85,.5) var(--d) infinite; }
@keyframes ph-leak   { 0% { transform: translate(0, 0) rotate(0) scale(.6); opacity: 0; } 12% { opacity: .95; }
                       100% { transform: translate(var(--dx), var(--dy)) rotate(140deg) scale(1); opacity: 0; } }
@keyframes ph-return { 0% { transform: translate(var(--dx), var(--dy)) rotate(140deg) scale(1); opacity: 0; } 30% { opacity: .9; }
                       100% { transform: translate(0, 0) rotate(0) scale(.5); opacity: 0; } }
/* 교차 카드 호버 — 흐려졌다 번쩍, 격자가 반대 상태로 잠깐 뒤집혔다 돌아온다 */
.ph-x:hover { animation: ph-blur .75s ease-out; }
@keyframes ph-blur { 14% { filter: blur(1.6px) brightness(2); } 36% { filter: blur(.5px) brightness(1.35); } 100% { filter: none; } }
.ph-x:hover .ph-alt { display: block; opacity: 0; animation: ph-alt-in .75s ease-out; }
@keyframes ph-alt-in { 0% { opacity: 0; } 24%, 46% { opacity: 1; } 100% { opacity: 0; } }
.ph-x:hover > .card-lattice, .ph-x:hover .ph-band { animation: ph-main-out .75s ease-out; }
@keyframes ph-main-out { 24%, 46% { opacity: 0; } }
/* 전투 — 4 · 5단계 효과가 일어날 때 카드 전체가 한 번 크게 일렁인다 (card.js phasePulse) */
.ph-surge { animation: ph-surge 1.4s cubic-bezier(.2,.7,.3,1); }
@keyframes ph-surge { 12% { filter: brightness(2.3) blur(1.2px); transform: scale(1.05); } 40% { filter: brightness(1.4); } 100% { filter: none; transform: none; } }
.ph-surge .ph-alt { display: block; opacity: 0; animation: ph-alt-in 1.4s ease-out; }

@media (prefers-reduced-motion: reduce) {
  .ph-x:hover, .ph-x:hover *, .ph-g.on, .ph-surge, .ph-surge *, .ph-front path, .ph-mote, .ph-shard { animation: none !important; }
  .ph-mote { opacity: .5; transform: translate(calc(var(--dx) * .5), calc(var(--dy) * .5)); }
  .ph-shard { opacity: .6; transform: translate(calc(var(--dx) * .4), calc(var(--dy) * .4)); }
}
.reduce-motion .ph-x:hover, .reduce-motion .ph-x:hover *, .reduce-motion .ph-g.on, .reduce-motion .ph-surge, .reduce-motion .ph-surge *, .reduce-motion .ph-front path, .reduce-motion .ph-mote, .reduce-motion .ph-shard { animation: none !important; }
.reduce-motion .ph-mote { opacity: .5; transform: translate(calc(var(--dx) * .5), calc(var(--dy) * .5)); }
.reduce-motion .ph-shard { opacity: .6; transform: translate(calc(var(--dx) * .4), calc(var(--dy) * .4)); }
