/* ═══ 원소 몸 — 제작대의 재료 (js/elbody.js, 목업 project plan/mockups/261014_craft_matter 의 E 응집) ═══
   겹: 보관함(.eb-case, 멈춤 · 둔중하게 조금) / 안개(.eb-mist, 멈춤) / 속(.eb-core · .eb-shell · .eb-press · .eb-water, 움직임).
   움직임은 transform · opacity뿐. 결(craft.js FEEL)의 CSS 변수를 그대로 받아 속에서 키워 쓴다 */
.el-body { position: relative; isolation: isolate; vertical-align: -.22em; pointer-events: none; }   /* 몸은 노드보다 커서(1.5배) 누름을 받지 않는다 — 노드 · ✕가 받는다 */
.hb .jin-node .node-x { z-index: 3; }   /* 결(.lb-spin z-index 1) 위로 — 몸에 가려 ✕ 아래쪽이 눌리지 않았다 */
.el-body > svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; }
.el-body .eb-mv, .el-body > .eb-case { will-change: transform; }
.hb .jin-orb .el-body { width: calc(var(--orb) * 1.5); height: calc(var(--orb) * 1.5); flex-shrink: 0; }
.hb .dock-els .el-dock { width: 1.65em; height: 1.65em; flex-shrink: 0; pointer-events: none; }   /* 원소 바 — 성운 창(elbody.js elDock) */
/* 노드 둘레의 원 · 색 번짐은 몸이 대신한다. 노드째 흔들던 결 · 회전 빛점(.lb-glint)도 몸 안으로 옮겼다 */
.hb .jin-orb { background: none; border-color: transparent; }
.hb .jin-node.active .jin-orb { border-color: var(--line); }
.hb .jin-orb .lb-glint { display: none !important; }
.hb .jin-orb.feel { animation: none; }
.hb .feel-wind > .lb-spin { animation: none; }
.hb .feel-earth::before, .hb .feel-water::before, .hb .feel-water .lb-aura::after { display: none; }

/* 출처 회전 — 성운이 원소 결 그대로 돈다(7.5초, 흙 30초). 정제 · 원소 바는 멈춤 */
.eb-spin, .eb-knot, .eb-gale, .eb-orbit, .eb-drink { transform-origin: 0 0; }
.lb.rot .eb-spin { animation: eb-spin 7.5s linear infinite; }
.lb.rot.ccw .eb-spin { animation-direction: reverse; }
.lb.rot.feel-earth .eb-spin { animation-duration: 30s; }
@keyframes eb-spin { to { transform: rotate(360deg); } }
/* 보조 빛점 — 노드를 고르거나 올렸을 때만 연하게 방향을 짚어 준다(꼬리는 지나온 쪽) */
.eb-orbit { display: none; }
.jin-node.active .lb.rot .eb-orbit { display: inline; opacity: .4; animation: eb-spin 5.5s linear infinite; }
@media (hover: hover) { .jin-node:hover .lb.rot .eb-orbit { display: inline; opacity: .4; animation: eb-spin 5.5s linear infinite; } }
.jin-node .lb.rot.ccw .eb-orbit { animation-direction: reverse; }
.lb.cw .eb-tail-ccw, .lb.ccw .eb-tail-cw { display: none; }

/* 응어리 — 모든 원소: 속이 조였다 풀린다(원본 숨쉬기 박자 --bp · 세기 --br) */
.jin-orb .eb-knot { animation: eb-knot var(--bp, 4.6s) ease-in-out infinite; }
@keyframes eb-knot { 50% { transform: scale(calc(.9 - var(--br, .1) * .25)); } }
.eb-feel, .eb-knot, .eb-fl, .eb-gale, .eb-drink, .eb-press, .el-body > .eb-case { animation-delay: calc(var(--ph, 0) * -1s) !important; }

/* 불 · 빛 — 속이 떨고, 짙은 덩이가 깜빡이거나(불) 번쩍인다(빛) */
.feel-fire .eb-feel, .feel-light .eb-feel { animation: eb-jit var(--jp) linear infinite; }
@keyframes eb-jit {
  0%, 100% { transform: translate(0, 0); }
  17% { transform: translate(calc(var(--jx) * 2), calc(var(--jx) * -.8)); }
  33% { transform: translate(calc(var(--jx) * -1.4), calc(var(--jx) * 1.2)); }
  50% { transform: translate(var(--jx), calc(var(--jx) * .6)); }
  67% { transform: translate(calc(var(--jx) * -2), calc(var(--jx) * -1)); }
  83% { transform: translate(calc(var(--jx) * .6), calc(var(--jx) * 1.6)); }
}
.feel-fire .eb-fl { animation: eb-flick var(--fp) linear infinite; }
@keyframes eb-flick {
  0%, 100% { opacity: .3; } 12% { opacity: calc(.3 + var(--fl) * .6); } 21% { opacity: .35; } 37% { opacity: calc(.3 + var(--fl)); }
  46% { opacity: .4; } 63% { opacity: calc(.3 + var(--fl) * .8); } 78% { opacity: .3; } 88% { opacity: calc(.3 + var(--fl) * .5); }
}
.feel-light .eb-fl { animation: eb-flash var(--fp) linear infinite; }
@keyframes eb-flash { 0%, 40%, 50%, 100% { opacity: .3; } 43% { opacity: calc(.3 + var(--fl)); } 45% { opacity: .4; } 47% { opacity: calc(.3 + var(--fl) * .8); } }

/* 바람 — 회오리. 성운을 둘러싼 껍질이 출처 방향으로 계속 돈다(3성일수록 빠르고 짙다, --k = 결 세기). 성운은 그 박자로 부푼다.
   정제(출처 없음)는 방향을 말하지 않도록 비틀었다 돌아온다 */
.eb-shell { opacity: 0; }
.feel-wind .eb-shell { opacity: calc(.12 + var(--k, 0) * .6); }
.feel-wind .eb-gale { animation: eb-gale calc(var(--tp, 1s) * 3.4) cubic-bezier(.45,0,.25,1) infinite alternate; }
@keyframes eb-gale {
  from { transform: rotate(calc(var(--k, 0) * -38deg)) scale(calc(1 - var(--k, 0) * .04)); }
  to { transform: rotate(calc(var(--k, 0) * 38deg)) scale(calc(1 + var(--k, 0) * .1)); }
}
.feel-wind .eb-feel { animation: eb-surge calc(var(--tp, 1s) * 3.4) cubic-bezier(.45,0,.25,1) infinite alternate; }
@keyframes eb-surge {
  from { transform: rotate(calc(var(--k, 0) * -22deg)) scale(1); }
  to { transform: rotate(calc(var(--k, 0) * 22deg)) scale(calc(1 + var(--k, 0) * .16)); }
}
.lb.rot.feel-wind .eb-gale { animation: eb-spin calc(16s - var(--k, 0) * 10s) linear infinite; }
.lb.rot.ccw.feel-wind .eb-gale { animation-direction: reverse; }
.lb.rot.feel-wind .eb-feel { animation: eb-swell calc(var(--tp, 1s) * 3.4) cubic-bezier(.45,0,.25,1) infinite alternate; }
@keyframes eb-swell { to { transform: scale(calc(1 + var(--k, 0) * .14)); } }

/* 흙 — 떠다니지 않는다. 무게중심은 아래이고, 무겁게 떨어져 오래 눌렸다가 천천히 든다(원본 주기 × 2). 숨도 없다.
   둥근 바닥 줄 대신 원소 모양 안의 납작한 눌림 빛이 같은 박자로 켜진다 */
.feel-earth .eb-knot { animation: none; }
.feel-earth .eb-feel { animation: eb-settle calc(var(--sp) * 2) linear infinite; }
@keyframes eb-settle {
  0% { transform: translate(0, 0) scale(1, 1); animation-timing-function: cubic-bezier(.7,0,1,.5); }
  30% { transform: translate(0, calc(var(--sink) * 1.1)) scale(calc(1 + var(--sq) * 3), calc(1 - var(--sq) * 4)); animation-timing-function: linear; }
  78% { transform: translate(0, calc(var(--sink) * 1.1)) scale(calc(1 + var(--sq) * 3), calc(1 - var(--sq) * 4)); animation-timing-function: cubic-bezier(.5,0,.5,1); }
  100% { transform: translate(0, 0) scale(1, 1); }
}
.eb-press { opacity: 0; transform-box: fill-box; transform-origin: 50% 50%; }
.feel-earth .eb-press { animation: eb-press calc(var(--sp) * 2) linear infinite; }
@keyframes eb-press {
  0% { opacity: calc(var(--press) * .15); transform: scale(.7, 1); animation-timing-function: cubic-bezier(.6,0,1,.6); }
  30% { opacity: calc(var(--press) * .85); transform: scale(1.1, 1); animation-timing-function: linear; }
  78% { opacity: calc(var(--press) * .7); transform: scale(1.08, 1); animation-timing-function: cubic-bezier(.5,0,.5,1); }
  100% { opacity: calc(var(--press) * .15); transform: scale(.7, 1); }
}

/* 물 — 둘레의 어둠이 그라데이션 띠로 안쪽까지 스며든다(두 겹이 엇갈려). 흔들림은 속만 */
.eb-water { opacity: 0; }
.feel-water .eb-water { opacity: 1; }
.eb-drink { opacity: 0; }
.feel-water .eb-drink { animation: eb-drink calc(var(--wp) * 1.1) cubic-bezier(.35,0,.65,1) infinite; }
.feel-water .eb-drink2 { animation-delay: calc(var(--ph, 0) * -1s - var(--wp) * .55) !important; }
@keyframes eb-drink {
  0% { transform: scale(1.3); opacity: 0; }
  30% { opacity: calc(.15 + var(--drink) * .55); }
  75% { opacity: calc(.12 + var(--drink) * .5); }
  100% { transform: scale(.55); opacity: 0; }
}
.feel-water .eb-feel { animation: eb-sway var(--wp) ease-in-out infinite; }
@keyframes eb-sway { 25% { transform: translate(calc(var(--sway) * 1.2), calc(var(--sway) * -.3)); } 50% { transform: translate(0, calc(var(--sway) * .15)); } 75% { transform: translate(calc(var(--sway) * -1.2), calc(var(--sway) * -.3)); } }

/* 보관함은 둔중하다 — 속보다 훨씬 작게(¼ 남짓), 조금 늦게 따라 움직인다. 3성일수록 속과 함의 차이가 커진다 */
.feel-fire .el-body > .eb-case, .feel-light .el-body > .eb-case { animation: eb-case-jit calc(var(--jp) * 2.2) ease-in-out infinite; }
@keyframes eb-case-jit { 0%, 100% { transform: translate(0, 0); } 30% { transform: translate(calc(var(--jx) * .3), calc(var(--jx) * -.15)); } 65% { transform: translate(calc(var(--jx) * -.25), calc(var(--jx) * .2)); } }
.feel-water .el-body > .eb-case { animation: eb-case-sway calc(var(--wp) * 1.15) ease-in-out infinite; }
@keyframes eb-case-sway { 25% { transform: translate(calc(var(--sway) * .25), 0); } 75% { transform: translate(calc(var(--sway) * -.25), 0); } }
.feel-wind .el-body > .eb-case { animation: eb-case-gale calc(var(--tp, 1s) * 3.4) cubic-bezier(.45,0,.25,1) infinite alternate; }
@keyframes eb-case-gale { from { transform: rotate(calc(var(--k, 0) * -2.5deg)); } to { transform: rotate(calc(var(--k, 0) * 2.5deg)); } }
.feel-earth .el-body > .eb-case { animation: eb-case-sink calc(var(--sp) * 2) linear infinite; }
@keyframes eb-case-sink {
  0%, 100% { transform: translate(0, 0); animation-timing-function: cubic-bezier(.7,0,1,.5); }
  32% { transform: translate(0, calc(var(--sink) * .18)); animation-timing-function: linear; }
  78% { transform: translate(0, calc(var(--sink) * .18)); animation-timing-function: cubic-bezier(.5,0,.5,1); }
}

/* 멈춤 — 화면 밖 · 연출 줄이기 · 움직임 줄이기 */
.el-body.eb-off *, .el-body.eb-off > svg { animation-play-state: paused !important; }
.el-body.eb-off .eb-mv, .el-body.eb-off > .eb-case { will-change: auto; }
.hb.lite .el-body, .hb.lite .el-body *, .pt-charging:not(.has-fx) .el-body * { animation: none !important; }
@media (prefers-reduced-motion: reduce) { .el-body, .el-body * { animation: none !important; } }
.reduce-motion .el-body, .reduce-motion .el-body * { animation: none !important; }

/* 결합 — 재료는 진 순서대로 하나씩 떠난다(노드 --i × --eb-step, craft.js JinFx). 속이 먼저, 안개가 뒤따라 걷히고, 보관함은 빈 함으로 옅게 남는다 */
.hb .hb-bench.has-fx .jin-node { animation: none; opacity: 1; }
.hb .hb-bench.has-fx .jin-node .hb-lab { opacity: .16; transition: opacity .3s; }
.hb .hb-bench.has-fx .lb-aura { opacity: 0; }
.hb .hb-bench.has-fx .el-body > .eb-core { animation: eb-empty .22s ease-in forwards !important; animation-delay: calc(var(--i, 0) * var(--eb-step, 230ms)) !important; }
.hb .hb-bench.has-fx .el-body > :is(.eb-mist, .eb-shell, .eb-press, .eb-water) { animation: eb-empty .7s ease-in forwards !important; animation-delay: calc(var(--i, 0) * var(--eb-step, 230ms) + 60ms) !important; }
.hb .hb-bench.has-fx .el-body > .eb-case { animation: eb-shell-fade 1s ease-in forwards !important; animation-delay: 0s !important; }
@keyframes eb-empty { to { opacity: 0; } }
@keyframes eb-shell-fade { to { opacity: .28; } }
.jin-fx.eb-fx { mix-blend-mode: screen; }

/* 결과 카드 — 진의 50%로 나타나 66%까지 커지고(craft.js revealCard), 그 크기로 빛나며 머문다. 누르면 아래 더미로 거둔다.
   머무는 크기 --eb-cs는 진 높이를 재어 정한다. 빛 두 겹: 뒤 번짐(::before) · 카드 위 빛(::after, screen) — 정지 그라데이션, 투명도만 숨쉰다 */
.hb .jin-core-card { transform: translate(-50%, -50%) scale(var(--eb-cs, var(--cs, .74))); }
.hb .jin-core-card::before, .hb .jin-core-card::after { content: ''; position: absolute; pointer-events: none; }
.hb .jin-core-card::before { left: 50%; top: 50%; width: 190%; height: 160%; transform: translate(-50%, -50%); z-index: -1; border-radius: 50%; opacity: .55;
  background: radial-gradient(closest-side, color-mix(in srgb, var(--eb-cc, #fff6e6) 45%, #fff6e6) 0%, color-mix(in srgb, var(--eb-cc, #fff6e6) 28%, transparent) 35%, transparent 100%);
  animation: eb-card-breath 4.2s ease-in-out infinite; }
.hb .jin-core-card::after { inset: 0; border-radius: 10px; z-index: 2; mix-blend-mode: screen; opacity: .45;
  background: radial-gradient(ellipse at 50% 42%, rgba(255,251,242,.55) 0%, color-mix(in srgb, var(--eb-cc, #fff6e6) 35%, transparent) 40%, transparent 80%);
  animation: eb-card-shine 4.2s ease-in-out infinite; }
@keyframes eb-card-breath { 50% { opacity: .8; } }
@keyframes eb-card-shine { 50% { opacity: .7; } }
.hb .jin-core-card.collect::before, .hb .jin-core-card.collect::after { animation: none; opacity: 0; transition: opacity .2s; }
.hb.lite .jin-core-card::before, .hb.lite .jin-core-card::after { animation: none; }
@media (prefers-reduced-motion: reduce) { .hb .jin-core-card::before, .hb .jin-core-card::after { animation: none; } }
.reduce-motion .hb .jin-core-card::before, .reduce-motion .hb .jin-core-card::after { animation: none; }
