/* ===== tokens.css ===== */
/* ── 데스크탑 전용 앱 ──────────────────────────────────────────────────────
 * 반응형(모바일) 레이아웃은 지원하지 않는다. 뷰포트 폭 기반 @media
 * (max-width/min-width) 브레이크포인트를 새로 추가하지 말 것.
 * 모션 접근성용 @media (prefers-reduced-motion) 은 허용한다.
 * 화면 최소 폭은 --app-min-w 이며, 그보다 좁은 뷰포트에서는 레이아웃을
 * 압축하지 않고 가로 스크롤을 노출한다. */
@font-face {
  font-family: "Pretendard";
  src: url("../../assets/fonts/pretendard/Pretendard-Regular.woff2") format("woff2");
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: "Pretendard";
  src: url("../../assets/fonts/pretendard/Pretendard-Medium.woff2") format("woff2");
  font-weight: 500;
  font-display: swap;
}
@font-face {
  font-family: "Pretendard";
  src: url("../../assets/fonts/pretendard/Pretendard-SemiBold.woff2") format("woff2");
  font-weight: 600;
  font-display: swap;
}
@font-face {
  font-family: "Pretendard";
  src: url("../../assets/fonts/pretendard/Pretendard-Bold.woff2") format("woff2");
  font-weight: 700;
  font-display: swap;
}

:root {
  --bg-0: #070910;
  --bg-1: #1a2030;
  --bg-2: #242c40;
  --border: #3a4358;
  --text-0: #f4f6fb;
  --text-1: #c6ccd9;
  --text-2: #8e96ab;
  --accent: #d9a441;
  --accent-hi: #f0c06a;
  --danger: #c04a4a;
  /* rgba() 가변 알파용 RGB 트리플 + 반복 색 토큰. */
  --accent-rgb: 217, 164, 65;
  --accent-hi-rgb: 240, 192, 106;
  --danger-rgb: 192, 74, 74;
  --fx-attn-dur: 1.6s; /* 주목 글로우 펄스 주기 — reduced-motion 에서 0s 로 멈춤 */
  --hover-bg: #232a3d;
  --hover-bg-2: #2a3348;
  --backdrop: rgba(0, 0, 0, 0.65);
  --overlay-backdrop: rgba(4, 6, 12, 0.72);
  --danger-soft: #ffb3b3;
  --success-soft: #b5e6c4;

  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 14px;

  --header-h: 3.5rem;
  /* 게임 화면 최소 폭 — 뷰포트가 이보다 좁으면 문서에 가로 스크롤바가 생긴다.
     전체화면 오버레이(position:fixed)는 문서 스크롤을 따라오지 않으므로
     각자 overflow:auto 로 자체 가로 스크롤을 갖는다. */
  --app-min-w: 1280px;

  font-synthesis: none;
}

/* ── 아이템/장비 등급 색 — 단일 출처 ──────────────────────────────────────
 * data-rarity / data-grade 가 붙은 요소에서 --rarity-color(텍스트)·--rarity-edge(보더)를
 * 정의한다. 자식 이름 요소는 `color: var(--rarity-color)` 한 줄로 색을 받는다(cascade).
 * 10단계: 유니크 > 고대 > 유물 > 전설 > 영웅 > 희귀 > 고급 > 일반 > 재료 > 잡템.
 * data-grade 블록은 뒤에 두어 동일 요소에서 등급(세트=녹색)이 rarity 색을 덮는다. */
[data-rarity="junk"]      { --rarity-color: #9aa0ad; --rarity-edge: #7a7e89; }
[data-rarity="common"]    { --rarity-color: #e6e8ef; --rarity-edge: #cfd3df; }
[data-rarity="material"]  { --rarity-color: #9cd0c8; --rarity-edge: #7ab8b0; }
[data-rarity="uncommon"]  { --rarity-color: #8cc89a; --rarity-edge: #5d9b6a; }
[data-rarity="rare"]      { --rarity-color: #93b7e8; --rarity-edge: #5b88c8; }
[data-rarity="epic"]      { --rarity-color: #cc97e3; --rarity-edge: #a35cc7; }
[data-rarity="legendary"] { --rarity-color: var(--accent-hi); --rarity-edge: #d9a441; }
[data-rarity="artifact"]  { --rarity-color: #f0dca8; --rarity-edge: #e6cc80; }
[data-rarity="ancient"]   { --rarity-color: #f0a64a; --rarity-edge: #e68a00; }
[data-rarity="unique"]    { --rarity-color: #ffb066; --rarity-edge: #ff8000; }
[data-grade="set"]        { --rarity-color: #34e0c0; --rarity-edge: #1fb89c; }
/* 잔혼(영혼군단 전용 재료) 전용색 — 등급색과 무관하게 한눈에 구분.
 * data-grade 와 같은 후순위 블록이라 동일 요소에서 rarity/grade 색을 덮는다(source-order).
 * 8속성 재료(가루/결정/보석)는 연금·강화 범용 재료라 전용색 없이 등급색을 그대로 쓴다. */
[data-family="janhon"]    { --rarity-color: #e87fb5; --rarity-edge: #d65a9a; }

html { font-size: clamp(15px, 1.7vh, 27px); }

html, body {
  margin: 0;
  padding: 0;
  min-width: var(--app-min-w);
  background: var(--bg-0);
  color: var(--text-0);
  font-family: "Pretendard", system-ui, -apple-system, "Segoe UI", sans-serif;
  -webkit-font-smoothing: antialiased;
}
*, *::before, *::after { box-sizing: border-box; }

button {
  font-family: inherit;
  font-size: 1rem;
  color: inherit;
  background: transparent;
  border: 0;
  cursor: pointer;
}

button:disabled { cursor: not-allowed; opacity: 0.5; }

/* ── 전역 스크롤바 — 황금 톤으로 통일.
 * 더 구체적인 컴포넌트 셀렉터(예: .exp-combat-log, .exp-combat-log-wrap)가 있으면 그쪽이 우선한다. */
* {
  scrollbar-width: thin;
  scrollbar-color: rgba(217, 164, 65, 0.45) transparent;
}
*::-webkit-scrollbar { width: 8px; height: 8px; }
*::-webkit-scrollbar-track { background: transparent; margin: 0.4rem 0; }
*::-webkit-scrollbar-thumb {
  background: linear-gradient(180deg, rgba(240, 192, 106, 0.5), rgba(217, 164, 65, 0.35));
  border-radius: 999px;
  border: 1px solid rgba(0, 0, 0, 0.3);
}
*::-webkit-scrollbar-thumb:hover {
  background: linear-gradient(180deg, rgba(240, 192, 106, 0.78), rgba(217, 164, 65, 0.55));
}
*::-webkit-scrollbar-corner { background: transparent; }

/* ── 주목(attention) 글로우 펄스 — 단일 출처 ──────────────────────────────
 * 알림·NEW·수령 가능 배지에 일관된 "눈에 띄는" 박동 효과를 준다. 모션은 통일하고
 * 색만 --fx-attn-rgb 로 바꾼다(기본 금색=보상/수령, 빨강=NEW/미확인 카운트).
 * tokens.css 는 번들 최상단·전 페이지 로드라 keyframe·변수가 페이지별 CSS 에서도 참조된다.
 * 사용: 셀렉터에 `animation: fx-attn-pulse var(--fx-attn-dur) ease-in-out infinite;`
 *   (또는 .fx-attn 클래스). 빨강은 셀렉터에서 --fx-attn-rgb: var(--danger-rgb); 만 셋.
 * --fx-attn-dur 를 변수로 둬 reduced-motion 에서 한 번에 모션을 멈춘다(전역 가드). */
@keyframes fx-attn-pulse {
  0%, 100% { box-shadow: 0 0 0.15rem 0 rgba(var(--fx-attn-rgb, var(--accent-hi-rgb)), 0.45); filter: brightness(1); }
  50%      { box-shadow: 0 0 0.7rem 0.12rem rgba(var(--fx-attn-rgb, var(--accent-hi-rgb)), 0.9); filter: brightness(1.18); }
}
/* ⚠ HTML 소비처는 현재 0 이지만 **지우지 말 것** — 토큰 계층의 공개 API 다.
   같은 이름의 @keyframes 를 9개 CSS 파일의 20여 셀렉터가 쓰고, 아래 reduced-motion
   가드 목록의 첫 항목이기도 하다. 새 주목 요소는 이 클래스나 위 animation 중 택1. */
.fx-attn { animation: fx-attn-pulse var(--fx-attn-dur) ease-in-out infinite; }

/* reduced-motion: 주목 펄스를 쓰는 전 셀렉터를 한 곳에서 끈다(단일 가드).
 * 셀렉터가 다른 파일에 정의돼 있어도 규칙은 전역 적용된다. 새 주목 요소 추가 시 여기에도 등록. */
@media (prefers-reduced-motion: reduce) {
  .fx-attn,
  .lvms-badge,
  .item-cell__new-dot,
  .mail-card__new-dot,
  .stats-head__points.is-active,
  .hero-slots__talent-btn.has-points,
  .hero-slots__pt-badge,
  .codex-cell--item.is-claimable,
  .codex-ms.is-ready .codex-claim-btn--sm,
  .gq-claim:not(:disabled),
  .goal__claim:not(:disabled),
  .menu-tab__badge,
  .equip-slot-row__new,
  .equip-slot__new,
  .mypage-widget__badge,
  /* 제작 연출(연금 양조 · 대장간 · 세공대). 진행 바는 craft-fx.js 가 transition 없이 즉시 채운다. */
  .crf-brew__bubble,
  .acf-forge__anvil::after,
  .acf-forge__spark,
  .acf-forge__gem { animation: none !important; } /* !important: tokens.css 가 번들 최상단이라 후순위 파일 룰을 이겨야 함(a11y 가드) */
}

/* ── 배지형 컴포넌트 줄바꿈 금지 ──────────────────────────────────────
 * 배지·칩·태그·필(pill)은 한 줄짜리 라벨이 전제라 줄바꿈되면 높이가 튀고
 * 그리드/행 정렬이 무너진다. 셀렉터가 다른 파일에 있어도 규칙은 전역 적용되므로
 * 여기 한 곳에서 관리한다. 새 배지형 컴포넌트를 만들면 여기에도 등록.
 * 후순위 파일이 white-space 를 재선언하지 않는 한 이 규칙이 유지된다. */
.lvms-badge,
.hero-slots__pt-badge,
.mypage-widget__badge,
.major-log-row__badge,
.menu-tab__badge,
.item-cell__badge,
.item-cell__new-badge,
.item-tooltip__godroll-badge,
.dmg-pop__crit-tag,
.section-head__tag,
.class-card__tag,
.enh-tag,
.spire-floor-tag,
.union-points-chip,
.union-merit-chip,
.union-ranks__you,
.union-ranks__label,
.cd-hero__rank,
.gq-tier-badge,
.gq-card__metric,
.gq-card__chip,
.gq-rank__badge,
.shop-modal__chip,
.cd-chip,
.cd-grow-chip,
.acf-chip,
.crf-shop-card__badge,
.crf-qty-chip,
.crf-filter-chip,
.codex-chip,
.souls-resonance__chip,
.souls-resonance__state,
.system-hint__chip,
.resonance__chip,
.res-surge-banner__chip,
.status-badge,
.combat-actor__reaction-chip,
.exp-status-badge,
.exp-school-chip,
.exp-step-chip,
.exp-city-group__stage,
.exp-region-card__dungeon-badge,
.exp-city-cleared-badge,
.gth-city-group__stage,
.gth-region-card__rare-badge,
.gth-step-chip,
.gth-gated__tag,
.gth-miss__tag,
.gth-running-counts__chip,
.union-supply-card__badge,
.gdm-stat__armory,
.gdm-resist__chip,
.outpost-guard-card__resist { white-space: nowrap; }

/* ===== layout.css ===== */
.app-root {
  width: 100%;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

/* ── 본문에 섞이는 링크 ───────────────────────────────────────────
   🔴 저장소에 전역 `a` 규칙이 없다. 그래서 색을 지정하지 않은 링크는 브라우저 기본값이
      그대로 나오고, **한 번 방문하면 :visited 보라색이 어두운 배경에 묻혀 글씨가 보이지
      않는다.** 방문 여부와 무관하게 강조색으로 고정한다(:visited 에는 color 만 허용된다).
   layout.css 에 두는 이유는 푸터와 같다 — core.bundle.css 두 번째 항목이라 per-page CSS 를
   무엇으로 싣든 따라온다. 문단 안에 링크를 넣을 때 이 클래스를 쓴다. */
.inline-link,
.inline-link:visited {
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.inline-link:hover { color: var(--accent-hi); }

/* ── 사이트 공용 푸터 ─────────────────────────────────────────────
   views/_partials/site-footer.php 의 두 표현형(full / compact).

   🔴 layout.css 에 두는 이유: 이 파일은 core.bundle.css 의 두 번째 항목이라
      per-page CSS 를 무엇으로 싣든(landing / characters / home / legal) 규칙이 따라온다.
      화면별 CSS 에 나눠 적으면 표기가 갈라진다.
   ⚠ 위키(views/wiki-layout.php)는 tokens+icons+wiki.css 만 실어 이 규칙이 닿지 않는다.
      그래서 위키 푸터는 파티셜을 쓰지 않고 자기 .wk-footer__link 로 링크를 건다. */
.site-footer {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.35rem;
  margin-top: 1.5rem;
  padding: 1rem 0.5rem 0;
  font-size: 0.78rem;
  line-height: 1.6;
  color: var(--text-2);
  text-align: center;
}
.site-footer__links,
.site-footer__biz {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin: 0;
}
.site-footer__copy { margin: 0; opacity: 0.7; }
.site-footer__sep { color: var(--border); }
.site-footer__link {
  color: var(--text-2);
  text-decoration: none;
  white-space: nowrap;
}
.site-footer__link:hover { color: var(--accent-hi); text-decoration: underline; }
.site-footer__link--em { color: var(--text-1); font-weight: 600; }

/* compact — 게임 하단 상태바(.home__bottom) 안에 한 줄로 들어간다.
   ⚠ .home * { min-width: 0 } 이 뒤에서 이기므로 폭은 min-width 로 잡지 않는다.
      줄바꿈 방지는 위 .site-footer__link 의 white-space 가 맡는다. */
.site-footer--compact {
  display: inline-flex;
  flex-direction: row;
  gap: 0.35rem;
  margin: 0;
  padding: 0;
  font-size: inherit;
  line-height: inherit;
}

/* ===== item-display.css ===== */
/* 공통 아이템 표시 — itemCell()/itemRow()/currencyRow() (item-display.js) 의 스타일 단일 출처.
 * 등급 색은 tokens.css 의 --rarity-color/--rarity-edge 에서 cascade.
 * 그리드/리스트 컨테이너의 배치(grid-template, gap)는 각 화면 CSS 가 담당한다. */

/* ── 가로 셀 (인벤토리·채집 보상 등 그리드) ───────────────────────────── */
.item-cell {
  position: relative;
  min-height: 2.6rem;
  padding: 0.35rem 0.55rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--bg-2);
  display: flex;
  align-items: center;
  gap: 0.55rem;
  text-align: left;
  cursor: pointer;
  transition: border-color 100ms ease, transform 100ms ease, background 100ms ease;
  user-select: none;
}
.item-cell:hover { border-color: var(--accent); }
.item-cell:focus-visible { outline: 2px solid var(--accent-hi); outline-offset: 2px; }

.item-cell--empty {
  border-style: dashed;
  background: var(--bg-1);
  cursor: default;
  justify-content: center;
}
.item-cell--empty:hover { border-color: var(--border); }
.item-cell__empty-label {
  font-size: 0.72rem;
  color: var(--text-2);
  letter-spacing: 0.04em;
}

.item-cell.is-picked {
  border-color: var(--accent-hi);
  box-shadow: 0 0 0 1px var(--accent-hi) inset;
  background: linear-gradient(180deg, rgba(var(--accent-rgb), 0.22), rgba(var(--accent-rgb), 0.04));
}
.item-cell.is-dim { opacity: 0.32; filter: grayscale(0.6); }

/* 매각 불가/잡템 등 비활성 셀(상점 판매 마이그레이션 대비). */
.item-cell--junk, .item-cell--locked { cursor: not-allowed; opacity: 0.55; filter: grayscale(0.5); }
.item-cell--junk:hover, .item-cell--locked:hover { border-color: var(--border); }

/* 착용 요구 레벨 미달 — 회색 처리 + 잠금 배지("🔒 Lv.N 필요"). 인벤토리·장비 후보 공통. */
.item-cell--locked-level { opacity: 0.6; filter: grayscale(0.55); }
.item-cell--locked-level:hover { border-color: var(--border); }
.item-cell__req {
  flex: 0 0 auto;
  margin-left: auto;
  font-size: 0.72rem;
  font-weight: 700;
  white-space: nowrap;
  color: var(--danger-soft);
  background: rgba(var(--danger-rgb), 0.18);
  border: 1px solid rgba(var(--danger-rgb), 0.42);
  padding: 0.05rem 0.4rem;
  border-radius: 0.4rem;
}
.item-cell__qty + .item-cell__req,
.item-cell__enhance + .item-cell__req { margin-left: 0.35rem; }

/* 새로 들어온 아이템 — 좌상단 펄스 점. */
.item-cell__new-dot {
  position: absolute;
  top: 0.25rem;
  left: 0.25rem;
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 999px;
  background: var(--accent-hi);
  box-shadow: 0 0 0 2px var(--bg-2), 0 0 0.45rem rgba(var(--accent-hi-rgb), 0.55);
  pointer-events: none;
  animation: fx-attn-pulse var(--fx-attn-dur) ease-in-out infinite;
}

/* 신규 획득 코너 배지(장비 교체 팝업 후보 등) — 슬롯 행 NEW 배지와 동일 의미. */
.item-cell__new-badge {
  position: absolute;
  top: 0.25rem;
  right: 0.25rem;
  z-index: 1;
  padding: 0.02rem 0.3rem;
  font-size: 0.56rem;
  font-weight: 800;
  letter-spacing: 0.05em;
  line-height: 1.5;
  color: #fff;
  background: var(--danger);
  border-radius: 999px;
  box-shadow: 0 0 0.5rem rgba(var(--danger-rgb), 0.55);
  pointer-events: none;
  --fx-attn-rgb: var(--danger-rgb);
  animation: fx-attn-pulse var(--fx-attn-dur) ease-in-out infinite;
}

/* 드래그&드롭 상태. (grab 커서는 실제 draggable 셀에만 — 인벤토리 한정) */
.item-cell[draggable="true"] { cursor: grab; }
.item-cell.is-dragging { opacity: 0.4; cursor: grabbing; border-style: dashed; }
.item-cell.is-drop-target {
  border-color: var(--accent-hi);
  box-shadow: 0 0 0 2px var(--accent-hi) inset;
  background: linear-gradient(180deg, rgba(var(--accent-rgb), 0.28), rgba(var(--accent-rgb), 0.06));
  transform: scale(1.04);
}
.item-cell.is-drop-target.item-cell--empty { border-style: solid; }

.item-cell__icon {
  flex: 0 0 auto;
  width: 1.85rem;
  height: 1.85rem;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.4rem;
}
.item-cell__icon .icon { width: 100%; height: 100%; object-fit: contain; }

/* 골드·경험치 마크(currencyCell)는 아이템 아이콘과 달리 도안에 여백이 없어 박스를 꽉 채운다.
   그대로 두면 같은 그리드의 아이템 아이콘보다 눈에 띄게 커 보이므로 시각 크기를 맞춘다. */
.item-cell--currency .item-cell__icon .icon { width: 74%; height: 74%; }

.item-cell__name {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--rarity-color, var(--text-0));
  white-space: normal;
  overflow-wrap: anywhere;
  word-break: keep-all;
  line-height: 1.3;
}

.item-cell__qty {
  flex: 0 0 auto;
  margin-left: auto;
  font-size: 0.74rem;
  font-weight: 700;
  color: var(--text-0);
  background: rgba(0, 0, 0, 0.55);
  border-radius: 4px;
  padding: 0.05rem 0.4rem;
  line-height: 1.4;
  pointer-events: none;
  transform-origin: right center;
  transition: transform 240ms ease-out, color 240ms ease-out, background 240ms ease-out;
}
.item-cell__qty::before { content: "×"; opacity: 0.7; margin-right: 0.1rem; }
.item-cell__qty.is-counting {
  transform: scale(1.45);
  color: var(--accent-hi);
  background: rgba(var(--accent-rgb), 0.55);
}

.item-cell__badge {
  flex: 0 0 auto;
  margin-left: auto;
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--accent-hi);
  background: rgba(var(--accent-rgb), 0.16);
  border: 1px solid rgba(var(--accent-rgb), 0.35);
  padding: 0.05rem 0.4rem;
  border-radius: 0.4rem;
}
.item-cell__qty + .item-cell__badge { margin-left: 0.35rem; }

/* 통화 셀(골드/EXP) — 보상 그리드에서 아이템 셀과 동일 형태, 수량 대신 +금액. */
.item-cell--currency { cursor: default; }
.item-cell--currency:hover { border-color: var(--border); }
.item-cell__amount {
  flex: 0 0 auto;
  margin-left: auto;
  font-size: 0.78rem;
  font-weight: 800;
  color: var(--accent-hi);
  font-variant-numeric: tabular-nums;
}

/* 등급 보더 — tokens 의 --rarity-edge. */
.item-cell[data-rarity] { border-color: var(--rarity-edge); }

/* 보상 결과 그리드 — 모달 폭에 맞춰 자동 줄바꿈(인벤토리 4열 강제 오버라이드).
   .inventory-grid 가 번들 뒤쪽이라 단일 클래스로는 못 덮으므로 compound 셀렉터로 명시.
   보상 이름은 한 줄(nowrap) 고정이므로 셀 폭을 넉넉히 줘 2단 배열에서도 줄바꿈 없이 들어가게 한다. */
.inventory-grid.reward-grid {
  grid-template-columns: repeat(auto-fit, minmax(10.5rem, 1fr));
  text-align: left;
}
.reward-grid .item-cell { cursor: default; }
.reward-grid .item-cell:hover { border-color: var(--rarity-edge, var(--border)); }
/* 보상 셀 이름은 한 줄 유지 — 넘치면 …로 줄이되(아이콘+수량은 항상 보이게).
   말줄임은 이름 **텍스트** span 에만 건다 — .item-cell__name 에 걸면 뒤에 붙은 아이템 레벨 배지가
   긴 이름에서 통째로 잘려 나간다(장비 셀에서 iLv 가 사라지는 회귀). 배지는 flex 로 자리를 지킨다. */
.reward-grid .item-cell__name {
  display: flex;
  align-items: baseline;
  min-width: 0;
}
.reward-grid .item-cell__name-text {
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.reward-grid .item-ilvl { flex: 0 0 auto; }

/* ── 가로 행 (탐험·우편 보상 등 리스트) ───────────────────────────────── */
.item-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.9rem;
  color: var(--text-1);
}
.item-row__icon {
  flex: 0 0 auto;
  width: 1.5rem;
  height: 1.5rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 1rem;
}
.item-row__icon .icon, .item-row__icon img { width: 1.4rem; height: 1.4rem; object-fit: contain; }
.item-row__name {
  flex: 1 1 auto;
  min-width: 0;
  color: var(--rarity-color, var(--text-0));
}
.item-row__sub { margin-left: 0.4rem; font-size: 0.78rem; color: var(--text-2); }

/* 장비 아이템 레벨 — 이름 바로 뒤 보조 표기(itemLevelBadge / PHP item_level_badge 단일 출처).
   셀·행·손조립 슬롯(홈 페이퍼돌·장비 교체 팝업·캐릭터 시트) 다섯 자리가 이 한 클래스를 공유한다.
   등급색(--rarity-color)을 따라가지 않고 늘 보조 톤이라, 이름이 등급색으로 튀어도 배지는 가라앉는다.
   font-size 는 em(부모 기준) — 셀 0.82rem·행 0.9rem·슬롯 0.85rem 어디서든 같은 비율로 작아진다. */
.item-ilvl {
  margin-left: 0.3rem;
  font-size: 0.72em;
  font-weight: 600;
  color: var(--text-2);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.item-row__enhance {
  display: inline-flex;
  align-items: center;
  vertical-align: middle;
  margin-left: 0.45rem;
  padding: 0.03rem 0.36rem;
  border: 1px solid rgba(79, 214, 200, 0.36);
  border-radius: 999px;
  background: rgba(79, 214, 200, 0.1);
  color: #7ee7d8;
  font-size: 0.68rem;
  font-weight: 800;
  line-height: 1.35;
  white-space: nowrap;
}
.item-row__trailing {
  flex: 0 0 auto;
  margin-left: auto;
  color: var(--accent-hi);
  font-weight: 600;
}

/* 아이콘 앞 커스텀 영역(분해/판매 체크박스 등). */
.item-row__lead { flex: 0 0 auto; display: inline-flex; align-items: center; }
.item-row__lead input[type="checkbox"] { margin: 0; cursor: pointer; }

/* 행 우측 인라인 액션 버튼(분해/판매/해제). */
.item-row__act {
  flex: 0 0 auto;
  margin-left: 0.5rem;
  padding: 0.3rem 0.7rem;
  background: var(--accent);
  color: #1a1108;
  border: 0;
  border-radius: 4px;
  cursor: pointer;
  font-size: 0.85rem;
  font-weight: 600;
}
.item-row__act:hover { filter: brightness(1.08); }

/* 재료 부족 등 미충족 행 — 우측 수치 강조. */
.item-row.is-short .item-row__trailing { color: var(--danger, #e0686b); }

/* 재료 수량 "필요 N · 보유 M" (matCountHtml 단일 출처).
   제작·도면 화면이 공유한다. 라벨(i)은 늘 보조 톤이고 숫자(b)만 색을 갖는다 —
   필요는 강조색, 보유는 본문색, 모자라면 보유 쪽만 위험색으로 뒤집힌다.
   tabular-nums: 행마다 자릿수가 달라도 숫자 폭이 흔들리지 않게. */
.mat-count {
  flex: 0 0 auto;
  margin-left: auto;
  display: inline-flex;
  align-items: baseline;
  gap: 0.3rem;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.mat-count i { font-style: normal; margin-right: 0.2rem; font-size: 0.72em; color: var(--text-2); }
.mat-count b { font-weight: 700; }
.mat-count__need b { color: var(--accent-hi); }
.mat-count__have b { color: var(--text-1); }
.mat-count__sep { color: var(--text-2); opacity: 0.5; }
.mat-count.is-short .mat-count__have i,
.mat-count.is-short .mat-count__have b { color: var(--danger-soft, #e0686b); }

/* ── 셀/행 옵션 보조 (상점·전투슬롯 등 마이그레이션) ──────────────────── */

/* 비활성 셀 상태(상점 판매 잡템/매각불가, 상품 마감). */
.item-cell.is-junk, .item-cell.is-locked, .item-cell.is-soldout {
  cursor: not-allowed;
  opacity: 0.55;
  filter: grayscale(0.5);
}
.item-cell.is-junk:hover, .item-cell.is-locked:hover, .item-cell.is-soldout:hover {
  border-color: var(--rarity-edge, var(--border));
}

/* 선택된 후보 셀(전투 물약 슬롯 피커). */
.item-cell.is-selected {
  border-color: var(--accent-hi);
  box-shadow: 0 0 0 1px var(--accent-hi) inset;
  background: linear-gradient(180deg, rgba(var(--accent-rgb), 0.22), rgba(var(--accent-rgb), 0.04));
}

/* 하단 보조 줄(상점 일일 한도·만료 카운트다운·마감) — 셀을 줄바꿈시켜 아래에 깐다. */
.item-cell:has(.item-cell__foot) { flex-wrap: wrap; }
.item-cell__foot {
  flex-basis: 100%;
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem 0.6rem;
  margin-top: 0.15rem;
  font-size: 0.72rem;
  color: var(--text-2);
}
.item-cell__sub { white-space: nowrap; }
.item-cell__enhance {
  flex: 0 0 auto;
  max-width: 100%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-left: 0;
  color: #7ee7d8;
  background: rgba(79, 214, 200, 0.1);
  border: 1px solid rgba(79, 214, 200, 0.38);
  border-radius: 999px;
  padding: 0.02rem 0.36rem;
  font-size: 0.68rem;
  font-weight: 800;
  line-height: 1.45;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  pointer-events: none;
}
.item-cell__enhance + .item-cell__qty,
.item-cell__enhance + .item-cell__badge { margin-left: 0.35rem; }

.item-cell:has(.item-cell__enhance) {
  display: grid;
  grid-template-columns: 1.85rem minmax(0, 1fr) auto;
  grid-template-areas:
    "icon name qty"
    "icon enhance enhance"
    "foot foot foot";
  column-gap: 0.55rem;
  row-gap: 0.16rem;
  align-items: center;
}
.item-cell:has(.item-cell__enhance) .item-cell__icon { grid-area: icon; }
.item-cell:has(.item-cell__enhance) .item-cell__name { grid-area: name; }
.item-cell:has(.item-cell__enhance) .item-cell__enhance {
  grid-area: enhance;
  justify-self: start;
}
.item-cell:has(.item-cell__enhance) .item-cell__qty,
.item-cell:has(.item-cell__enhance) .item-cell__badge,
.item-cell:has(.item-cell__enhance) .item-cell__req {
  grid-area: qty;
  justify-self: end;
  margin-left: 0;
}
.item-cell:has(.item-cell__enhance) .item-cell__foot { grid-area: foot; }

/* ===== reward-grid.css ===== */
/* ── 보상 그리드 (공유) ──────────────────────────────────────────
 * 탐험·첨탑 종료 보상 화면(rewardGridHtml)과 이계 상자 개봉 팝업(vault-page.js showOpenResult)이
 * 코드/시각적으로 동일한 보상 그리드를 쓰도록 explore.css 에서 분리한 공유 규칙.
 * core.bundle.css 에 편입되어 모든 페이지에서 사용 가능(탐험 화면 전용 .exp-reward-title/running 은 explore.css 유지).
 * ────────────────────────────────────────────────────────────── */

/* 보상 카드 — rewardGridHtml 산출물(라벨·그리드·재화 블록)을 세로로 쌓는 그릇.
   text-align 은 첨탑 정비/recap 화면의 가운데 정렬 상속을 끊기 위해 명시한다. */
.exp-reward-body {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  padding: 0.8rem 1rem;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  margin-bottom: 1rem;
  text-align: left;
}

/* 획득 아이템 — 인벤토리와 동일한 셀(item-display.css .item-cell) 그리드. */
.exp-reward-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.4rem;
}
.exp-reward-grid .item-cell { cursor: default; }
/* 골드·경험치는 아이템과 분리해 별도 섹션으로. 아이템이 있으면 구분선을 둔다. */
/* 골드·경험치는 한 행에 2단(2열)으로 나란히. */
.exp-reward-currency { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.25rem 0.6rem; }
.exp-reward-grid + .exp-reward-currency {
  margin-top: 0.6rem;
  padding-top: 0.6rem;
  border-top: 1px dashed var(--border);
}
/* 각 칸을 칩처럼 정돈 — 아이콘+라벨은 왼쪽, 수량은 강조해 오른쪽 정렬. */
.exp-reward-currency .item-row {
  gap: 0.4rem;
  padding: 0.45rem 0.65rem;
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}
.exp-reward-currency .item-row__name { flex: 0 0 auto; color: var(--text-2); font-size: 0.82rem; }
.exp-reward-currency .item-row__trailing { font-size: 1rem; font-weight: 700; }
.exp-reward-empty { color: var(--text-2); text-align: center; padding: 0.5rem; }

/* 보상 섹션 헤더 — 장비/아이템 시각 분리. */
.exp-reward-section-label {
  margin: 0.6rem 0 0.1rem;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  color: var(--text-2);
}
.exp-reward-feature + .exp-reward-section-label,
.exp-reward-section-label:first-child { margin-top: 0.2rem; }
/* 섹션 라벨 도입으로 기존 `.exp-reward-grid + .exp-reward-currency` 인접 셀렉터가 안 걸릴 수 있어 상단 간격 보강. */
.exp-reward-currency { margin-top: 0.6rem; }

/* 영혼 군단 성장 — 동행 영혼의 레벨업/EXP/유대를 전체 폭 상세 행으로. 화폐 그리드와 달리 1열. */
.exp-reward-souls { display: flex; flex-direction: column; gap: 0.3rem; margin-top: 0.1rem; }
.exp-reward-soul {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.35rem 0.5rem;
  padding: 0.45rem 0.65rem;
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: 0.82rem;
}
.exp-reward-soul.is-levelup {
  border-color: color-mix(in srgb, var(--accent-hi) 45%, var(--border));
  background: color-mix(in srgb, var(--accent-hi) 8%, var(--bg-1));
}
.exp-reward-soul__spark { flex: 0 0 auto; color: var(--accent-hi); }
.exp-reward-soul__name { flex: 0 0 auto; font-weight: 700; color: var(--text-1); }
.exp-reward-soul__level {
  display: inline-flex;
  align-items: baseline;
  gap: 0.25rem;
  font-weight: 700;
  color: var(--accent-hi);
}
.exp-reward-soul__arrow { opacity: 0.7; font-weight: 400; }
.exp-reward-soul__up { font-size: 0.72rem; color: var(--success, #6ec07a); }
.exp-reward-soul__meta { margin-left: auto; color: var(--text-2); font-size: 0.78rem; }

/* 고등급(영웅 이상) 장비 획득 피처 배너 — "득템" 강조. 등급색은 tokens.css data-rarity cascade. */
.exp-reward-feature {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: 0.5rem;
  padding: 0.65rem 0.9rem;
  border-radius: var(--radius-md);
  border: 1px solid var(--rarity-edge, var(--accent));
  background:
    radial-gradient(120% 140% at 0% 50%, rgba(255, 255, 255, 0.07), transparent 60%),
    linear-gradient(180deg, rgba(255, 255, 255, 0.05), rgba(0, 0, 0, 0.18));
  box-shadow: 0 0 14px var(--rarity-edge, transparent);
  animation: exp-reward-feature-pulse 2.2s ease-in-out infinite;
}
.exp-reward-feature__icon { font-size: 1.7rem; line-height: 1; flex: 0 0 auto; }
.exp-reward-feature__icon img, .exp-reward-feature__icon .icon {
  width: 2.1rem; height: 2.1rem;
  filter: drop-shadow(0 0 8px var(--rarity-edge, transparent));
}
.exp-reward-feature__body { display: flex; flex-direction: column; gap: 0.12rem; min-width: 0; }
.exp-reward-feature__headline { font-size: 0.95rem; color: var(--rarity-color, var(--accent-hi)); }
.exp-reward-feature__name {
  font-size: 0.82rem; font-weight: 700; color: var(--text-0);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.exp-reward-feature__spark {
  margin-left: auto;
  font-size: 1.1rem;
  color: var(--rarity-color, var(--accent-hi));
  animation: exp-reward-feature-spark 1.6s ease-in-out infinite;
}
@keyframes exp-reward-feature-pulse {
  0%, 100% { box-shadow: 0 0 8px var(--rarity-edge, transparent); }
  50%      { box-shadow: 0 0 20px var(--rarity-edge, transparent); }
}
@keyframes exp-reward-feature-spark {
  0%, 100% { opacity: 0.55; transform: scale(1); }
  50%      { opacity: 1;    transform: scale(1.25) rotate(8deg); }
}

.exp-reward-mail-notice {
  margin-top: 0.7rem;
  padding: 0.45rem 0.7rem;
  background: rgba(190, 80, 80, 0.12);
  border: 1px solid rgba(190, 80, 80, 0.4);
  border-radius: var(--radius-md);
  color: var(--danger);
  font-size: 0.8rem;
  text-align: center;
}

/* ===== modal.css ===== */
/* 전체화면 오버레이 공통 규칙 — position:fixed 라 문서 가로 스크롤(--app-min-w)을
   따라오지 않는다. overflow:auto 로 자체 스크롤을 갖고, safe 정렬로 넘칠 때
   시작점이 잘려 접근 불가해지는 것을 막는다. 백드롭은 fixed 로 항상 뷰포트를 덮는다. */
.modal {
  position: fixed;
  inset: 0;
  z-index: 10050;
  display: flex;
  align-items: safe center;
  justify-content: safe center;
  overflow: auto;
  padding: 1.5rem;
}

.modal__backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.65);
  backdrop-filter: blur(2px);
}

.modal__panel {
  position: relative;
  min-width: 18rem;
  max-width: min(28rem, 100%);
  max-height: 100%;            /* 뷰포트(오버레이 패딩 안)를 넘지 않도록 — 항목 多 시 잘림 방지. */
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: 0 1.5rem 3rem rgba(0, 0, 0, 0.55);
  color: var(--text-0);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  animation: modal-in 120ms ease-out;
}

@keyframes modal-in {
  from { opacity: 0; transform: translateY(0.5rem) scale(0.98); }
  to   { opacity: 1; transform: none; }
}

.modal__header {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.9rem 1rem;
  border-bottom: 1px solid var(--border);
  background: var(--bg-2);
}

.modal__icon {
  flex: 0 0 auto;
  width: 1.5rem;
  height: 1.5rem;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: 0.9rem;
  line-height: 1;
  color: var(--bg-0);
}

.modal__title {
  font-size: 0.95rem;
  font-weight: 600;
  letter-spacing: 0.02em;
}

.modal__body {
  padding: 1rem;
  font-size: 0.95rem;
  line-height: 1.55;
  color: var(--text-1);
  white-space: pre-wrap;
  word-break: break-word;
  min-height: 0;               /* flex 자식이 콘텐츠보다 작아질 수 있게 — 아래 스크롤 활성화. */
  overflow-y: auto;            /* 헤더/푸터는 고정, 본문이 길면 본문만 스크롤. */
}

/* 선택적 상세 슬롯 — 본문(.modal__body) 아래 임의 HTML(보상 그리드 등).
   본문과 가로 패딩을 맞추고, 그리드가 길면 스크롤. */
.modal__detail {
  padding: 0 1rem 0.75rem;
  max-height: 18rem;
  overflow-y: auto;
}

.modal__expected {
  display: inline-block;
  margin-top: 0.6rem;
  padding: 0.25rem 0.5rem;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.85rem;
  color: var(--text-0);
  user-select: all;
}

.modal__input {
  display: block;
  width: 100%;
  margin-top: 0.75rem;
  padding: 0.6rem 0.8rem;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text-0);
  font-size: 0.95rem;
  font-family: inherit;
  box-sizing: border-box;
}
.modal__input:focus { outline: none; border-color: var(--accent); }
.modal--warning .modal__input:focus { border-color: var(--danger); }

.modal__actions {
  display: flex;
  justify-content: flex-end;
  gap: 0.5rem;
  padding: 0.75rem 1rem 1rem;
  border-top: 1px solid var(--border);
  background: var(--bg-1);
}

.modal__btn {
  min-width: 5rem;
  padding: 0.5rem 0.9rem;
  font-size: 0.9rem;
  font-weight: 600;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--bg-2);
  color: var(--text-0);
  transition: background 120ms ease, border-color 120ms ease;
}
.modal__btn:hover  { background: #2d3650; }
.modal__btn:focus  { outline: 2px solid var(--accent); outline-offset: 2px; }

.modal__btn--ghost {
  background: transparent;
  color: var(--text-1);
}
.modal__btn--ghost:hover { background: rgba(255, 255, 255, 0.04); color: var(--text-0); }

/* Notice (기본 알림) — accent 컬러로 잔잔한 강조. */
.modal--notice .modal__panel  { border-color: rgba(var(--accent-rgb), 0.45); }
.modal--notice .modal__header { border-bottom-color: rgba(var(--accent-rgb), 0.35); }
.modal--notice .modal__icon   { background: var(--accent); }
.modal--notice .modal__title  { color: var(--accent-hi); }
.modal--notice .modal__btn--primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--bg-0);
}
.modal--notice .modal__btn--primary:hover { background: var(--accent-hi); border-color: var(--accent-hi); }

/* Warning (경고) — danger 컬러로 강한 경고. */
.modal--warning .modal__panel  { border-color: rgba(192, 74, 74, 0.6); }
.modal--warning .modal__header { border-bottom-color: rgba(192, 74, 74, 0.5); background: rgba(192, 74, 74, 0.12); }
.modal--warning .modal__icon   { background: var(--danger); color: var(--text-0); }
.modal--warning .modal__title  { color: #ff9a9a; }
.modal--warning .modal__btn--primary {
  background: var(--danger);
  border-color: var(--danger);
  color: var(--text-0);
}
.modal--warning .modal__btn--primary:hover { background: #d86060; border-color: #d86060; }

/* 창 잠금 — 「이 캐릭터는 다른 창에서 플레이 중입니다」(한 캐릭터 = 한 창).
   입력을 막는 것이 목적이라 idle 경고와 같은 최상단에 둔다. */
.modal--window-lock { z-index: 10100; }
.modal--window-lock .modal__body {
  /* 🔴 기본 .modal__body 는 white-space: pre-wrap 이다 — 템플릿 리터럴의 들여쓰기와 줄바꿈이
     그대로 렌더돼 문단 사이가 텅 빈다(idle 모달이 같은 이유로 같은 해제를 한다). */
  white-space: normal;
  padding: 1.1rem 1.25rem;
}
.modal--window-lock .modal__body p { margin: 0 0 0.5rem; }
.modal--window-lock .modal__body p:last-child { margin-bottom: 0; color: var(--text-2); font-size: 0.9rem; }

/* 서비스 점검 — 창 잠금·유휴 경고(10100)보다 상위 사실이라 그 위에 둔다.
   (모듈이 그 둘을 제거하지만, 제거 전에 그려지는 한 프레임도 가리지 않게 한다.) */
.modal--maintenance { z-index: 10150; }
.modal--maintenance .modal__body {
  white-space: normal;            /* 기본 .modal__body 의 pre-wrap 해제(템플릿 들여쓰기 무시). */
  padding: 1.1rem 1.25rem;
}
.modal--maintenance .modal__body p { margin: 0 0 0.5rem; }
.modal--maintenance .modal__body p:last-child { margin-bottom: 0; }
.modal--maintenance .maint-lock__until {
  color: var(--accent);
  font-weight: 600;
}
.modal--maintenance .maint-lock__note { color: var(--text-2); font-size: 0.9rem; }

/* Idle 자동 로그아웃 경고.
   - 다른 모든 팝업(아이템 툴팁 z-index 10090 포함) 위에 떠야 하므로 가장 높게. */
.modal--idle { z-index: 10100; }

.modal--idle .modal__body {
  white-space: normal;            /* 기본 .modal__body 의 pre-wrap 해제(템플릿 들여쓰기 무시). */
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.35rem;
  padding: 1.4rem 1.25rem 1.1rem;
}
.modal--idle .idle-warn__lead { margin: 0; color: var(--text-0); font-weight: 600; }
.modal--idle .idle-warn__sub  { margin: 0; color: var(--text-2); font-size: 0.88rem; }

/* 남은 시간 — 큰 숫자 + 작은 단위 라벨을 세로로 정렬해 시선 집중. */
.modal--idle .modal__countdown {
  margin-top: 0.7rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.1rem;
}
.modal--idle .modal__countdown b {
  color: var(--danger-soft);
  font-size: 2.4rem;
  font-weight: 800;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.modal--idle .idle-warn__unit { font-size: 0.8rem; color: var(--text-2); letter-spacing: 0.02em; }

/* 단일 버튼이라 가운데 정렬 + 살짝 넓게. */
.modal--idle .modal__actions { justify-content: center; }
.modal--idle .modal__actions .modal__btn { min-width: 9rem; }

/* Quantity prompt — stack 일부 처분/이동에 쓰는 수량 picker. */
.modal--qty .qty-stepper-wrap { padding-top: 0; }
.qty-stepper {
  display: flex;
  align-items: stretch;
  gap: 0.35rem;
  margin-top: 0.6rem;
}
.qty-stepper__btn {
  flex: 0 0 auto;
  min-width: 2.4rem;
  padding: 0.45rem 0.5rem;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text-0);
  font-weight: 600;
  font-size: 0.9rem;
  cursor: pointer;
  transition: background 120ms ease, border-color 120ms ease;
}
.qty-stepper__btn:hover { background: #2d3650; border-color: var(--accent); }
.qty-stepper__btn--max  { background: rgba(var(--accent-rgb), 0.16); border-color: rgba(var(--accent-rgb), 0.4); color: var(--accent-hi); }
.qty-stepper__btn--max:hover { background: rgba(var(--accent-rgb), 0.28); }
.qty-stepper__input {
  flex: 1 1 auto;
  min-width: 0;
  padding: 0.45rem 0.6rem;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text-0);
  font: inherit;
  font-weight: 700;
  text-align: center;
  -moz-appearance: textfield;
}
.qty-stepper__input::-webkit-outer-spin-button,
.qty-stepper__input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.qty-stepper__input:focus { outline: none; border-color: var(--accent); }

.qty-meta {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 0.4rem 1rem;
  margin-top: 0.6rem;
  font-size: 0.88rem;
  color: var(--text-1);
}
.qty-meta b { color: var(--text-0); }
.qty-total b { color: var(--accent-hi); }

/* ── 공통 중앙 모달 스캐폴딩 ───────────────────────────────────────────
 * 동일 구조 5종(인벤토리/상점/착용/전투슬롯/우편)의 컨테이너·백드롭 단일 출처.
 * 패널/헤더/본문 등 컴포넌트별 스타일은 각 파일에 유지.
 * (community/talent/풀오버레이는 z-index·정렬·alpha 가 달라 제외.) */
.inv-modal, .shop-modal, .equip-modal, .cslot-modal, .mail-modal, .char-detail-modal {
  position: fixed;
  inset: 0;
  z-index: 10040;
  display: flex;
  align-items: safe center;
  justify-content: safe center;
  overflow: auto;
  padding: 1.25rem;
}
.inv-modal__backdrop, .shop-modal__backdrop, .equip-modal__backdrop,
.cslot-modal__backdrop, .mail-modal__backdrop, .char-detail-modal__backdrop {
  position: fixed;
  inset: 0;
  background: var(--backdrop);
  backdrop-filter: blur(2px);
}

/* ── 동의형 모달(kind="agree") ──────────────────────────────────────────
   showAgreeConfirm() 전용. 체크박스를 켜기 전에는 확인 버튼이 disabled 다.
   ⚠ disabled 버튼의 시각적 상태는 tokens.css 의 전역 `button:disabled`
     (cursor:not-allowed; opacity:.5)가 담당한다 — 여기서 다시 칠하면 두 벌이 되어 갈라진다.
     input-confirm(정확 문구 입력형)이 이미 같은 규칙에 기대고 있다. */
.modal__agree {
  padding-top: 0;
  /* ⚠ .modal__body 의 white-space: pre-wrap 을 여기서 되돌린다 — 동의 문구는 서버가
     <template> 로 실어 보낸 마크업이라 줄바꿈·들여쓰기가 그대로 살아 있다. pre-wrap 이면
     그 공백이 빈 줄과 첫 줄 들여쓰기로 렌더돼 체크박스만 위로 떨어져 보인다.
     (.modal--idle .modal__body 가 같은 이유로 같은 해제를 한다.) */
  white-space: normal;
}
.modal__agree-row {
  display: flex;
  align-items: flex-start;
  gap: 0.55rem;
  padding: 0.7rem 0.8rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-2);
  cursor: pointer;
}
.modal__agree-row:hover { background: var(--hover-bg); }
.modal__agree-box {
  flex: 0 0 auto;
  width: 1.05rem;
  height: 1.05rem;
  /* 좌우는 브라우저 기본 여백(3~4px)을 지워 gap 만 간격의 주인이 되게 하고,
     위쪽 0.1rem 만 남겨 첫 줄 글자 중심에 체크박스 중심을 맞춘다. */
  margin: 0.1rem 0 0;
  accent-color: var(--accent);
  cursor: pointer;
}
.modal__agree-label {
  font-size: 0.86rem;
  line-height: 1.5;
  color: var(--text-1);
}
.modal__agree-label a {
  color: var(--accent-hi);
  text-decoration: underline;
}

/* 동의 모달의 상세 슬롯 — 고지 항목 목록. .modal__detail 안에 들어간다. */
.guest-notice {
  margin: 0;
  padding-left: 1.1rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  font-size: 0.86rem;
  line-height: 1.55;
  color: var(--text-1);
}
.guest-notice li::marker { color: var(--danger-soft); }
.guest-notice b { color: var(--danger-soft); }
.guest-notice__limits {
  margin: 0.7rem 0 0;
  padding-top: 0.7rem;
  border-top: 1px solid var(--border);
  font-size: 0.82rem;
  line-height: 1.55;
  color: var(--text-2);
}
.guest-notice__limits b { color: var(--text-1); }

/* 선택지 모달 — 세 갈래 이상의 되돌릴 수 없는 선택(비회원 기록 인계). 세로로 쌓아 읽히게 한다. */
.modal__choices {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding: 0 1rem 0.9rem;
}
.modal__choice {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  width: 100%;
  padding: 0.65rem 0.8rem;
  text-align: left;
  border: 1px solid var(--border);
  border-radius: 0.4rem;
  background: var(--bg-1);
  color: var(--text-0);
  cursor: pointer;
  transition: border-color 0.12s ease, background 0.12s ease;
}
.modal__choice:hover,
.modal__choice:focus-visible { border-color: var(--accent); background: var(--bg-2); }
.modal__choice--primary { border-color: var(--accent); }
.modal__choice-label { font-size: 0.92rem; font-weight: 600; }
.modal__choice-desc  { font-size: 0.82rem; line-height: 1.5; color: var(--text-2); }
.modal--choice .modal__actions { justify-content: center; }

/* ===== mail.css ===== */
/* 우편함 모달 + 메뉴 뱃지.
   - layout.php에서 항상 로드되므로 어느 화면에서나 메뉴 뱃지/모달이 동작한다.
*/

/* ── 메뉴 뱃지 ─────────────────────────────────────────── */
.menu-tab__badge {
  position: absolute;
  top: 0.3rem;
  right: 0.4rem;
  min-width: 1.1rem;
  height: 1.1rem;
  padding: 0 0.35rem;
  border-radius: 999px;
  background: var(--danger);
  color: var(--text-0);
  font-size: 0.7rem;
  font-weight: 700;
  line-height: 1.1rem;
  text-align: center;
  box-shadow: 0 0 0 2px var(--bg-2);
  pointer-events: none;
  --fx-attn-rgb: var(--danger-rgb);
  animation: fx-attn-pulse var(--fx-attn-dur) ease-in-out infinite;
}
.menu-tab.is-active .menu-tab__badge { box-shadow: 0 0 0 2px var(--bg-1); }
/* 텍스트 변형(월드보스 '공략중' 등) — 숫자 배지와 달리 폭 가변·nowrap. 배지는 nowrap 규약. */
.menu-tab__badge--text {
  min-width: 0;
  height: auto;
  border-radius: 0.55rem;
  padding: 0.05rem 0.4rem;
  font-size: 0.58rem;
  line-height: 1.25;
  white-space: nowrap;
}

/* ── 모달 컨테이너 ─────────────────────────────────────── */
/* .mail-modal 컨테이너·백드롭은 modal.css 공통 스캐폴딩에서 정의. */
.mail-modal__panel {
  position: relative;
  width: min(36rem, 100%);
  max-height: min(40rem, 92vh);
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: 0 1.5rem 3rem rgba(0, 0, 0, 0.55);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  animation: mail-modal-in 140ms ease-out;
}
@keyframes mail-modal-in {
  from { opacity: 0; transform: translateY(0.5rem) scale(0.98); }
  to   { opacity: 1; transform: none; }
}

.mail-modal__header {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.85rem 1rem;
  border-bottom: 1px solid var(--border);
  background: var(--bg-2);
}
.mail-modal__title {
  flex: 1;
  font-size: 1rem;
  font-weight: 700;
  color: var(--accent-hi);
  letter-spacing: 0.02em;
}
.mail-modal__claim-all {
  padding: 0.4rem 0.85rem;
  font-size: 0.8rem;
  font-weight: 600;
  border-radius: var(--radius-sm);
  border: 1px solid var(--accent);
  background: var(--accent);
  color: var(--bg-0);
  transition: background 120ms ease;
}
.mail-modal__claim-all:hover { background: var(--accent-hi); border-color: var(--accent-hi); }
.mail-modal__claim-all:disabled { opacity: 0.5; cursor: not-allowed; }

/* 일괄 삭제 — 파괴적 동작이므로 ghost + danger 톤으로 수령 버튼과 구분. */
.mail-modal__delete-all {
  padding: 0.4rem 0.85rem;
  font-size: 0.8rem;
  font-weight: 600;
  border-radius: var(--radius-sm);
  border: 1px solid var(--danger);
  background: transparent;
  color: var(--danger);
  transition: background 120ms ease, color 120ms ease;
}
.mail-modal__delete-all:hover { background: var(--danger); color: var(--text-0); }
.mail-modal__delete-all:disabled { opacity: 0.4; cursor: not-allowed; }
.mail-modal__delete-all:disabled:hover { background: transparent; color: var(--danger); }
.mail-modal__close {
  width: 2rem;
  height: 2rem;
  border-radius: 999px;
  font-size: 1rem;
  color: var(--text-1);
  background: transparent;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.mail-modal__close:hover { background: rgba(255, 255, 255, 0.06); color: var(--text-0); }

.mail-modal__body {
  flex: 1;
  overflow-y: auto;
  padding: 0.75rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  scrollbar-width: thin;
}

.mail-modal__empty {
  text-align: center;
  color: var(--text-2);
  padding: 3rem 1rem;
  font-size: 0.95rem;
  line-height: 1.6;
}
.mail-modal__empty strong { display: block; color: var(--text-1); margin-bottom: 0.4rem; font-size: 1.05rem; }

/* ── 메일 카드 ─────────────────────────────────────────── */
.mail-card {
  position: relative;
  flex-shrink: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-2);
  overflow: hidden;
  transition: border-color 120ms ease;
}
.mail-card:hover { border-color: var(--accent); }
.mail-card.is-expanded { border-color: var(--accent); }
.mail-card.is-new {
  background: linear-gradient(90deg, rgba(var(--accent-rgb), 0.10), var(--bg-2) 40%);
  border-color: rgba(var(--accent-rgb), 0.55);
}

.mail-card__head {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.7rem 0.85rem;
  cursor: pointer;
}

/* 신규 우편 펄스 점 — 아이템 NEW 점과 동일 톤.
   .mail-card 의 abs 자식으로 두어 head grid 레이아웃에 영향 없게 한다. */
.mail-card__new-dot {
  position: absolute;
  top: 0.4rem;
  left: 0.35rem;
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 999px;
  background: var(--accent-hi);
  box-shadow: 0 0 0 2px var(--bg-2), 0 0 0.45rem rgba(240, 187, 85, 0.55);
  pointer-events: none;
  z-index: 1;
  animation: fx-attn-pulse var(--fx-attn-dur) ease-in-out infinite;
}
.mail-card__icon {
  width: 2.25rem;
  height: 2.25rem;
  border-radius: var(--radius-sm);
  background: var(--bg-1);
  border: 1px solid var(--border);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 1.15rem;
  flex-shrink: 0;
}
.mail-card__main {
  flex: 1 1 0%;
  min-width: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 0.15rem;
  overflow: hidden;
}
.mail-card__sender {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.7rem;
  font-weight: 600;
  color: var(--text-2);
  letter-spacing: 0.02em;
  margin: 0;
  min-width: 0;
}
.mail-card__sender > span:last-child {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 읽음/읽지 않음 상태 칩 — 양방향으로 명시해 상태를 확실히 알 수 있게 한다. */
.mail-card__status-slot { flex-shrink: 0; }
.mail-card__status {
  display: inline-block;
  padding: 0.05rem 0.4rem;
  border-radius: 999px;
  font-size: 0.65rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  line-height: 1.4;
}
.mail-card__status.is-unread {
  color: var(--accent-hi);
  background: rgba(var(--accent-rgb), 0.16);
  border: 1px solid rgba(var(--accent-rgb), 0.45);
}
.mail-card__status.is-read {
  color: var(--text-2);
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--border);
}

/* 카드 헤더 삭제 버튼(휴지통). 펼침/받기와 무관하게 곧장 버릴 수 있다. */
.mail-card__delete {
  flex-shrink: 0;
  width: 1.9rem;
  height: 1.9rem;
  border-radius: var(--radius-sm);
  font-size: 0.95rem;
  color: var(--text-2);
  background: transparent;
  border: 1px solid transparent;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background 120ms ease, color 120ms ease, border-color 120ms ease;
}
.mail-card__delete:hover {
  color: var(--danger);
  background: rgba(var(--danger-rgb), 0.12);
  border-color: rgba(var(--danger-rgb), 0.45);
}
.mail-card__title {
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--text-0);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin: 0;
}
.mail-card__meta {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.2rem;
  font-size: 0.7rem;
  color: var(--text-2);
  flex-shrink: 0;
}
.mail-card__expires { color: var(--text-2); }
.mail-card__expires.is-soon { color: #ff9a9a; font-weight: 600; }

.mail-card__expand {
  border-top: 1px solid var(--border);
  padding: 0.85rem 1rem 1rem;
  background: var(--bg-1);
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}
.mail-card__expand[hidden] { display: none; }
.mail-card__body {
  font-size: 0.9rem;
  line-height: 1.55;
  color: var(--text-1);
  white-space: pre-wrap;
  word-break: break-word;
}
.mail-card__body:empty { display: none; }

.mail-card__rewards {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  padding: 0.6rem 0.7rem;
  border-radius: var(--radius-sm);
  background: var(--bg-2);
  border: 1px dashed var(--border);
}
/* 통화는 공통 .item-row(item-display.css), 아이템·장비는 인벤토리와 동일한
   .inventory-grid + .item-cell 로 표시. 좁은 카드 폭에 맞춰 열 수만 auto-fill.
   .inventory-grid(4열 고정)이 번들 뒤쪽에 와서 단일 클래스로는 덮이므로,
   두 클래스를 함께 지정해 우선순위를 높인다. 우편 첨부는 보통 1~2개라
   넉넉한 트랙으로 한글 이름이 한 줄에 들어오게 한다. */
.mail-card__grid.inventory-grid {
  grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
}
/* 셀 폭이 좁아지더라도 아이템명은 한 줄 고정 — 글자별 세로 줄바꿈을 원천 차단하고,
   넘치면 말줄임(…). 전체 이름은 셀 툴팁(data-item-meta)에서 확인 가능. */
/* 말줄임은 이름 텍스트 span 에만 — .item-cell__name 에 걸면 뒤의 아이템 레벨 배지가 같이 잘린다
   (reward-grid 와 동일 처방, item-display.css 참고). */
.mail-card__grid .item-cell__name {
  display: flex;
  align-items: baseline;
  min-width: 0;
}
.mail-card__grid .item-cell__name-text {
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  word-break: normal;
  overflow-wrap: normal;
}
.mail-card__grid .item-ilvl { flex: 0 0 auto; }
.mail-card__rewards-empty {
  margin: 0;
  font-size: 0.88rem;
  color: var(--text-2);
}

.mail-card__actions {
  display: flex;
  justify-content: flex-end;
  gap: 0.5rem;
}
.mail-card__claim {
  padding: 0.5rem 1.1rem;
  font-size: 0.9rem;
  font-weight: 700;
  border-radius: var(--radius-sm);
  border: 1px solid var(--accent);
  background: var(--accent);
  color: var(--bg-0);
  transition: background 120ms ease;
}
.mail-card__claim:hover { background: var(--accent-hi); border-color: var(--accent-hi); }
.mail-card__claim:disabled { opacity: 0.5; cursor: not-allowed; }

/* 펼친 영역의 삭제 버튼 — 받기 옆 ghost danger. */
.mail-card__discard {
  padding: 0.5rem 1rem;
  font-size: 0.9rem;
  font-weight: 600;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: transparent;
  color: var(--text-2);
  transition: background 120ms ease, color 120ms ease, border-color 120ms ease;
}
.mail-card__discard:hover {
  color: var(--danger);
  border-color: rgba(var(--danger-rgb), 0.5);
  background: rgba(var(--danger-rgb), 0.1);
}

/* ── 모바일 ───────────────────────────────────────────── */

/* ===== level-up.css ===== */
/* 레벨업 전용 모달 + 사이드바 EXP 바 강조 효과. */

.modal--levelup .modal__backdrop {
  background: radial-gradient(ellipse at center, rgba(255, 210, 110, 0.18) 0%, rgba(0, 0, 0, 0.78) 60%);
  backdrop-filter: blur(4px);
}

.modal__panel--levelup {
  min-width: 22rem;
  max-width: min(30rem, 100%);
  border-color: rgba(255, 210, 110, 0.55);
  background: linear-gradient(180deg, #1c1a14 0%, #14130f 100%);
  box-shadow:
    0 0 0 1px rgba(255, 210, 110, 0.15),
    0 1.5rem 3rem rgba(0, 0, 0, 0.7),
    0 0 4rem rgba(255, 210, 110, 0.18);
  animation: levelup-pop 360ms cubic-bezier(0.2, 1.4, 0.4, 1);
}

@keyframes levelup-pop {
  0%   { opacity: 0; transform: translateY(1rem) scale(0.86); }
  60%  { opacity: 1; transform: translateY(0)    scale(1.02); }
  100% { opacity: 1; transform: translateY(0)    scale(1);    }
}

.modal--levelup.is-closing .modal__panel--levelup {
  opacity: 0;
  transform: translateY(0.4rem) scale(0.97);
  transition: opacity 140ms ease-in, transform 140ms ease-in;
}

.levelup__crest {
  position: relative;
  height: 7.5rem;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  background:
    radial-gradient(circle at center, rgba(255, 210, 110, 0.22) 0%, transparent 65%),
    linear-gradient(180deg, rgba(255, 210, 110, 0.06), transparent);
  border-bottom: 1px solid rgba(255, 210, 110, 0.18);
}

.levelup__crest-text {
  position: relative;
  z-index: 2;
  font-size: 1.9rem;
  font-weight: 800;
  letter-spacing: 0.28em;
  color: #ffe7ad;
  text-shadow:
    0 0 0.4rem rgba(255, 210, 110, 0.7),
    0 0 1.2rem rgba(255, 170, 60, 0.45);
  animation: levelup-glow 1.4s ease-in-out infinite alternate;
}

@keyframes levelup-glow {
  from { text-shadow: 0 0 0.3rem rgba(255, 210, 110, 0.55), 0 0 0.9rem rgba(255, 170, 60, 0.35); }
  to   { text-shadow: 0 0 0.6rem rgba(255, 210, 110, 0.95), 0 0 1.6rem rgba(255, 170, 60, 0.7);  }
}

.levelup__crest-ring {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 6rem;
  height: 6rem;
  margin: -3rem 0 0 -3rem;
  border-radius: 50%;
  border: 2px solid rgba(255, 210, 110, 0.6);
  opacity: 0;
  animation: levelup-ring 1.6s ease-out infinite;
}
.levelup__crest-ring--lg {
  width: 9rem;
  height: 9rem;
  margin: -4.5rem 0 0 -4.5rem;
  animation-delay: 0.5s;
}
@keyframes levelup-ring {
  0%   { transform: scale(0.6); opacity: 0.0; }
  20%  { opacity: 0.7; }
  100% { transform: scale(1.6); opacity: 0.0; }
}

.levelup__body {
  padding: 1.2rem 1.4rem 0.4rem;
  text-align: center;
  color: var(--text-0);
}

.levelup__lv {
  font-size: 1rem;
  letter-spacing: 0.06em;
  color: var(--text-2);
}
.levelup__lv strong {
  font-size: 2.4rem;
  font-weight: 800;
  color: #ffd980;
  margin-left: 0.2rem;
  vertical-align: -0.15rem;
  text-shadow: 0 0 0.6rem rgba(255, 210, 110, 0.55);
}

.levelup__msg {
  margin: 0.4rem 0 0.9rem;
  color: var(--text-1);
  font-size: 0.95rem;
  letter-spacing: 0.02em;
}

.levelup__points {
  margin: 0;
  padding: 0.6rem 0.8rem;
  border-radius: var(--radius-sm);
  background: rgba(255, 210, 110, 0.08);
  border: 1px solid rgba(255, 210, 110, 0.22);
  color: var(--text-0);
  font-size: 0.92rem;
}
.levelup__points strong {
  color: #ffd980;
  font-weight: 800;
  font-size: 1.1rem;
  margin: 0 0.15rem;
}

.modal--levelup .modal__actions {
  border-top-color: rgba(255, 210, 110, 0.18);
  background: transparent;
  padding-top: 1rem;
}
.modal--levelup .modal__btn--primary {
  background: linear-gradient(180deg, #f5c45e, #d99a3a);
  border-color: #d99a3a;
  color: #2a1d08;
  font-weight: 700;
  letter-spacing: 0.04em;
}
.modal--levelup .modal__btn--primary:hover {
  background: linear-gradient(180deg, #ffd684, #e7a847);
  border-color: #e7a847;
}

/* 사이드바 패널 깜빡 강조 (한 레벨 단위 전환 시점). */
.panel.hero--leveled {
  box-shadow: 0 0 0 1px rgba(255, 210, 110, 0.55), 0 0 1.6rem rgba(255, 210, 110, 0.4);
  transition: box-shadow 140ms ease-out;
}

/* ── 경험치 획득 전용 모달 (레벨업 없이 순수 EXP 획득) ─────────────────────── */
/* 레벨업 모달과 같은 톤이되, 초록빛 강조로 "경험치 증가"를 구분한다. */
.modal--exp .modal__backdrop {
  background: radial-gradient(ellipse at center, rgba(140, 220, 120, 0.14) 0%, rgba(0, 0, 0, 0.72) 60%);
  backdrop-filter: blur(3px);
}

.modal__panel--exp {
  min-width: 20rem;
  max-width: min(26rem, 100%);
  border-color: rgba(150, 220, 130, 0.5);
  background: linear-gradient(180deg, #16190f 0%, #11130d 100%);
  box-shadow:
    0 0 0 1px rgba(150, 220, 130, 0.14),
    0 1.5rem 3rem rgba(0, 0, 0, 0.7),
    0 0 3rem rgba(150, 220, 130, 0.16);
  animation: levelup-pop 320ms cubic-bezier(0.2, 1.4, 0.4, 1);
}

.modal--exp.is-closing .modal__panel--exp {
  opacity: 0;
  transform: translateY(0.4rem) scale(0.97);
  transition: opacity 140ms ease-in, transform 140ms ease-in;
}

/* 공용 .modal__body 의 white-space:pre-wrap 이 템플릿 들여쓰기/줄바꿈을 여백으로 렌더해
   세로가 늘어난다 — 해제하고 콘텐츠에 맞는 컴팩트한 패딩으로. */
.modal--exp .modal__body {
  text-align: center;
  white-space: normal;
  padding: 1.1rem 1.2rem 1rem;
}

.exp-gain__amount {
  font-size: 1.8rem;
  font-weight: 800;
  color: #b8e6a0;
  letter-spacing: 0.02em;
  text-shadow: 0 0 0.7rem rgba(140, 220, 120, 0.5);
  margin: 0 0 0.5rem;
}

/* 현재 레벨 표기(레벨업 연출 중 숫자가 증가). */
.exp-gain__lv {
  margin: 0 0 0.6rem;
  color: var(--text-2);
  font-size: 0.9rem;
  letter-spacing: 0.04em;
}
.exp-gain__lv strong {
  display: inline-block;
  font-size: 1.3rem;
  font-weight: 800;
  color: #cfeeb8;
  margin-left: 0.15rem;
  vertical-align: -0.1rem;
}

/* 모달 안의 EXP 바 — home.css .bar/.bar__fill(width 600ms transition) 재사용, 두께만 키움. */
.exp-gain__bar {
  height: 0.7rem;
  margin: 0 auto;
  max-width: 20rem;
}

.exp-gain__meta {
  margin: 0.6rem 0 0;
  color: var(--text-2);
  font-size: 0.9rem;
  letter-spacing: 0.03em;
}

/* 레벨업 순간 표시되는 "LEVEL UP" 배지 — 바깥은 펄스(scale), 안쪽 span 은 지속 글로우. */
.exp-gain__levelup {
  margin: 0 0 0.55rem;
  font-size: 1.4rem;
  font-weight: 800;
  letter-spacing: 0.3em;
  color: #ffe7ad;
  line-height: 1.1;
}
.exp-gain__levelup span {
  display: inline-block;
  text-shadow: 0 0 0.5rem rgba(255, 210, 110, 0.8), 0 0 1.4rem rgba(255, 170, 60, 0.55);
  animation: levelup-glow 1.1s ease-in-out infinite alternate;
}

/* 레벨업 시 획득 능력치 포인트. */
.exp-gain__points {
  margin: 0.8rem auto 0;
  max-width: 20rem;
  padding: 0.5rem 0.7rem;
  border-radius: var(--radius-sm);
  background: rgba(255, 210, 110, 0.08);
  border: 1px solid rgba(255, 210, 110, 0.22);
  color: var(--text-0);
  font-size: 0.9rem;
}
.exp-gain__points strong { color: #ffd980; font-weight: 800; margin-left: 0.15rem; }

/* 레벨업 스탯 증가 내역 — 라벨 좌 / +값 우 정렬 행 목록. */
.exp-gain__stats {
  margin: 0.7rem auto 0;
  max-width: 20rem;
  padding: 0.55rem 0.75rem;
  border-radius: var(--radius-sm);
  background: rgba(120, 200, 255, 0.07);
  border: 1px solid rgba(120, 200, 255, 0.2);
  text-align: left;
}
.exp-gain__stats-title {
  margin: 0 0 0.4rem;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--text-1);
  text-align: center;
}
.exp-gain__stat-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.16rem 0.1rem;
  font-size: 0.88rem;
}
.exp-gain__stat-row + .exp-gain__stat-row { border-top: 1px solid rgba(255, 255, 255, 0.05); }
.exp-gain__stat-name  { color: var(--text-1); }
.exp-gain__stat-delta { color: #8fe388; font-weight: 800; font-variant-numeric: tabular-nums; }

/* 레벨업 순간 펄스(배지·레벨 숫자 공용). */
.exp-gain__levelup.is-pulse { animation: exp-lvpulse 560ms cubic-bezier(0.2, 1.4, 0.4, 1); }
.exp-gain__lv strong.is-pulse { animation: exp-lvpulse 560ms cubic-bezier(0.2, 1.4, 0.4, 1); }
@keyframes exp-lvpulse {
  0%   { transform: scale(0.6); opacity: 0.2; }
  45%  { transform: scale(1.35); opacity: 1; }
  100% { transform: scale(1); opacity: 1; }
}

/* 레벨업 순간 골든 플래시(패널 전면을 짧게 번쩍). */
.exp-gain__flash {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  opacity: 0;
  z-index: 2;
  background: radial-gradient(circle at 50% 42%, rgba(255, 232, 160, 0.5) 0%, rgba(255, 205, 100, 0.12) 38%, transparent 66%);
}
.exp-gain__flash.is-on { animation: exp-flash 560ms ease-out; }
@keyframes exp-flash {
  0%   { opacity: 0; }
  22%  { opacity: 1; }
  100% { opacity: 0; }
}

/* 레벨업 순간 확산 링 버스트(패널 중앙에서 2겹). */
.exp-gain__ring {
  position: absolute;
  left: 50%;
  top: 44%;
  width: 3.5rem;
  height: 3.5rem;
  margin: -1.75rem 0 0 -1.75rem;
  border-radius: 50%;
  border: 2px solid rgba(255, 214, 120, 0.85);
  box-shadow: 0 0 0.8rem rgba(255, 200, 90, 0.5);
  pointer-events: none;
  opacity: 0;
  z-index: 3;
  animation: exp-ring 820ms ease-out forwards;
}
.exp-gain__ring--lg {
  animation-delay: 130ms;
  border-color: rgba(255, 228, 155, 0.6);
}
@keyframes exp-ring {
  0%   { transform: scale(0.4); opacity: 0; }
  20%  { opacity: 0.95; }
  100% { transform: scale(2.6); opacity: 0; }
}

.modal--exp .modal__actions {
  border-top-color: rgba(150, 220, 130, 0.16);
  background: transparent;
  padding-top: 1rem;
}
.modal--exp .modal__btn--primary {
  background: linear-gradient(180deg, #86c46a, #5f9a4a);
  border-color: #5f9a4a;
  color: #10210a;
  font-weight: 700;
  letter-spacing: 0.04em;
}
.modal--exp .modal__btn--primary:hover {
  background: linear-gradient(180deg, #9ad684, #6ea753);
  border-color: #6ea753;
}

/* ── 레벨업을 포함한 경우: 초록톤 대신 골드톤으로 축하 강조. ─────────────────── */
.modal--exp-levelup .modal__backdrop {
  background: radial-gradient(ellipse at center, rgba(255, 210, 110, 0.16) 0%, rgba(0, 0, 0, 0.76) 60%);
}
.modal--exp-levelup .modal__panel--exp {
  border-color: rgba(255, 210, 110, 0.55);
  background: linear-gradient(180deg, #1c1a14 0%, #14130f 100%);
  box-shadow:
    0 0 0 1px rgba(255, 210, 110, 0.15),
    0 1.5rem 3rem rgba(0, 0, 0, 0.7),
    0 0 4rem rgba(255, 210, 110, 0.18);
}
.modal--exp-levelup .exp-gain__amount {
  color: #ffe7ad;
  text-shadow: 0 0 0.7rem rgba(255, 210, 110, 0.55);
}
.modal--exp-levelup .exp-gain__lv strong { color: #ffd980; }
.modal--exp-levelup .modal__btn--primary {
  background: linear-gradient(180deg, #f5c45e, #d99a3a);
  border-color: #d99a3a;
  color: #2a1d08;
}
.modal--exp-levelup .modal__btn--primary:hover {
  background: linear-gradient(180deg, #ffd684, #e7a847);
  border-color: #e7a847;
}
/* 레벨업일 땐 EXP 바 채움도 골드로. */
.modal--exp-levelup .exp-gain__bar .bar__fill {
  background: linear-gradient(90deg, #e7a847, #ffd684);
}

/* ===== afk-reward.css ===== */
/* 오프라인(AFK) 누적 보상 수령 팝업.
   modal.css 스캐폴드(.modal/.modal__*) 재사용 + 보물상자/보상 등장 연출. 금빛 톤. */

.modal--afk .modal__panel {
  /* 보상이 인벤토리 셀 2단 그리드로 들어가므로, 이름이 한 줄(nowrap)로 들어갈 폭을 확보한다.
     width 로 고정해 내용이 적어도 패널이 좁아져 1단으로 무너지지 않게 한다. */
  width: min(30rem, 100%);
  max-width: min(30rem, 100%);
  background: linear-gradient(180deg, #1c1a14 0%, #14130f 100%);
  border-color: rgba(245, 196, 94, 0.35);
}
.modal--afk .modal__header {
  border-bottom-color: rgba(245, 196, 94, 0.28);
  background: rgba(245, 196, 94, 0.10);
}
.modal--afk .modal__icon  { background: var(--accent); color: var(--bg-0); }
.modal--afk .modal__title { color: #ffe7ad; }

.modal--afk .modal__body {
  white-space: normal;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.4rem;
  padding: 1.25rem 1.25rem 0.75rem;
}

/* 보물상자 — 등장 시 통통 튀고 은은한 금빛. 수령(.is-opened) 시 한 번 더 강조. */
.modal--afk .afk__chest {
  font-size: 3.4rem;
  line-height: 1;
  margin: 0.2rem 0 0.4rem;
  filter: drop-shadow(0 0 14px rgba(255, 210, 110, 0.55));
  animation: afk-chest-pop 420ms cubic-bezier(0.2, 1.4, 0.4, 1) both,
             afk-chest-glow 1.8s ease-in-out 420ms infinite;
}
.modal--afk.is-opened .afk__chest { animation: afk-chest-burst 480ms cubic-bezier(0.2, 1.2, 0.3, 1) both; }

.modal--afk .afk__lead { margin: 0; color: var(--text-0); font-size: 0.98rem; }
.modal--afk .afk__lead b { color: #ffd980; }
.modal--afk .afk__sub  { margin: 0; color: var(--text-2); font-size: 0.82rem; }
.modal--afk .afk__note { margin: 0.5rem 0 0; color: var(--accent-hi); font-size: 0.8rem; }

/* 보상 목록 — item-display 의 .item-row 재사용. */
.modal--afk .afk__rewards {
  width: 100%;
  margin-top: 0.7rem;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  padding: 0.6rem;
  border: 1px dashed rgba(245, 196, 94, 0.30);
  border-radius: var(--radius-md);
  background: rgba(0, 0, 0, 0.25);
}
/* .is-revealing — 처음부터 보상이 채워진 채 열리는 모달(일일과업 등)의 순차 등장 연출.
   보상은 인벤토리 셀 그리드(.reward-grid .item-cell)로 렌더되므로 셀을 대상으로 한다. */
.modal--afk .afk__rewards.is-revealing .item-cell {
  animation: afk-row-in 320ms cubic-bezier(0.2, 0.9, 0.3, 1.4) both;
}
.modal--afk .afk__rewards.is-revealing .item-cell:nth-child(2) { animation-delay: 80ms; }
.modal--afk .afk__rewards.is-revealing .item-cell:nth-child(3) { animation-delay: 160ms; }
.modal--afk .afk__rewards.is-revealing .item-cell:nth-child(4) { animation-delay: 240ms; }
.modal--afk .afk__rewards.is-revealing .item-cell:nth-child(n+5) { animation-delay: 320ms; }
/* .is-claimed — 이미 보여주던 목록을 비우지 않고(깜빡임 없이) "수령 확정"을 연출.
   컨테이너는 금빛 글로우, 각 셀은 톡 튀는 팝(transform 만 사용 → 리플로우/크기변화 없음).
   오프라인/레벨 마일스톤 수령 연출에 사용(닫힘→재오픈처럼 보이던 .is-revealing 대체). */
.modal--afk .afk__rewards.is-claimed {
  border-color: rgba(245, 196, 94, 0.6);
  animation: afk-rewards-confirm 620ms ease-out both;
}
.modal--afk .afk__rewards.is-claimed .item-cell {
  animation: afk-row-claim 460ms cubic-bezier(0.2, 0.9, 0.3, 1.4) both;
}
.modal--afk .afk__rewards.is-claimed .item-cell:nth-child(2) { animation-delay: 90ms; }
.modal--afk .afk__rewards.is-claimed .item-cell:nth-child(3) { animation-delay: 180ms; }
.modal--afk .afk__rewards.is-claimed .item-cell:nth-child(4) { animation-delay: 270ms; }
.modal--afk .afk__rewards.is-claimed .item-cell:nth-child(n+5) { animation-delay: 360ms; }

/* 여정 속도(신발 move_speed) 보너스 — 본 보상과 구분되는 녹빛 박스로 "더 모은 양"을 강조. */
.modal--afk .afk__speed {
  width: 100%;
  margin-top: 0.55rem;
  padding: 0.55rem 0.6rem 0.6rem;
  border: 1px solid rgba(120, 210, 140, 0.35);
  border-radius: var(--radius-md);
  background: rgba(70, 150, 90, 0.10);
}
.modal--afk .afk__speed-head {
  margin: 0 0 0.45rem;
  font-size: 0.82rem;
  color: #c2efcc;
}
.modal--afk .afk__speed-head b { color: #8fe6a4; }

/* 단일 버튼 가운데 정렬 + 금빛 강조. */
.modal--afk .modal__actions { justify-content: center; }
.modal--afk .modal__actions .modal__btn { min-width: 9rem; }
.modal--afk .modal__btn--primary {
  background: linear-gradient(180deg, #f5c45e, #d99a3a);
  border-color: #d99a3a;
  color: #2a1c08;
}
.modal--afk .modal__btn--primary:hover { background: linear-gradient(180deg, #ffd684, #e7a847); border-color: #e7a847; }

@keyframes afk-chest-pop {
  0%   { opacity: 0; transform: translateY(0.6rem) scale(0.7); }
  60%  { opacity: 1; transform: translateY(0) scale(1.08); }
  100% { opacity: 1; transform: none; }
}
@keyframes afk-chest-glow {
  0%, 100% { filter: drop-shadow(0 0 10px rgba(255, 210, 110, 0.40)); }
  50%      { filter: drop-shadow(0 0 18px rgba(255, 210, 110, 0.85)); }
}
@keyframes afk-chest-burst {
  0%   { transform: scale(1); }
  40%  { transform: scale(1.25) rotate(-4deg); }
  100% { transform: scale(1) rotate(0); }
}
@keyframes afk-row-in {
  from { opacity: 0; transform: translateY(0.4rem) scale(0.96); }
  to   { opacity: 1; transform: none; }
}
@keyframes afk-rewards-confirm {
  0%   { box-shadow: 0 0 0 rgba(255, 210, 110, 0); }
  40%  { box-shadow: 0 0 16px rgba(255, 210, 110, 0.55); }
  100% { box-shadow: 0 0 0 rgba(255, 210, 110, 0); }
}
/* 행별 수령 팝 — opacity 는 1 로 고정(비워지지 않음), scale 만 변해 레이아웃에 영향 없음. */
@keyframes afk-row-claim {
  0%   { transform: scale(0.96); box-shadow: 0 0 0 rgba(255, 210, 110, 0); }
  45%  { transform: scale(1.035); box-shadow: 0 0 12px rgba(255, 210, 110, 0.5); }
  100% { transform: scale(1); box-shadow: 0 0 0 rgba(255, 210, 110, 0); }
}

/* ===== level-milestone.css ===== */
/* 레벨 마일스톤 — 사이드바 캐릭터 카드 레벨 표시 옆 "수령 가능" 배지.
 * 모달 자체는 .modal--afk 스킨을 재사용하므로 추가 스타일 없음. */
.lvms-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  margin-left: 0.4rem;
  padding: 0.1rem 0.5rem;
  border: 1px solid color-mix(in srgb, var(--accent) 50%, transparent);
  border-radius: 999px;
  background: color-mix(in srgb, var(--accent) 18%, transparent);
  color: var(--accent-hi, var(--accent));
  font-size: 0.7rem;
  font-weight: 700;
  cursor: pointer;
  animation: fx-attn-pulse var(--fx-attn-dur) ease-in-out infinite;
  vertical-align: middle;
}
.lvms-badge:hover {
  background: color-mix(in srgb, var(--accent) 30%, transparent);
}
.lvms-badge:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ===== combat-slots.css ===== */
/* 전투 슬롯 설정 모달.
 * mail.css 의 mail-modal 톤을 따른다 (z-index 10040, dark backdrop).
 */

/* .cslot-modal 컨테이너·백드롭은 modal.css 공통 스캐폴딩에서 정의. */
.cslot-modal__panel {
  position: relative;
  width: min(38rem, 100%);
  max-height: min(44rem, 92vh);
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: 0 1.5rem 3rem rgba(0, 0, 0, 0.55);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  animation: cslot-modal-in 140ms ease-out;
}
@keyframes cslot-modal-in {
  from { opacity: 0; transform: translateY(0.5rem) scale(0.98); }
  to   { opacity: 1; transform: none; }
}

.cslot-modal__header {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.85rem 1rem;
  border-bottom: 1px solid var(--border);
  background: var(--bg-2);
}
.cslot-modal__title {
  flex: 1;
  font-size: 1rem;
  font-weight: 700;
  color: var(--accent-hi);
  letter-spacing: 0.02em;
}
.cslot-modal__close {
  width: 2rem;
  height: 2rem;
  border-radius: 999px;
  font-size: 1rem;
  color: var(--text-1);
  background: transparent;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.cslot-modal__close:hover { background: rgba(255, 255, 255, 0.06); color: var(--text-0); }

.cslot-modal__body {
  flex: 1;
  overflow-y: auto;
  padding: 0.85rem 1rem 0.5rem;
  display: flex;
  flex-direction: column;
  gap: 1rem;
  scrollbar-width: thin;
}

.cslot-modal__empty {
  text-align: center;
  color: var(--text-2);
  padding: 1.5rem 1rem;
  font-size: 0.9rem;
  line-height: 1.6;
}
.cslot-modal__empty strong { display: block; color: var(--text-1); margin-bottom: 0.3rem; }

/* ── 섹션 ─────────────────────────────────────────────── */
.cslot-section { display: flex; flex-direction: column; gap: 0.45rem; }
.cslot-section__title {
  font-size: 0.78rem;
  letter-spacing: 0.08em;
  color: var(--text-2);
  text-transform: uppercase;
  font-weight: 700;
}
.cslot-section__desc {
  font-size: 0.78rem;
  color: var(--text-2);
  line-height: 1.4;
}

/* ── 현재 슬롯 ────────────────────────────────────────── */
.cslot-current {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.5rem;
}
.cslot-current__slot {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.3rem;
  padding: 0.75rem 0.6rem 0.7rem;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  text-align: center;
  cursor: pointer;
  font: inherit;
  color: inherit;
  transition: background 100ms ease, border-color 100ms ease, box-shadow 100ms ease;
}
.cslot-current__slot:hover { background: var(--hover-bg); border-color: var(--accent); }
.cslot-current__slot.is-active {
  border-color: var(--accent-hi);
  box-shadow: 0 0 0 1px var(--accent-hi) inset;
  background: linear-gradient(180deg, rgba(var(--accent-rgb), 0.14), rgba(var(--accent-rgb), 0.02));
}
.cslot-current__slot--empty {
  border-style: dashed;
  background: var(--bg-1);
}
.cslot-current__slot--locked {
  border-style: dashed;
  background: var(--bg-1);
  opacity: 0.5;
  cursor: default;
}
.cslot-current__slot--locked:hover { background: var(--bg-1); border-color: var(--border); }
.cslot-current__slot--locked .cslot-current__icon { filter: grayscale(1); }
.cslot-current__idx {
  position: absolute;
  top: 0.3rem;
  left: 0.45rem;
  font-size: 0.62rem;
  font-weight: 700;
  color: var(--text-2);
  letter-spacing: 0.08em;
}
.cslot-current__slot.is-active .cslot-current__idx { color: var(--accent-hi); }
.cslot-current__icon {
  font-size: 1.7rem;
  width: 2.2rem;
  height: 2.2rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.cslot-current__icon .icon { width: 2rem; height: 2rem; }
.cslot-current__text { width: 100%; min-width: 0; }
.cslot-current__name {
  font-weight: 700;
  color: var(--text-0);
  font-size: 0.82rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.cslot-current__meta { font-size: 0.7rem; color: var(--text-2); margin-top: 0.1rem; }
.cslot-current__clear {
  position: absolute;
  top: 0.25rem;
  right: 0.3rem;
  width: 1.2rem;
  height: 1.2rem;
  border-radius: 999px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 0.7rem;
  color: var(--text-2);
  background: rgba(0, 0, 0, 0.25);
  cursor: pointer;
}
.cslot-current__clear:hover { color: #ff8a8a; background: rgba(255, 0, 0, 0.15); }

/* ── 후보 그리드 ──────────────────────────────────────── */
.cslot-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr));
  gap: 0.45rem;
}

/* ── 푸터 / 버튼 ──────────────────────────────────────── */
.cslot-modal__footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.75rem 1rem;
  border-top: 1px solid var(--border);
  background: var(--bg-2);
}
.cslot-modal__autosave {
  font-size: 0.78rem;
  color: var(--text-3);
  transition: color 120ms ease;
}
.cslot-modal__autosave.is-saved { color: var(--accent-hi); }
.cslot-modal__autosave.is-error { color: var(--danger, #e06c6c); }
.cslot-btn {
  padding: 0.5rem 1rem;
  border-radius: var(--radius-sm);
  font-size: 0.85rem;
  font-weight: 600;
  cursor: pointer;
  border: 1px solid var(--border);
  background: var(--bg-2);
  color: var(--text-1);
  transition: background 100ms ease, border-color 100ms ease, color 100ms ease;
}
.cslot-btn--primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--bg-0);
}
.cslot-btn--primary:hover {
  background: var(--accent-hi);
  border-color: var(--accent-hi);
}

/* 폰: 와이드(38rem) 모달 → 풀스크린. */

/* ===== equip-modal.css ===== */
/* 장비 착용 팝업.
 * combat-slots.css 톤을 따른다 (z-index 10040, dark backdrop, --accent 강조).
 * 좌측 슬롯 목록 + 우측 후보 피커의 2열 레이아웃.
 */

/* .equip-modal 컨테이너·백드롭은 modal.css 공통 스캐폴딩에서 정의. */
.equip-modal__panel {
  position: relative;
  width: min(52rem, 100%);
  max-height: min(50rem, 92vh);
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: 0 1.5rem 3rem rgba(0, 0, 0, 0.55);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  animation: equip-modal-in 140ms ease-out;
}
@keyframes equip-modal-in {
  from { opacity: 0; transform: translateY(0.5rem) scale(0.98); }
  to   { opacity: 1; transform: none; }
}

.equip-modal__header {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.85rem 1rem;
  border-bottom: 1px solid var(--border);
  background: var(--bg-2);
}
.equip-modal__title {
  flex: 1;
  font-size: 1rem;
  font-weight: 700;
  color: var(--accent-hi);
  letter-spacing: 0.02em;
}
.equip-modal__close {
  width: 2rem;
  height: 2rem;
  border-radius: 999px;
  font-size: 1rem;
  color: var(--text-1);
  background: transparent;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.equip-modal__close:hover { background: rgba(255, 255, 255, 0.06); color: var(--text-0); }

/* ── 상단 스탯 바(종합 스탯 + 착용 실시간 델타) ───────────────
   5×2 균등 그리드(스탯 9개 → 5+4). 세로를 2행으로 눌러 슬롯 목록에 높이를 양보한다.
   각 셀은 라벨(좌)·값(우) 정렬 → 열마다 숫자가 우측으로 가지런히 맞아 표처럼 읽힌다.
   내부 구분선(우/상)만 그려 격자를 만들되, 첫 행 상단·마지막 열 우측·마지막 셀 우측 선은 제거해 겹침을 피한다. */
.equip-modal__statbar {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  border-bottom: 1px solid var(--border);
  background: var(--bg-2);
}
.equip-modal__statbar:empty { display: none; }
.equip-stat {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.5rem 1rem;
  min-width: 0;
  border-top: 1px solid var(--border-soft, var(--border));
  border-right: 1px solid var(--border-soft, var(--border));
}
.equip-stat:nth-child(-n + 5) { border-top: none; }   /* 첫 행(1~5): 헤더 border 와 겹침 방지 */
.equip-stat:nth-child(5n)     { border-right: none; }  /* 마지막 열(5·10): 우측 선 제거 */
.equip-stat:last-child        { border-right: none; }  /* 마지막 행이 덜 찼을 때(9번째) 끝단 선 제거 */
.equip-stat__label {
  font-size: 0.74rem;
  color: var(--text-2);
  letter-spacing: 0.02em;
  white-space: nowrap;
}
.equip-stat__val {
  font-size: 0.92rem;
  font-weight: 700;
  color: var(--text-0);
  font-variant-numeric: tabular-nums;
  display: inline-flex;
  align-items: baseline;
  gap: 0.3rem;
  white-space: nowrap;
}
.equip-stat__delta {
  font-size: 0.72rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  animation: equip-stat-delta-in 260ms ease-out;
}
.equip-stat__delta.is-up   { color: var(--success-soft, #8cc89a); }
.equip-stat__delta.is-down { color: var(--danger-soft, #ffb3b3); }
@keyframes equip-stat-delta-in {
  from { opacity: 0; transform: translateY(-0.25rem); }
  to   { opacity: 1; transform: none; }
}

.equip-modal__body {
  flex: 1;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
.equip-modal__loading,
.equip-modal__empty {
  text-align: center;
  color: var(--text-2);
  padding: 1.5rem 1rem;
  font-size: 0.9rem;
  line-height: 1.6;
}
.equip-modal__loading strong { display: block; color: var(--text-1); margin-bottom: 0.3rem; }

/* ── 2열 레이아웃 ─────────────────────────────────────── */
.equip-modal__cols {
  flex: 1;
  display: grid;
  grid-template-columns: 17rem 1fr;
  min-height: 0;
  overflow: hidden;
}
.equip-modal__slots {
  display: flex;
  flex-direction: column;
  gap: 0.24rem;
  padding: 0.55rem;
  overflow-y: auto;
  border-right: 1px solid var(--border);
  background: var(--bg-0);
  scrollbar-width: thin;
}
.equip-modal__picker {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  padding: 0.85rem 1rem;
  overflow-y: auto;
  scrollbar-width: thin;
}

/* ── 좌측: 슬롯 행 ────────────────────────────────────── */
.equip-slot-row {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.38rem 0.6rem;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  text-align: left;
  cursor: pointer;
  font: inherit;
  color: inherit;
  transition: background 100ms ease, border-color 100ms ease, box-shadow 100ms ease;
}
.equip-slot-row:hover { background: var(--hover-bg); border-color: var(--accent); }
.equip-slot-row.is-active {
  border-color: var(--accent-hi);
  box-shadow: 0 0 0 1px var(--accent-hi) inset;
  background: linear-gradient(180deg, rgba(var(--accent-rgb), 0.14), rgba(var(--accent-rgb), 0.02));
}
.equip-slot-row.is-empty .equip-slot-row__icon { opacity: 0.6; }
.equip-slot-row.is-locked { opacity: 0.6; }
/* NEW(업그레이드 알림) 코너 배지 — 로비 슬롯과 동일 의미. */
.equip-slot-row { position: relative; }
.equip-slot-row__new {
  position: absolute;
  top: 0.28rem;
  right: 0.34rem;
  z-index: 1;
  padding: 0.02rem 0.3rem;
  font-size: 0.58rem;
  font-weight: 800;
  letter-spacing: 0.05em;
  line-height: 1.45;
  color: #fff;
  background: var(--danger);
  border-radius: 999px;
  box-shadow: 0 0 0.5rem rgba(192, 74, 74, 0.55);
  pointer-events: none;
  --fx-attn-rgb: var(--danger-rgb);
  animation: fx-attn-pulse var(--fx-attn-dur) ease-in-out infinite;
}
.equip-slot-row__icon {
  width: 2rem;
  height: 2rem;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 1.3rem;
}
.equip-slot-row__icon .icon { width: 1.8rem; height: 1.8rem; }
/* 2행 고정 그리드: 1행=라벨(전체폭), 2행=아이템명(1fr, 생략표시) + 강화 배지(우측).
   강화 배지를 아이템명과 같은 줄에 두어 행 높이를 강화 유무와 무관하게 일정하게 유지 →
   12개 슬롯이 강화 장비를 껴도 스크롤바 없이 한 화면에 들어온다. */
.equip-slot-row__body {
  flex: 1;
  min-width: 0;
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: baseline;
  column-gap: 0.4rem;
  row-gap: 0.1rem;
}
.equip-slot-row__label {
  grid-column: 1 / -1;
  font-size: 0.7rem;
  letter-spacing: 0.05em;
  color: var(--text-2);
  text-transform: uppercase;
  font-weight: 700;
}
.equip-slot-row__item {
  display: flex;
  align-items: baseline;
  min-width: 0;
  font-size: 0.86rem;
  font-weight: 600;
  color: var(--rarity-color, var(--text-0)); /* 등급 색(부모 data-rarity/grade 에서 cascade) */
}
/* 말줄임은 이름 텍스트에만 — 뒤에 붙는 아이템 레벨 배지(.item-ilvl)는 잘리지 않고 자리를 지킨다. */
.equip-slot-row__item-name {
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.equip-slot-row__item .item-ilvl { flex: 0 0 auto; }
.equip-slot-row__enhance {
  align-self: baseline;
  justify-self: end;
  max-width: 100%;
  padding: 0.02rem 0.38rem;
  border: 1px solid rgba(79, 214, 200, 0.36);
  border-radius: 999px;
  background: rgba(79, 214, 200, 0.1);
  color: #7ee7d8;
  font-size: 0.68rem;
  font-weight: 800;
  line-height: 1.4;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.equip-slot-row.is-empty .equip-slot-row__item { color: var(--text-2); font-weight: 400; }

/* ── 우측: 피커 ───────────────────────────────────────── */
.equip-picker__head {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
}
.equip-picker__title {
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--accent-hi);
}
.equip-picker__locked {
  font-size: 0.72rem;
  color: #ff8a8a;
  font-weight: 700;
}
.equip-picker__sub {
  font-size: 0.74rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-2);
  font-weight: 700;
  margin-top: 0.2rem;
}

.equip-equipped {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.6rem 0.7rem;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}
.equip-equipped--empty {
  justify-content: center;
  color: var(--text-2);
  font-size: 0.84rem;
  border-style: dashed;
}
.equip-equipped__icon {
  width: 2rem;
  height: 2rem;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 1.4rem;
}
.equip-equipped__icon .icon { width: 1.8rem; height: 1.8rem; }
.equip-equipped__name {
  flex: 1;
  min-width: 0;
  font-weight: 700;
  color: var(--rarity-color, var(--text-0)); /* 등급 색(부모 data-rarity/grade 에서 cascade) */
  font-size: 0.9rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.equip-picker__grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr));
  gap: 0.45rem;
}
.equip-cand {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.55rem 0.7rem;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  text-align: left;
  cursor: pointer;
  min-height: 3.2rem;
  transition: background 100ms ease, border-color 100ms ease;
}
.equip-cand:hover { background: var(--hover-bg); border-color: var(--accent); }
.equip-cand__icon {
  width: 1.8rem;
  height: 1.8rem;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 1.3rem;
}
.equip-cand__icon .icon { width: 1.6rem; height: 1.6rem; }
.equip-cand__name {
  flex: 1;
  min-width: 0;
  font-size: 0.88rem;
  font-weight: 700;
  color: var(--rarity-color, var(--text-0)); /* 등급 색(부모 data-rarity/grade 에서 cascade) */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ── 버튼 ─────────────────────────────────────────────── */
.equip-btn {
  padding: 0.4rem 0.85rem;
  border-radius: var(--radius-sm);
  font-size: 0.82rem;
  font-weight: 600;
  cursor: pointer;
  border: 1px solid var(--border);
  background: var(--bg-2);
  color: var(--text-1);
  flex-shrink: 0;
  transition: background 100ms ease, border-color 100ms ease, color 100ms ease;
}
.equip-btn--ghost:hover { background: rgba(255, 0, 0, 0.12); border-color: #ff8a8a; color: #ff8a8a; }


/* 폰: 와이드(52rem) 모달 → 풀스크린. */

/* ===== character-detail-modal.css ===== */
/* 캐릭터 상세보기 팝업.
 * equip-modal.css 톤을 따른다 (z-index 10040, dark backdrop, --accent 강조).
 * 헤더(클래스/레벨/경험치) + 2열 본문(좌: 전투 스탯·장비 효과·능력치 / 우: 착용 장비 그리드).
 * .char-detail-modal 컨테이너·백드롭은 modal.css 공통 스캐폴딩에서 정의.
 */
.char-detail-modal__panel {
  position: relative;
  width: min(54rem, 100%);
  max-height: min(48rem, 92vh);
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: 0 1.5rem 3rem rgba(0, 0, 0, 0.55);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  animation: char-detail-modal-in 140ms ease-out;
}
@keyframes char-detail-modal-in {
  from { opacity: 0; transform: translateY(0.5rem) scale(0.98); }
  to   { opacity: 1; transform: none; }
}

.char-detail-modal__header {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.85rem 1rem;
  border-bottom: 1px solid var(--border);
  background: var(--bg-2);
}
.char-detail-modal__title {
  flex: 1;
  font-size: 1rem;
  font-weight: 700;
  color: var(--accent-hi);
  letter-spacing: 0.02em;
}
.char-detail-modal__close {
  width: 2rem;
  height: 2rem;
  border-radius: 999px;
  font-size: 1rem;
  color: var(--text-1);
  background: transparent;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.char-detail-modal__close:hover { background: rgba(255, 255, 255, 0.06); color: var(--text-0); }

.char-detail-modal__body {
  flex: 1;
  overflow-y: auto;
  scrollbar-width: thin;
  padding: 1rem;
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
}
.char-detail-modal__loading {
  text-align: center;
  color: var(--text-2);
  padding: 1.5rem 1rem;
  font-size: 0.9rem;
  line-height: 1.6;
}
.char-detail-modal__loading strong { display: block; color: var(--text-1); margin-bottom: 0.3rem; }

/* ── 헤더: 클래스/레벨/경험치 ───────────────────────────────── */
.cd-hero {
  display: flex;
  align-items: center;
  gap: 0.85rem;
}
.cd-hero__icon {
  width: 3.2rem;
  height: 3.2rem;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.cd-hero__icon .icon { width: 3rem; height: 3rem; }
.cd-hero__id { flex: 1; min-width: 0; }
.cd-hero__name { font-size: 1.15rem; font-weight: 800; color: var(--text-0); }
.cd-hero__meta { font-size: 0.82rem; color: var(--text-2); margin-top: 0.1rem; }
/* 협회 계급 배지 — 협회 해금(Lv.15) 캐릭터에만 렌더된다. */
.cd-hero__rank {
  display: inline-block;
  margin-top: 0.25rem;
  padding: 0.1rem 0.5rem;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: rgba(255, 255, 255, 0.04);
  font-size: 0.75rem;
  color: var(--text-1);
}
.cd-hero__lv {
  display: inline-block;
  margin-top: 0.25rem;
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--accent-hi);
}

.cd-exp__text { font-size: 0.78rem; color: var(--text-2); margin-bottom: 0.3rem; }
.cd-exp__next { color: var(--accent-hi); font-weight: 700; }
.cd-exp__bar {
  height: 0.5rem;
  border-radius: 999px;
  background: var(--bg-0);
  border: 1px solid var(--border);
  overflow: hidden;
}
.cd-exp__fill {
  height: 100%;
  background: linear-gradient(90deg, var(--accent), var(--accent-hi));
  transition: width 200ms ease;
}

/* ── 성장 현황(표시 전용) ─────────────────────────────────── */
/* "지금 가능"한 미사용 자원과 다음 목표를 강조 박스로 보여준다. */
.cd-growth {
  background: linear-gradient(180deg, rgba(var(--accent-rgb), 0.10), rgba(var(--accent-rgb), 0.03));
  border: 1px solid rgba(var(--accent-rgb), 0.35);
  border-radius: var(--radius-md);
  padding: 0.85rem 0.95rem;
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
}
.cd-growth__head {
  font-size: 0.84rem;
  font-weight: 800;
  color: var(--accent-hi);
  letter-spacing: 0.02em;
}
.cd-growth__pending { display: flex; align-items: flex-start; gap: 0.6rem; flex-wrap: wrap; }
.cd-growth__cap {
  flex-shrink: 0;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  color: var(--text-2);
  text-transform: uppercase;
  padding-top: 0.3rem;
}
.cd-growth__chips { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.cd-grow-chip {
  font-size: 0.82rem;
  color: var(--text-1);
  padding: 0.28rem 0.6rem;
  border-radius: 999px;
  background: rgba(var(--accent-rgb), 0.14);
  border: 1px solid rgba(var(--accent-rgb), 0.45);
  cursor: default;
}
.cd-grow-chip strong { color: var(--accent-hi); font-weight: 800; }
.cd-grow-rest { font-size: 0.82rem; color: var(--text-2); padding-top: 0.26rem; }

.cd-growth__goals {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
  gap: 0.55rem 0.9rem;
  border-top: 1px dashed rgba(var(--accent-rgb), 0.25);
  padding-top: 0.8rem;
}
.cd-growth__goal { display: flex; flex-direction: column; gap: 0.35rem; min-width: 0; }
.cd-growth__goal-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem;
}
.cd-growth__goal-label { font-size: 0.82rem; font-weight: 700; color: var(--text-1); flex-shrink: 0; }
.cd-growth__goal-note {
  font-size: 0.74rem;
  color: var(--text-2);
  text-align: right;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ── 본문: 위 2기둥(전투스탯 | 착용장비) + 아래 요약띠 ──────────── */
.cd-cols {
  display: grid;
  grid-template-columns: 1.1fr 1fr;
  gap: 0.85rem;
  align-items: start;
}
.cd-col { display: flex; flex-direction: column; gap: 0.85rem; min-width: 0; }

/* 가장 중요한 전투 스탯 — 살짝 강조(테두리·타이틀 색). */
.cd-section--combat { border-color: rgba(var(--accent-rgb), 0.4); }
.cd-section--combat > .cd-section__title { color: var(--accent-hi); }

/* 능력치·장비효과·속성저항을 가로 전체 폭 카드로 흐르게(빈 섹션은 자연 제외). */
.cd-sub {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: 0.85rem;
  align-items: start;
}

.cd-section {
  background: var(--bg-0);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0.7rem 0.8rem;
}
.cd-section__title {
  font-size: 0.74rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-2);
  font-weight: 700;
  margin-bottom: 0.55rem;
}

/* ── 파생 전투 스탯(기본 vs 장비 분해) ──────────────────────── */
.cd-stat-rows { display: flex; flex-direction: column; gap: 0.5rem; }
.cd-stat-row {
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0.5rem 0.6rem;
}
.cd-stat-row__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem;
}
.cd-stat-row__label { font-size: 0.9rem; font-weight: 700; color: var(--text-1); }
.cd-stat-row__total { font-size: 1.05rem; font-weight: 800; color: var(--accent-hi); }
.cd-stat-row__break {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
  margin-top: 0.4rem;
}
.cd-stat-row__note { display: block; margin-top: 0.3rem; font-size: 0.72rem; color: var(--text-2); }

.cd-chip {
  font-size: 0.74rem;
  font-weight: 600;
  padding: 0.12rem 0.45rem;
  border-radius: 999px;
  border: 1px solid var(--border);
  white-space: nowrap;
}
.cd-chip--base { color: var(--text-1); background: var(--bg-1); }
.cd-chip--item { color: var(--accent-hi); background: rgba(var(--accent-rgb), 0.12); border-color: rgba(var(--accent-rgb), 0.4); }

/* ── 장비 효과 모디파이어 ───────────────────────────────────── */
.cd-mods { display: flex; flex-wrap: wrap; gap: 0.35rem; }
.cd-mod {
  font-size: 0.78rem;
  color: var(--text-1);
  padding: 0.2rem 0.5rem;
  border-radius: var(--radius-sm);
  background: var(--bg-2);
  border: 1px solid var(--border);
}
.cd-mod strong { color: var(--accent-hi); }

/* ── 능력치 6대 ─────────────────────────────────────────────── */
.cd-base-stats {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 0.35rem;
}
.cd-base-stat {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.35rem 0.55rem;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}
.cd-base-stat.is-primary { border-color: var(--accent); box-shadow: 0 0 0 1px rgba(var(--accent-rgb), 0.3) inset; }
.cd-base-stat__label { font-size: 0.82rem; color: var(--text-1); }
.cd-base-stat__label em { font-style: normal; font-size: 0.66rem; color: var(--accent-hi); font-weight: 700; }
.cd-base-stat__val { font-size: 0.92rem; font-weight: 700; color: var(--text-0); }

/* ── 착용 장비 페이퍼돌 그리드 ──────────────────────────────── */
.cd-slots {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.35rem;
}
.cd-slot {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.45rem 0.55rem;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}
.cd-slot.is-empty .cd-slot__icon { opacity: 0.55; }
.cd-slot__icon {
  width: 1.9rem;
  height: 1.9rem;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 1.25rem;
}
.cd-slot__icon .icon { width: 1.7rem; height: 1.7rem; }
.cd-slot__body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 0.1rem; }
.cd-slot__label {
  font-size: 0.66rem;
  letter-spacing: 0.05em;
  color: var(--text-2);
  text-transform: uppercase;
  font-weight: 700;
}
.cd-slot__item {
  display: flex;
  align-items: baseline;
  min-width: 0;
  font-size: 0.84rem;
  font-weight: 600;
  color: var(--rarity-color, var(--text-0)); /* 등급 색(부모 data-rarity/grade 에서 cascade) */
}
/* 말줄임은 이름 텍스트에만 — 뒤에 붙는 아이템 레벨 배지(.item-ilvl)는 잘리지 않고 자리를 지킨다. */
.cd-slot__item-name {
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.cd-slot__item .item-ilvl { flex: 0 0 auto; }
.cd-slot__enhance {
  font-size: 0.7rem;
  font-weight: 700;
  color: #4fd6c8;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.cd-slot.is-empty .cd-slot__item { color: var(--text-2); font-weight: 400; }


/* 폰: 와이드(54rem) 모달 → 풀스크린. */

/* ── 스탯 이름 호버 설명 ─────────────────────────────────────
   설명이 달린 스탯 이름엔 점선 밑줄 + 도움말 커서로 호버 가능을 알린다. */
.cd-tip { cursor: help; text-decoration: underline dotted var(--border-strong, var(--border)); text-underline-offset: 0.18em; }
.cd-tip:hover { text-decoration-color: var(--accent); }

/* body(스크롤 영역)에 붙는 부유 툴팁 — 모달(z 10040) 위로. JS 가 position:fixed 좌표를 채운다. */
.cd-stat-tip {
  position: fixed;
  z-index: 10050;
  max-width: 18rem;
  padding: 0.5rem 0.65rem;
  background: var(--bg-0, #14161d);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  box-shadow: 0 0.6rem 1.4rem rgba(0, 0, 0, 0.5);
  font-size: 0.78rem;
  line-height: 1.5;
  color: var(--text-1);
  pointer-events: none;
}
.cd-stat-tip[hidden] { display: none; }

/* ===== inventory.css ===== */
/* 인벤토리(가방) 모달 — WoW 풍 그리드.
 * 모달 chrome 은 mail-modal/cslot-modal 톤을 따른다.
 * 토큰: tokens.css 의 --bg-* /--text-* /--accent* 색을 그대로 사용한다.
 */

/* ── 모달 컨테이너 ─────────────────────────────────────── */
/* .inv-modal 컨테이너·백드롭은 modal.css 공통 스캐폴딩에서 정의. */
.inv-modal__panel {
  position: relative;
  width: min(60rem, 100%);
  max-height: min(55rem, 90vh);
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: 0 1.5rem 3rem rgba(0, 0, 0, 0.55);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  animation: inv-modal-in 140ms ease-out;
}
@keyframes inv-modal-in {
  from { opacity: 0; transform: translateY(0.5rem) scale(0.98); }
  to   { opacity: 1; transform: none; }
}

.inv-modal__header {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.85rem 1rem;
  border-bottom: 1px solid var(--border);
  background: var(--bg-2);
}
.inv-modal__title {
  flex: 1;
  font-size: 1rem;
  font-weight: 700;
  color: var(--accent-hi);
  letter-spacing: 0.02em;
}
.inv-modal__close {
  width: 2rem;
  height: 2rem;
  border-radius: 999px;
  font-size: 1rem;
  color: var(--text-1);
  background: transparent;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.inv-modal__close:hover { background: rgba(255, 255, 255, 0.06); color: var(--text-0); }

.inv-modal__body {
  flex: 1;
  overflow-y: auto;
  padding: 0.85rem 1rem 1rem;
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
  scrollbar-width: thin;
}

.inv-modal__summary {
  font-size: 0.85rem;
  color: var(--text-1);
  line-height: 1.5;
}
.inv-modal__summary b { color: var(--text-0); }
.inv-modal__next {
  color: var(--accent-hi);
  margin-left: 0.2rem;
}

/* ── 분류 탭(장비/소비/재료/잔혼) ─────────────────────────────────── */
.inventory-tabs {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0.4rem;
}
.inventory-tab {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.15rem;
  padding: 0.5rem 0.35rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-2);
  color: var(--text-1);
  font-family: inherit;
  cursor: pointer;
  transition: background 100ms ease, border-color 100ms ease, color 100ms ease;
}
.inventory-tab:hover { background: var(--hover-bg); color: var(--text-0); }
.inventory-tab.is-active {
  border-color: var(--accent);
  background: var(--hover-bg);
  color: var(--accent-hi);
}
.inventory-tab__icon { font-size: 1.1rem; line-height: 1; }
.inventory-tab__label { font-size: 0.82rem; font-weight: 600; }
.inventory-tab__count { font-size: 0.72rem; color: var(--text-2); }
.inventory-tab.is-active .inventory-tab__count { color: var(--accent-hi); }
.inventory-tab__dot {
  position: absolute;
  top: 0.3rem;
  right: 0.4rem;
  width: 0.45rem;
  height: 0.45rem;
  border-radius: 999px;
  background: var(--accent-hi, #f5a623);
  box-shadow: 0 0 0 2px var(--bg-2);
}

/* ── 분류별 용량 바 ────────────────────────────────────────── */
.inv-modal__cap {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}
.inv-modal__cap-text { font-size: 0.85rem; color: var(--text-1); }
.inv-modal__cap-text b { color: var(--text-0); }
.inv-modal__cap-bar {
  height: 0.4rem;
  border-radius: 999px;
  background: var(--bg-2);
  overflow: hidden;
}
.inv-modal__cap-fill {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--accent), var(--accent-hi));
  transition: width 200ms ease;
}

.inventory-toolbar {
  display: flex;
  gap: 0.5rem;
  align-items: center;
  padding: 0.4rem 0;
}
.inventory-search {
  flex: 1;
  min-width: 0;
  padding: 0.5rem 0.75rem;
  font-size: 0.85rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-1);
  color: var(--text-0);
  font-family: inherit;
  outline: none;
  transition: border-color 100ms ease;
}
.inventory-search::placeholder { color: var(--text-2); }
.inventory-search:focus { border-color: var(--accent); }

.inventory-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.5rem 0.85rem;
  font-size: 0.82rem;
  font-weight: 600;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-2);
  color: var(--text-1);
  transition: background 100ms ease, border-color 100ms ease, color 100ms ease;
}
.inventory-btn .icon { width: 1.05rem; height: 1.05rem; }
.inventory-btn:hover {
  background: var(--hover-bg);
  border-color: var(--accent);
  color: var(--accent-hi);
}

/* ── 그리드 ─────────────────────────────────────────────── */
/* 모든 아이템은 [아이콘 + 이름 + 수량] 가로 행으로 표기한다. */
.inventory-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0.4rem;
}
/* 폰: 4열은 320~375px에서 과밀 → 2열로 reflow. 우편 첨부(.inventory-grid 재사용)도 함께 적용. */

/* ── 분해 결과 그리드(모달 detail) ─────────────────────────
   분해 산출물을 인벤토리/우편 보상과 동일한 itemCell 로 표시한다.
   showAlert detailHtml(.modal__detail) 안에 들어가므로 폭에 맞춰 auto-fill. */
.dis-result-grid {
  display: grid;
  /* 명시 폭으로 모달 패널을 넓혀(.modal__panel max 28rem 한도 내) 두 열을 확보.
     좁은 화면에선 max-width:100% 로 한 열로 접히며, 어느 쪽이든 셀 폭이 넉넉해
     이름이 한 줄에 들어온다. */
  width: 22rem;
  max-width: 100%;
  grid-template-columns: repeat(auto-fill, minmax(9.5rem, 1fr));
  gap: 0.4rem;
  margin-top: 0.25rem;
}
/* 산출물 이름은 한 줄 고정 — 글자별 세로 줄바꿈 차단, 넘치면 말줄임(전체명은 셀 툴팁). */
.dis-result-grid .item-cell__name {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  word-break: normal;
  overflow-wrap: normal;
}
.dis-result-note {
  margin-top: 0.6rem;
  font-size: 0.82rem;
  color: var(--text-2, #a8b0c0);
  line-height: 1.45;
}

/* ── 매각 결과(영수증) 목록(모달 detail) ───────────────────
   분해와 동형으로 공용 itemRow 사용. 행은 전체 폭이라 wrap 걱정이 없고,
   명시 폭으로 모달을 살짝 넓혀 이름+수량+매각가가 한 줄에 들어온다. */
.sell-result-list {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  margin-top: 0.25rem;
  width: 20rem;
  max-width: 100%;
}
.sell-result-list .item-row__name {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  word-break: normal;
  overflow-wrap: normal;
}
.sell-result-list .item-row__trailing { color: var(--accent-hi); }

/* ── 묶음 판매 선택 목록 행 정리 ───────────────────────────
   좁은 리스트에서 스캔하기 좋게: 행 여백·구분선·호버, 이름 한 줄,
   우측은 [총액/개당 2줄] + 고스트 판매 버튼(솔리드 노란 띠 제거). */
.item-row--sell {
  gap: 0.55rem;
  padding: 0.3rem 0.55rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.05);
  cursor: pointer; /* 행 어디를 눌러도 선택 토글 */
}
.item-row--sell:last-child { border-bottom: 0; }
.item-row--sell:hover { background: rgba(255, 255, 255, 0.035); }

/* 장비 분해 행도 행 전체 클릭으로 선택 토글 — 클릭 가능함을 커서로 표시.
   묶음판매 행과 동일한 중간 간격으로 통일. */
.item-row--dis { gap: 0.55rem; padding: 0.3rem 0.55rem; cursor: pointer; border-radius: 6px; }
.item-row--dis:hover { background: rgba(255, 255, 255, 0.035); }
.item-row--sell .item-row__name {
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.item-row--sell .item-row__sub { font-weight: 400; color: var(--text-2); }

.sell-row__price {
  flex: 0 0 auto;
  margin-left: auto;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  line-height: 1.2;
  min-width: 5rem;
}
.sell-row__total { font-weight: 700; color: var(--accent-hi); white-space: nowrap; }
.sell-row__unit { margin-top: 0.05rem; font-size: 0.72rem; color: var(--text-2); white-space: nowrap; }

.sell-row__btn {
  flex: 0 0 auto;
  padding: 0.3rem 0.8rem;
  background: transparent;
  color: var(--accent-hi);
  border: 1px solid rgba(var(--accent-rgb), 0.5);
  border-radius: 5px;
  cursor: pointer;
  font-size: 0.85rem;
  font-weight: 600;
  transition: background 110ms ease, color 110ms ease, border-color 110ms ease;
}
.sell-row__btn:hover { background: var(--accent); color: #1a1108; border-color: var(--accent); }

/* ── 상세 팝오버 ──────────────────────────────────────── */
.inv-popover {
  position: absolute;
  /* body 자식이라 .inv-modal(modal.css:270, 10040) 과 형제다 — 10030 이면 인벤토리 패널
   * 뒤에 깔려 아예 보이지도 눌리지도 않았다. 모달 스캐폴딩보다는 위, 확인 모달(10050)
   * 보다는 아래여야 판매 확인창이 팝오버를 덮는다. */
  z-index: 10045;
  min-width: 14rem;
  max-width: 18rem;
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: 0 0.6rem 1.4rem rgba(0, 0, 0, 0.55);
  padding: 0.7rem 0.85rem;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  animation: inv-pop-in 110ms ease-out;
}
@keyframes inv-pop-in {
  from { opacity: 0; transform: translateY(-0.3rem); }
  to   { opacity: 1; transform: none; }
}
.inv-popover__head {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.inv-popover__icon {
  width: 1.8rem; height: 1.8rem;
  display: inline-flex; align-items: center; justify-content: center;
}
.inv-popover__icon .icon { width: 1.6rem; height: 1.6rem; }
.inv-popover__name { font-weight: 700; color: var(--text-0); flex: 1; }
.inv-popover[data-rarity] .inv-popover__name   { color: var(--rarity-color, var(--text-0)); }
.inv-popover[data-rarity] .inv-popover__rarity { color: var(--rarity-color, var(--text-2)); }
.inv-popover__rarity {
  font-size: 0.7rem;
  color: var(--text-2);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.inv-popover__desc {
  font-size: 0.78rem;
  color: var(--text-1);
  line-height: 1.45;
}
.inv-popover__meta {
  display: flex;
  gap: 0.6rem;
  font-size: 0.72rem;
  color: var(--text-2);
}
.inv-popover__actions {
  display: flex;
  gap: 0.4rem;
  margin-top: 0.2rem;
}
.inv-popover__btn {
  flex: 1;
  padding: 0.4rem 0.6rem;
  font-size: 0.78rem;
  font-weight: 600;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-2);
  color: var(--text-1);
}
.inv-popover__btn:hover {
  background: var(--hover-bg);
  border-color: var(--accent);
  color: var(--accent-hi);
}
.inv-popover__btn--sell {
  background: rgba(var(--accent-rgb), 0.16);
  border-color: rgba(var(--accent-rgb), 0.45);
  color: var(--accent-hi);
}
.inv-popover__btn--sell:hover {
  background: rgba(var(--accent-rgb), 0.28);
  border-color: var(--accent);
  color: var(--text-0);
}
.inv-popover__btn--equip {
  background: rgba(96, 165, 250, 0.16);
  border-color: rgba(96, 165, 250, 0.45);
  color: #9ec5fe;
}
.inv-popover__btn--equip:hover {
  background: rgba(96, 165, 250, 0.28);
  border-color: #60a5fa;
  color: #d7e7ff;
}

/* ── 모바일: 와이드(60rem) 모달 → 풀스크린 ──
 * 컨테이너/패널 좌표는 inventory.js 가 인라인 cssText 로 못 박으므로(외부 CSS 로드
 * 실패 대비) 인라인을 이기려면 !important 가 필요하다. CSS 가 로드된 정상 경로에서만
 * 적용되고, 로드 실패 시엔 인라인 폴백이 그대로 살아 의도가 보존된다. */

/* ===== shop.css ===== */
/* 상점 모달 — 순회 상인.
 * 상인 3명이 나란히 서고 각자 3칸을 진열한다(총 9칸, 중복 없음).
 * 모달 chrome 은 inventory/mail 톤을 따른다. 설계: docs/shop-design.md
 */

/* .shop-modal 컨테이너·백드롭은 modal.css 공통 스캐폴딩에서 정의. */
.shop-modal__panel {
  position: relative;
  width: min(64rem, 100%);
  /* 탭 전환 시 패널 크기가 흔들리지 않도록 height 를 고정한다. 본문은 .shop-modal__body 가 스크롤.
     상인 카드가 이 높이를 그대로 채운다(.mer-grid height:100%) — 카드 안이 남는 높이를 흡수하도록
     설계돼 있으므로 여기 값을 바꾸면 상품 줄 높이가 함께 변한다. */
  height: min(38rem, 92vh);
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: 0 1.5rem 3rem rgba(0, 0, 0, 0.55);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  animation: shop-modal-in 140ms ease-out;
}
@keyframes shop-modal-in {
  from { opacity: 0; transform: translateY(0.5rem) scale(0.98); }
  to   { opacity: 1; transform: none; }
}

.shop-modal__header {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.85rem 1rem;
  border-bottom: 1px solid var(--border);
  background: var(--bg-2);
}
.shop-modal__title {
  font-size: 1rem;
  font-weight: 700;
  color: var(--accent-hi);
  letter-spacing: 0.02em;
}
.shop-modal__resources {
  flex: 1;
  display: flex;
  gap: 0.85rem;
  justify-content: flex-end;
  font-size: 0.92rem;
  color: var(--text-1);
}
.shop-modal__res b { color: var(--text-0); margin-left: 0.2rem; }
.shop-modal__close {
  width: 2rem;
  height: 2rem;
  border-radius: 999px;
  font-size: 1rem;
  color: var(--text-1);
  border: 1px solid var(--border);
  background: var(--bg-1);
}
.shop-modal__close:hover { color: var(--text-0); border-color: var(--accent); }

/* 메인 탭 ----------------------------------------------------- */
.shop-modal__tabs {
  display: flex;
  gap: 0.4rem;
  padding: 0.65rem 0.85rem 0;
  border-bottom: 1px solid var(--border);
  background: var(--bg-2);
}
.shop-modal__tab {
  padding: 0.55rem 0.95rem;
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
  background: transparent;
  border: 1px solid transparent;
  border-bottom: 0;
  color: var(--text-1);
  font-weight: 600;
  font-size: 0.95rem;
}
.shop-modal__tab:hover { color: var(--text-0); }
.shop-modal__tab.is-active {
  color: var(--accent-hi);
  background: var(--bg-1);
  border-color: var(--border);
}

/* 본문 ------------------------------------------------------- */
.shop-modal__body {
  flex: 1;
  overflow-y: auto;
  padding: 0.9rem;
}
.shop-modal__empty {
  text-align: center;
  color: var(--text-2);
  padding: 2rem 0.5rem;
  line-height: 1.7;
}

/* 상인 카드 ---------------------------------------------------
 * 3열 고정. 데스크탑 전용(min-width 1280)이라 반응형 분기를 두지 않는다.
 *
 * 카드는 **팝업 본문 높이를 그대로 채운다**(.mer-grid height:100%). 남는 높이는 상품 목록이
 * 흡수하고(.mer-card__goods flex:1), 머리·대사·성격 문구는 제 크기를 지킨다.
 * 그래서 상인마다 대사 길이가 달라도 세 카드의 상품 줄이 같은 y 에 정렬된다.
 */
.mer-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.75rem;
  /* 본문(.shop-modal__body)은 flex:1 이라 높이가 확정돼 있다 → 100% 가 해석된다. */
  height: 100%;
  align-items: stretch;
}

.mer-card {
  display: flex;
  flex-direction: column;
  padding: 0.85rem 0.85rem 0.75rem;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  min-height: 0;         /* flex 자식이 내용보다 작아질 수 있게(상품 목록 스크롤 대비) */
}

/* 머리 — 초상 + 이름/칭호 + 남은 시간 */
.mer-card__head {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  padding-bottom: 0.6rem;
  border-bottom: 1px solid var(--border);
}
.mer-card__portrait {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.9rem;
  height: 2.9rem;
  flex: 0 0 auto;
  font-size: 1.5rem;
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: 999px;
}
.mer-card__portrait .icon { width: 62%; height: 62%; object-fit: contain; }
.mer-card__ident {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  min-width: 0;          /* 긴 칭호가 타이머를 밀어내지 않게 */
  flex: 1;
}
.mer-card__name {
  font-weight: 700;
  color: var(--text-0);
  font-size: 1rem;
}
.mer-card__title {
  font-size: 0.76rem;
  color: var(--text-2);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* 타이머는 절대 줄바꿈되지 않는다(뱃지 규약). flex 안의 span 은 내용보다 좁아질 수
   있으므로 flex-shrink 를 명시적으로 끈다. */
.mer-card__timer {
  flex: 0 0 auto;
  align-self: flex-start;
  white-space: nowrap;
  font-size: 0.78rem;
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
}
.mer-card__timer b { color: var(--text-1); }
.mer-card__timer b.is-soon { color: var(--danger, #e06c6c); }

/* 대사 — 인용 부호 대신 왼쪽 선으로 말임을 표시한다.
   ⚠ min-height 2줄 고정이 세 카드의 상품 줄을 같은 y 에 맞추는 장치다. 이게 없으면 대사가
     1줄인 상인만 상품 영역이 그만큼 길어져(flex:1 이 흡수) 옆 카드와 행 경계가 어긋난다. */
.mer-card__greeting {
  margin: 0.7rem 0 0.75rem;
  padding-left: 0.6rem;
  border-left: 2px solid var(--border);
  font-size: 0.82rem;
  line-height: 1.55;
  min-height: 3.1em;     /* = 2줄 */
  color: var(--text-1);
  font-style: italic;
}

/* 상품 3칸 — 남는 높이를 전부 가져간다.
   ⚠ 1열 세로 스택이다. 3열로 두면 카드 폭(≈20rem)이 셀당 6rem 남짓이라 아이템명이 두 줄로
     접히고, 세로로 길어진 카드에서는 그 접힘이 더 도드라진다. 한 줄에 아이콘·이름·가격을
     나란히 놓는 편이 읽기도, 높이를 채우기도 낫다. */
.mer-card__goods {
  flex: 1 1 auto;
  min-height: 0;
  display: grid;
  grid-template-rows: repeat(3, minmax(0, 1fr));
  gap: 0.45rem;
}
/* 셀은 행 높이를 꽉 채우고 내용은 세로 가운데. 남는 높이가 늘어도 어색하지 않다. */
.mer-card__goods .item-cell {
  height: 100%;
  align-content: center;
  padding: 0.5rem 0.65rem;
}
.mer-card__goods .item-cell__icon { width: 2.1rem; height: 2.1rem; font-size: 1.55rem; }
.mer-card__goods .item-cell__name { font-size: 0.86rem; }

/* 성격 문구 — 카드 바닥. 상품과 구분되도록 선을 하나 둔다. */
.mer-card__flavor {
  margin: 0.7rem 0 0;
  padding-top: 0.55rem;
  border-top: 1px solid var(--border);
  font-size: 0.74rem;
  color: var(--text-2);
  line-height: 1.45;
}

/* 시세 배지 — 이 상인의 정가 대비. 셀 하단 footHtml 로 들어간다. */
.mer-trend {
  display: inline-block;
  white-space: nowrap;
  font-size: 0.72rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.mer-trend--up   { color: var(--danger, #e06c6c); }
.mer-trend--down { color: var(--success, #6fbf73); }
.mer-trend--flat { color: var(--text-2); font-weight: 400; }

/* 창당 1인 구매 상한 배지 — 시세 배지와 같은 줄(`.item-cell__foot`)에 나란히 선다.
 * 공통 재고가 아니라 「내 몫」이므로 남과 겨루는 뉘앙스(품절·매진)를 쓰지 않는다.
 * ⚠ 간격은 `.item-cell__foot` 의 gap 이 준다 — 여기서 margin 을 더하지 않는다.
 * ⚠ 다 산 칸의 흐림·회색조·not-allowed 는 공용 상태 `.item-cell.is-soldout`
 *   (item-display.css 「상품 마감」)이 이미 준다 — 여기서 다시 쓰지 않는다.
 *   누를 수는 있게 둔다: 눌러야 이유를 안내받는다(pointer-events 를 끄면 툴팁까지 죽는다). */
.mer-stock {
  white-space: nowrap;
  font-size: 0.72rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--text-2);
}
.mer-stock--out { color: var(--danger, #e06c6c); }
.mer-card__goods .item-cell.is-soldout .item-cell__badge { text-decoration: line-through; }

/* 결제 탭 — 종류별 묶음 ---------------------------------------
 * 「결제」 탭은 상품을 kind 별 <section> 으로 갈라 쌓는다. 묶음 머리는 화폐 레지스트리의
 * 이름·아이콘·설명을 그대로 쓰고(서버 paidGroups), 오른쪽에 지금 보유 잔액을 붙인다.
 * 첫 묶음은 위 여백을 지운다 — 본문 padding 과 겹쳐 머리글이 아래로 밀려 보인다.
 */
.shop-group + .shop-group { margin-top: 1.15rem; }
.shop-group__head {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  margin-bottom: 0.55rem;
  padding-bottom: 0.4rem;
  border-bottom: 1px solid var(--border);
}
.shop-group__icon {
  width: 1.9rem;
  height: 1.9rem;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.15rem;
  flex: 0 0 auto;
}
.shop-group__icon img { width: 1.5rem; height: 1.5rem; }
.shop-group__ident { min-width: 0; }   /* 말줄임이 먹도록 — flex 자식 기본 min-width:auto 방어 */
.shop-group__title {
  margin: 0;
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--text-0);
  line-height: 1.3;
}
.shop-group__desc {
  margin: 0.1rem 0 0;
  font-size: 0.76rem;
  color: var(--text-2);
  line-height: 1.35;
}
.shop-group__bal {
  margin-left: auto;
  flex: 0 0 auto;
  white-space: nowrap;
  font-size: 0.78rem;
  color: var(--text-2);
}
.shop-group__bal b {
  color: var(--text-1);
  font-variant-numeric: tabular-nums;
}

/* 카드 그리드 ------------------------------------------------ */
.shop-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
  gap: 0.75rem;
}

.shop-card {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  padding: 0.75rem 0.8rem 0.65rem;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  position: relative;
}
.shop-card__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.4rem;
}
.shop-card__icon {
  width: 3.2rem;
  height: 3.2rem;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 2rem;
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}
.shop-card__icon img { width: 2.4rem; height: 2.4rem; }
.shop-card__rarity {
  font-size: 0.72rem;
  letter-spacing: 0.04em;
  color: var(--text-2);
  padding: 0.1rem 0.45rem;
  border-radius: 999px;
  background: var(--bg-1);
  border: 1px solid var(--border);
}
.shop-card__rarity--paid { color: var(--accent-hi); border-color: var(--accent); }

.shop-card__name {
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--text-0);
  margin: 0.1rem 0 0;
  line-height: 1.25;
}
.shop-card__desc {
  font-size: 0.78rem;
  color: var(--text-2);
  line-height: 1.4;
  margin: 0;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.shop-card__meta {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 0.85rem;
  margin-top: auto;
}
.shop-card__price {
  color: var(--accent-hi);
  font-weight: 700;
}
.shop-card__price--cash { color: #7fbfff; }
/* 기간제 SKU(배틀패스) 전용 — 남은 기간. .shop-card__meta 가 space-between 이라 가격 오른쪽에 앉는다.
   ⚠ nowrap 이 필요하다 — 「남은 30일」이 두 줄로 접히면 카드 높이가 이 카드만 달라진다. */
.shop-card__owned {
  font-size: 0.74rem;
  color: var(--accent-hi);
  white-space: nowrap;
}
/* 보유 중 카드는 테두리로만 구분한다 — 버튼은 「연장하기」로 살아 있어야 하므로 흐리지 않는다. */
.shop-card--paid.is-owned { border-color: var(--accent); }
.shop-card__limit {
  font-size: 0.74rem;
  color: var(--text-2);
}
.shop-card__timer {
  font-size: 0.72rem;
  color: var(--text-2);
  letter-spacing: 0.02em;
}
.shop-card__timer b { color: var(--text-1); font-variant-numeric: tabular-nums; }
.shop-card__timer b.is-soon { color: var(--danger); }
.shop-card__buy {
  margin-top: 0.35rem;
  padding: 0.5rem 0.6rem;
  border-radius: var(--radius-sm);
  background: var(--accent-hi);
  color: var(--bg-0);
  font-weight: 700;
  font-size: 0.9rem;
  border: 1px solid var(--accent);
}
.shop-card__buy:hover { filter: brightness(1.05); }
.shop-card__buy:disabled { background: var(--bg-1); color: var(--text-2); border-color: var(--border); }
.shop-card__buy--paid {
  background: linear-gradient(180deg, #7fbfff 0%, #4a86d6 100%);
  color: var(--bg-0);
  border-color: #4a86d6;
}

/* 희귀도 보더 색 — tokens.css 의 --rarity-edge 단일 출처. */
.shop-card[data-rarity] { border-color: var(--rarity-edge); }
.shop-card[data-rarity="unique"] { box-shadow: 0 0 0 1px rgba(var(--accent-hi-rgb), 0.25); }

/* ===== union.css ===== */
/* 협회 화면 — 단일 화면(보급·공동 목표·기여의 전당·협회 교환소). 뒤 둘은 팝업. */

.union-page { display: flex; flex-direction: column; gap: 1rem; }

/* ── 협회 공적(누적) · 협회 포인트(소모) ────────────────────────── */

.section-head__aside { margin-left: auto; display: flex; align-items: center; gap: 0.5rem; }
.union-points-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  background: rgba(var(--accent-rgb), 0.10);
  border: 1px solid rgba(var(--accent-rgb), 0.35);
  color: var(--accent-hi);
  padding: 0.3rem 0.7rem;
  border-radius: 999px;
  font-size: 0.9rem;
}
.union-points-chip .icon { width: 1rem; height: 1rem; }

/* 협회 공적 칩 — 누적 공적 + 계급 + 다음 계급까지의 진행 게이지.
   소모성 재화인 포인트 칩과 한눈에 구분되도록 강조색 대신 중립 표면색을 쓴다. */
.union-merit-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--border);
  color: var(--text-0);
  padding: 0.3rem 0.7rem;
  border-radius: 999px;
  font: inherit;
  font-size: 0.9rem;
  cursor: pointer;
  transition: border-color 0.15s ease, background 0.15s ease;
}
.union-merit-chip:hover {
  background: rgba(255, 255, 255, 0.07);
  border-color: rgba(var(--accent-rgb), 0.45);
}
.union-merit-chip .icon { width: 1rem; height: 1rem; opacity: 0.8; }
.union-merit-chip__rank { color: var(--text-2); font-size: 0.82rem; }
.union-merit-chip__bar {
  width: 3.5rem;
  height: 0.3rem;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.10);
  overflow: hidden;
}
.union-merit-chip__bar > i {
  display: block;
  height: 100%;
  border-radius: inherit;
  background: var(--accent-hi);
  transition: width 0.3s ease;
}

/* ── 탭 패널 자리표시/로딩 ──────────────────────────────────────── */

.union-pane__loading,
.union-pane__placeholder,
.union-pane__error {
  text-align: center;
  color: var(--text-2);
  padding: 2.5rem 1rem;
  line-height: 1.6;
}
.union-pane__error { color: var(--danger, #d66); }

/* ── 잠금 카드 ─────────────────────────────────────────────────── */

.union-locked {
  text-align: center;
  padding: 2.5rem 1rem;
  border: 1px dashed var(--border);
  border-radius: var(--radius-md);
  background: rgba(var(--accent-rgb), 0.04);
}
.union-locked__icon { font-size: 2.5rem; margin-bottom: 0.5rem; }
.union-locked__title { font-size: 1.1rem; color: var(--text-0); margin-bottom: 0.5rem; }
.union-locked__desc  { color: var(--text-2); line-height: 1.6; }

/* ── 협회 허브 2×2 카드 ─────────────────────────────────────────
   네 기능(보급·공동 목표·기여의 전당·교환소)이 전부 "카드 → 팝업" 으로 통일됐다.
   데스크탑 전용(--app-min-w:1280px)이라 폭 기반 @media 없이 2열 고정.
   중앙 컬럼 실폭 ≈656px → 카드 1장 ≈314px.
   minmax(0,1fr): 긴 제목이 트랙을 밀어내 열 폭이 어긋나는 것을 막는다. */

.union-hub-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.9rem;
  align-items: stretch;
}

.union-hub-card {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  background: linear-gradient(180deg, var(--bg-2), var(--bg-1));
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.16);
  padding: 0.9rem;
  transition: border-color 0.15s, transform 0.1s, box-shadow 0.15s;
}
/* 카드 자체는 클릭 대상이 아니다 — 안쪽 버튼이 유일한 인터랙션이라
   :focus-visible 이 아니라 :focus-within 으로 들어올린다. */
.union-hub-card:hover,
.union-hub-card:focus-within {
  border-color: var(--accent);
  transform: translateY(-2px);
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.22);
}

/* min-height — 뱃지가 lazy 로 나중에 채워질 때 카드 높이가 튀지 않게 자리를 미리 잡는다. */
.union-hub-card__head {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  min-height: 2.2rem;
}
.union-hub-card__icon { flex: 0 0 auto; display: inline-flex; }
.union-hub-card__title {
  margin: 0;
  font-size: 1.05rem;
  font-weight: bold;
  color: var(--text-0);
}

/* 설명 길이가 카드마다 달라도 네 장의 버튼 줄이 같은 높이에 놓이도록 3줄분을 확보한다.
   그리드 행 stretch 는 같은 행끼리만 맞추므로 위·아래 행을 맞추려면 이게 필요하다. */
.union-hub-card__desc {
  margin: 0;
  color: var(--text-2);
  font-size: 0.85rem;
  line-height: 1.5;
  min-height: 3.8em;
}
.union-hub-card__desc b { color: var(--accent-hi); font-weight: 600; }

.union-hub-card__foot { margin-top: auto; }
.union-hub-card__btn {
  width: 100%;
  border: none;
  border-radius: var(--radius-md);
  padding: 0.55rem 1rem;
  font-weight: bold;
  background: var(--accent);
  color: var(--bg-0);
  cursor: pointer;
}
.union-hub-card__btn:hover { background: var(--accent-hi); }
.union-hub-card__btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* 상태 뱃지 — 지금 할 일이 있는 칸을 팝업을 열지 않고 알린다. */
.union-hub-card__badge {
  margin-left: auto;
  flex-shrink: 0;
  white-space: nowrap;
  font-size: 0.75rem;
  padding: 0.1rem 0.5rem;
  border-radius: 999px;
}
.union-hub-card__badge--ready {
  background: rgba(90, 190, 120, 0.15);
  color: var(--success-soft, #6fcf8e);
  border: 1px solid rgba(90, 190, 120, 0.4);
}
.union-hub-card__badge--idle {
  background: rgba(255, 255, 255, 0.05);
  color: var(--text-2);
  border: 1px solid var(--border);
}
/* 할 일이 있는 카드는 테두리로도 알린다. */
.union-hub-card:has(.union-hub-card__badge--ready) {
  border-color: rgba(90, 190, 120, 0.5);
  box-shadow: inset 0 0 0 1px rgba(90, 190, 120, 0.25);
}

/* ── 보급 카드 (누적 사다리) ───────────────────────────────────── */

/* 적립 규칙 안내 — 카드 위에 항상 노출한다(하루 거르면 소멸). */
.union-supply__rule {
  margin: 0 0 0.5rem;
  font-size: 0.85rem;
  line-height: 1.65;
  color: var(--text-1);
}
.union-supply__rule strong { color: var(--accent-hi); font-weight: 600; }

/* 소멸 경고 — 놓치면 쌓아 둔 보급이 통째로 날아간다. 본문과 같은 회색으로 흘리면
   읽히지 않으므로 왼쪽 띠로 떼어 낸다(문구 자체는 짧게 유지한다). */
.union-supply__warn {
  margin: 0 0 0.7rem;
  padding: 0.45rem 0.6rem;
  border-left: 2px solid rgba(var(--danger-rgb), 0.55);
  border-radius: 0 var(--radius-sm, 4px) var(--radius-sm, 4px) 0;
  background: rgba(var(--danger-rgb), 0.06);
  font-size: 0.8rem;
  line-height: 1.6;
  color: var(--text-2);
}
.union-supply__warn strong { color: var(--danger-soft); font-weight: 600; }

.union-supply__rank {
  margin: 0 0 0.6rem;
  display: flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.82rem;
  color: var(--text-2);
}
.union-supply__resets { margin-left: auto; }

/* 트랙 3장(골드·회복 물약·공격 버프 물약). 데스크탑 전용이라 폭 기반 @media 없이 3열 고정. */
.union-supply-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0.75rem;
}

.union-supply-card {
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 0.85rem 0.75rem;
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
}
.union-supply-card.is-acted { opacity: 0.7; }

/* 3열이라 좁다 — 라벨과 배지를 나란히 두면 "일일 보/급" 으로 접힌다. 세로로 쌓는다. */
.union-supply-card__head {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.2rem;
}
.union-supply-card__label { font-weight: bold; color: var(--text-0); white-space: nowrap; }
.union-supply-card__badge {
  align-self: flex-start;
  font-size: 0.78rem;
  color: var(--accent);
  background: var(--bg-2);
  border-radius: var(--radius-sm);
  padding: 0.1rem 0.45rem;
}

.union-supply-card__rewards {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  font-size: 0.9rem;
  color: var(--text-1);
  min-height: 4.2rem; /* 물약 이름이 최대 세 줄로 접혀도 카드끼리 사다리가 같은 높이에서 시작하도록. */
}
/* 카드가 좁아(~145px) 아이템 이름이 여러 줄로 쪼개진다 — 이름이 남는 폭을 다 쓰게 하고
   수량은 오른쪽 끝에 고정한다. 어절 가운데서는 끊지 않는다("견습 종합 회/복 물약" 방지). */
.union-supply-card__rewards li {
  display: flex;
  align-items: center;
  gap: 0.3rem;
  word-break: keep-all;
  font-size: 0.82rem;
}
.union-supply-card__rewards li > .icon { flex-shrink: 0; }
.union-supply-card__rewards li [data-role="item-name"] { flex: 1; min-width: 0; }

/* 물약 계열이 오늘 추첨된 것인지, 적립으로 고정된 것인지 알리는 문구.
   문장 길이가 카드마다 달라도 사다리가 같은 높이에서 시작하도록 높이를 고정한다(3줄분). */
.union-supply-card__note {
  margin: 0;
  min-height: 3rem;
  font-size: 0.72rem;
  line-height: 1.4;
  color: var(--text-2);
}

/* 카운트업 중 강조 — inventory 의 .item-cell__qty.is-counting 과 같은 언어. */
.union-supply-card__num {
  color: var(--text-0);
  transition: color 200ms, transform 200ms;
  display: inline-block;
}
.union-supply-card__num.is-counting {
  color: var(--accent);
  transform: scale(1.25);
}

/* 사다리 — 일차별 실지급 수치를 세로로 나열한다(가로 5칸에는 "12,000" 이 들어가지 않는다).
   도달한 일차는 채워진 점 + 밝은 글자. */
.union-supply-ladder {
  list-style: none;
  margin: 0.15rem 0;
  padding: 0.5rem 0;
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
}
/* 카드가 ~180px 라 한 행에 쓸 수 있는 폭이 ~120px 뿐이다("30일 12,000" 이 딱 들어간다). */
.union-supply-ladder__step {
  display: flex;
  align-items: center;
  gap: 0.3rem;
  color: var(--text-2);
  font-size: 0.74rem;
  white-space: nowrap;
}
.union-supply-ladder__dot {
  flex-shrink: 0;
  width: 0.45rem;
  height: 0.45rem;
  border-radius: 50%;
  border: 1px solid var(--border-hi, var(--border));
  background: transparent;
  transition: background 200ms, box-shadow 200ms;
}
.union-supply-ladder__days { min-width: 2rem; }
/* 수치는 우측 정렬 + 자릿수 폭 고정 — 200 / 12,000 이 세로로 나란히 읽힌다. */
.union-supply-ladder__amount {
  margin-left: auto;
  font-variant-numeric: tabular-nums;
  color: var(--text-1);
}
.union-supply-ladder__step.is-reached { color: var(--text-0); }
.union-supply-ladder__step.is-reached .union-supply-ladder__amount {
  color: var(--accent);
  font-weight: bold;
}
.union-supply-ladder__step.is-reached .union-supply-ladder__dot {
  background: var(--accent);
  border-color: var(--accent);
  box-shadow: 0 0 0.35rem var(--accent);
}

/* 3열이라 카드가 좁다(~180px). 버튼 둘을 나란히 두면 글자가 잘려 세로로 쌓는다. */
.union-supply-card__foot {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}

.union-supply-card__claim,
.union-supply-card__accrue {
  width: 100%;
  border: 0;
  padding: 0.45rem 0.3rem;
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-size: 0.85rem;
  font-weight: bold;
  white-space: nowrap;
  transition: background 120ms;
}
.union-supply-card__claim { background: var(--accent); color: var(--bg-0); }
.union-supply-card__claim:hover:not(:disabled) { background: var(--accent-hi); }
.union-supply-card__accrue {
  background: var(--bg-2);
  color: var(--text-1);
  border: 1px solid var(--border);
}
.union-supply-card__accrue:hover:not(:disabled) { color: var(--text-0); }
.union-supply-card__claim:disabled,
.union-supply-card__accrue:disabled {
  background: var(--bg-2);
  color: var(--text-2);
  cursor: not-allowed;
}

/* 문구가 남는 세로 공간을 모두 먹고, 버튼(foot)은 카드 바닥에 붙는다.
   덕분에 트랙마다 문구 길이가 달라도 카드 세 장의 버튼 줄이 정확히 정렬된다. */
.union-supply-card__hint {
  flex: 1;
  margin: 0;
  font-size: 0.78rem;
  line-height: 1.45;
  color: var(--text-2);
}

/* ── 기여의 전당(협회 요청 3슬롯) ───────────────────────────────── */

.ureq { display: flex; flex-direction: column; gap: 0.9rem; }
.ureq__intro { color: var(--text-1); font-size: 0.9rem; line-height: 1.6; margin: 0; }
.ureq__intro b { color: var(--accent-hi); }

.ureq-slots {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.7rem;
  align-items: start;
}

.ureq-card {
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 0.7rem 0.75rem;
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
  min-width: 0;
}
.ureq-card__head { display: flex; align-items: center; gap: 0.6rem; min-width: 0; }
.ureq-card__head .item-cell { flex: 0 0 auto; width: 3.6rem; }
/* 카드 제목이 이름을 크게 싣는다 — 셀은 아이콘 타일 겸 툴팁 앵커로만 쓴다(이름 중복 방지). */
.ureq-card__head .item-cell__name { display: none; }
.ureq-card__title { display: flex; flex-direction: column; gap: 0.15rem; min-width: 0; }
.ureq-card__title b {
  font-size: 0.95rem;
  color: var(--rarity-color, var(--text-0));
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ureq-card__unit { font-size: 0.76rem; color: var(--text-2); }

/* 진행 게이지 — 전 서버가 함께 채운다. */
.ureq-gauge {
  height: 0.5rem;
  border-radius: 999px;
  background: var(--bg-0);
  border: 1px solid var(--border);
  overflow: hidden;
}
.ureq-gauge > i {
  display: block;
  height: 100%;
  background: var(--accent-hi);
  transition: width 220ms ease-out;
}
.ureq-card__nums {
  display: flex;
  justify-content: space-between;
  font-size: 0.8rem;
  color: var(--text-1);
}
.ureq-card__mine { color: var(--text-2); }
.ureq-card__empty { margin: 0; font-size: 0.82rem; color: var(--text-2); }

/* 3열 카드는 폭이 좁다 — 소계와 버튼을 한 줄에 넣으면 둘 다 줄바꿈된다. 세로로 쌓는다. */
.ureq-card__foot {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  margin-top: 0.1rem;
}
.ureq-card__sub {
  font-size: 0.8rem;
  color: var(--accent-hi);
  font-weight: 600;
  min-height: 1.1em; /* 선택 0 일 때도 카드 높이 흔들림 방지 */
  line-height: 1.4;
}
.ureq-card__sub.is-warn { color: var(--danger-soft); font-weight: 500; }

.ureq-stepper { display: flex; align-items: center; gap: 0.25rem; }
.ureq-stepper__input {
  flex: 1 1 auto;
  min-width: 0;
  text-align: center;
  font-size: 0.95rem;
  height: 1.8rem;
  padding: 0 0.3rem;
  color: var(--text-0);
  background: var(--bg-0);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm, 4px);
  -moz-appearance: textfield;
}
.ureq-stepper__input::-webkit-outer-spin-button,
.ureq-stepper__input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.ureq-stepper__input:focus { outline: none; border-color: var(--accent-hi); }

.ureq-btn {
  height: 1.9rem;
  padding: 0 0.7rem;
  font-size: 0.85rem;
  line-height: 1;
  border-radius: var(--radius-sm, 4px);
  border: 1px solid var(--border);
  cursor: pointer;
  white-space: nowrap;
}
.ureq-btn--step {
  flex: 0 0 auto;
  min-width: 1.8rem;
  height: 1.8rem;
  padding: 0 0.45rem;
  color: var(--text-0);
  background: var(--bg-2);
  user-select: none;
}
.ureq-btn--step:hover { background: var(--bg-3, var(--bg-2)); border-color: var(--accent-hi); }
.ureq-btn--step:active { transform: translateY(1px); }
.ureq-btn--ghost { background: transparent; color: var(--text-1); }
.ureq-btn--ghost:hover { color: var(--text-0); border-color: var(--text-2); }
.ureq-btn--primary {
  background: var(--accent-hi);
  color: var(--bg-0);
  border-color: var(--accent-hi);
  font-weight: 700;
}
.ureq-btn--primary:hover:not(:disabled) { filter: brightness(1.08); }
.ureq-btn--primary:disabled { opacity: 0.45; cursor: not-allowed; }

/* 장비 묶음 — 인스턴스마다 굴림이 달라 유저가 직접 고른다. */
.ureq-gear[hidden] { display: none; }
.ureq-gear__list {
  max-height: 16rem;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  padding-right: 0.2rem;
}
.ureq-gear__check { flex: 0 0 auto; cursor: pointer; accent-color: var(--accent-hi); }

.ureq-recent {
  border-top: 1px solid var(--border);
  padding-top: 0.6rem;
}
.ureq-recent__title { font-size: 0.82rem; color: var(--text-2); margin-bottom: 0.35rem; }
.ureq-recent ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.2rem; }
.ureq-recent li {
  display: flex;
  justify-content: space-between;
  font-size: 0.84rem;
  color: var(--text-1);
}
.ureq-recent__pts { color: var(--accent-hi); font-weight: bold; }

/* ── 협회 교환소(재료 교환 3슬롯) ───────────────────────────────── */

.uxc { display: flex; flex-direction: column; gap: 0.9rem; }
.uxc__intro { color: var(--text-1); font-size: 0.9rem; line-height: 1.6; margin: 0; }
.uxc__intro b { color: var(--accent-hi); }

.uxc-slots {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.7rem;
  align-items: start;
}

.uxc-card {
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 0.7rem 0.75rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  min-width: 0;
}
.uxc-card.is-empty { opacity: 0.6; }

.uxc-card__head { display: flex; align-items: center; justify-content: space-between; gap: 0.4rem; }
.uxc-card__tag {
  font-size: 0.74rem;
  padding: 0.1rem 0.4rem;
  border-radius: 999px;
  border: 1px solid var(--border);
  color: var(--text-2);
  white-space: nowrap;
}
.uxc-card__tag.is-up   { color: var(--accent-hi); border-color: var(--accent); }
.uxc-card__tag.is-down { color: var(--text-1); }
.uxc-card__cost { font-size: 0.84rem; color: var(--accent-hi); font-weight: 600; white-space: nowrap; }
.uxc-card__free { color: var(--text-2); font-weight: 400; }

/* 투입 → 산출. 3열 카드라 폭이 좁으므로 화살표를 가운데 고정폭으로 둔다. */
.uxc-card__trade {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: start;
  gap: 0.3rem;
}
.uxc-card__side {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.2rem;
  min-width: 0;
}
/* itemCell 은 가로형 위젯이라 좁은 칸에서 이름이 세로로 찌그러진다. 기여의 전당
   (.ureq-card__head)과 같은 처리 — 셀은 아이콘 타일 겸 툴팁 앵커로만 쓰고 이름은 카드가 싣는다. */
.uxc-card__side .item-cell { width: 3.2rem; flex: 0 0 auto; }
.uxc-card__side .item-cell__name { display: none; }

/* 이름 길이가 칸마다 달라도 카드 높이가 어긋나지 않게 두 줄 자리를 늘 비워 둔다
   (3열 그리드라 폭이 좁아 두 줄 넘김이 흔하다). */
.uxc-card__name {
  min-height: 2.4em;
  font-size: 0.82rem;
  line-height: 1.2;
  color: var(--rarity-color, var(--text-0));
  text-align: center;
  word-break: keep-all;
  overflow: hidden;
}
.uxc-card__mine { font-size: 0.74rem; color: var(--text-2); }
.uxc-card__arrow { color: var(--accent-hi); font-size: 1.1rem; align-self: center; }
.uxc-card__empty { margin: 0; font-size: 0.8rem; color: var(--text-2); line-height: 1.5; }

/* 3열 카드는 폭이 좁다 — 소계와 버튼을 한 줄에 넣으면 둘 다 줄바꿈된다. 세로로 쌓는다. */
.uxc-card__foot { display: flex; flex-direction: column; gap: 0.35rem; }
.uxc-card__sub {
  font-size: 0.78rem;
  color: var(--accent-hi);
  font-weight: 600;
  min-height: 1.1em;   /* 선택 전에도 카드 높이 흔들림 방지 */
  line-height: 1.4;
}

.uxc-stepper { display: flex; align-items: center; gap: 0.25rem; }
.uxc-stepper__input {
  flex: 1 1 auto;
  min-width: 0;
  text-align: center;
  font-size: 0.95rem;
  height: 1.8rem;
  padding: 0 0.3rem;
  color: var(--text-0);
  background: var(--bg-0);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm, 4px);
  -moz-appearance: textfield;
}
.uxc-stepper__input::-webkit-outer-spin-button,
.uxc-stepper__input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.uxc-stepper__input:focus { outline: none; border-color: var(--accent-hi); }

.uxc-btn {
  height: 1.9rem;
  padding: 0 0.7rem;
  font-size: 0.85rem;
  line-height: 1;
  border-radius: var(--radius-sm, 4px);
  border: 1px solid var(--border);
  cursor: pointer;
  white-space: nowrap;
}
.uxc-btn--step {
  flex: 0 0 auto;
  min-width: 1.8rem;
  height: 1.8rem;
  padding: 0 0.45rem;
  color: var(--text-0);
  background: var(--bg-2);
  user-select: none;
}
.uxc-btn--step:hover { background: var(--bg-3, var(--bg-2)); border-color: var(--accent-hi); }
.uxc-btn--step:active { transform: translateY(1px); }
.uxc-btn--primary {
  background: var(--accent-hi);
  color: var(--bg-0);
  border-color: var(--accent-hi);
  font-weight: 700;
}
.uxc-btn--primary:hover:not(:disabled) { filter: brightness(1.08); }
.uxc-btn--primary:disabled { opacity: 0.45; cursor: not-allowed; }

/* 다시 뽑기는 골드를 태우는 행동이다 — 주 동작과 또렷이 구분되도록 조용한 색으로 둔다. */
.uxc-btn--reset {
  background: transparent;
  color: var(--text-2);
  font-size: 0.78rem;
  height: 1.7rem;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.25rem;
}
.uxc-btn--reset:hover { color: var(--text-0); border-color: var(--text-2); }

.uxc-recent { border-top: 1px solid var(--border); padding-top: 0.6rem; }
.uxc-recent__title { font-size: 0.82rem; color: var(--text-2); margin-bottom: 0.35rem; }
.uxc-recent ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.2rem; }
.uxc-recent li {
  display: flex;
  justify-content: space-between;
  gap: 0.5rem;
  font-size: 0.84rem;
  color: var(--text-1);
}
.uxc-recent__pair { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.uxc-recent__pair i { color: var(--accent-hi); font-style: normal; }
.uxc-recent__pts { color: var(--accent-hi); font-weight: bold; white-space: nowrap; }

/* ── 로비 좌측 커뮤니티 위젯 ───────────────────────────────────── */

[data-role="union-widget"] .panel__title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
}
.union-widget__actions {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
}
.union-widget__open {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text-1);
  font-size: 0.74rem;
  padding: 0.18rem 0.55rem;
  border-radius: 999px;
  cursor: pointer;
  font-weight: normal;
}
.union-widget__open:hover {
  background: rgba(var(--accent-rgb), 0.08);
  color: var(--accent-hi);
  border-color: var(--accent);
}
.union-widget__refresh {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text-1);
  width: 1.6rem;
  height: 1.6rem;
  border-radius: 999px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
}
.union-widget__refresh .icon {
  width: 0.85rem;
  height: 0.85rem;
  opacity: 0.85;
}
.union-widget__refresh:hover {
  background: rgba(var(--accent-rgb), 0.08);
  border-color: var(--accent);
}
.union-widget__refresh:hover .icon { opacity: 1; }
.union-widget__refresh:disabled { cursor: wait; opacity: 0.6; }
.union-widget__refresh.is-spinning .icon { animation: union-widget-spin 0.8s linear infinite; }
@keyframes union-widget-spin {
  to { transform: rotate(360deg); }
}

.union-widget__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.union-widget__list li { border-bottom: 1px solid var(--border); }
.union-widget__list li:last-child { border-bottom: 0; }
.union-widget__list a {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  padding: 0.45rem 0.25rem;
  text-decoration: none;
  color: inherit;
}
.union-widget__list a:hover { background: rgba(var(--accent-rgb), 0.06); }
.union-widget__list .title {
  color: var(--text-0);
  font-size: 0.86rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.union-widget__list .meta { color: var(--text-2); font-size: 0.74rem; }

.union-widget__empty {
  color: var(--text-2);
  font-size: 0.82rem;
  text-align: center;
  padding: 0.75rem 0.25rem;
}
.union-widget__empty a {
  display: inline-block;
  margin-top: 0.4rem;
  color: var(--accent-hi);
  text-decoration: none;
}
.union-widget__empty a:hover { text-decoration: underline; }

/* ── 공동 목표 (Union Co-op Objective) ─────────────────────────────────── */
.gq__intro { color: var(--text-2); line-height: 1.6; margin-bottom: 1rem; }

/* 협회 계급 배너 — 계급이 보상 규모를 키운다는 것을 화면 맨 위에서 말해 준다. */
.gq-rank {
  display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap;
  padding: 0.55rem 0.85rem; margin-bottom: 0.35rem;
  background: rgba(var(--accent-rgb), 0.08);
  border: 1px solid var(--border); border-radius: var(--radius-md);
}
.gq-rank__badge {
  font-size: 0.82rem; font-weight: bold; color: var(--accent-hi);
  background: rgba(var(--accent-rgb), 0.14); border-radius: 999px; padding: 0.12rem 0.65rem;
}
.gq-rank__gain { font-size: 0.85rem; color: var(--text-1); }
.gq-rank__next { margin-left: auto; font-size: 0.8rem; color: var(--text-2); }
.gq-rank__note { font-size: 0.78rem; color: var(--text-2); margin: 0 0 1.1rem; line-height: 1.5; }

/* 트랙(일일/주간/지난 목표) 묶음. */
.gq-track { margin-bottom: 1.6rem; }
.gq-track:last-child { margin-bottom: 0; }
.gq-track__head { display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.3rem; }
.gq-track__icon { font-size: 1.05rem; }
.gq-track__title { font-size: 1rem; font-weight: bold; color: var(--text-0); margin: 0; }
.gq-track__timer { margin-left: auto; font-size: 0.8rem; color: var(--text-2); }
.gq-track__blurb { color: var(--text-2); font-size: 0.84rem; line-height: 1.5; margin: 0 0 0.7rem; }
.gq-track--backlog .gq-card { border-color: rgba(var(--accent-rgb), 0.35); }

/* 회차당 목표가 3개(일일·주간 모두)라 3열 고정. 지난 목표(백로그)도 같은 리듬으로 이어진다.
   데스크탑 전용(전역 min-width 1280px)이라 폭 기반 분기 없이 고정 3열로 둔다. */
.gq-list {
  list-style: none; margin: 0; padding: 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1rem;
  align-items: stretch;
}
.gq-card {
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--bg-1);
  padding: 1rem 1.1rem;
  /* 카드마다 내용 길이가 달라 [보상 수령] 버튼 줄이 어긋난다 — 바닥에 맞춘다. */
  display: flex;
  flex-direction: column;
}
.gq-card__reward { flex: 1 1 auto; }
.gq-card__foot   { margin-top: auto; }
.gq-card__head { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; margin-bottom: 0.6rem; }
.gq-card__title { font-size: 1.05rem; font-weight: bold; color: var(--text-0); }
.gq-card__metric {
  margin-left: auto; font-size: 0.78rem; color: var(--accent-hi);
  background: rgba(var(--accent-rgb), 0.12); border-radius: 999px; padding: 0.1rem 0.6rem;
}
.gq-gauge {
  position: relative; height: 1.4rem; border-radius: 999px;
  background: rgba(var(--accent-rgb), 0.10); border: 1px solid var(--border);
  overflow: hidden; margin-bottom: 0.7rem;
}
.gq-gauge__fill { height: 100%; background: var(--accent); transition: width 0.4s ease; }
.gq-gauge__fill.is-reached { background: var(--accent-hi); }
.gq-gauge__label {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  font-size: 0.76rem; font-weight: bold; color: var(--text-0); text-shadow: 0 1px 2px rgba(0,0,0,0.4);
}
/* 3열 카드는 좁다 — 기여·등급·다음등급 안내가 한 줄에 안 들어가면 접힌다. */
.gq-card__mine { display: flex; align-items: center; flex-wrap: wrap; gap: 0.4rem 0.6rem; margin-bottom: 0.5rem; font-size: 0.85rem; color: var(--text-2); }
.gq-card__contrib b { color: var(--text-0); }
.gq-tier-badge {
  font-size: 0.75rem; font-weight: bold; border-radius: 999px; padding: 0.1rem 0.55rem;
  background: rgba(255,255,255,0.06); color: var(--text-2); border: 1px solid var(--border);
}
.gq-tier-badge[data-tier="t1"] { color: #93b7e8; border-color: #5b88c8; }
.gq-tier-badge[data-tier="t2"] { color: #cc97e3; border-color: #a35cc7; }
.gq-tier-badge[data-tier="t3"] { color: var(--accent-hi); border-color: #d9a441; }
.gq-card__tier-hint { margin-left: auto; font-size: 0.78rem; color: var(--text-2); }
.gq-card__reward { font-size: 0.85rem; color: var(--text-1); margin-bottom: 0.8rem; }
.gq-card__reward-label { display: block; color: var(--text-2); margin-bottom: 0.35rem; }
.gq-card__reward-label em { font-style: normal; color: var(--text-2); opacity: 0.85; }
/* 최소 기여를 못 채운 목표 — 협회가 달성해도 내 몫은 없다. 보상을 흐려 "아직 내 것이 아님"을 보인다. */
.gq-card.is-ineligible .reward-grid { opacity: 0.5; }
.gq-card.is-ineligible .gq-card__chip { opacity: 0.6; }
/* 이계 상자 칩도 같이 흐려야 한다 — 상자만 또렷하면 "저건 내 것"으로 읽힌다.
   (칩이 알약 `.gq-card__chip` 에서 공용 `.chest-chip` 으로 옮겨 가며 위 규칙에서 빠졌다.) */
.gq-card.is-ineligible .chest-chips { opacity: 0.6; }
/* 보상 미리보기 그리드는 rewardLootHtml(itemCell) 단일 출처. 카드 안이라 칸을 조금 좁힌다.
   보상 품목이 늘어(2026-08-05) 카드는 최대 8셀이다. 공유 헬퍼(rewardLootHtml)는 탐험·던전·첨탑·
   우편이 함께 쓰므로 건드리지 않고 여기 카드 스코프에서만 최소 칸폭을 조정한다.
   ⚠ 6.5rem 까지 줄여 2열을 만들었다가 되돌렸다 — 3열 카드(≈330px) 안에서 2열이면 셀이 145px 라
   이름이 "골.." "암.."으로 잘려 **무엇을 받는지 알 수 없는 미리보기**가 된다. 공유 기본값 10.5rem 은
   바로 그래서 넉넉한 값이다. 8.5rem 은 1열을 유지하면서 카드 폭이 넓어지면 2열로 접히게 두는 값이다
   (실측: 카드 높이 478px[읽을 수 없음] → 650px[전부 읽힘]. 읽히는 쪽을 택했다). */
.gq-card__reward .reward-grid {
  justify-content: flex-start; margin-bottom: 0.4rem;
  grid-template-columns: repeat(auto-fit, minmax(8.5rem, 1fr));
}
.gq-card__chip {
  display: inline-block; margin-right: 0.4rem;
  font-size: 0.78rem; color: var(--text-1);
  background: rgba(255,255,255,0.05); border: 1px solid var(--border);
  border-radius: 999px; padding: 0.1rem 0.6rem;
}
.gq-card__foot { display: flex; justify-content: flex-end; }
.gq-claim {
  border: none; border-radius: var(--radius-md); padding: 0.5rem 1.2rem; font-weight: bold;
  background: var(--accent); color: var(--bg-0); cursor: pointer;
}
.gq-claim:not(:disabled) { animation: fx-attn-pulse var(--fx-attn-dur) ease-in-out infinite; }
.gq-claim:disabled { background: rgba(255,255,255,0.06); color: var(--text-2); cursor: default; animation: none; }

/* ── 협회 모달 팝업 (기여의 전당 등) — community-modal 동형 ──────── */
.union-modal {
  position: fixed; inset: 0; z-index: 10000;
  display: flex; align-items: safe center; justify-content: safe center;
  overflow: auto; padding: 1rem;
}
.union-modal__backdrop {
  position: fixed; inset: 0;
  background: var(--overlay-backdrop); backdrop-filter: blur(3px);
}
.union-modal__panel {
  position: relative; width: min(46rem, 100%); max-height: calc(100vh - 3rem);
  display: flex; flex-direction: column;
  background: var(--bg-1); border: 1px solid rgba(var(--accent-rgb), 0.35);
  border-radius: var(--radius-lg);
  box-shadow: 0 1.5rem 3rem rgba(0, 0, 0, 0.6), 0 0 2rem rgba(var(--accent-rgb), 0.08);
  overflow: hidden; animation: union-modal-in 180ms ease-out;
}
/* 3열 카드가 들어가는 팝업(공동 목표)용. 46rem 이면 카드 내부가 인라인 시절보다
   좁아져(189px→177px) .gq-card__mine 이 접힌다 — 그 화면만 넓힌다.
   rem 이 뷰포트 높이 연동(tokens.css)이라 1280×720(rem 15px)에서도 900px 로 여유롭다. */
.union-modal__panel--wide { width: min(60rem, 100%); }
@keyframes union-modal-in {
  from { opacity: 0; transform: translateY(1rem) scale(0.97); }
  to   { opacity: 1; transform: none; }
}
.union-modal__header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 0.75rem 1rem; border-bottom: 1px solid var(--border); background: var(--bg-2);
}
.union-modal__title { font-size: 1.05rem; color: var(--text-0); font-weight: bold; }
.union-modal__close {
  background: transparent; border: 0; color: var(--text-2); font-size: 1.2rem; cursor: pointer;
}
.union-modal__close:hover { color: var(--accent-hi); }
.union-modal__body { padding: 1rem; overflow-y: auto; }

/* ── 협회 계급도 (union-ranks.js) ────────────────────────────────── */

.union-ranks { display: flex; flex-direction: column; gap: 0.75rem; }

/* 내 계급 요약 카드 */
.union-ranks__me {
  background: rgba(var(--accent-rgb), 0.08);
  border: 1px solid rgba(var(--accent-rgb), 0.35);
  border-radius: var(--radius-lg);
  padding: 0.75rem 0.9rem;
}
.union-ranks__me-top { display: flex; align-items: baseline; justify-content: space-between; }
.union-ranks__me-rank { font-size: 1.1rem; font-weight: bold; color: var(--accent-hi); }
.union-ranks__me-merit { font-size: 0.9rem; color: var(--text-1); }
.union-ranks__me-bar {
  margin: 0.5rem 0 0.35rem;
  height: 0.4rem; border-radius: 999px; overflow: hidden;
  background: rgba(255, 255, 255, 0.10);
}
.union-ranks__me-bar > i { display: block; height: 100%; background: var(--accent-hi); }
.union-ranks__me-foot { font-size: 0.82rem; color: var(--text-2); }

.union-ranks__note { font-size: 0.82rem; color: var(--text-2); margin: 0; }

/* 표 — 4열 그리드. 헤더와 행이 같은 템플릿을 공유한다. */
.union-ranks__head,
.union-ranks__row {
  display: grid;
  grid-template-columns: 2.2rem minmax(8rem, 1fr) 7rem 7rem;
  gap: 0.9rem;
  align-items: center;
}
.union-ranks__head {
  padding: 0 0.5rem 0.35rem;
  font-size: 0.78rem; color: var(--text-2);
  border-bottom: 1px solid var(--border);
}
.union-ranks__head > span:nth-child(3),
.union-ranks__head > span:nth-child(4) { text-align: right; }
.union-ranks__row > .union-ranks__next:last-child { padding-right: 0.25rem; }

.union-ranks__list { list-style: none; margin: 0; padding: 0; }
.union-ranks__row {
  padding: 0.4rem 0.5rem;
  border-radius: var(--radius-sm);
  font-size: 0.88rem;
  border: 1px solid transparent;
}
.union-ranks__row:nth-child(odd) { background: rgba(255, 255, 255, 0.02); }
.union-ranks__row.is-current {
  background: rgba(var(--accent-rgb), 0.12);
  border-color: rgba(var(--accent-rgb), 0.45);
}

.union-ranks__no { color: var(--text-2); text-align: center; }
.union-ranks__label { color: var(--text-0); display: flex; align-items: center; gap: 0.35rem; }
.union-ranks__row.is-current .union-ranks__label { color: var(--accent-hi); font-weight: bold; }
.union-ranks__you {
  font-size: 0.7rem; font-weight: normal;
  padding: 0.05rem 0.35rem; border-radius: 999px;
  background: var(--accent-hi); color: var(--bg-0);
}
.union-ranks__cum,
.union-ranks__next { text-align: right; color: var(--text-1); font-variant-numeric: tabular-nums; }
.union-ranks__next { color: var(--text-2); }

/* ===== codex.css ===== */
/* 도감(Codex) — 수집 컨텐츠. /codex 페이지. */

.codex-page { display: flex; flex-direction: column; gap: 1rem; }

/* ── 개요 카드 ── */
.codex-overview {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.75rem;
}
.codex-stat {
  display: grid;
  grid-template-columns: auto 1fr auto;
  grid-template-areas: "icon label count" "icon bar bar";
  align-items: center;
  gap: 0.15rem 0.6rem;
  padding: 0.6rem 0.8rem;
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}
.codex-stat__icon { grid-area: icon; font-size: 1.2rem; }
.codex-stat__label { grid-area: label; color: var(--text-1); font-weight: 600; }
.codex-stat__count { grid-area: count; color: var(--text-2); font-variant-numeric: tabular-nums; }
.codex-stat__count b { color: var(--accent-hi); }
.codex-stat__bar { grid-area: bar; height: 5px; border-radius: 3px; background: var(--bg-0); overflow: hidden; }
.codex-stat__bar i { display: block; height: 100%; background: linear-gradient(90deg, var(--accent), var(--accent-hi)); }

/* ── 탭 ── */
.codex-tabs { display: flex; gap: 0.35rem; border-bottom: 1px solid var(--border); flex-wrap: wrap; }
.codex-tab {
  appearance: none;
  background: transparent;
  border: 0;
  border-bottom: 2px solid transparent;
  color: var(--text-2);
  font-weight: 600;
  padding: 0.5rem 0.9rem;
  cursor: pointer;
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}
.codex-tab .icon { width: 1.05rem; height: 1.05rem; background-color: currentColor; }
.codex-tab:hover { color: var(--text-0); background: var(--hover-bg); }
.codex-tab.is-active { color: var(--accent-hi); border-bottom-color: var(--accent); background: color-mix(in srgb, var(--accent) 10%, transparent); }

/* ── 패널 ── */
.codex-panel { display: none; flex-direction: column; gap: 0.6rem; }
.codex-panel.is-active { display: flex; }
/* ── 가로 드릴다운 + 좁혀 보기 (2026-08-22) ─────────────────────────────────
   좌측 232px `<details>` 3단 아코디언을 걷어냈다. 버킷이 121 → 169 로 늘면서 세로 내비가
   감당하지 못했고, 회수한 폭은 카드 그리드로 보냈다(4열 → 5열 · 셀 폭은 그대로).
   행은 전부 SSR 되어 있고 JS 는 `.is-hidden` 만 토글한다 — ⚠ `hidden` 속성이 아니다
   (`[hidden]` 은 저자 `display:flex` 에 진다). */
.codex-panel { container: codexmon / inline-size; }
.codex-regions { display: flex; flex-direction: column; gap: 0.7rem; min-width: 0; }

.codex-drill { display: flex; flex-direction: column; gap: 0.35rem; min-width: 0; }
.codex-drill__row { display: flex; flex-wrap: wrap; gap: 0.35rem; align-items: center; min-width: 0; }
.codex-drill__row.is-hidden { display: none; }
/* 계층은 캡션이 아니라 **들여쓰기 + 급 낮추기**로 보인다 — 축 이름 라벨을 두려면 CSV 에
   없는 라벨 맵을 코드에 만들어야 한다(그 대신 pane 머리글의 빵부스러기가 말해 준다). */
.codex-drill__row--sub    { padding-left: 0.9rem; }
.codex-drill__row--bucket { padding-left: 0.9rem; }
.codex-drill__row--sub::before,
.codex-drill__row--bucket::before {
  content: "";
  flex: 0 0 auto;
  width: 2px; align-self: stretch; min-height: 1.4rem;
  margin-right: 0.35rem;
  background: var(--border);
  border-radius: 1px;
}

/* 그룹·중간축 칩 */
.codex-drillchip {
  appearance: none;
  display: inline-flex;
  align-items: center;
  gap: 0.34rem;
  padding: 0.34rem 0.6rem;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: 999px;
  cursor: pointer;
  color: var(--text-1);
  transition: border-color 120ms ease, background 120ms ease, color 120ms ease, box-shadow 120ms ease;
}
.codex-drillchip:hover { border-color: var(--accent); background: var(--hover-bg-2); }
.codex-drillchip.is-active {
  background: var(--bg-1);
  border-color: var(--accent);
  color: var(--accent-hi);
}
.codex-drillchip__name { font-size: 0.84rem; font-weight: 700; white-space: nowrap; }
.codex-drillchip__count { font-size: 0.72rem; color: var(--text-2); font-variant-numeric: tabular-nums; white-space: nowrap; }
.codex-drillchip__count.is-complete { color: var(--success-soft); font-weight: 700; }
.codex-drillchip__dot { font-size: 0.75rem; flex: 0 0 auto; }
/* 보상 대기 — 🔴 **테두리는 선택 상태 전용 채널**이다. 여기서 border-color 를 건드리면
   "선택됨"과 완전히 같은 금테가 돼 둘을 구분할 수 없다(2026-08-24 수정 전이 그랬다 —
   차이가 배경 rgb 10 뿐이었다). 보상은 바깥 골드 헤일로 + 🎁 박동으로만 알린다.
   .codex-cell--item.is-claimable 이 쓰는 골드 링과 같은 관용구다. */
.codex-drillchip.has-claim { box-shadow: 0 0 0.5rem 0 rgba(var(--accent-rgb), 0.5); }
.codex-drillchip.has-claim .codex-drillchip__dot { animation: fx-attn-pulse var(--fx-attn-dur) ease-in-out infinite; }
/* 그룹 행은 한 급 크게 — 여기가 계층의 꼭대기다. */
.codex-drill__row--group .codex-drillchip { padding: 0.42rem 0.72rem; }
.codex-drill__row--group .codex-drillchip__name { font-size: 0.9rem; }

/* 최종 버킷 칩 — 아이콘을 달아 그룹·중간축 칩과 한눈에 구분된다. */
.codex-region-item {
  appearance: none;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.34rem 0.6rem;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  cursor: pointer;
  text-align: left;
  transition: border-color 120ms ease, background 120ms ease, box-shadow 120ms ease;
}
.codex-region-item:hover { border-color: var(--accent); background: var(--hover-bg-2); }
.codex-region-item.is-active { background: var(--bg-1); border-color: var(--accent); }
.codex-region-item__icon {
  flex: 0 0 auto;
  width: 1.2rem; height: 1.2rem;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--text-1);
}
.codex-region-item__icon .icon { width: 1.2rem; height: 1.2rem; }
.codex-region-item.is-active .codex-region-item__icon { color: var(--accent-hi); }
.codex-region-item__name {
  color: var(--text-0);
  font-size: 0.84rem;
  font-weight: 600;
  white-space: nowrap;
}
.codex-region-item.is-active .codex-region-item__name { color: var(--accent-hi); }
.codex-region-item__count {
  flex: 0 0 auto;
  font-size: 0.72rem;
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.codex-region-item__count.is-complete { color: var(--success-soft); font-weight: 700; }
.codex-region-item__reward { flex: 0 0 auto; font-size: 0.8rem; }
/* 보상 대기 — 위 .codex-drillchip.has-claim 과 같은 계약: 테두리는 선택 전용, 보상은 헤일로. */
.codex-region-item.has-claim { box-shadow: 0 0 0.5rem 0 rgba(var(--accent-rgb), 0.5); }
.codex-region-item.has-claim .codex-region-item__reward {
  animation: fx-attn-pulse var(--fx-attn-dur) ease-in-out infinite;
}

/* ── 좁혀 보기 줄 ── */
.codex-filters {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem 0.7rem;
  padding: 0.45rem 0.6rem;
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}
.codex-filters__axis { display: flex; flex-wrap: wrap; align-items: center; gap: 0.28rem; min-width: 0; }
.codex-filters__label { font-size: 0.74rem; color: var(--text-2); margin-right: 0.15rem; }
.codex-filterchip {
  appearance: none;
  padding: 0.2rem 0.5rem;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: 999px;
  cursor: pointer;
  color: var(--text-2);
  font-size: 0.76rem;
  line-height: 1.5;
  white-space: nowrap;
  transition: border-color 120ms ease, background 120ms ease, color 120ms ease;
}
.codex-filterchip:hover { border-color: var(--accent); color: var(--text-1); }
.codex-filterchip.is-active {
  background: var(--bg-1);
  border-color: var(--accent);
  color: var(--accent-hi);
  font-weight: 700;
}
.codex-filters__axis--state { margin-left: auto; }
.codex-filters__search {
  flex: 0 1 12rem;
  min-width: 7rem;
  padding: 0.24rem 0.5rem;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text-0);
  font-size: 0.78rem;
}
.codex-filters__search:focus { border-color: var(--accent); outline: none; }
.codex-filters__result { font-size: 0.74rem; color: var(--text-2); font-variant-numeric: tabular-nums; }
.codex-cell.is-filtered-out { display: none; }

/* 좌측 항목 안의 던전 태그는 더 작게. */

/* 우측 상세 */
.codex-region-detail { min-width: 0; }
.codex-region-pane { display: none; }
.codex-region-pane.is-active {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  overflow: hidden;
}
.codex-region-pane__head {
  display: flex;
  align-items: flex-start;
  gap: 0.8rem;
  padding: 0.85rem 0.95rem;
  background: var(--bg-0);
  border-bottom: 1px solid var(--border);
}
.codex-region-pane__icon {
  flex: 0 0 auto;
  width: 2.6rem;
  height: 2.6rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--accent-hi);
}
.codex-region-pane__icon .icon { width: 2.6rem; height: 2.6rem; }
.codex-region-pane__main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 0.3rem; }
.codex-region-pane__titlerow { display: flex; align-items: center; flex-wrap: wrap; gap: 0.5rem; }
.codex-region-pane__title { color: var(--text-0); font-size: 1.05rem; font-weight: 700; }
.codex-region-pane__prog {
  margin-left: auto;
  font-size: 0.8rem;
  color: var(--accent-hi);
  font-variant-numeric: tabular-nums;
}
.codex-region-pane__prog.is-complete { color: var(--success-soft); font-weight: 700; }
.codex-region-pane__intro { margin: 0; font-size: 0.82rem; line-height: 1.5; color: var(--text-1); }

/* 완성 보상 스트립 — 드릴다운과 좁혀 보기 **사이**에 산다(pane 밖).
   보상 단위가 최종 버킷이라 자기를 정하는 드릴다운에 붙어 있어야 한다. 좁혀 보기 아래로
   내려가면 계통 필터와 인접해 "계통별 보상"으로 읽힌다(2026-08-24 이전이 그랬다). */
.codex-regions > [data-role="pct-strip"]:empty { display: none; }
.codex-regions > [data-role="pct-strip"] .codex-ms { border-bottom: 1px solid var(--border); }

/* ── 그리드 + 셀 ── */
.codex-grid {
  list-style: none;
  margin: 0;
  padding: 0.6rem 0.85rem 0.85rem;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(108px, 1fr));
  gap: 0.5rem;
}
.codex-cell {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.2rem;
  padding: 0.55rem 0.4rem;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  text-align: center;
  position: relative;
  min-height: 96px;
}
.codex-cell__icon { font-size: 1.6rem; line-height: 1; position: relative; }
.codex-cell__name {
  font-size: 0.78rem;
  color: var(--text-1);
  word-break: keep-all;
  line-height: 1.2;
}
.codex-cell__lv { font-size: 0.7rem; color: var(--text-2); font-variant-numeric: tabular-nums; }
.codex-cell__count {
  font-size: 0.68rem;
  font-weight: 700;
  color: var(--accent-hi);
  background: rgba(var(--accent-rgb), 0.12);
  border-radius: 999px;
  padding: 0.02rem 0.4rem;
  font-variant-numeric: tabular-nums;
}

.codex-cell.is-locked { opacity: 0.5; filter: grayscale(0.6); }
.codex-cell.is-locked .codex-cell__name { color: var(--text-2); letter-spacing: 0.1em; }
.codex-cell.is-locked .codex-cell__icon .icon { opacity: 0.4; }

/* 아이템 셀: 등급 테두리. */
.codex-cell--item[data-rarity] { border-color: var(--rarity-edge, var(--border)); }
.codex-cell--item .codex-cell__name { color: var(--rarity-color, var(--text-1)); }

/* 보스 셀: 강조 테두리. */
.codex-cell--boss {
  --rank-color: var(--accent-hi);
  min-height: 110px;
  align-items: stretch;
  gap: 0.45rem;
  padding: 0.75rem;
  border-color: rgba(var(--accent-rgb), 0.4);
  justify-content: flex-start;
  text-align: left;
}
.codex-cell--boss .codex-cell__name {
  color: var(--text-0);
  font-size: 0.92rem;
  font-weight: 800;
  text-align: left;
}
.codex-cell--boss .codex-cell__count {
  align-self: flex-start;
}

/* ── 세트 수집 트래커 셀 ── */
.codex-cell--set {
  justify-content: flex-start;
  min-height: 120px;
  border-color: var(--rarity-edge, rgba(95, 211, 107, 0.4));
}
.codex-cell--set .codex-cell__name { color: var(--rarity-color, #5fd36b); font-weight: 700; }
.codex-cell--set.is-complete {
  border-color: #5fd36b;
  box-shadow: 0 0 0 1px rgba(95, 211, 107, 0.5), 0 0 12px rgba(95, 211, 107, 0.22);
}

/* ── 몬스터 셀(향상된 카드: 등급색 + 초상화 프레임) ── */
/* 전 도감 **5열 고정** — 대분류를 옮겨도 카드 크기가 그대로라 같은 화면으로 읽힌다.
   auto-fill 은 열 수가 출렁여 카드·일러스트 크기가 같이 흔들리므로 쓰지 않는다.
   🔴 2026-08-22 에 4 → 5. 좌측 내비 244px + gap 을 회수했기 때문에 **열을 늘렸는데 셀이 넓어진다**
      — 실측(뷰포트 1440 · 센터 패널 775px): 구 4열 ≈123px → 신 5열 **142px**(+15%).
      그래서 4열이 강제하던 제약 — `.codex-kvgrid` 2×2(실측 56px 씩) · 드랍 행 2줄 ·
      일러스트 3/2 배너 — 이 전부 여유 있게 성립한다.
   ⚠ 이 값을 더 올리려면 셀 폭부터 재고, `.codex-kvgrid` 가 2×2 를 유지하는지 확인할 것. */
[data-codex-panel] .codex-grid { grid-template-columns: repeat(5, 1fr); }

/* 좁은 폭에서 2열로 접는다.
   🔴 컨테이너 쿼리는 명시도를 더하지 않는다 — 위 5열 규칙과 `[data-codex-panel] .codex-grid`
   로 **명시도가 같아** 순서가 승부를 가른다. 그래서 이 블록은 반드시 5열 선언 **뒤**에 온다.
   (2026-08-24 이전엔 위쪽 주석의 짝 없는 닫기 기호가 이 블록을 통째로 삼켜 죽어 있었고,
   되살리고 보니 자리까지 앞이라 여전히 지고 있었다 — 두 겹으로 고장나 있었다.)
   ⚠ 이 주석 안에 닫기 기호를 리터럴로 쓰지 말 것 — 거기서 주석이 끝나 버린다. */
@container codexmon (max-width: 560px) {
  [data-codex-panel] .codex-grid { grid-template-columns: repeat(2, 1fr); }
  .codex-filters__axis--state { margin-left: 0; }
}
.codex-cell--mon {
  --rank-color: var(--text-2);
  min-height: 128px;
  gap: 0.38rem;
  padding: 0.7rem;
  justify-content: flex-start;
}
.codex-cell--mon[data-rank="elite"]   { --rank-color: var(--accent-hi); }
.codex-cell--mon[data-rank="boss"]    { --rank-color: #ff8a5c; }
/* normal 외 등급은 카드 테두리 틴트 + 좌측 강조 바로 한눈에 구분. */
.codex-cell--mon[data-rank="elite"],
.codex-cell--mon[data-rank="boss"] {
  border-color: color-mix(in srgb, var(--rank-color) 50%, var(--border));
  box-shadow: inset 3px 0 0 var(--rank-color);
}

/* 초상화 프레임 — 등급색 링으로 감싼 확대 초상화. */
.codex-cell__portrait {
  position: relative;
  width: 58px;
  height: 58px;
  display: grid;
  place-items: center;
  background: var(--bg-0);
  border: 1px solid color-mix(in srgb, var(--rank-color) 55%, var(--border));
  border-radius: var(--radius-sm);
}
.codex-cell__portrait .codex-cell__icon { font-size: 2.1rem; }
.codex-cell__portrait .codex-cell__icon .icon { width: 2.1rem; height: 2.1rem; }

/* 몬스터 카드는 **일러스트 영역을 항상 예약**한다 — 발견/미발견·원화 유무와 무관하게 같은
   크기의 배너를 둬야 3열 그리드의 행 높이가 들쭉날쭉하지 않다.
   원본 일러스트는 1024×1024(1:1)이므로 3:2 로 잘라 상단(머리 쪽)을 살린다. */
.codex-cell--mon .codex-cell__portrait,
.codex-cell--boss .codex-cell__portrait {
  width: 100%;
  height: auto;
  aspect-ratio: 3 / 2;
  background: var(--bg-1);
  overflow: hidden;
}
/* 원화가 없는 카드(미발견·원화 미생성)는 예약된 배너 한가운데 실루엣 아이콘. */
.codex-cell--mon .codex-cell__portrait .codex-cell__icon,
.codex-cell--boss .codex-cell__portrait .codex-cell__icon { font-size: 3rem; }
.codex-cell--mon .codex-cell__portrait .codex-cell__icon .icon,
.codex-cell--boss .codex-cell__portrait .codex-cell__icon .icon { width: 3rem; height: 3rem; }

/* 등급 배지 — 초상화 하단 중앙. normal 은 배지 없음. */
.codex-cell__rank {
  position: absolute;
  bottom: -7px;
  left: 50%;
  transform: translateX(-50%);
  font-size: 0.6rem;
  font-weight: 700;
  line-height: 1;
  padding: 0.12rem 0.36rem;
  border-radius: 999px;
  white-space: nowrap;
  color: #15110a;
  background: var(--rank-color);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.45);
}

/* 이름 — 가장 또렷하게(위계 정리). */
.codex-cell--mon .codex-cell__name {
  margin-top: 0.25rem;
  font-size: 0.84rem;
  font-weight: 600;
  color: var(--text-0);
}
/* 메타 — 레벨 · 처치수 한 줄. */
.codex-cell__meta {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  flex-wrap: wrap;
  justify-content: center;
}

/* 발견된 몬스터/보스 카드의 상시 정보 영역. 툴팁 없이 전투 정보를 즉시 읽게 한다. */
.codex-detail,
.codex-info-block {
  width: 100%;
  min-width: 0;
}
.codex-detail {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  padding-top: 0.2rem;
}
/* 4열 그리드에서 카드 내용 폭이 ≈119px 라 4-across 는 셀당 27px — '1,271' 이 넘친다.
   2×2 면 셀당 ≈57px 로 여유가 생긴다. */
.codex-kvgrid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.25rem;
  width: 100%;
}
.codex-kvgrid span {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.06rem;
  min-width: 0;
  min-height: 38px;
  padding: 0.24rem 0.18rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-0);
  color: var(--text-1);
  font-size: 0.72rem;
  font-variant-numeric: tabular-nums;
}
.codex-kvgrid b {
  color: var(--text-2);
  font-size: 0.62rem;
  font-weight: 600;
}
.codex-info-block {
  display: flex;
  flex-direction: column;
  gap: 0.28rem;
  padding-top: 0.25rem;
  border-top: 1px solid rgba(255, 255, 255, 0.07);
  text-align: left;
}
/* 속성 행 — 공격/약점/저항. 라벨을 고정폭으로 두어 칩의 왼쪽 기준선이 세 줄 모두 일치한다. */
.codex-attr-row {
  display: grid;
  grid-template-columns: 2.1rem minmax(0, 1fr);
  align-items: baseline;
  gap: 0.3rem;
  width: 100%;
  min-width: 0;
}
.codex-attr-row__label {
  color: var(--text-2);
  font-size: 0.66rem;
  font-weight: 700;
  white-space: nowrap;
}

.codex-info-block__title {
  color: var(--text-0);
  font-size: 0.7rem;
  font-weight: 800;
}
.codex-mini-list,
.codex-drop-list,
.codex-mini-list li {
  display: flex;
  flex-direction: column;
  gap: 0.12rem;
  min-width: 0;
  padding: 0.32rem 0.38rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: rgba(0, 0, 0, 0.12);
}
.codex-mini-list__main {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.35rem;
  min-width: 0;
}
.codex-mini-list__main b {
  min-width: 0;
  overflow-wrap: anywhere;
  color: var(--text-0);
  font-size: 0.72rem;
}
.codex-mini-list__sub {
  color: var(--text-2);
  font-size: 0.66rem;
  line-height: 1.35;
  overflow-wrap: anywhere;
}
/* 4열 그리드에선 카드가 좁아 [아이콘][이름][확률] 한 줄이 뭉개진다 →
   아이콘은 세로 병합하고 오른쪽을 이름 / 확률·수량 2줄로 쌓는다.
   행 전체가 아이템 툴팁 앵커라 커서를 올리면 인벤토리와 같은 상세가 뜬다. */
.codex-drop-list li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  grid-template-rows: auto auto;
  align-items: center;
  column-gap: 0.32rem;
  row-gap: 0.05rem;
  min-height: 28px;
  padding: 0.26rem 0.34rem;
  border: 1px solid var(--rarity-edge, var(--border));
  border-radius: var(--radius-sm);
  background: rgba(0, 0, 0, 0.12);
  cursor: help;                       /* 호버하면 정보가 더 있다는 신호 */
}
.codex-drop-list li > .icon { grid-row: 1 / span 2; }
.codex-drop-list__name { grid-column: 2; grid-row: 1; }
.codex-drop-list__meta { grid-column: 2; grid-row: 2; }
.codex-drop-list .icon { width: 1rem; height: 1rem; }
.codex-drop-list__name {
  min-width: 0;
  color: var(--rarity-color, var(--text-1));
  font-size: 0.68rem;
  font-weight: 700;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.codex-drop-list__meta {
  color: var(--text-2);
  font-size: 0.64rem;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.codex-empty-line {
  width: 100%;
  color: var(--text-2);
  font-size: 0.66rem;
  line-height: 1.35;
  text-align: center;
}
.codex-ms {
  margin: 0;
  padding: 0.5rem 0.85rem;
  border-bottom: 1px solid var(--border);
  background: var(--bg-0);
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}
.codex-ms.is-ready {
  background: rgba(var(--accent-rgb), 0.12);
  box-shadow: inset 0 0 0 1px rgba(var(--accent-rgb), 0.28);
}
.codex-ms.is-done { background: transparent; }
.codex-ms__top { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; }
.codex-ms__label { font-size: 0.78rem; font-weight: 600; color: var(--text-1); }
.codex-ms.is-ready .codex-ms__label { color: var(--accent-hi); }
.codex-ms.is-done .codex-ms__label { color: var(--success-soft); }
.codex-ms__prog { font-size: 0.74rem; color: var(--text-2); font-variant-numeric: tabular-nums; white-space: nowrap; }
.codex-ms__bar { height: 7px; border-radius: 4px; background: var(--bg-2); overflow: hidden; box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.3); }
.codex-ms__bar i {
  display: block; height: 100%; border-radius: 4px;
  background: linear-gradient(90deg, var(--accent), var(--accent-hi));
  transition: width 280ms ease;
}
.codex-ms.is-ready .codex-ms__bar i { box-shadow: 0 0 8px rgba(var(--accent-rgb), 0.7); }

/* 보상 미리보기 — 아이콘+등급색 칩. */
.codex-ms__chips { display: flex; flex-wrap: wrap; gap: 0.3rem; }


/* 보스 셀 내부 스트립은 더 촘촘하게(작은 셀). */
.codex-cell--boss [data-role="ms-strip"] { width: 100%; }
.codex-cell--boss .codex-ms { padding: 0.35rem 0; border-bottom: 0; background: transparent; gap: 0.25rem; box-shadow: none; }
.codex-cell--boss .codex-ms.is-ready { box-shadow: none; }
.codex-cell--boss .codex-ms__label { font-size: 0.68rem; }

/* 작은 수령 버튼(스트립용) — 도달 시 골드 그라디언트 전체폭 + 주의 펄스. */
.codex-claim-btn--sm { padding: 0.4rem 0.7rem; font-size: 0.8rem; align-self: stretch; width: 100%; }
.codex-ms.is-ready .codex-claim-btn--sm {
  border-color: #d99a3a;
  background: linear-gradient(180deg, #f5c45e, #d99a3a);
  color: #2a1c08;
  animation: fx-attn-pulse var(--fx-attn-dur) ease-in-out infinite;
}
.codex-ms.is-ready .codex-claim-btn--sm:hover:not(:disabled) {
  background: linear-gradient(180deg, #ffd684, #e7a847);
}

/* 수령 가능 아이템 셀(클릭 수령) — 스트립 버튼과 동일한 골드 톤 주의 펄스. */
/* 아이템 카드도 강조는 테두리까지만 — 깜빡임·클릭은 우상단 핀이 전담한다
   (카드 전체가 깜빡이면 5열 그리드에서 화면이 산만해진다). */
.codex-cell--item.is-claimable {
  border-color: var(--accent);
  box-shadow: 0 0 0 1px rgba(var(--accent-rgb), 0.4);
}

/* ── 헤더 아래 보상 배너(수령할 보상 N건 + 전체 수령) ── */
.codex-reward-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.6rem 0.9rem;
  border: 1px solid var(--accent);
  border-radius: var(--radius-md);
  background: rgba(var(--accent-rgb), 0.12);
  box-shadow: inset 0 0 0 1px rgba(var(--accent-rgb), 0.18);
  animation: fx-attn-pulse var(--fx-attn-dur) ease-in-out infinite;
}
.codex-reward-banner__text {
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--accent-hi);
}
.codex-reward-banner__text b { font-variant-numeric: tabular-nums; font-weight: 800; }
.codex-claim-all-btn {
  white-space: nowrap;
  background: linear-gradient(180deg, #f5c45e, #d99a3a);
  border-color: #d99a3a;
  color: #2a1c08;
}
.codex-claim-all-btn:hover:not(:disabled) { background: linear-gradient(180deg, #ffd684, #e7a847); }
.codex-claim-all-btn:disabled { opacity: 0.7; cursor: default; }


/* ── 약점/저항 칩 ── */
/* 카드 안의 모든 블록이 왼쪽 기준선을 공유하도록 좌정렬(코덱스 카드 전용 클래스). */
.codex-chips { display: flex; flex-wrap: wrap; gap: 0.24rem; justify-content: flex-start; align-items: center; max-width: 100%; min-width: 0; }
.codex-chip {
  font-size: 0.7rem;
  padding: 0.06rem 0.4rem;
  border-radius: 999px;
  border: 1px solid currentColor;
  line-height: 1.3;
  font-weight: 600;
}
/* 속성 칩: 학교색 기반 옅은 배경 틴트로 색 식별↑(단색 빨강 틴트 대체). */
.codex-chip--weak,
.codex-chip--school { background: color-mix(in srgb, currentColor 16%, transparent); }
.codex-chip--resist { background: color-mix(in srgb, currentColor 10%, transparent); opacity: 0.9; }
.codex-chip--tiny {
  flex: 0 0 auto;
  font-size: 0.62rem;
  padding: 0.04rem 0.32rem;
}
.codex-chip[data-school="physical"] { color: #d6d6d6; }
.codex-chip[data-school="holy"]     { color: #ffe680; }
.codex-chip[data-school="fire"]     { color: #ff6a3d; }
.codex-chip[data-school="nature"]   { color: #5ed16b; }
.codex-chip[data-school="frost"]    { color: #7ec8ff; }
.codex-chip[data-school="shadow"]   { color: #a36bff; }
.codex-chip[data-school="arcane"]   { color: #ff79c6; }
.codex-chip[data-school="poison"]   { color: #9be36b; }
.codex-claim-btn {
  appearance: none;
  border: 1px solid var(--accent);
  background: rgba(var(--accent-rgb), 0.16);
  color: var(--accent-hi);
  font-weight: 700;
  padding: 0.45rem 0.9rem;
  border-radius: var(--radius-sm);
  cursor: pointer;
  white-space: nowrap;
}
.codex-claim-btn:hover:not(:disabled) { background: rgba(var(--accent-rgb), 0.28); }
.codex-claim-btn:disabled { border-color: var(--border); background: var(--bg-2); color: var(--text-2); cursor: default; }

/* 탐험 보상 화면 상단의 도감 신규 발견 배너(core.bundle 전역). */
.exp-reward-codex {
  margin: 0 0 0.6rem;
  padding: 0.45rem 0.7rem;
  border-radius: var(--radius-sm);
  background: rgba(var(--accent-rgb), 0.14);
  border: 1px solid var(--accent);
  color: var(--accent-hi);
  font-weight: 600;
  font-size: 0.85rem;
  text-align: center;
}

/* ── 잠금 안내 ── */
.codex-locked { text-align: center; padding: 2.5rem 1rem; color: var(--text-2); }
.codex-locked__icon { font-size: 2rem; margin-bottom: 0.5rem; }
.codex-locked__title { color: var(--text-1); font-weight: 700; margin-bottom: 0.35rem; }


/* ── 마일스톤 보상 수령 결과 모달 ──
   공통 결과 모달(reward-modal.js, .modal--reward-result)을 재사용하며, 골드/아이템/도면은
   .afk__rewards 박스 안의 일관된 item-row 목록으로 통일 렌더된다. 도감 전용 강조(아이콘 톤·폭)만 남긴다. */
.modal--codex-reward .modal__panel { max-width: min(30rem, 100%); }
.modal--codex-reward .modal__icon { background: var(--accent); color: var(--bg-0); }

/* ── 일러스트 썸네일(발견 카드) ──
   발견된 몬스터/보스 카드는 실루엣 아이콘 대신 PNG 일러스트 썸네일을 띄운다(없으면 폴백).
   클릭 시 codex-page.js 가 같은 그리드를 갤러리로 묶어 라이트박스를 연다. */
.codex-illust-btn {
  appearance: none;
  border: 0;
  padding: 0;
  margin: 0;
  background: transparent;
  cursor: zoom-in;
  display: block;
  width: 100%;
  height: 100%;
  line-height: 0;
  border-radius: inherit;
  overflow: hidden;
}
.codex-illust-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* 예약된 배너를 원화가 가득 채운다(크기는 .codex-cell--mon .codex-cell__portrait 가 정한다). */
.codex-cell--mon .codex-cell__illust,
.codex-cell--boss .codex-cell__illust {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 28%;   /* 1:1 원화를 3:2 로 자를 때 머리 쪽을 살린다 */
  display: block;
  transition: transform 0.25s ease;
}
.codex-cell--mon.has-illust:hover .codex-cell__illust,
.codex-cell--boss.has-illust:hover .codex-cell__illust { transform: scale(1.04); }
/* 등급 배지는 **예약 배너 안쪽** 우하단에 둔다(원화 유무 무관).
   배너에 overflow:hidden 이 걸려 있어 종전처럼 bottom:-7px 로 걸치면 잘린다. */
.codex-cell--mon .codex-cell__rank,
.codex-cell--boss .codex-cell__rank { bottom: 6px; right: 6px; left: auto; transform: none; }

/* ══════════════════════════════════════════════════════════════════════
   2026-07-22 도감 리뉴얼 — 3대분류(몬스터/수집재료/장비) 체계
   ══════════════════════════════════════════════════════════════════════ */

/* 대분류 레일: 완전 수집 보상이 열린 대분류는 눈에 띄게. */
.codex-stat.is-ready { border-color: var(--accent); box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 35%, transparent) inset; }
.codex-stat .codex-claim-btn { grid-area: bar; justify-self: start; margin-top: 0.3rem; }
.codex-tab { position: relative; }
.codex-tab__dot { position: absolute; top: 0.15rem; right: 0.1rem; font-size: 0.6rem; line-height: 1; }

/* 소분류 완성률 스트립 — 25/50/75/100 단계 버튼. */
.codex-pct-steps { display: flex; gap: 0.35rem; flex-wrap: wrap; margin-top: 0.45rem; }
.codex-pct-step {
  flex: 0 0 auto;
  white-space: nowrap;                 /* 뱃지류는 줄바꿈 금지 */
  padding: 0.22rem 0.55rem;
  font-size: 0.68rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--text-2);
  background: var(--bg-0);
  border: 1px solid var(--border);
  border-radius: 999px;
  cursor: default;
}
.codex-pct-step.is-ready {
  color: #1a1207;
  background: linear-gradient(180deg, #f3c96b, #d9a441);
  border-color: #b98a2f;
  cursor: pointer;
}
.codex-pct-step.is-ready:hover { filter: brightness(1.08); }
.codex-pct-step.is-claimed { color: #5fd36b; border-color: color-mix(in srgb, #5fd36b 45%, var(--border)); }
.codex-pct-step:disabled { cursor: default; }

/* 지연 로딩 표시 */
.codex-bucket-loading {
  padding: 1.6rem 0;
  text-align: center;
  color: var(--text-2);
  font-size: 0.8rem;
}

/* 개별 발견 보상 상태 */
/* 수령 가능 카드는 테두리로만 알린다 — 클릭 타깃은 우상단 핀 버튼 하나뿐이므로
   카드에 cursor:pointer 를 주면 "아무 데나 눌러도 된다"는 거짓 신호가 된다. */
.codex-cell.is-claimable { border-color: color-mix(in srgb, #d9a441 55%, var(--border)); }

/* ── 우상단 수령 핀 ──
   카드 어디를 눌러야 할지 분명하도록 **실제 버튼**으로 만든다. 카드가 position:relative 라
   그 기준으로 붙는다. 일러스트 배너 위에 겹치므로 그림자로 띄워 대비를 확보한다. */
.codex-claim-pin {
  position: absolute;
  top: 5px;
  right: 5px;
  z-index: 3;
  display: inline-flex;
  align-items: center;
  gap: 0.14rem;
  padding: 0.16rem 0.42rem;
  font-size: 0.64rem;
  font-weight: 800;
  line-height: 1.2;
  white-space: nowrap;                 /* 뱃지류는 줄바꿈 금지 */
  color: #2a1c08;
  background: linear-gradient(180deg, #f5c45e, #d99a3a);
  border: 1px solid #b98a2f;
  border-radius: 999px;
  cursor: pointer;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.45);
  animation: fx-attn-pulse var(--fx-attn-dur) ease-in-out infinite;
}
.codex-claim-pin:hover { background: linear-gradient(180deg, #ffd684, #e7a847); }
.codex-claim-pin:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.codex-claim-pin.is-busy { opacity: 0.65; cursor: default; animation: none; }

/* 수령 완료 — 같은 자리의 조용한 배지(버튼 아님). */
.codex-claim-pin--done {
  color: #5fd36b;
  background: var(--bg-0);
  border-color: color-mix(in srgb, #5fd36b 45%, var(--border));
  box-shadow: none;
  cursor: default;
  animation: none;
  font-weight: 700;
}

/* 출현 지역 / 획득처 / 쓰임 칩 */
/* 좁은 카드에서 긴 지역명은 말줄임한다. 단 '던전' 표식은 flex 로 고정해
   이름이 잘려도 표식만은 남긴다(표식이 밀려 사라지면 던전 여부를 알 수 없다). */
.codex-chip--where {
  display: inline-flex;
  align-items: baseline;
  max-width: 100%;
  min-width: 0;
  color: var(--text-1);
  background: var(--bg-0);
  border: 1px solid var(--border);
}
.codex-chip__txt {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.codex-chip--where b {
  flex: 0 0 auto;
  color: var(--accent-hi);
  font-weight: 700;
  font-size: 0.62rem;
  margin-left: 0.15rem;
}

/* ── 재료 카드 상세 3섹션 — 아이템 툴팁과 같은 내용을 인라인으로 ──
   필요 재료 → 획득 단서 → 제작 재료로 쓰임. 5열 그리드에서 카드 폭이 좁아(내용 ≈97px)
   본문을 한 단계 낮추고, 묘사 문구는 **줄바꿈**시킨다.
   ⚠ .codex-chip--where 를 쓰면 안 된다 — nowrap+ellipsis 라 문구가 첫 몇 글자만 남는다. */

/* 획득 단서 한 줄: 라벨(굵게) + 묘사(이탤릭, 흐리게). 세로 스택. */
.codex-src {
  display: block;
  font-size: 0.64rem;
  line-height: 1.45;
  color: var(--text-2);
  text-align: left;
  white-space: normal;          /* 칩과 달리 반드시 줄바꿈 */
  word-break: keep-all;         /* 한글 어절 보존 */
  overflow-wrap: anywhere;      /* 그래도 넘치는 긴 토큰은 강제 분절 */
}
.codex-src + .codex-src { margin-top: 0.22rem; }
.codex-src b {
  color: var(--accent-hi);
  font-weight: 700;
  margin-right: 0.2rem;
}
.codex-src i { font-style: italic; }
/* 상한(종류당 2개)에 잘린 나머지 개수. 라벨이 없는 꼬리줄이라 묘사 쪽에 맞춰 들여쓴다. */
.codex-src--more {
  opacity: 0.75;
  padding-left: 0.6rem;
  margin-top: 0.1rem;
}
.codex-src + .codex-src--more { margin-top: 0.1rem; }

/* 제작 재료로 쓰임 — 제품명 알약(등급색). 이름은 짧아 nowrap+말줄임이 안전하다. */
/* ⚠ 말줄임(nowrap+ellipsis)을 쓰면 안 된다 — 제품명이 "감독자의 무쇠 …" 처럼 앞부분이 겹쳐
   8개가 전부 똑같아 보인다(정보가 0이 된다). 좁은 카드에서는 줄바꿈이 유일한 답이다. */
.codex-use {
  max-width: 100%;
  padding: 0.06rem 0.36rem;
  font-size: 0.63rem;
  font-weight: 600;
  line-height: 1.35;
  border-radius: 0.5rem;
  border: 1px solid color-mix(in srgb, var(--rarity-color, var(--border)) 45%, transparent);
  color: var(--rarity-color, var(--text-1));
  background: var(--bg-0);
  white-space: normal;
  word-break: keep-all;      /* 한글 어절 보존 */
  overflow-wrap: anywhere;
  text-align: left;
}
.codex-use--more { color: var(--text-2); border-color: var(--border); }

/* 필요 재료 — "이름 ×수량"(등급색). */
/* 이름은 줄이고 수량(×N)은 고정 — 수량이 잘리면 이 줄의 의미가 없다. */
.codex-recipe-mat {
  display: inline-flex;
  align-items: baseline;
  text-align: left;
  max-width: 100%;
  min-width: 0;
  padding: 0.04rem 0.34rem;
  font-size: 0.63rem;
  font-weight: 600;
  line-height: 1.35;
  border-radius: var(--radius-sm);
  border: 1px solid color-mix(in srgb, var(--rarity-color, var(--border)) 45%, transparent);
  color: var(--rarity-color, var(--text-1));
  background: var(--bg-0);
}
.codex-recipe-mat__name {
  min-width: 0;
  white-space: normal;       /* 재료명도 줄여 버리면 무슨 재료인지 알 수 없다 */
  word-break: keep-all;
  overflow-wrap: anywhere;
}
.codex-recipe-mat b {
  flex: 0 0 auto;               /* 수량은 절대 줄지 않는다 */
  color: var(--text-0);
  font-weight: 800;
  margin-left: 0.16rem;
  font-variant-numeric: tabular-nums;
}
/* "N개 산출" — 섹션 제목 옆 보조 표기. 제목과 붙어 어색하게 꺾이지 않도록 nowrap. */
.codex-recipe__out {
  margin-left: 0.3rem;
  font-size: 0.6rem;
  font-weight: 600;
  color: var(--accent-hi);
  white-space: nowrap;
}


/* 아이템 설명 */
.codex-cell__desc {
  margin: 0.2rem 0 0;
  font-size: 0.7rem;
  line-height: 1.45;
  color: var(--text-2);
}

/* 소모품 효과 줄 — 아이템 툴팁의 .item-tooltip__effect 와 같은 강조 톤.
   묘사(.codex-cell__desc)는 분위기, 이쪽이 수치다. */
.codex-cell__effect {
  margin: 0.15rem 0 0;
  font-size: 0.7rem;
  line-height: 1.45;
  color: var(--accent-hi);
}

/* 장비 카드 — 등급색은 data-rarity/data-grade 가 tokens.css 에서 준다. */
.codex-cell--gear .codex-cell__name { color: var(--rarity-color, var(--text-0)); font-weight: 700; }
/* 규칙 설명이 붙으면서 카드가 세로로 자란다(재료 카드와 같은 방식 — min-height 는 바닥값일 뿐).
   상단 정렬로 고정해 같은 행의 짧은 카드와 아이콘·이름 기준선이 어긋나지 않게 한다. */
.codex-cell--gear { justify-content: flex-start; gap: 0.3rem; }
.codex-cell--gear .codex-cell__desc { text-align: left; width: 100%; }
/* 요약 줄(부위·재질 / Lv·테마·역할 / 역할·범위)은 이름보다 작아야 한다.
   .codex-cell__meta 에는 font-size 규칙이 없어 카드 기본값을 그대로 물려받는데, 몬스터·재료는
   내용이 짧아("Lv.1 처치 1회") 안 드러났을 뿐이다. 장비는 문장이 길어 이름을 압도한다. */
/* 아래 정보 블록들이 전부 좌정렬이라 요약 줄만 가운데면 시선이 튄다. */
.codex-cell--gear .codex-cell__meta {
  font-size: 0.68rem;
  line-height: 1.4;
  color: var(--text-2);
  justify-content: flex-start;
  text-align: left;
  width: 100%;
}
/* 「2세트」는 몇 부위인지가 정보다 — 접히면 안 읽힌다. 본문(i)만 줄바꿈시킨다. */
.codex-cell--gear .codex-src b { white-space: nowrap; }

/* ===== souls.css ===== */
/* 영혼 군단 — 수집/편성 화면. */

.souls-page { display: flex; flex-direction: column; gap: 1rem; }

.souls-locked {
  min-height: 14rem;
  display: grid;
  place-items: center;
  align-content: center;
  gap: 0.45rem;
  color: var(--text-2);
  text-align: center;
}
.souls-locked__icon {
  width: 2.8rem;
  height: 2.8rem;
  display: grid;
  place-items: center;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}
.souls-locked__title { color: var(--text-0); font-weight: 700; }
.souls-locked__desc { max-width: 28rem; font-size: 0.82rem; line-height: 1.45; }

/* 편성 지휘력(핵심 지표)을 좌측 강조 카드로 분리하고, 봉인 영혼/봉인 가능(수집 지표)은 우측에 묶는다. */
.souls-overview {
  display: grid;
  grid-template-columns: minmax(0, 1.7fr) minmax(0, 1fr);
  gap: 0.7rem;
  align-items: stretch;
}
.souls-overview__collection {
  display: grid;
  grid-template-rows: 1fr 1fr;
  gap: 0.7rem;
}
.souls-stat {
  min-height: 4.3rem;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 0.15rem;
  padding: 0.65rem 0.8rem;
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}
.souls-stat__label { color: var(--text-2); font-size: 0.75rem; }
.souls-stat__value { color: var(--text-1); font-size: 0.95rem; font-variant-numeric: tabular-nums; }
.souls-stat__value b { color: var(--accent-hi); }
.souls-stat__hint { color: var(--text-2); font-size: 0.68rem; line-height: 1.35; margin-top: 0.1rem; }
.souls-stat__hint b { color: var(--accent-hi); font-weight: 700; }

/* 강조 카드: 편성 지휘력 */
.souls-stat--command {
  gap: 0.35rem;
  border-color: rgba(var(--accent-rgb), 0.5);
  background: linear-gradient(180deg, rgba(var(--accent-rgb), 0.12), var(--bg-1) 70%);
}
.souls-stat--command .souls-stat__label { color: var(--accent-hi); font-weight: 600; }
.souls-stat--command .souls-stat__value { font-size: 1.5rem; line-height: 1.1; }
.souls-stat--command .souls-stat__sep { color: var(--text-2); font-weight: 400; margin: 0 0.1rem; }
.souls-btn--buy { margin-top: 0.35rem; }
.souls-btn--buy:disabled { opacity: 0.5; cursor: default; }

/* 지휘력 사용량 게이지 */
.souls-gauge {
  height: 0.42rem;
  border-radius: 999px;
  background: var(--bg-0);
  overflow: hidden;
}
.souls-gauge__fill {
  height: 100%;
  width: 0;
  border-radius: inherit;
  background: linear-gradient(90deg, var(--accent), var(--accent-hi));
  transition: width 0.22s ease;
}

.souls-layout {
  display: grid;
  grid-template-columns: minmax(15rem, 19rem) minmax(0, 1fr);
  gap: 1rem;
  align-items: start;
}
.souls-loadout,
.souls-collection {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}
.souls-loadout {
  padding: 0.8rem;
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  position: sticky;                    /* 스크롤 시 화면 상단에 고정되어 따라옴 */
  top: 3rem;                           /* sticky 상단바(≈2.65rem) 아래로 여유 */
  max-height: calc(100vh - 3.75rem);   /* 뷰포트보다 크면 여기서 잘림 */
  overflow-y: auto;                    /* 초과분은 카드 내부에서 세로 스크롤 */
  scrollbar-width: thin;               /* Firefox — 최소 두께 */
}
.souls-loadout::-webkit-scrollbar { width: 6px; }  /* WebKit — 전역 8px보다 얇게 */
.souls-loadout__head,
.souls-collection__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.65rem;
  flex-wrap: wrap;
}
.souls-subtitle {
  margin: 0;
  color: var(--text-0);
  font-size: 0.9rem;
  font-weight: 700;
}
.souls-muted {
  margin: 0.15rem 0 0;
  color: var(--text-2);
  font-size: 0.72rem;
  line-height: 1.35;
}

.souls-loadout__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
}
.souls-loadout__item {
  min-height: 2.7rem;
  display: grid;
  grid-template-columns: 2rem minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 0.55rem;
  padding: 0.42rem 0.55rem;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-color: var(--rarity-edge, var(--border));
  border-radius: var(--radius-sm);
}
.souls-loadout__remove {
  width: 1.5rem;
  height: 1.5rem;
  display: grid;
  place-items: center;
  color: var(--text-2);
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 999px;
  font-size: 0.95rem;
  line-height: 1;
  cursor: pointer;
  transition: color 0.12s, border-color 0.12s, background 0.12s;
}
.souls-loadout__remove:hover {
  color: var(--danger-soft);
  border-color: var(--danger-soft);
  background: rgba(var(--danger-rgb), 0.12);
}
.souls-loadout__icon,
.soul-card__icon {
  width: 2rem;
  height: 2rem;
  display: grid;
  place-items: center;
  color: var(--rarity-color, var(--text-1));
}
.souls-loadout__icon .icon,
.soul-card__icon .icon {
  width: 1.85rem;
  height: 1.85rem;
}
.souls-loadout__name {
  min-width: 0;
  color: var(--rarity-color, var(--text-0));
  font-size: 0.82rem;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.souls-loadout__cost,
.soul-card__cost {
  color: var(--accent-hi);
  font-size: 0.72rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.souls-empty {
  min-height: 3.6rem;
  display: grid;
  place-items: center;
  padding: 0.7rem;
  color: var(--text-2);
  font-size: 0.78rem;
  text-align: center;
  border: 1px dashed var(--border);
  border-radius: var(--radius-sm);
}
/* display:grid 가 UA [hidden]{display:none} 를 동일 특이도로 눌러버리므로(빈 배치 안내가
   편성이 차 있어도 노출되는 함정) hidden 속성을 명시적으로 다시 숨긴다. */
.souls-empty[hidden] { display: none; }
.souls-loadout__msg {
  min-height: 1.1rem;
  color: var(--success-soft);
  font-size: 0.76rem;
  line-height: 1.25;
}
.souls-loadout__msg.is-warning { color: var(--danger-soft); }

.souls-resonance {
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
}
.souls-resonance__title {
  color: var(--text-2);
  font-size: 0.72rem;
  font-weight: 800;
}
.souls-resonance__note {
  margin: -0.15rem 0 0.1rem;
  color: var(--text-2);
  font-size: 0.68rem;
  line-height: 1.4;
}
.souls-resonance__item {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  padding: 0.55rem;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}
.souls-resonance__item.is-active {
  border-color: #6aa1c8;
  background: color-mix(in srgb, #6aa1c8 14%, var(--bg-2));
}
/* 미발동 카드는 한 단계 눌러 발동 카드와 대비를 준다. */
.souls-resonance__item.is-idle {
  border-style: dashed;
  opacity: 0.82;
}
.souls-resonance__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.4rem;
}
.souls-resonance__name {
  min-width: 0;
  color: var(--text-0);
  font-size: 0.78rem;
  font-weight: 800;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* 상태 배지 — 발동/미발동을 확실히 구분되는 pill 로. */
.souls-resonance__state {
  flex: 0 0 auto;
  padding: 0.1rem 0.45rem;
  border-radius: 999px;
  font-size: 0.64rem;
  font-weight: 800;
  color: var(--text-2);
  background: var(--bg-0);
  border: 1px solid var(--border);
  white-space: nowrap;
}
.souls-resonance__item.is-active .souls-resonance__state {
  color: #d8ecff;
  background: color-mix(in srgb, #6aa1c8 32%, transparent);
  border-color: #6aa1c8;
}
.souls-resonance__bonus {
  color: var(--accent-hi);
  font-size: 0.72rem;
  font-weight: 700;
  line-height: 1.35;
}
/* 필요 영혼 칩 — 편성됨(초록 ✓)/미편성(점선 ＋) 대비. */
.souls-resonance__reqs {
  display: flex;
  flex-wrap: wrap;
  gap: 0.28rem;
  margin-top: 0.1rem;
}
.souls-resonance__chip {
  padding: 0.1rem 0.4rem;
  border-radius: 999px;
  font-size: 0.66rem;
  font-weight: 600;
  border: 1px solid var(--border);
  white-space: nowrap;
}
.souls-resonance__chip.is-have {
  color: #b7e0c0;
  background: color-mix(in srgb, #5ba36a 18%, transparent);
  border-color: color-mix(in srgb, #5ba36a 55%, transparent);
}
.souls-resonance__chip.is-need {
  color: var(--text-2);
  background: transparent;
  border-style: dashed;
}
.souls-resonance__hint {
  color: var(--text-2);
  font-size: 0.66rem;
  line-height: 1.35;
}

.souls-filter {
  display: inline-flex;
  gap: 0.25rem;
  padding: 0.2rem;
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}
.souls-filter__btn {
  min-width: 3.4rem;
  min-height: 1.9rem;
  padding: 0 0.55rem;
  color: var(--text-2);
  font-size: 0.78rem;
  border-radius: var(--radius-sm);
}
.souls-filter__btn:hover { color: var(--text-0); background: var(--hover-bg); }
.souls-filter__btn.is-active { color: var(--bg-0); background: var(--accent-hi); font-weight: 700; }

.souls-filters {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  width: 100%;
}
.souls-filter-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
}
.souls-filter__label {
  flex: 0 0 2.4rem;
  color: var(--text-2);
  font-size: 0.74rem;
  font-weight: 700;
}
.souls-filters .souls-filter { flex-wrap: wrap; }

.souls-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr));
  gap: 0.65rem;
}
.soul-card {
  min-width: 0;
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  overflow: hidden;
}
.soul-card.is-selected {
  border-color: var(--accent);
  box-shadow: inset 0 0 0 1px rgba(var(--accent-rgb), 0.25);
}
.soul-card.is-ready:not(.is-bound) { border-color: #6b9f7a; }
.soul-card__select {
  width: 100%;
  min-height: 4.1rem;
  display: grid;
  grid-template-columns: 2.3rem minmax(0, 1fr) auto;
  align-items: center;
  gap: 0.55rem;
  padding: 0.65rem;
  text-align: left;
}
.soul-card__select:not(:disabled):hover { background: var(--hover-bg); }
.soul-card__main {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 0.16rem;
}
.soul-card__name {
  color: var(--rarity-color, var(--text-0));
  font-size: 0.88rem;
  font-weight: 700;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.soul-card__meta {
  color: var(--text-2);
  font-size: 0.72rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.soul-card__inloadout {
  align-self: flex-start;
  margin-top: 0.1rem;
  padding: 0.08rem 0.4rem;
  color: var(--accent-hi);
  background: rgba(var(--accent-rgb), 0.16);
  border: 1px solid rgba(var(--accent-rgb), 0.4);
  border-radius: 999px;
  font-size: 0.66rem;
  font-weight: 700;
  line-height: 1.3;
}
.soul-card__body {
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
  padding: 0 0.65rem 0.7rem;
}
.soul-card__progress {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}
.soul-card__progress-top {
  display: flex;
  justify-content: space-between;
  gap: 0.5rem;
  color: var(--text-2);
  font-size: 0.72rem;
  font-variant-numeric: tabular-nums;
}
.soul-card__progress-top b { color: var(--text-0); }
.soul-card__bar {
  height: 5px;
  background: var(--bg-0);
  border-radius: 999px;
  overflow: hidden;
}
.soul-card__bar i {
  display: block;
  height: 100%;
  background: linear-gradient(90deg, #6aa1c8, var(--accent-hi));
}
.soul-card__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
}
.soul-card__chips span,
.soul-card__hint {
  color: var(--text-2);
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0.2rem 0.42rem;
  font-size: 0.72rem;
}
/* 영혼 카드 공명 설명 — 이 영혼이 참여하는 공명(효과·조건)을 표시. */
.soul-card__resonance {
  display: flex;
  flex-direction: column;
  gap: 0.28rem;
  padding: 0.45rem 0.5rem;
  background: color-mix(in srgb, #6aa1c8 8%, var(--bg-2));
  border: 1px solid color-mix(in srgb, #6aa1c8 35%, var(--border));
  border-radius: var(--radius-sm);
}
.soul-card__resonance-title {
  color: #b7d9f0;
  font-size: 0.66rem;
  font-weight: 800;
}
.soul-card__resonance-line {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.2rem 0.4rem;
}
.soul-card__resonance-name {
  color: var(--text-0);
  font-size: 0.72rem;
  font-weight: 700;
}
.soul-card__resonance-bonus {
  color: var(--accent-hi);
  font-size: 0.7rem;
  font-weight: 700;
}
.soul-card__resonance-cond {
  flex-basis: 100%;
  color: var(--text-2);
  font-size: 0.66rem;
  line-height: 1.35;
}
.soul-skills {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}
.soul-skill {
  padding: 0.45rem 0.5rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-1);
}
.soul-skill__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
}
.soul-skill__name {
  min-width: 0;
  color: var(--text-1);
  font-size: 0.76rem;
  font-weight: 700;
}
.soul-skill__meta {
  flex: 0 0 auto;
  color: var(--text-3);
  font-size: 0.68rem;
}
.soul-skill__desc {
  margin-top: 0.22rem;
  color: var(--text-2);
  font-size: 0.7rem;
  line-height: 1.4;
}
.soul-memory {
  color: var(--text-2);
  font-size: 0.74rem;
}
.soul-memory summary {
  color: var(--text-1);
  cursor: pointer;
}
.soul-memory p {
  margin: 0.35rem 0 0;
  line-height: 1.45;
}
.soul-upgrade,
.soul-evolution {
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
  padding: 0.55rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-2);
}
.soul-upgrade.is-ready,
.soul-evolution.is-ready {
  border-color: #7fa36c;
  background: color-mix(in srgb, #7fa36c 10%, var(--bg-2));
}
.soul-upgrade.is-complete,
.soul-evolution.is-complete {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 10%, var(--bg-2));
}
.soul-upgrade__title,
.soul-evolution__title {
  color: var(--text-1);
  font-size: 0.76rem;
  font-weight: 800;
}
.soul-upgrade__reqs,
.soul-evolution__reqs {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
}
.soul-upgrade__reqs span,
.soul-evolution__reqs span {
  color: var(--text-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0.18rem 0.38rem;
  font-size: 0.7rem;
}
.soul-upgrade__reqs span.is-ok,
.soul-evolution__reqs span.is-ok {
  color: #b8dbb1;
  border-color: #6b9f7a;
}
.soul-evolution p {
  margin: 0;
  color: var(--text-2);
  font-size: 0.72rem;
  line-height: 1.45;
}

.souls-btn {
  min-height: 2rem;
  padding: 0 0.75rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text-1);
  background: var(--bg-2);
  font-size: 0.78rem;
  font-weight: 700;
}
.souls-btn:hover:not(:disabled) { border-color: var(--accent); color: var(--text-0); background: var(--hover-bg-2); }
.souls-btn--primary {
  color: var(--bg-0);
  background: var(--accent-hi);
  border-color: var(--accent-hi);
}
.souls-btn--small {
  align-self: flex-start;
  min-height: 1.85rem;
}

/* 조건을 충족해 지금 누를 수 있는 액션(봉인·승급·진화) — 카드 더미 속에서 눈에 띄게. */
.souls-btn--ready {
  color: #0f1710;
  background: #8fbb7c;
  border-color: #a7d094;
  box-shadow: 0 0 0 0 rgba(143, 187, 124, 0.55);
  animation: souls-ready-pulse 2s ease-out infinite;
}
.souls-btn--ready:hover:not(:disabled) {
  color: #0f1710;
  background: #a7d094;
  border-color: #c2e2b2;
}
/* 요청 진행 중(is-busy → disabled)에는 강조를 끈다. */
.souls-btn--ready:disabled {
  animation: none;
  box-shadow: none;
  opacity: 0.55;
}
@keyframes souls-ready-pulse {
  0%   { box-shadow: 0 0 0 0 rgba(143, 187, 124, 0.5); }
  70%  { box-shadow: 0 0 0 0.4rem rgba(143, 187, 124, 0); }
  100% { box-shadow: 0 0 0 0 rgba(143, 187, 124, 0); }
}
@media (prefers-reduced-motion: reduce) {
  .souls-btn--ready { animation: none; }
}



/* ===== vault.css ===== */
/* 이계 상자(Sealed Vault) — 상자 카드 그리드 + 개봉 결과 모달 보조 스타일.
   등급 색은 data-rarity 토큰(tokens.css --rarity-color/--rarity-edge)을 그대로 받는다. */

/* 이계 상자 획득 배너(chestBannerHtml) — 모든 지급 화면(탐험/던전/첨탑/파티/보상 모달) 공통.
   표시 전용(클릭 없음), 보상 그리드 위에 가로 배너로 강조. 등급색은 data-rarity cascade. */
.chest-banner {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: 0.6rem;
  padding: 0.6rem 0.9rem;
  border-radius: 8px;
  border: 1px solid var(--rarity-edge, var(--border));
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.04), rgba(0, 0, 0, 0.12));
  animation: vault-ready-pulse 2.4s ease-in-out infinite;
}
.chest-banner__icon { font-size: 1.6rem; line-height: 1; }
.chest-banner__icon img, .chest-banner__icon .icon {
  width: 2rem;
  height: 2rem;
  filter: drop-shadow(0 0 6px var(--rarity-edge, transparent));
}
.chest-banner__body { display: flex; flex-direction: column; gap: 0.1rem; min-width: 0; }
.chest-banner__title { font-size: 0.92rem; }
.chest-banner__tier { font-size: 0.8rem; font-weight: 700; color: var(--rarity-color, inherit); }

/* ── 이계 상자 미리보기 칩(chestChipsHtml) ──────────────────────────────────
 * 🔴 위 배너의 짝. 배너 문구가 "이계의 상자를 손에 넣으셨습니다!" 라 **지급이 끝난 뒤에만** 참이다.
 *    수령 전 화면(각인 보상표·각인 수령 팝업 상세·협회 공동목표 카드)은 이 칩으로 예고한다.
 *    어느 쪽을 그릴지는 CSS 가 아니라 rewardGridHtml/rewardLootHtml 의 granted 축이 정하며,
 *    **기본값이 칩**이라 새 화면은 아무것도 안 넘겨도 안전하다.
 * 치수는 `.item-cell`(item-display.css) 을 미러링한다 — 같은 보상 목록 안에 나란히 서므로
 * 크기가 어긋나면 칩만 따로 노는 것처럼 보인다. 좁은 칸(각인 3단 포디움)의 압축은
 * archive.css 가 후손 스코프로 따로 건다.
 * 등급색은 tokens.css 의 `[data-rarity] { --rarity-edge }` cascade — 여기서 색을 정의하지 않는다. */
.chest-chips { display: flex; flex-direction: column; gap: 0.3rem; margin-top: 0.4rem; }
.chest-chip {
  display: flex; align-items: center; gap: 0.55rem;
  min-height: 2.6rem;
  padding: 0.35rem 0.55rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-2);
}
.chest-chip[data-rarity] { border-color: var(--rarity-edge); }
.chest-chip__icon { flex: 0 0 auto; font-size: 1.1rem; line-height: 1; }
.chest-chip__icon .icon,
.chest-chip__icon img { width: 1.6rem; height: 1.6rem; }
.chest-chip__name {
  flex: 1 1 auto; min-width: 0;
  color: var(--text-0, #e8ebf2);
  font-size: 0.84rem;
  line-height: 1.25;
}
.chest-chip__qty {
  flex: 0 0 auto;
  color: var(--text-1, #b9bfd0);
  font-size: 0.78rem;
  font-weight: 700;
  white-space: nowrap;
}

.vault-page .vault-hint {
  margin: 0 0 1rem;
  color: var(--text-dim, #aab);
  font-size: 0.9rem;
}

.vault-section { margin-bottom: 1.6rem; }

.vault-subtitle {
  margin: 0 0 0.7rem;
  font-size: 1rem;
  font-weight: 700;
}
.vault-subtitle--row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
  flex-wrap: wrap;
}
.vault-btn--openall {
  font-size: 0.85rem;
  padding: 0.35rem 0.8rem;
}
.vault-muted { color: var(--text-dim, #99a); font-weight: 500; font-size: 0.85rem; }

/* 🔴 개봉 규칙 콜아웃 — 「내 레벨 이상 몬스터만 봉인을 앞당긴다」(2026-08-31).
 * 화면에서 가장 먼저 읽혀야 하는 한 줄이라 안내문(.vault-hint)보다 위에, 테두리와
 * 강조색을 준다. ⚠ 카드의 "내 레벨 이상 N처치" 라벨과 **같은 사실**을 말한다 —
 * 한쪽만 고치면 화면 안에서 규칙이 갈린다. */
.vault-rule {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  margin: 0 0 0.8rem;
  padding: 0.7rem 0.85rem;
  border: 1px solid rgba(217, 164, 65, 0.45);
  border-left-width: 3px;
  border-radius: 0.4rem;
  background: rgba(217, 164, 65, 0.08);
}
.vault-rule__mark { font-size: 1.1rem; line-height: 1.35; }
.vault-rule__body { display: flex; flex-direction: column; gap: 0.18rem; }
.vault-rule__title { font-size: 0.95rem; font-weight: 700; color: var(--text, #e8e8f0); }
.vault-rule__title em { font-style: normal; color: var(--accent-hi, #d9a441); }
.vault-rule__desc { font-size: 0.85rem; line-height: 1.5; color: var(--text-dim, #aab); }
.vault-rule__desc b { color: var(--accent-hi, #d9a441); font-weight: 700; }

/* 섹션별 규칙 안내문 — 슬롯 제한/자동 승격을 화면에서 바로 읽히게. */
.vault-note {
  margin: -0.2rem 0 0.7rem;
  color: var(--text-dim, #98a);
  font-size: 0.82rem;
  line-height: 1.5;
}
.vault-note b { color: var(--accent-hi, #d9a441); font-weight: 700; }

/* 해제 슬롯 게이지 — 채워진 pip = 봉인 해제가 진행 중인 칸. */
.vault-pips {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  white-space: nowrap;
}
.vault-pip {
  width: 0.62rem;
  height: 0.62rem;
  border-radius: 50%;
  border: 1px solid var(--border, #3a3f4b);
  background: rgba(0, 0, 0, 0.3);
}
.vault-pip.is-filled {
  border-color: var(--accent-hi, #d9a441);
  background: var(--accent-hi, #d9a441);
  box-shadow: 0 0 7px -1px var(--accent-hi, #d9a441);
}

/* 빈 해제 슬롯 — 상자 카드와 같은 칸을 차지하되 점선으로 "잠긴 자리"임을 보여준다. */
.vault-slot-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.3rem;
  padding: 1rem 0.8rem;
  min-height: 9.5rem;
  border: 1px dashed var(--border, #3a3f4b);
  border-radius: 0.7rem;
  background: repeating-linear-gradient(
    -45deg,
    rgba(255, 255, 255, 0.015) 0 8px,
    transparent 8px 16px
  );
  text-align: center;
  color: var(--text-dim, #79808d);
}
.vault-slot-empty__mark { font-size: 1.5rem; line-height: 1; opacity: 0.55; }
.vault-slot-empty__name { font-size: 0.85rem; font-weight: 700; }
.vault-slot-empty__desc { font-size: 0.72rem; line-height: 1.35; opacity: 0.8; }

.vault-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
  gap: 0.8rem;
}
.vault-grid--queue {
  grid-template-columns: repeat(auto-fill, minmax(8rem, 1fr));
}

.vault-chest {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  padding: 1rem 0.8rem;
  border: 1px solid var(--rarity-edge, #3a3f4b);
  border-radius: 0.7rem;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.03), rgba(0, 0, 0, 0.12));
  text-align: center;
}
.vault-chest.is-ready {
  box-shadow: 0 0 0 1px var(--rarity-edge, #d9a441), 0 0 16px -4px var(--rarity-edge, #d9a441);
  animation: vault-ready-pulse 2.4s ease-in-out infinite;
}
@keyframes vault-ready-pulse {
  0%, 100% { box-shadow: 0 0 0 1px var(--rarity-edge), 0 0 10px -4px var(--rarity-edge); }
  50%      { box-shadow: 0 0 0 1px var(--rarity-edge), 0 0 20px -2px var(--rarity-edge); }
}
.vault-chest.is-queued { opacity: 0.72; }

.vault-chest__icon { font-size: 1.8rem; line-height: 1; }
.vault-chest__icon img, .vault-chest__icon .icon { width: 2.2rem; height: 2.2rem; }
.vault-chest--legend .vault-chest__icon,
.vault-chest--epic .vault-chest__icon { filter: drop-shadow(0 0 6px var(--rarity-edge)); }

.vault-chest__name {
  font-size: 0.88rem;
  font-weight: 700;
  color: var(--rarity-color, #e6e8ef);
}

.vault-chest__bar {
  width: 100%;
  height: 0.5rem;
  border-radius: 0.4rem;
  background: rgba(0, 0, 0, 0.35);
  overflow: hidden;
}
.vault-chest__fill {
  display: block;
  height: 100%;
  border-radius: 0.4rem;
  background: linear-gradient(90deg, var(--rarity-edge, #5b88c8), var(--rarity-color, #93b7e8));
  transition: width 0.6s ease;
}
.vault-chest__eta {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.12rem;
  font-size: 0.74rem;
  color: var(--text-dim, #9aa);
  line-height: 1.35;
}
.vault-chest__eta-label,
.vault-chest__eta-row {
  display: block;
  white-space: nowrap;
}
.vault-chest__eta b { color: var(--text, #e6e8ef); }
.vault-chest__queued { font-size: 0.78rem; color: var(--text-dim, #888f9c); }

.vault-btn {
  cursor: pointer;
  border: 1px solid var(--rarity-edge, #5b88c8);
  border-radius: 0.5rem;
  padding: 0.4rem 0.9rem;
  font-size: 0.85rem;
  font-weight: 700;
  background: transparent;
  color: var(--rarity-color, #e6e8ef);
  transition: background 0.15s ease, transform 0.05s ease;
}
.vault-btn--primary {
  background: var(--rarity-edge, #5b88c8);
  color: #0d0f14;
}
.vault-btn:hover { filter: brightness(1.08); }
.vault-btn:active { transform: translateY(1px); }
.vault-btn.is-busy { opacity: 0.6; cursor: progress; }

.vault-empty {
  color: var(--text-dim, #889);
  font-size: 0.85rem;
  padding: 0.6rem 0;
}

/* ── 개봉 결과 모달 보조 ─────────────────────────────────────── */
.modal--vault-result .vault-result__souls {
  margin-top: 0.9rem;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  padding-top: 0.7rem;
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
}
.modal--vault-result .vault-result__souls-head {
  margin: 0 0 0.2rem;
  font-size: 0.82rem;
  color: var(--text-dim, #9aa);
}
.modal--vault-result .vault-soul {
  display: grid;
  grid-template-columns: 1.8rem minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 0.5rem;
}
.modal--vault-result .vault-soul__icon img,
.modal--vault-result .vault-soul__icon .icon { width: 1.6rem; height: 1.6rem; }
.modal--vault-result .vault-soul__name {
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--rarity-color, #e6e8ef);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.modal--vault-result .vault-soul__star { font-size: 0.78rem; color: var(--accent-hi, #d9a441); }
.modal--vault-result .vault-btn--soul {
  border-color: #a35cc7;
  color: #cc97e3;
  padding: 0.3rem 0.6rem;
  font-size: 0.78rem;
}
.modal--vault-result .vault-soul.is-done { opacity: 0.55; }
.modal--vault-result .vault-soul.is-done .vault-btn--soul {
  border-color: #5d9b6a;
  color: #8cc89a;
  pointer-events: none;
}


/* ===== battlepass.css ===== */
/* 이계의 서약(배틀패스) — /battlepass
   트랙 30칸은 **가로 스크롤 없이 6열 격자**로 편다(30 = 6 × 5). 한 칸(티어)은 **카드 한 장**이고,
   무료 줄·서약 줄은 그 카드 **안에서** 갈린다 — 자세한 계측은 아래 「트랙」 절 주석에. */

.bp-page { display: flex; flex-direction: column; gap: 0.9rem; }

/* ── 머리 ─────────────────────────────────────────────────────────────── */
.bp-head {
  display: grid;
  grid-template-columns: auto 1fr auto auto;
  align-items: center;
  gap: 0.75rem;
  padding: 0.7rem 0.9rem;
  border: 1px solid var(--border);
  border-radius: 0.6rem;
  background: var(--bg-2);
}
.bp-head__tier { display: flex; align-items: baseline; gap: 0.3rem; white-space: nowrap; }
.bp-head__tier-label { font-size: 0.78rem; color: var(--text-2); }
.bp-head__tier b { font-size: 1.5rem; color: var(--accent-hi); line-height: 1; }
.bp-head__tier-max { font-size: 0.82rem; color: var(--text-2); }
.bp-head__bar {
  height: 0.55rem;
  border-radius: 0.3rem;
  background: var(--bg-1);
  overflow: hidden;
}
.bp-head__fill {
  display: block; height: 100%;
  background: linear-gradient(90deg, var(--accent), var(--accent-hi));
  transition: width 0.35s ease;
}
.bp-head__exp { font-size: 0.8rem; color: var(--text-2); white-space: nowrap; }
.bp-head__exp b { color: var(--text-1); }
.bp-badge {
  font-size: 0.74rem; padding: 0.18rem 0.5rem; border-radius: 999px;
  border: 1px solid var(--border); color: var(--text-2);
  /* ⚠ nowrap — 「서약 중 · 남은 30일」이 접히면 머리 행 높이가 들쭉날쭉해진다. */
  white-space: nowrap;
}
.bp-badge--paid { border-color: var(--accent); color: var(--accent-hi); }

.bp-note { font-size: 0.8rem; color: var(--text-2); line-height: 1.5; margin: 0; }
.bp-note--cta {
  padding: 0.6rem 0.8rem; border: 1px dashed var(--border); border-radius: 0.5rem;
}
.bp-note--cta b { color: var(--accent-hi); }
.bp-muted { color: var(--text-2); font-weight: 400; font-size: 0.78rem; }

.bp-section { display: flex; flex-direction: column; gap: 0.5rem; min-width: 0; }
.bp-subtitle { font-size: 0.92rem; margin: 0; display: flex; align-items: baseline; gap: 0.4rem; }
/* 소제목 · 범례 띠 · 「전부 받기」를 한 줄에 눕힌다 — 각자 한 줄씩 쓰면 66px 를 머리에만 쓴다. */
.bp-subtitle--row {
  display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap;
  font-size: 0.92rem; margin: 0;
}
.bp-subtitle--row > .bp-lanes { flex: 1 1 auto; }
.bp-subtitle--row > .bp-btn   { flex: 0 0 auto; margin-left: auto; }

/* ── 오늘의 적립 ───────────────────────────────────────────────────────── */
 /* 🔴 7줄을 그대로 쌓으면 95px 를 먹는다. 이 화면은 세로가 빠듯하므로(본문 상자 ≈560px)
    2열로 접어 4줄로 만든다 — 45px 회수. */
.bp-sources {
  list-style: none; margin: 0; padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
  gap: 0.3rem 1.2rem;
}
.bp-source {
  display: grid;
  grid-template-columns: 7.5rem 1fr auto;
  align-items: center;
  gap: 0.6rem;
  font-size: 0.78rem;
}
.bp-source__label { color: var(--text-2); white-space: nowrap; }
.bp-source__bar {
  height: 0.4rem; border-radius: 0.2rem; overflow: hidden;
  background: var(--bg-1);
}
.bp-source__fill { display: block; height: 100%; background: var(--accent); }
.bp-source__num { color: var(--text-2); white-space: nowrap; font-variant-numeric: tabular-nums; }
.bp-source.is-full .bp-source__fill { background: var(--accent-hi); }
.bp-source.is-full .bp-source__num { color: var(--accent-hi); }

/* ── 트랙 — 6열 카드 격자 ───────────────────────────────────────────────
   🔴 가로 스크롤을 버렸다. 종전엔 30칸을 한 줄로 늘어놓아 내용 폭이 5,219px 인데 스크롤 창이
   579.6px 였다(약 9배). 「지금 몇 칸인가」를 보려면 매번 옆으로 밀어야 했다.

   ⚠ 이 화면의 가용 폭은 **뷰포트 폭 − 37rem** 이고(home.css:298 의 `16rem 1fr 18rem`),
     `rem` 이 뷰포트 **높이**에 묶여 있어(tokens.css:89) 화면이 세로로 길수록 오히려 좁아진다
     (1280×1800 → 281px). 그래서 고정 열 수를 박지 않고 유동으로 둔다 — spire.css:307 이
     같은 계측을 남겨 뒀다.

   상한 6열인 이유: **30 = 6 × 5** 라 마지막 줄이 들쭉날쭉하지 않다.
   식은 docs/ui-ux-guidelines.md:314 의 「N열 상한」 관용 그대로다(주둔지·강화·탐험이 같은 식).
   ⚠ gap 이 rem 이므로 calc 의 뺄셈도 **반드시 같은 변수**로 쓴다(px 를 섞으면 조용히 어긋난다). */
.bp-grid {
  --bp-gap: 0.5rem;
  /* 🔴 행 간격은 **열 간격과 따로** 둔다(0.5 → 1.05rem). 무료·서약을 한 카드로 묶은 뒤로는
     카드끼리 위아래로 붙으면 「어디까지가 한 칸인가」가 다시 흐려진다. 번호 배지가 카드
     윗 테두리에 걸터앉으므로 그 몫(≈0.45rem)도 이 간격에서 낸다.
     ⚠ 아래 열 수 계산식은 **열 간격**만 쓴다 — 여기에 행 간격을 섞으면 열 수가 어긋난다. */
  --bp-gap-row: 1.05rem;
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns:
    repeat(auto-fill, minmax(max(6rem, calc((100% - 5 * var(--bp-gap)) / 6 - 1px)), 1fr));
  gap: var(--bp-gap-row) var(--bp-gap);
}

/* 🔴 `container-type` 은 **격자를 감싸는 상자**에 둔다. 컨테이너 쿼리는 자기 컨테이너 자신을
   스타일할 수 없어서(자손만 고칠 수 있다), 격자에 직접 걸면 아래에서 열 수를 못 바꾼다. */
.bp-gridwrap { container-type: inline-size; min-width: 0; padding-top: 0.35rem; }

/* 카드 = **한 칸(티어) 한 장**. 번호 배지 + 무료 줄 + 서약 줄이 하나의 테두리 안에 든다.
   🔴 종전엔 무료·서약이 각자 테두리를 가진 낱개 상자였다 — 격자에 60개의 상자가 널려
   「이 둘이 같은 칸이다」가 안 읽혔고, 세로 간격을 넓히면 오히려 한 쌍이 갈라져 보였다.
   테두리를 카드가 가져가고, 두 줄은 **카드 안에서** 경계선·레인 띠·바탕 틴트로 가른다.
   ⚠ 번호를 따로 한 줄로 두면 5행 × 19px 를 번호에만 쓴다 — 주둔지 Lv 배지와 같은 수법으로
     카드 윗 테두리에 걸터앉힌다(`pointer-events: none` 이라 칸 클릭을 안 가린다). */
.bp-card {
  position: relative;
  display: grid;
  grid-template-rows: 1fr 1fr;
  min-width: 0;
  border: 1px solid var(--border);
  border-radius: 0.5rem;
  background: var(--bg-2);
}
.bp-card.is-reached { border-color: color-mix(in srgb, var(--accent) 32%, var(--border)); }
.bp-card__no {
  position: absolute;
  top: -0.45rem;
  left: 0.4rem;
  z-index: 1;
  padding: 0 0.32rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--bg-0);
  font-size: 0.62rem;
  line-height: 1.45;
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
  pointer-events: none;   /* 칸 클릭(수령)을 가리지 않는다 */
}
.bp-card.is-reached .bp-card__no { color: var(--accent-hi); border-color: var(--accent); font-weight: 700; }

/* ── 칸(카드 안의 두 줄) ── */
.bp-cell {
  /* 버튼으로도, div 로도 난다(받을 수 있을 때만 button). 둘이 같아 보이도록 여기서 초기화한다. */
  position: relative;
  font: inherit;
  text-align: left;
  width: 100%;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.3rem 0.35rem 0.3rem 0.6rem;   /* 왼쪽 여백은 레인 띠 몫이다 */
  border: 0;
  background: transparent;
  min-height: 2.2rem;
}
/* 🔴 테두리가 카드의 것이 된 뒤로, 줄의 정체는 **왼쪽 레인 띠**가 진다(바탕 틴트·경계선은 보조).
   띠는 폭 0.22rem 이라 칩이 쓸 가로를 거의 안 먹는다 — 글자 라벨(「무료」·「서약」)로 내면
   좁은 쪽(칸 58px)에서 칩이 통째로 밀려난다. */
.bp-cell::before {
  content: "";
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 0.22rem;
  background: var(--bp-rail);
  pointer-events: none;
}
/* ⚠ 안쪽 반지름은 카드(0.5rem) − 테두리(1px) ≈ 0.44rem — 틴트/링이 카드 모서리 밖으로 새지 않게. */
.bp-cell--free {
  --bp-rail: color-mix(in srgb, var(--text-2) 55%, transparent);
  border-radius: 0.44rem 0.44rem 0 0;
}
.bp-cell--free::before { border-radius: 0.44rem 0 0 0; }
/* 서약 줄 = 금색 **점선** 레인 띠 + 점선 경계 + 금색 틴트.
   🔴 점선은 이 화면에서 「서약해야 열린다」의 표기라 어느 상태에서도 유지한다(범례 견본과 한 벌). */
.bp-cell--paid {
  --bp-rail: repeating-linear-gradient(180deg, var(--accent) 0 0.28rem, transparent 0.28rem 0.5rem);
  border-top: 1px dashed color-mix(in srgb, var(--accent) 50%, var(--border));
  border-radius: 0 0 0.44rem 0.44rem;
  background: color-mix(in srgb, var(--accent) 8%, transparent);
}
.bp-cell--paid::before { border-radius: 0 0 0 0.44rem; }
button.bp-cell { cursor: pointer; }
/* 받을 수 있는 줄 — 카드 테두리를 물들이지 않고 **안쪽 링**으로 낸다(테두리는 이제 카드의 것이라,
   여기서 건드리면 옆 칸까지 번져 보인다). */
.bp-cell.is-ready { background: var(--hover-bg); box-shadow: inset 0 0 0 1px var(--accent); }
.bp-cell--paid.is-ready { background: color-mix(in srgb, var(--accent) 14%, transparent); }
button.bp-cell.is-ready:hover { box-shadow: inset 0 0 0 1px var(--accent-hi); }
.bp-cell.is-claimed { opacity: 0.5; }
/* 미서약 잠금 칸은 더 눌러 둔다 — 「지금은 내 것이 아니다」가 한눈에 보여야 한다.
   ⚠ 바탕을 중립으로 덮지 않는다 — 틴트를 지우면 잠긴 서약 줄이 무료 줄과 똑같아진다. */
.bp-cell.is-locked { opacity: 0.42; }
.bp-cell.is-pending { opacity: 0.72; }

/* ── 칩 ── */
.bp-chips { list-style: none; margin: 0; padding: 0; display: flex; align-items: center; gap: 0.3rem; min-width: 0; flex: 1 1 auto; }
.bp-chip { display: flex; align-items: center; gap: 0.28rem; font-size: 0.7rem; min-width: 0; }
/* 🔴 수량은 **이름 문자열이 아니라 아이콘 위 배지**다. 종전엔 `이름 ×수량` 한 덩이라 말줄임이
   걸리면 가장 중요한 수량부터 사라졌다(2026-08-25 실측: 칩 67개 중 21개). 배지로 빼면
   잘려도 잃는 것은 이름 뒷부분뿐이다. */
.bp-chip__icon { position: relative; flex: 0 0 auto; line-height: 1; }
.bp-chip__qty {
  position: absolute;
  right: -0.3rem;
  bottom: -0.25rem;
  padding: 0 0.18rem;
  border-radius: 0.3rem;
  background: var(--bg-0);
  color: var(--text-1);
  font-size: 0.6rem;
  line-height: 1.3;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
/* 이름은 한 줄 말줄임. 좁아지면 아래 컨테이너 쿼리가 통째로 접는다. */
.bp-chip__name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.bp-chip--more { color: var(--text-2); font-size: 0.66rem; flex: 0 0 auto; }
.bp-chip--none { color: var(--text-2); }

/* 상태 표식 — 칸 오른쪽 끝. 글자가 아니라 기호라 폭을 거의 안 먹는다. */
.bp-cell__mark { flex: 0 0 auto; font-size: 0.7rem; color: var(--text-2); line-height: 1; }
.bp-cell.is-ready .bp-cell__mark { color: var(--accent-hi); }

/* 🔴 칸이 좁아지면 **이름만** 접는다 — 아이콘과 수량 배지는 남는다(탐험 compact 카드와 같은 수법).
   이름이 사라져도 호버 툴팁이 이름·설명·효과·획득 단서를 전부 보여 준다.
   기준 52rem: 6열일 때 칸당 ≈8.5rem 아래로 떨어지는 지점이고, 8.5rem 은 이 코드베이스가
   이미 시험해서 되돌린 하한이다 — union.css:877 에 「6.5rem 으로 줄였더니 "골.." "암.." 으로
   잘려 8.5rem 으로 되돌렸다」는 기록이 있다.
   ⚠ font-size: 0 이 아니라 display: none 이다. font-size 를 죽이면 아이콘까지 딸려 죽는다. */
@container (max-width: 52rem) {
  .bp-chip__name { display: none; }
  .bp-chips { justify-content: center; }
  /* ⚠ 왼쪽만은 레인 띠 몫(0.22rem)을 남긴다 — 0으로 깎으면 아이콘이 띠 위에 올라탄다. */
  .bp-cell { justify-content: center; padding: 0.25rem 0.25rem 0.25rem 0.45rem; min-height: 1.95rem; }
  /* 🔴 이름이 접혔으면 칸은 아이콘 하나 폭이면 된다 — 6열을 그대로 두면 102px 칸 안에 26px
     아이콘만 덩그러니 놓이고 **행이 5줄로 남아 세로만 잡아먹는다**. 열을 10으로 올려
     30 = 10 × 3 으로 접는다(세로 약 250px 회수).
     ⚠ 하한 2.6rem: 세로로 아주 긴 화면에서는 컨테이너가 281px 까지 줄어든다(rem 이 뷰포트
       높이에 묶여 있어서 — tokens.css:89). 하한을 6rem 으로 두면 그 화면에서 **1열 × 30행**이 된다. */
  .bp-grid {
    /* ⚠ 좁은 쪽은 행이 더 많아질 수 있으니(세로로 아주 긴 화면에선 2열 × 15행) 행 간격도 조금 줄인다. */
    --bp-gap-row: 0.85rem;
    grid-template-columns:
      repeat(auto-fill, minmax(max(2.6rem, calc((100% - 9 * var(--bp-gap)) / 10 - 1px)), 1fr));
  }
  .bp-card__no { font-size: 0.6rem; left: 0.1rem; }
  .bp-chip--more { font-size: 0.6rem; }
}

.bp-btn {
  font: inherit; font-size: 0.75rem;
  padding: 0.22rem 0.5rem;
  border-radius: 0.35rem;
  border: 1px solid var(--border);
  background: transparent;
  color: var(--text-1);
  cursor: pointer;
}
.bp-btn--primary { border-color: var(--accent); color: var(--accent-hi); }
.bp-btn:disabled { opacity: 0.5; cursor: default; }
/* ⚠ `[hidden]{display:none}` 은 UA 스타일이라 저자 display 에 진다. 「전부 받기」를 감출 때
   실제로 사라지도록 명시한다(.bp-cta·.bp-section 이 이미 겪은 함정). */
.bp-btn[hidden] { display: none; }

/* ── 레인 범례 띠 · 서약 유도 ──────────────────────────────────────────── */
.bp-lanes { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 0.25rem 1.1rem; }
.bp-lanes__item { display: flex; align-items: center; gap: 0.4rem; font-size: 0.78rem; color: var(--text-2); }
.bp-lanes__item b { color: var(--text-1); }
.bp-lanes__item--paid b { color: var(--accent-hi); }
/* 견본은 카드 안 줄의 문법을 그대로 쓴다 — **레인 띠까지** 같아야 눈이 이어 붙인다.
   ⚠ 칸이 카드로 묶이면서 견본의 「점선 테두리」는 「점선 레인 띠」로 옮겨 갔다. 한쪽만 고치면
     범례가 실물과 다른 것을 가리킨다. */
.bp-lanes__swatch {
  position: relative;
  width: 1.15rem; height: 0.8rem; border-radius: 0.22rem; flex: 0 0 auto;
  border: 1px solid var(--border);
  background: var(--bg-2);
  --bp-rail: color-mix(in srgb, var(--text-2) 55%, transparent);
}
.bp-lanes__swatch::before {
  content: "";
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 0.22rem;
  border-radius: 0.18rem 0 0 0.18rem;
  background: var(--bp-rail);
}
.bp-lanes__item--paid .bp-lanes__swatch {
  --bp-rail: repeating-linear-gradient(180deg, var(--accent) 0 0.28rem, transparent 0.28rem 0.5rem);
  border-color: color-mix(in srgb, var(--accent) 50%, var(--border));
  background: color-mix(in srgb, var(--accent) 10%, var(--bg-2));
}
.bp-lanes__on { color: var(--accent-hi); font-weight: 700; }

.bp-cta {
  display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap;
  padding: 0.5rem 0.75rem;
  border: 1px dashed color-mix(in srgb, var(--accent) 55%, transparent);
  border-radius: 0.5rem;
  background: color-mix(in srgb, var(--accent) 6%, transparent);
}
.bp-cta__text { font-size: 0.8rem; color: var(--text-2); line-height: 1.5; flex: 1 1 18rem; min-width: 0; }
.bp-cta__text b { color: var(--accent-hi); }
/* 🔴 `[hidden]{display:none}` 은 **UA 스타일**이라 위의 저자 `display:flex` 에 진다.
   명시하지 않으면 서약한 뒤에도 「아직 잠겨 있습니다」 띠가 그대로 남는다
   (.crf-ess-rail · .mail-card__expand 가 이미 겪은 같은 함정). */
.bp-cta[hidden] { display: none; }
/* .bp-section 도 flex 라 지난 서약 블록을 숨길 때 같은 함정에 걸린다(renderPast 가 hidden 을 쓴다). */
.bp-section[hidden] { display: none; }

/* ── 지난 서약 ────────────────────────────────────────────────────────── */
.bp-past { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.35rem; }
.bp-past__row {
  display: grid;
  grid-template-columns: 7rem 1fr auto;
  align-items: center;
  gap: 0.6rem;
  padding: 0.4rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: 0.4rem;
}
.bp-past__tier { font-size: 0.76rem; color: var(--text-2); white-space: nowrap; }
.bp-past__row .bp-chips { flex-direction: row; flex-wrap: wrap; gap: 0.5rem; }

/* ===== outpost.css ===== */
/* 주둔지(Outpost) — 계정당 단일 거점(2026-07-16 단일화). 구 "도시별 카드" 레이아웃의 잔재
   클래스명이 일부 남아 있으나 도시 축은 없다. */

.outpost-page {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

/* ── 상단 2단 — 좌: 현황 카드+힌트 / 우: 공격·기록 ────────────────────── */
.outpost-top {
  display: grid;
  /* 아래 배치도 행(.outpost-city__top)과 같은 열 폭 — 좌/우가 한 2단으로 정렬된다. */
  grid-template-columns: 1fr minmax(320px, 400px);
  gap: 18px;
  align-items: start;
}

.outpost-top__main {
  display: flex;
  flex-direction: column;
  gap: 12px;
  min-width: 0;
}

.outpost-top__side {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 14px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--panel-2, rgba(255, 255, 255, 0.02));
}

/* ── 성격별 그룹(내 주둔지) ──────────────────────────────────────────── */
.outpost-group {
  display: flex;
  flex-direction: column;
  gap: 10px;
  /* 상단(현황·공격/기록)과 내 주둔지 영역을 확실히 가르는 구분선. */
  border-top: 1px solid var(--border);
  padding-top: 16px;
  margin-top: 2px;
}

.outpost-group__head {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0;
  font-size: 1rem;
  font-weight: 700;
  color: var(--text-0);
}

/* ── 수비대 요약 4명(내 주둔지 상단) — 카드 클릭 시 관리 모달 ──────────── */
/* 방어 줄 = 수비대 4카드 + 보호막 발동. 둘 다 "내 방어 수단"이라 한 줄에 둔다.
   보호막을 .outpost-guards 안에 넣지 않는 이유는 view 주석 참조(role="group" 오염). */
.outpost-defense {
  display: flex;
  align-items: stretch;   /* 보호막 버튼이 수비대 카드와 같은 높이로 선다 */
  gap: 8px;
}

.outpost-defense > .outpost-guards {
  flex: 1 1 auto;
  min-width: 0;   /* 그리드가 flex 안에서 줄어들 수 있게 — 없으면 우측 버튼을 밀어낸다 */
}

/* 4×1 — 한 줄에 4명. 카드 폭이 ~136px(본문 ~112px)까지 눌리므로 카드는 **세로형**이어야 한다:
   머리(아이콘+이름)를 눕히고 스탯을 "라벨 왼쪽 · 값 오른쪽"으로 쌓는다. 가로로 늘어놓으면
   "치명 피해 ×1.50"(~87px)이 안 들어가 라벨과 값이 겹쳐 찍힌다(실측). */
.outpost-guards {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
}

/* 보호막 발동 — 수비대 카드와 같은 시각 언어(테두리·라운드·호버)로 맞춘다.
   .outpost-btn--action(width:100%)을 쓰지 않는 이유: 여기선 내용폭 고정이 필요하다. */
.outpost-shield-card {
  display: flex;
  flex: 0 0 auto;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  width: 180px;
  min-height: 112px;
  padding: 12px 10px;
  border-radius: 8px;
}

.outpost-shield-card__icon {
  display: inline-flex;
  line-height: 1;
}

.outpost-shield-card__icon .icon {
  width: 1.4rem;   /* 수비대 카드 아이콘과 같은 크기 — 한 줄에 서므로 눈높이를 맞춘다 */
  height: 1.4rem;
}

.outpost-shield-card__label {
  font-weight: 700;
}

/* 세로형 — 머리 / 스탯 / 저항 / 장비배지 를 위에서 아래로. 폭이 좁은 대신 높이를 쓴다. */
.outpost-guard-card {
  display: flex;
  flex-direction: column;
  gap: 7px;
  padding: 11px 10px;
  min-height: 196px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.02);
  color: var(--text-0);
  text-align: left;
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s, transform 0.15s;
}

.outpost-guard-card:hover:not(:disabled) {
  border-color: var(--accent);
  background: rgba(255, 255, 255, 0.04);
  transform: translateY(-1px);
}

.outpost-guard-card:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

.outpost-guard-card.is-empty {
  border-style: dashed;
}

.outpost-guard-card__icon {
  display: inline-flex;
  flex: 0 0 auto;
  color: var(--text-2);
}

.outpost-guard-card__icon .icon {
  width: 1.4rem;
  height: 1.4rem;
}

.outpost-guard-card.is-filled .outpost-guard-card__icon {
  color: var(--outpost-accent, var(--accent));
}

/* 머리 — 아이콘 + (이름/클래스) 를 한 줄로 눕힌다. min-width:0 이 있어야 이름 말줄임이 먹는다. */
.outpost-guard-card__head {
  display: flex;
  align-items: center;
  gap: 7px;
  min-width: 0;
}

.outpost-guard-card__title {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
  flex: 1 1 auto;
}

.outpost-guard-card__role {
  font-size: 0.82rem;
  font-weight: 700;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.outpost-guard-card__sub {
  font-size: 0.72rem;
  color: var(--text-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* 빈 자리 안내 — 남은 높이를 통째로 먹고 가운데 선다(flex:1). 채워진 카드의 스탯 자리와
   같은 공간이라 4장이 나란히 서도 높이가 흔들리지 않는다. */
.outpost-guard-card__cta {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 5px;
  text-align: center;
  color: var(--text-2);
}

.outpost-guard-card__cta-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border: 1px dashed var(--border);
  border-radius: 999px;
  font-size: 0.95rem;
  font-weight: 700;
  line-height: 1;
  color: var(--text-2);
}

.outpost-guard-card__cta-text {
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--text-1);
}

.outpost-guard-card__cta-sub {
  font-size: 0.62rem;
  line-height: 1.35;
  color: var(--text-2);
}

/* 호버 — 테두리와 함께 안내도 살아난다. "이 카드는 눌리는 것"을 한 번 더 말한다. */
.outpost-guard-card:hover:not(:disabled) .outpost-guard-card__cta-mark {
  border-color: var(--accent);
  color: var(--accent);
}

.outpost-guard-card:hover:not(:disabled) .outpost-guard-card__cta-text {
  color: var(--accent);
}

/* 장비 배지 — margin-top:auto 로 카드 바닥에 붙인다(카드 높이가 달라도 아래 선이 맞는다). */
.outpost-guard-card__equip {
  flex: 0 0 auto;
  align-self: flex-start;
  margin-top: auto;
  padding: 1px 6px;
  border: 1px solid var(--border);
  border-radius: 999px;
  font-size: 0.64rem;
  color: var(--text-2);
  white-space: nowrap;
}

/* 전투가 쓰는 축 전부 — 수비대 관리 모달과 같은 라벨(값·문자열 소유자는 서버).
   좁은 폭(본문 ~112px)이라 **한 줄에 하나씩**, 라벨 왼쪽 · 값 오른쪽으로 세워 표처럼 읽힌다.
   가로 배치는 "치명 피해 ×1.50"(~87px)이 안 들어가 겹쳐 찍힌다(실측). */
.outpost-guard-card__stats {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding-top: 6px;
  border-top: 1px solid var(--border-soft, var(--border));
  font-size: 0.68rem;
}

.outpost-guard-card__stats > span {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 6px;
  min-width: 0;
}

.outpost-guard-card__stats i {
  font-style: normal;
  color: var(--text-2);
  white-space: nowrap;
}

/* ⚠ flex-shrink 를 막지 않으면 좁은 칸에서 값이 라벨 위로 눌려 겹쳐 찍힌다(줄바꿈이 아니라 겹침). */
.outpost-guard-card__stats b {
  flex: 0 0 auto;
  color: var(--text-0);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* 속성 저항 — 0 인 학교는 서버가 안 내리므로 칩이 1~2개뿐이다(대개 한 줄). */
/* 속성 저항 — 0 인 학교는 서버가 안 내리므로 대개 1~2개다. 스탯 표와 구분선으로 나눈다. */
.outpost-guard-card__resists {
  display: flex;
  flex-wrap: wrap;
  gap: 2px 8px;
  padding-top: 6px;
  border-top: 1px solid var(--border-soft, var(--border));
  font-size: 0.63rem;
  color: var(--text-2);
}

.outpost-guard-card__resist {
  display: inline-flex;
  align-items: baseline;
  gap: 3px;
}

.outpost-guard-card__resist b {
  color: var(--text-1);
  font-variant-numeric: tabular-nums;
}

.outpost-guard-card__dot {
  align-self: center;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  flex: none;
}

.outpost-hint {
  font-size: 0.85rem;
  color: var(--text-2);
  line-height: 1.6;
  margin: 0;
}

.outpost-muted {
  color: var(--text-2);
}

/* ── 버튼 — 앱 표준 버튼(.exp-btn) 레시피와 동일 ─────────────────────────
   채운 배경(--bg-2)·1px --border·radius-sm·weight 600·hover 액센트 테두리·active 눌림.
   🔴 이 기본 규칙이 없으면 .outpost-btn 은 배경·테두리·패딩·라운드가 전부 없어 **버튼으로
   보이지 않는다** — hover/active/disabled 와 --primary 변형은 전부 이 규칙 위에 얹힌다.
   (2026-08-23 죽은 클래스 정리가 주석 속 `.party-btn` 참조를 지우다 주석 닫기와 이 규칙까지
   함께 잘라내 실제로 그렇게 됐다. 2026-08-24 복원.) */
.outpost-btn {
  min-width: 6rem;
  padding: 0.55rem 1rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-2);
  color: var(--text-0);
  font-size: 0.9rem;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, transform 0.1s;
}

.outpost-btn:hover:not(:disabled) {
  border-color: var(--accent);
  background: var(--hover-bg-2, #2a3348);
}

.outpost-btn:active:not(:disabled) {
  transform: translateY(1px);
}

.outpost-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* 주요 액션 — 액센트 골드 필(표준 --primary 변형). */
.outpost-btn--primary {
  border-color: var(--accent);
  background: var(--accent);
  color: var(--bg-0);
}

.outpost-btn--primary:hover:not(:disabled) {
  border-color: var(--accent-hi);
  background: var(--accent-hi);
}

/* 좌측 액센트 보더는 전면 제거(사용자 확정) — 강조는 게이지·선택 링·배치도 틴트가 진다. */
.outpost-card {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 14px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--panel-2, rgba(255, 255, 255, 0.02));
}

/* ── 재고 게이지 ─────────────────────────────────────────────────────── */
.outpost-card__stock {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.outpost-card__bar {
  height: 6px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.07);
  overflow: hidden;
}

.outpost-card__fill {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: var(--outpost-accent, var(--accent));
  transition: width 0.35s ease;
}

.outpost-card__stock-row {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 16px;
  font-size: 0.92rem;
}

/* 골드/재료 <b> 는 일반 인라인으로 둔다 — .icon--gold/.icon 의 vertical-align 튜닝(icons.css)
   이 살아나 아이콘·숫자·/max 가 한 베이스라인에 앉는다. inline-flex 로 감싸면 그 정렬이 죽는다. */
.outpost-card__stock-row b {
  white-space: nowrap;
}

/* ── 메타 ────────────────────────────────────────────────────────────── */
.outpost-card__meta {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 18px;
  margin: 0;
  font-size: 0.8rem;
}

.outpost-card__meta > div {
  display: flex;
  gap: 5px;
  white-space: nowrap;
}

.outpost-card__meta dt {
  color: var(--text-2);
}

.outpost-card__meta dd {
  margin: 0;
  color: var(--text-0);
}

.outpost-bld {
  display: flex;
  flex-direction: column;
  gap: 5px;
  font-size: 0.8rem;
}

.outpost-bld__row {
  display: flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
}

.outpost-bld__icon {
  display: inline-flex;
  width: 14px;
  height: 14px;
  color: var(--text-2);
  flex: 0 0 auto;
}

.outpost-bld__name {
  overflow: hidden;
  text-overflow: ellipsis;
  cursor: help;
}

.outpost-bld__lv {
  margin-left: auto;
  color: var(--text-2);
}

/* 미건설 건물은 이름만 흐리게 — 비용/버튼까지 흐려지면 무엇이 모자란지 안 읽힌다. */
.outpost-bld.is-empty .outpost-bld__row {
  opacity: 0.6;
}

.outpost-bld.is-working .outpost-bld__lv {
  color: var(--accent);
}

/* ── 다음 단계 비용 ──────────────────────────────────────────────────── */
.outpost-bld__next,
.outpost-bld__work {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding-left: 20px; /* 아이콘 폭만큼 들여쓰기 — 건물에 딸린 정보임을 보여준다 */
}

/* 필요 재료 — 연금·제작과 같은 표준 .item-row 를 카드 폭에 맞춰 컴팩트하게. */
.outpost-bld__reqs {
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.outpost-bld__reqs .item-row { font-size: 0.82rem; }
.outpost-bld__reqs .item-row__icon { width: 1.3rem; height: 1.3rem; }
.outpost-bld__reqs .item-row__icon .icon { width: 1.2rem; height: 1.2rem; }
/* 골드 통화 행 — 코인 마크를 금색으로(그 외엔 재료 등급색). */
.outpost-bld__reqs .item-row--currency .item-row__icon { color: var(--accent-hi); }

/* "Lv 올리기" 버튼의 소요시간 — 금색 버튼 위 옅은 톤. */
.outpost-mini__time {
  margin-left: 2px;
  font-weight: 400;
  opacity: 0.7;
}


.outpost-cost {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  white-space: nowrap;
}

/* 소요 시간은 금화와 시각적으로 구분되어야 한다 — 둘 다 "비용"이지만 성격이 다르다. */

/* 모자란 것은 붉게 — 왜 버튼이 잠겼는지 카드에서 바로 읽힌다. */
.outpost-cost.is-short,

.outpost-bld__done {
  padding-left: 20px;
  color: var(--text-2);
  font-style: italic;
}

/* ── 작은 버튼(건설·즉시완공) ────────────────────────────────────────── */
.outpost-mini {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 10px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: transparent;
  color: var(--text-0);
  font-size: 0.8rem;
  white-space: nowrap;
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s, opacity 0.15s;
}

/* 정찰 버튼과 **나란히 서는 짝** — 기본 .outpost-mini(0.8rem·4px)는 건물 카드 속 보조 버튼용이라
   여기선 너무 작다. 골드 액수를 읽고 눌러야 하는 결제 버튼인데 옆 버튼보다 작으면 눌릴 것처럼
   보이지 않는다. .outpost-btn 과 같은 글자 크기·좌우 여백으로 올리고, 높이는 부모의
   align-items:stretch 가 맞춘다(위 .outpost-raid__bar 주석). align-self 는 그래서 auto 로 되돌린다. */
.outpost-mini--pair {
  align-self: auto;
  justify-content: center;
  padding: 0.55rem 0.9rem;
  border-radius: var(--radius-sm);
  font-size: 0.9rem;
  font-weight: 600;
}

.outpost-mini:hover:not(:disabled) {
  border-color: var(--accent);
  background: rgba(255, 255, 255, 0.04);
}

.outpost-mini:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

/* 행동 버튼(건설·훈련·공격) — 액센트 필로 확실히 "버튼"으로 읽히게 한다. */
.outpost-mini--primary {
  padding: 7px 14px;
  border-color: var(--accent);
  background: var(--accent);
  color: #0d0f12;
  font-weight: 600;
}

.outpost-mini--primary:hover:not(:disabled) {
  border-color: color-mix(in srgb, var(--accent) 80%, #fff);
  background: color-mix(in srgb, var(--accent) 80%, #fff);
}

/* 즉시 완공 — 이계 상자의 골드 스킵 버튼과 같은 관용구. */
.outpost-mini--skip {
  border-color: var(--accent-hi, #d9a441);
  background: rgba(217, 164, 65, 0.08);
  color: var(--accent-hi, #d9a441);
  font-weight: 600;
}

.outpost-mini--skip:hover:not(:disabled) {
  border-color: var(--accent-hi, #d9a441);
  background: rgba(217, 164, 65, 0.18);
}

/* ── 진행 중인 공사 ──────────────────────────────────────────────────── */
.outpost-bld__bar {
  height: 4px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.07);
  overflow: hidden;
}

.outpost-bld__fill {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: var(--accent);
}

.outpost-bld__work-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.outpost-bld__eta {
  color: var(--text-2);
  white-space: nowrap;
}

.outpost-bld__eta b {
  color: var(--text-0);
}

/* ── 수비대 클래스 선택 — 수비대 관리 팝업(guard-equip-modal.js)이 쓴다. ──── */
.outpost-guard__class {
  flex: 1 1 auto;
  min-width: 0;
  padding: 3px 6px;
  border: 1px solid var(--border);
  border-radius: 5px;
  background: var(--panel, #16181d);
  color: var(--text-0);
  font-size: 0.8rem;
}

.outpost-guard__class:disabled {
  opacity: 0.5;
}

/* ── 공격/기록 버튼 바 — 탭 폐지, 각각 팝업을 연다 ───────────────────── */
.outpost-actions {
  display: flex;
  gap: 10px;
  align-items: center;
}

/* 상단 우열 — 세로 스택. */
.outpost-actions--stack {
  flex-direction: column;
  align-items: stretch;
}

/* 상단 우열의 공격/기록 — 레이아웃만(전폭·라벨+카운트 중앙). 시각은 표준 .outpost-btn 이 진다. */
.outpost-btn--action {
  display: flex;
  width: 100%;
  align-items: center;
  justify-content: center;
  gap: 8px;
}

/* 탭 시절의 부속 표기를 버튼에서 재사용한다. */
.outpost-tab__count {
  font-size: 0.72rem;
  color: var(--text-2);
  white-space: nowrap;
}

/* ── 공격 패널 ───────────────────────────────────────────────────────── */
.outpost-raid {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

/* ⚠ align-items:stretch 가 "높이를 맞춘다"의 단일 장치다 — 두 버튼이 줄의 교차 크기를 함께
   받아 **저절로 같은 높이**가 된다. min-height 매직넘버로 맞추면 .outpost-btn 의 패딩이
   바뀌는 순간 조용히 어긋나고, 안쪽 골드 아이콘(.icon = 1.25em)이 글자 줄보다 커서
   패딩만 맞춰도 1px 씩 뜬다. 글자 span 만 가운데로 되돌린다(늘어나면 위로 붙는다). */
.outpost-raid__bar {
  display: flex;
  align-items: stretch;
  gap: 14px;
}

.outpost-raid__bar > .outpost-muted {
  align-self: center;
}

.outpost-raid__empty {
  padding: 24px;
  border: 1px dashed var(--border);
  border-radius: 10px;
  text-align: center;
  color: var(--text-2);
  font-size: 0.85rem;
}

/* 정찰 티켓 수명 — 목록 위 한 줄. .outpost-hint 와 같은 보조 텍스트 급이다.
   ⚠ display 를 선언하지 않는다 — <p> 의 기본 block 이면 UA 의 [hidden]{display:none}(특이도 0)이
     그대로 먹는다. display 를 주는 순간 [hidden] 이 져서 숨겨야 할 줄이 계속 보인다
     (.outpost-mini 가 정확히 그 사고를 냈다 — 이 파일의 [hidden] 함정 5번째 사례). */
.outpost-raid__ttl {
  margin: 0;
  color: var(--text-2);
  font-size: 0.85rem;
}

/* 5분 이하 — "지금 안 치면 다시 정찰해야 한다"를 미리 알린다. shop.css 의 만료 임박과 같은 토큰. */
.outpost-raid__ttl.is-soon b {
  color: var(--danger);
  font-weight: 700;
}

/* ── 후보(로그아웃한 3명) ────────────────────────────────────────────── */
.outpost-targets {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 12px;
  list-style: none;
  margin: 0;
  padding: 0;
}

.outpost-target {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 12px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--panel-2, rgba(255, 255, 255, 0.02));
}

.outpost-target__head {
  display: flex;
  align-items: baseline;
  gap: 8px;
}

.outpost-target__name {
  font-size: 0.92rem;
  color: var(--text-0);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}


/* ── 약탈 결과 ───────────────────────────────────────────────────────── */
.outpost-result__lead {
  margin: 0 0 10px;
  font-size: 0.92rem;
}

.outpost-result__lead--win b {
  color: var(--accent);
}

.outpost-result__lead--lose {
  color: var(--text-2);
}

/* ── 기록 패널 — 피격 내역 · 내 전적 ─────────────────────────────────── */
.outpost-log {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.outpost-log__head {
  margin: 6px 0 0;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--text-0);
}

.outpost-log__list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.outpost-log__empty {
  margin: 0;
  padding: 10px 12px;
  border: 1px dashed var(--border);
  border-radius: 8px;
  font-size: 0.8rem;
  color: var(--text-2);
}

/* 한 줄 = 한 번의 습격. 왼쪽부터 누가 · 어느 도시 · 얼마 · 언제 · 무엇을 할 수 있는가. */
.outpost-raidrow {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--panel-2, rgba(255, 255, 255, 0.02));
  font-size: 0.85rem;
}

/* 아직 못 본 피격은 왼쪽에 표식을 세운다 — 돌아왔을 때 눈이 먼저 가야 하는 줄이다. */
.outpost-raidrow.is-new {
  border-left: 3px solid var(--accent);
}

.outpost-raidrow.is-lost {
  background: rgba(220, 80, 80, 0.06);
}

.outpost-raidrow.is-won {
  background: rgba(120, 200, 140, 0.05);
}

.outpost-raidrow__who {
  font-weight: 600;
  color: var(--text-0);
}

.outpost-raidrow__loss {
  color: var(--bad, #e06060);
  font-variant-numeric: tabular-nums;
}

.outpost-raidrow__gain {
  color: var(--good, #6ac081);
  font-variant-numeric: tabular-nums;
}

.outpost-raidrow__held {
  color: var(--good, #6ac081);
  font-size: 0.8rem;
}

/* 시각은 오른쪽 끝으로 밀어 버튼과 붙지 않게 한다. */
.outpost-raidrow__at {
  margin-left: auto;
  font-size: 0.8rem;
}

.outpost-mini--raid {
  border-color: var(--accent);
  color: var(--accent);
}

/* 탭 배지 — 미확인 피격 + 쓸 수 있는 복수권. 0 이면 아예 렌더하지 않는다. */
.outpost-tab__badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: 999px;
  background: var(--accent);
  color: #0d0f12;
  font-size: 0.72rem;
  font-weight: 700;
  white-space: nowrap;
}
/* [hidden] 은 display 선언에 진다(UA 규칙 특이도 0) — 명시 오버라이드가 없으면
   배지가 0이어도 "0" 으로 계속 보인다. .outpost-bld[hidden] 과 같은 함정의 4번째 사례. */
.outpost-tab__badge[hidden] { display: none; }

/* 같은 함정의 5번째 사례 — .outpost-mini 는 display:inline-flex 라 [hidden] 을 이긴다.
   쿨타임이 없을 때도 "즉시 정찰 0" 버튼이 남아 공짜 결제 버튼처럼 보였다(실측). */
.outpost-mini[hidden] { display: none; }

/* 노란색(primary) 버튼 위에서는 카운트·배지를 어두운 톤으로 — 골드 배경 대비 확보. */
.outpost-btn--primary .outpost-tab__count {
  color: rgba(13, 15, 18, 0.68);
}
.outpost-btn--primary .outpost-tab__badge {
  background: rgba(13, 15, 18, 0.72);
  color: var(--accent-hi);
}

/* 리플레이 시점 표시 — 내가 방어자일 때 로그의 "당신"이 침입자임을 밝힌다. */
.outpost-replay-hint {
  margin-left: 10px;
  font-size: 0.8rem;
  color: var(--text-2);
}

.outpost-replay-hint[hidden] {
  display: none;
}

/* 재료는 약탈당하지 않는다(INV-2). 그 사실이 화면에서 읽혀야 은닉고와 헷갈리지 않는다. */
.outpost-card__safe-tag {
  margin-left: auto;
  padding: 1px 6px;
  border: 1px solid var(--good, #6ac081);
  border-radius: 999px;
  color: var(--good, #6ac081);
  font-size: 0.68rem;
  white-space: nowrap;
}

/* ⚠ 패널의 [hidden] 이 display 선언에 진다 — UA 의 [hidden]{display:none} 은 특이도 0 이라
 *   .outpost-raid{display:flex} / .outpost-log{display:flex} 가 이긴다(과거 세 패널이 언제나
 *   함께 보이던 버그). 클래스+속성(0,2,0)으로 눌러야 한다. */
.outpost-raid[hidden],
.outpost-log[hidden] {
  display: none;
}

.outpost-city-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}

.outpost-chip {
  padding: 1px 6px;
  border: 1px solid var(--border);
  border-radius: 999px;
  font-size: 0.68rem;
  color: var(--text-2);
  white-space: nowrap;
}

.outpost-chip--pierce {
  border-color: var(--accent);
  color: var(--accent);
}

/* 상대 카드 푸터 — 방어 칩 + 공격 버튼(단일 주둔지). */
.outpost-target__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding-top: 8px;
  border-top: 1px solid var(--border);
}

/* 칩은 남는 폭을 먹고 줄바꿈으로 흡수, 공격 버튼은 절대 눌리지 않는다.
   버튼에 flex-shrink 를 남겨 두면 칩 묶음의 max-content 가 넓을수록 버튼까지 같이 줄어든다 —
   Chrome 은 <button> 에 min-width:auto 의 콘텐츠 최소폭을 적용하지 않아 좌우 padding 이 깎인다.
   그래서 함정·무기고 칩이 있는 카드(칩 3개)만 버튼이 좁아지고, 칩 1개짜리 카드는 멀쩡해
   같은 줄의 공격 버튼 폭이 제각각으로 보인다.
   실측(카드 3열·정찰 모달): 카드 323px 에선 안 드러나고 260px 51.2/49.1, 220px 51.2/45.2 로
   벌어진다 — 이름이 길거나 "보호막 무시" 칩이 붙어 칩 줄이 늘면 더 좁은 폭에서도 터진다.
   align-self 는 .outpost-mini 의 flex-start 를 되돌린다. 칩이 두 줄인 카드에서 버튼만 위로
   붙어 보이던 것도 같은 원인이다. */
.outpost-target__foot > .outpost-city-chips {
  flex: 1 1 auto;
  min-width: 0;
}

.outpost-target__foot > .outpost-mini {
  flex: 0 0 auto;
  align-self: center;
  justify-content: center;
}

/* 복수 확인 모달 — 방어 요약 한 줄. */
.outpost-revenge-brief {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 8px 0 0;
}

/* ═══ UI 리뉴얼 — 도시 우선 탐색 · 마을 배치도 · 팝업 ═══════════════════ */

/* ── 단일 주둔지 레이아웃(2026-07-16) — 스트립 + [배치도 | 공사·상세] ─────── */
/* 배치도가 주인공(1fr) — 우측은 공사 슬롯 + 선택 건물 상세의 고정 폭 컬럼. */
.outpost-city__top {
  display: grid;
  grid-template-columns: 1fr minmax(320px, 400px);
  gap: 18px;
  align-items: start;
}

.outpost-city__side {
  display: flex;
  flex-direction: column;
  gap: 14px;
  min-width: 0;
}

/* ── 현황 카드 내 금화/재료 인라인 표기(통합 카드) ───────────────────── */
.outpost-strip__gold,
.outpost-strip__mat {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  white-space: nowrap;
}

.outpost-strip__gold b,
.outpost-strip__mat b {
  white-space: nowrap;
}

.outpost-strip__mat .outpost-card__safe-tag { margin-left: 4px; }

/* ── 마을 배치도 — 화톳불 중앙 3×3 고정 배치 ──────────────────────────── */
/* 구역형 배치도(2026-07-16, 27종) — grid-area 하드코딩 대신 구역 섹션 + auto-fill.
   건물이 늘어도 CSS 무수정: CSV 의 district 컬럼이 어느 구역에 설지 정한다. */
.outpost-map2 {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 14px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background:
    radial-gradient(circle at 50% 20%,
      color-mix(in srgb, var(--accent) 8%, transparent), transparent 68%),
    var(--panel-2, rgba(255, 255, 255, 0.02));
}

.outpost-district { display: flex; flex-direction: column; gap: 6px; }

.outpost-district__head {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin: 0;
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--text-0);
}

.outpost-district__head .outpost-muted { font-size: 0.68rem; font-weight: 400; }

.outpost-district__grid {
  display: grid;
  /* 열 수를 최대 7로 캡 — 산출(7개)이 행을 꽉 채워 화톳불(전열 폭)과 폭이 일치하고,
     빈 트랙이 안 생긴다. 좁은 화면에선 112px 하한으로 자연 래핑. 박스 크기는 구역 공통. */
  grid-template-columns: repeat(auto-fill, minmax(max(112px, calc((100% - 48px) / 7)), 1fr));
  gap: 8px;
}

/* 화톳불(격) — 산출 구역과 같은 전폭이되 가로형 "건물 카드"로. 배너 느낌을 없애고
   클릭·업그레이드 대상임이 읽히게 한다. 여전히 .outpost-map__plot 이라 선택/클릭 동작 유지. */
.outpost-map__plot.outpost-hearth {
  flex-direction: row;
  justify-content: flex-start;
  align-items: center;
  flex-wrap: wrap;
  text-align: left;
  gap: 16px;
  min-height: auto;
  padding: 16px 20px;
  border-color: color-mix(in srgb, var(--accent) 45%, var(--border));
}

.outpost-hearth__icon { flex: 0 0 auto; }
.outpost-hearth__icon .icon { width: 2.4rem; height: 2.4rem; }

.outpost-hearth__body {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  min-width: 0;
  flex: 1 1 auto;
}

/* 이름 줄만 Lv 배지(우상단 절대배치)를 피해 우측 여백 — 설명은 전폭으로 흐른다. */
.outpost-hearth__name { font-size: 1rem; font-weight: 700; padding-right: 44px; }
.outpost-hearth__desc { font-size: 0.78rem; color: var(--text-2); line-height: 1.4; }

.outpost-map__plot {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  min-height: 100px;
  padding: 10px 8px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.02);
  font-size: 0.8rem;
  text-align: center;
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s, transform 0.15s;
}

/* 클릭·업그레이드 어포던스 — 모든 플롯 hover 시 살짝 떠오르며 액센트 테두리(잠긴 터 제외). */
.outpost-map__plot:hover:not(.is-locked) {
  border-color: var(--accent);
  background: rgba(255, 255, 255, 0.045);
  transform: translateY(-1px);
}

.outpost-hearth:hover {
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 40%, transparent) inset;
}

/* 빈 터 — 점선 + 유령 아이콘. */
.outpost-map__plot.is-empty { border-style: dashed; }

/* 잠긴 터 — 해금 도시를 정복해야 열린다(탐험 blinded 문법). */
.outpost-map__plot.is-locked {
  border-style: dashed;
  opacity: 0.66;
  filter: saturate(0.4);
}
.outpost-map__plot.is-locked .outpost-map__name { color: var(--text-2); }
.outpost-map__unlock {
  font-size: 0.62rem;
  color: var(--text-2);
  white-space: nowrap;
}
.outpost-map__plot.is-empty .outpost-map__icon { opacity: 0.3; filter: grayscale(1); }
.outpost-map__plot.is-empty .outpost-map__name { color: var(--text-2); }

/* 완공 — 도시 테마색 보더 + 틴트. */
.outpost-map__plot.is-built {
  border-color: color-mix(in srgb, var(--outpost-accent, #8a8a8a) 55%, var(--border));
  background: color-mix(in srgb, var(--outpost-accent, #8a8a8a) 10%, transparent);
}

/* 공사 중 — 펄스 + 진행바 + 카운트다운. */
.outpost-map__plot.is-working {
  border-color: var(--accent);
  animation: outpost-plot-pulse 1.6s ease-in-out infinite;
}

@keyframes outpost-plot-pulse {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 35%, transparent); }
  50%      { box-shadow: 0 0 10px 2px color-mix(in srgb, var(--accent) 55%, transparent); }
}

/* 선택된 건물 — 우측 상세가 이 건물을 말하고 있다는 표식(액센트 링). 상태 규칙들보다
   뒤에 두어 is-built 의 보더색을 이긴다. */
.outpost-map__plot.is-selected {
  border-color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent) inset;
  background: color-mix(in srgb, var(--accent) 9%, transparent);
}

.outpost-map__icon .icon { width: 24px; height: 24px; }

.outpost-map__lv {
  position: absolute;
  top: 4px;
  right: 5px;
  padding: 0 5px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--outpost-accent, #8a8a8a) 80%, #000);
  color: #fff;
  font-size: 0.62rem;
  font-weight: 700;
  line-height: 14px;
}

.outpost-map__bar {
  width: 82%;
  height: 3px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.1);
  overflow: hidden;
}

.outpost-map__bar > span {
  display: block;
  height: 100%;
  background: var(--accent);
}

.outpost-map__eta {
  color: var(--accent);
  font-size: 0.68rem;
  font-variant-numeric: tabular-nums;
}

/* ── 건축 진행 슬롯 — 이계 상자 "여는 중" 슬롯 문법(진행 카드 + 점선 빈 자리) ── */
.outpost-works {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.outpost-works__head {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin: 0;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--text-0);
}

.outpost-works__head .outpost-muted {
  font-size: 0.72rem;
  font-weight: 400;
}

.outpost-works__list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  list-style: none;
  margin: 0;
  padding: 0;
}

.outpost-workslot {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 10px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.03), rgba(0, 0, 0, 0.12));
  font-size: 0.8rem;
}

.outpost-workslot__icon .icon { width: 20px; height: 20px; }

.outpost-workslot__main {
  display: flex;
  flex-direction: column;
  gap: 4px;
  flex: 1;
  min-width: 0;
}

.outpost-workslot__name {
  display: flex;
  align-items: baseline;
  gap: 6px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.outpost-workslot__to { color: var(--accent); }

.outpost-workslot__bar {
  height: 4px;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.35);
  overflow: hidden;
}

.outpost-workslot__bar > span {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: var(--accent);
  transition: width 0.6s ease;
}

.outpost-workslot__eta {
  color: var(--text-2);
  font-size: 0.72rem;
}

.outpost-workslot__eta b {
  color: var(--text-0);
  font-variant-numeric: tabular-nums;
}

.outpost-workslot .outpost-mini--skip { align-self: center; }

.outpost-workslot--empty {
  flex-direction: column;
  justify-content: center;
  gap: 3px;
  min-height: 54px;
  border-style: dashed;
  background: repeating-linear-gradient(
    -45deg,
    rgba(255, 255, 255, 0.015) 0 8px,
    transparent 8px 16px
  );
  color: var(--text-2);
}

.outpost-workslot--empty .outpost-workslot__mark {
  font-size: 1.05rem;
  line-height: 1;
  opacity: 0.55;
}

/* ── 선택 건물 상세 — 배치도에서 고른 건물 1개만 보여주는 패널 ─────────── */
.outpost-bld-detail {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.015);
}

/* ⚠ .outpost-bld{display:flex} 가 UA [hidden] 을 이긴다 — 명시 오버라이드 필수. */
.outpost-bld[hidden] { display: none; }

.outpost-bld-detail .outpost-bld { font-size: 0.85rem; gap: 8px; }
.outpost-bld-detail .outpost-bld__icon { width: 18px; height: 18px; }
.outpost-bld-detail .outpost-bld__name { font-size: 0.92rem; font-weight: 600; cursor: default; }
.outpost-bld-detail .outpost-bld__next,
.outpost-bld-detail .outpost-bld__work,
.outpost-bld-detail .outpost-bld__done { padding-left: 0; }

/* ── 건물 용도 설명(상시 노출) ─────────────────────────────────────────── */
.outpost-bld__desc {
  margin: 0;
  font-size: 0.8rem;
  color: var(--text-2);
  line-height: 1.5;
}

/* 현재 레벨의 구체 효과 — 설명 프로즈보다 눈에 띄게(액센트). */
.outpost-bld__effect {
  margin: 0;
  display: flex;
  align-items: baseline;
  gap: 6px;
  font-size: 0.84rem;
}
.outpost-bld__effect b { color: var(--accent-hi); font-weight: 700; }
.outpost-bld__effect-k {
  flex: 0 0 auto;
  padding: 0 6px;
  border-radius: 999px;
  border: 1px solid var(--border);
  font-size: 0.66rem;
  color: var(--text-2);
}

/* "Lv.N로 올리면 얻는 효과" — 빌드 카드 상단 안내. */
.outpost-bld__upgrade {
  display: flex;
  align-items: baseline;
  gap: 6px;
  font-size: 0.8rem;
  color: var(--text-1);
}
.outpost-bld__upgrade b { color: var(--accent-hi); font-weight: 600; }
.outpost-bld__upgrade-k { flex: 0 0 auto; color: var(--text-2); }

/* ── 공격/기록 팝업 — 앱 표준 모달 그래머(modal.css/equip-modal)와 동일한 룩 ──
   ⚠ z-index 는 전투 오버레이(10000)보다 낮게 유지: 약탈 시작 시 팝업이 안 닫히고
   오버레이가 그 위를 덮는 현행 동작을 보존한다(팝업을 위로 올리면 전투를 가린다). */
.outpost-pop {
  position: fixed;
  inset: 0;
  z-index: 1200;
  display: flex;
  align-items: safe center;
  justify-content: safe center;
  overflow: auto;
  padding: 1.25rem;
}

/* ⚠ [hidden] 명시 오버라이드 — display:flex 가 UA 규칙을 이기는 함정. */
.outpost-pop[hidden] { display: none; }

.outpost-pop__backdrop {
  position: fixed;
  inset: 0;
  background: var(--backdrop);
  backdrop-filter: blur(2px);
}

.outpost-pop__panel {
  position: relative;
  width: min(46rem, 100%);
  max-height: min(46rem, 92vh);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--bg-1);
  box-shadow: 0 1.5rem 3rem rgba(0, 0, 0, 0.55);
  animation: outpost-pop-in 130ms ease-out;
}

@keyframes outpost-pop-in {
  from { opacity: 0; transform: translateY(0.5rem) scale(0.98); }
  to   { opacity: 1; transform: none; }
}

.outpost-pop__head {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.9rem 1rem;
  border-bottom: 1px solid var(--border);
  background: var(--bg-2);
}

.outpost-pop__head h3 {
  margin: 0;
  flex: 1;
  font-size: 0.95rem;
  font-weight: 600;
  letter-spacing: 0.02em;
}

/* 표준 라운드 close 버튼(equip-modal 과 동일). */
.outpost-pop__close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  border: none;
  border-radius: 999px;
  background: transparent;
  color: var(--text-1);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
}

.outpost-pop__close:hover {
  background: rgba(255, 255, 255, 0.06);
  color: var(--text-0);
}

.outpost-pop__body {
  flex: 1;
  min-height: 0;
  padding: 1rem;
  overflow-y: auto;
}

/* ═══ 수비대 관리 팝업(guard-equip-modal.js) — equip-modal 골격 위의 확장 ══════
   주둔지의 유일 부대: 좌측 = 수비대원 4행, 우측 = 선택 대원의 클래스/훈련/12슬롯
   페이퍼돌 + 착용 후보. 팝업 컨테이너·2열·슬롯행·후보 그리드는 equip-modal.css 재사용. */

.equip-modal--guards .equip-modal__panel {
  width: min(58rem, 100%);
}

.gdm-head-note {
  flex: 1;
  font-size: 0.8rem;
  color: var(--text-2);
}

.gdm-note {
  margin: 10px 12px 0;
  padding: 8px 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.02);
  font-size: 0.8rem;
  color: var(--text-2);
  line-height: 1.6;
}

.gdm-muted { color: var(--text-2); }

.gdm-guard-row__equip {
  flex: 0 0 auto;
  padding: 1px 7px;
  border: 1px solid var(--border);
  border-radius: 999px;
  font-size: 0.68rem;
  color: var(--text-2);
  white-space: nowrap;
}

.gdm-head {
  display: flex;
  align-items: center;
  gap: 10px;
}

.gdm-head__role {
  font-size: 0.92rem;
  font-weight: 700;
  color: var(--text-0);
  white-space: nowrap;
}

.gdm-head .outpost-guard__class { max-width: 180px; }

.gdm-head__lv {
  margin-left: auto;
  font-size: 0.85rem;
  color: var(--text-0);
  white-space: nowrap;
}

/* ── 수비대원 스탯 — 전투가 쓰는 축 전부 + 착용 델타 ──────────────────────
   캐릭터 장비 팝업 상단 바의 원자(.equip-stat*)를 그대로 쓴다: 라벨/값 정렬·델타 색·
   애니메이션이 한 곳(equip-modal.css)에서 나온다.
   ⚠ 그 원자엔 **5열 격자 전용** nth-child 테두리 규칙이 붙어 있다(equip-modal.css:74-76).
     3열에서는 엉뚱한 칸에 선이 그어지므로 여기서 전부 지운다. 번들 순서상 equip-modal.css
     가 먼저라(build-css-bundle.php) 같은 특이도면 이쪽이 이긴다. */
.gdm-stats {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2px 14px;
  margin: 0;
}
.gdm-stats:empty { display: none; }
.gdm-stats .equip-stat {
  border: 0;
  padding: 3px 0;
  gap: 0.5rem;
}

/* 무기고가 그 축의 기본값을 대고 있다는 표식(자세한 내막은 title 툴팁). */
.gdm-stat__armory {
  margin-left: 5px;
  padding: 0 4px;
  border: 1px solid var(--border);
  border-radius: 3px;
  font-size: 0.62rem;
  color: var(--text-2);
  cursor: help;
}

/* 속성 저항 칩 — 0 인 학교는 서버가 안 내린다(해제 순간의 ▼ 만 is-zero 로 한 번 스친다). */
.gdm-resist {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 8px;
  margin-top: 6px;
}
.gdm-resist__chip {
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
  font-size: 0.72rem;
  color: var(--text-1);
}
.gdm-resist__chip.is-zero { opacity: 0.5; }
.gdm-resist__dot {
  align-self: center;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  flex: none;
}
.gdm-resist__label { color: var(--text-2); }
.gdm-resist__val {
  font-weight: 700;
  color: var(--text-0);
  font-variant-numeric: tabular-nums;
}

.gdm-train {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.015);
  font-size: 0.8rem;
}

.gdm-train b { color: var(--text-0); font-variant-numeric: tabular-nums; }

/* 훈련의 두 갈래("한 레벨" · "상한까지 즉시")를 한 묶음으로 오른쪽에 세운다. */
.gdm-train__actions {
  display: flex;
  align-items: center;
  gap: 6px;
}

/* 두 갈래는 **같은 행의 동급 액션**이라 크기가 같아야 한다. 기본 패딩이 갈려 있어서
   (--primary 7/14 = 행동 버튼 · --skip 4/10 = 공사 슬롯의 보조 버튼) 그냥 두면 31px vs
   25px 로 어긋난다. 여기서만 큰 쪽으로 맞춘다 — 전역 --skip 은 나란히 설 일이 없는
   보조 버튼이므로 작은 채로 남긴다. */
.gdm-train__actions .outpost-mini {
  padding: 7px 14px;
}

/* ── "상한까지 즉시" 확인 모달의 상세 슬롯 ──────────────────────────── */
.gdm-confirm {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 0.8rem;
}

.gdm-confirm__line {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
}

.gdm-confirm__k { color: var(--text-2); }

.gdm-confirm__v {
  color: var(--text-0);
  font-variant-numeric: tabular-nums;
}

.gdm-confirm__v small {
  margin-left: 4px;
  color: var(--text-2);
  font-size: 0.7rem;
}

/* 합계는 내역과 확실히 갈라 보이게 — 결국 사용자가 무는 값은 이 줄이다.
   구분선은 **행 전체**가 갖는다: 좌우 칸에 각각 그으면 flex gap 에서 끊겨
   선이 아니라 두 동강 난 얼룩으로 보인다. */
.gdm-confirm__line--total {
  margin-top: 2px;
  padding-top: 6px;
  border-top: 1px solid var(--border);
  font-weight: 700;
}

.gdm-confirm__line--total .gdm-confirm__k { color: var(--text-0); }
.gdm-confirm__line--total.is-short .gdm-confirm__v { color: var(--danger, #c86a6a); }

.gdm-confirm__mats {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-top: 6px;
}

.gdm-confirm__mats-title { color: var(--text-2); }

.gdm-mat-need {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  font-variant-numeric: tabular-nums;
}

.gdm-mat-need b { color: var(--text-0); font-weight: 700; }
.gdm-mat-need small { color: var(--text-2); font-size: 0.7rem; }

/* 모자란 재료는 붉게 — 왜 실패할지 누르기 전에 읽힌다(건물 카드와 같은 규칙). */
.gdm-mat-need.is-short b { color: var(--danger, #c86a6a); }

/* 12슬롯 미니 페이퍼돌 — 6×2 그리드. */
.gdm-doll {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 6px;
}

.gdm-slot {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  padding: 7px 4px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.02);
  color: var(--text-2);
  font-size: 0.68rem;
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s;
}

.gdm-slot .icon, .gdm-slot img { width: 22px; height: 22px; }
.gdm-slot__label { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }

.gdm-slot.is-empty .gdm-slot__icon { opacity: 0.4; filter: grayscale(1); }
.gdm-slot.is-filled { border-color: color-mix(in srgb, var(--accent) 45%, var(--border)); color: var(--text-0); }
.gdm-slot.is-locked { border-style: dashed; opacity: 0.5; }

.gdm-slot.is-active {
  border-color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent) inset;
  background: color-mix(in srgb, var(--accent) 9%, transparent);
  color: var(--text-0);
}


/* ===== community.css ===== */
/* 커뮤니티 팝업 — 페이스북 피드 스타일 게시판. */

.community-modal {
  position: fixed;
  inset: 0;
  z-index: 10000;
  display: flex;
  align-items: safe center;
  justify-content: safe center;
  overflow: auto;
  padding: 1rem;
}
.community-modal__backdrop {
  position: fixed;
  inset: 0;
  background: var(--overlay-backdrop);
  backdrop-filter: blur(3px);
}
.community-modal__panel {
  position: relative;
  width: min(46rem, 100%);
  max-height: calc(100vh - 3rem);
  display: flex;
  flex-direction: column;
  background: var(--bg-1);
  border: 1px solid rgba(var(--accent-rgb), 0.35);
  border-radius: var(--radius-lg);
  box-shadow: 0 1.5rem 3rem rgba(0, 0, 0, 0.6), 0 0 2rem rgba(var(--accent-rgb), 0.08);
  overflow: hidden;
  animation: community-in 180ms ease-out;
}
@keyframes community-in {
  from { opacity: 0; transform: translateY(1rem) scale(0.97); }
  to   { opacity: 1; transform: none; }
}
.community-modal__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.75rem 1rem;
  border-bottom: 1px solid var(--border);
  background: var(--bg-2);
}
.community-modal__title { font-size: 1.05rem; color: var(--text-0); font-weight: bold; }
.community-modal__close {
  background: transparent;
  border: 0;
  color: var(--text-2);
  font-size: 1.2rem;
  cursor: pointer;
}
.community-modal__close:hover { color: var(--accent-hi); }
.community-modal__body {
  padding: 1rem;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

/* ── 새 글 작성 폼 ─────────────────────────────────────────────── */

.community-compose {
  display: flex;
  gap: 0.5rem;
  align-items: flex-end;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 0.6rem;
}
.community-compose textarea {
  flex: 1;
  background: var(--bg-0);
  border: 1px solid var(--border);
  color: var(--text-0);
  padding: 0.55rem 0.65rem;
  border-radius: var(--radius-sm);
  resize: vertical;
  font-family: inherit;
  font-size: 0.92rem;
  min-height: 2.5rem;
  max-height: 8rem;
}
.community-compose button {
  background: var(--accent);
  color: var(--bg-0);
  border: 0;
  padding: 0.55rem 1rem;
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-weight: bold;
  white-space: nowrap;
}
.community-compose button:hover:not(:disabled) { background: var(--accent-hi); }
.community-compose button:disabled { opacity: 0.5; cursor: not-allowed; }

/* 글쓰기 잠금(Lv.15 미만) — 작성 폼은 흐리게, 안내문은 폼 하단 전체폭. */
.community-compose.is-locked { flex-wrap: wrap; }
.community-compose.is-locked textarea { opacity: 0.5; }
.community-compose__lock {
  flex-basis: 100%;
  margin: 0.1rem 0 0;
  color: var(--text-2);
  font-size: 0.82rem;
  text-align: center;
}

/* ── 피드 ──────────────────────────────────────────────────────── */

.community-feed { display: flex; flex-direction: column; gap: 0.75rem; }
.community-feed__loading,
.community-feed__empty {
  text-align: center;
  color: var(--text-2);
  padding: 2rem 1rem;
}

.community-post {
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 0.85rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.community-post.is-mine { border-color: rgba(var(--accent-rgb), 0.3); }
.community-post.is-highlight {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  transition: outline-color 200ms;
}

.community-post__head {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
}
.community-post__author { color: var(--text-0); font-weight: bold; }
.community-post__time   { color: var(--text-2); font-size: 0.78rem; }
.community-post__actions {
  margin-left: auto;
  display: inline-flex;
  gap: 0.35rem;
  opacity: 0;
  transition: opacity 120ms;
}
.community-post:hover .community-post__actions,
.community-post:focus-within .community-post__actions { opacity: 1; }
.community-post__actions button {
  background: transparent;
  border: 0;
  color: var(--text-2);
  font-size: 0.78rem;
  cursor: pointer;
  padding: 0.1rem 0.35rem;
}
.community-post__actions button:hover { color: var(--accent-hi); }
/* 「신고함」은 눌러도 소용없는 안내다 — 커서와 색으로 그 사실을 먼저 말한다. */
.community-post__actions button[disabled] {
  opacity: 0.55;
  cursor: default;
}
.community-post__actions button[disabled]:hover { color: var(--text-2); }

.community-post__body {
  color: var(--text-0);
  line-height: 1.6;
  white-space: pre-wrap;
  word-break: break-word;
}

/* ── 삭제된 글 자리표시자 ──────────────────────────────────────── */

.community-post.is-deleted {
  background: transparent;
  border-style: dashed;
  border-color: var(--border);
  padding: 0.6rem 0.8rem;
}
.community-post__deleted {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  color: var(--text-2);
  font-size: 0.88rem;
}
.community-post__deleted-icon { opacity: 0.7; }
.community-post__deleted-text { flex: 1; font-style: italic; }
/* 검토 중(신고 누적)과 확정 삭제는 다른 사건이다 — 테두리 색으로만 가른다.
   문구는 JS(PLACEHOLDER)가 소유하므로 여기서 ::after 로 덧붙이지 않는다. */
.community-post.is-hidden  { border-color: rgba(var(--accent-rgb), 0.45); }
.community-post.is-removed { border-color: rgba(var(--danger-rgb), 0.45); }

/* ── 신고 폼(카드 안에서 펼쳐진다) ─────────────────────────────── */

.community-report {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin-top: 0.35rem;
  padding: 0.7rem;
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}
.community-report__lead {
  margin: 0;
  color: var(--text-1);
  font-size: 0.85rem;
}
.community-report__reasons {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}
.community-report__reason {
  display: flex;
  align-items: flex-start;
  gap: 0.4rem;
  color: var(--text-1);
  font-size: 0.85rem;
  line-height: 1.45;
  cursor: pointer;
}
.community-report__reason input { margin-top: 0.25rem; flex: none; }
.community-report__reason:hover { color: var(--text-0); }
.community-report__detail {
  background: var(--bg-2);
  color: var(--text-0);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0.4rem 0.55rem;
  font: inherit;
  font-size: 0.85rem;
}
.community-report__note {
  margin: 0;
  color: var(--text-2);
  font-size: 0.78rem;
}
.community-report__actions {
  display: flex;
  justify-content: flex-end;
  gap: 0.4rem;
}
.community-report__actions button {
  background: var(--bg-2);
  color: var(--text-1);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0.3rem 0.75rem;
  font-size: 0.83rem;
  cursor: pointer;
}
.community-report__actions button[type="submit"] {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--bg-0);
}
.community-report__actions button:disabled { opacity: 0.5; cursor: not-allowed; }

/* ── 페이지 이동 ───────────────────────────────────────────────── */

.community-pager {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 1rem;
  color: var(--text-2);
  font-size: 0.85rem;
  padding: 0.5rem 0;
}
/* 🔴 `display:flex` 는 UA 의 `[hidden]{display:none}` 을 이긴다. JS 가 `pager.hidden = true`
   로 꺼도 「1 / 1」 + 비활성 버튼 줄이 그대로 남으므로 여기서 한 번에 막는다.
   (모달별 사본을 두면 새 모달이 생길 때마다 같은 함정을 다시 밟는다.) */
.community-pager[hidden] { display: none; }
.community-pager button {
  background: var(--bg-2);
  color: var(--text-1);
  border: 1px solid var(--border);
  padding: 0.35rem 0.8rem;
  border-radius: var(--radius-sm);
  cursor: pointer;
}
.community-pager button:disabled { opacity: 0.4; cursor: not-allowed; }

/* ── 닉네임 변경 모달 ──────────────────────────────────────────── */

.nickname-modal { /* community-modal 과 동일 레이아웃 사용 */ }
.nickname-form  { display: flex; flex-direction: column; gap: 0.75rem; }
.nickname-form .field { display: flex; flex-direction: column; gap: 0.3rem; }
.nickname-form .field label { color: var(--text-1); font-size: 0.85rem; }
.nickname-form .field input {
  background: var(--bg-0);
  border: 1px solid var(--border);
  color: var(--text-0);
  padding: 0.55rem 0.65rem;
  border-radius: var(--radius-sm);
  font-family: inherit;
  font-size: 0.95rem;
}
/* ⚠ 셀렉터가 `.nickname-form .notice` 였는데 마크업은 이 문단을 폼 **바깥**(형제)에 둔다 —
   그래서 규칙이 한 번도 맞지 않았고 안내 4줄이 붙어서 한 문단으로 흘렀다. 실제 클래스로
   고친다. (같은 규칙의 비밀번호 모달은 .notice 가 폼 안에 있어 멀쩡했다) */
.nickname-notice {
  background: rgba(var(--accent-rgb), 0.06);
  border: 1px solid rgba(var(--accent-rgb), 0.25);
  border-radius: var(--radius-sm);
  padding: 0.6rem 0.75rem;
  color: var(--text-1);
  font-size: 0.85rem;
  line-height: 1.55;
  white-space: pre-line;
}
.nickname-form .actions { display: flex; justify-content: flex-end; gap: 0.5rem; }
.nickname-form .actions button {
  padding: 0.5rem 1rem;
  border-radius: var(--radius-sm);
  cursor: pointer;
  border: 0;
  font-weight: bold;
}
.nickname-form .actions button[data-action="cancel"] {
  background: var(--bg-2);
  color: var(--text-1);
  border: 1px solid var(--border);
}
.nickname-form .actions button[type="submit"] {
  background: var(--accent);
  color: var(--bg-0);
}
.nickname-form .actions button:disabled { opacity: 0.5; cursor: not-allowed; }
.nickname-current { color: var(--text-2); font-size: 0.85rem; }
.nickname-current strong { color: var(--text-0); font-weight: bold; }

/* ── 1:1 문의 배너(우측 패널) + 문의 팝업 ──────────────────────────────────
   팝업은 .community-modal 셸을 그대로 쓴다(닉네임·활동기록 모달과 같은 방식) —
   새 CSS 파일을 만들지 않는 이유는 core.bundle.css 목록을 건드리지 않기 위해서다. */

.support-banner__lead {
  color: var(--text-2);
  font-size: 0.8rem;
  line-height: 1.5;
  margin: 0 0 0.55rem;
}
.support-banner__guest {
  color: var(--text-2);
  font-size: 0.8rem;
  line-height: 1.55;
  margin: 0 0 0.55rem;
}
.support-banner__btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  width: 100%;
  padding: 0.5rem 0.6rem;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text-0);
  font-family: inherit;
  font-size: 0.85rem;
  font-weight: bold;
  cursor: pointer;
  text-decoration: none;
}
.support-banner__btn:hover { background: var(--hover-bg-2); border-color: var(--accent); }
.support-banner__btn--ghost { font-weight: normal; color: var(--text-1); }
/* 배지는 JS 가 el.hidden 으로 껐다 켠다 — 저자 display 를 두지 않아야 [hidden] 이 이긴다. */
.support-banner__badge {
  padding: 0.1rem 0.4rem;
  border-radius: 999px;
  background: var(--accent);
  color: var(--bg-0);
  font-size: 0.7rem;
  font-weight: bold;
  white-space: nowrap;
}

/* ── 팝업: 첫 화면 ─────────────────────────────────────────────────────── */

.inquiry-intro { display: flex; flex-direction: column; gap: 0.9rem; }

.inquiry-faq {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.75rem 0.85rem;
  background: rgba(var(--accent-rgb), 0.08);
  border: 1px solid rgba(var(--accent-rgb), 0.3);
  border-radius: var(--radius-sm);
  color: var(--text-0);
  text-decoration: none;
}
.inquiry-faq:hover { background: rgba(var(--accent-rgb), 0.14); }
.inquiry-faq__icon { font-size: 1.3rem; flex: none; }
.inquiry-faq__text { display: flex; flex-direction: column; gap: 0.15rem; flex: 1 1 auto; min-width: 0; }
.inquiry-faq__text strong { font-size: 0.9rem; color: var(--accent-hi); }
.inquiry-faq__text span { font-size: 0.78rem; color: var(--text-2); }
.inquiry-faq__go { flex: none; color: var(--accent); font-weight: bold; }

.inquiry-notice {
  padding: 0.7rem 0.8rem;
  background: var(--bg-0);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text-1);
  font-size: 0.82rem;
  line-height: 1.6;
}

.inquiry-intro__actions { display: flex; gap: 0.5rem; }
.inquiry-intro__actions .inquiry-btn { flex: 1 1 0; }

/* ── 팝업: 공용 버튼·네비 ──────────────────────────────────────────────── */

.inquiry-btn {
  padding: 0.55rem 0.9rem;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text-0);
  font-family: inherit;
  font-size: 0.88rem;
  font-weight: bold;
  cursor: pointer;
}
.inquiry-btn:hover { background: var(--hover-bg-2); }
.inquiry-btn:disabled { opacity: 0.5; cursor: not-allowed; }
.inquiry-btn--primary { background: var(--accent); border-color: var(--accent); color: var(--bg-0); }
.inquiry-btn--primary:hover { background: var(--accent-hi); }
.inquiry-btn--sm { padding: 0.3rem 0.6rem; font-size: 0.78rem; font-weight: normal; }

.inquiry-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  margin-bottom: 0.75rem;
}
.inquiry-back {
  background: none;
  border: 0;
  padding: 0.2rem 0;
  color: var(--text-2);
  font-family: inherit;
  font-size: 0.82rem;
  cursor: pointer;
}
.inquiry-back:hover { color: var(--accent); }

/* ── 팝업: 작성 폼 ─────────────────────────────────────────────────────── */

.inquiry-form { display: flex; flex-direction: column; gap: 0.75rem; }
.inquiry-form .field { display: flex; flex-direction: column; gap: 0.3rem; }
.inquiry-form .field label { color: var(--text-1); font-size: 0.85rem; }
.inquiry-form input,
.inquiry-form textarea {
  background: var(--bg-0);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0.55rem 0.65rem;
  color: var(--text-0);
  font-family: inherit;
  font-size: 0.92rem;
  resize: vertical;
}
.inquiry-form input:focus,
.inquiry-form textarea:focus { outline: none; border-color: var(--accent); }
.inquiry-count { align-self: flex-end; color: var(--text-2); font-size: 0.75rem; }
.inquiry-form .actions { display: flex; justify-content: flex-end; gap: 0.5rem; }
.inquiry-form--reply { flex-direction: row; align-items: flex-end; gap: 0.5rem; margin-top: 0.9rem; }
.inquiry-form--reply textarea { flex: 1 1 auto; min-width: 0; }

/* ── 팝업: 목록 ────────────────────────────────────────────────────────── */

.inquiry-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.45rem; }
.inquiry-row {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  width: 100%;
  padding: 0.65rem 0.75rem;
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text-0);
  font-family: inherit;
  text-align: left;
  cursor: pointer;
}
.inquiry-row:hover { background: var(--hover-bg); border-color: var(--accent); }
.inquiry-row.is-unread { border-color: rgba(var(--accent-rgb), 0.55); }
.inquiry-row__head { display: flex; align-items: center; gap: 0.4rem; }
.inquiry-row__no { color: var(--text-2); font-size: 0.75rem; }
.inquiry-row__new {
  padding: 0.05rem 0.35rem;
  border-radius: 999px;
  background: var(--accent);
  color: var(--bg-0);
  font-size: 0.65rem;
  font-weight: bold;
}
.inquiry-row__title { font-size: 0.9rem; font-weight: bold; }
.inquiry-row__meta { color: var(--text-2); font-size: 0.75rem; }

.inquiry-row__status {
  padding: 0.08rem 0.4rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: 0.7rem;
  white-space: nowrap;
}
.inquiry-row__status.is-open     { color: var(--accent);       border-color: rgba(var(--accent-rgb), 0.45); }
.inquiry-row__status.is-answered { color: var(--success-soft); border-color: rgba(181, 230, 196, 0.4); }
.inquiry-row__status.is-closed   { color: var(--text-2); }

/* ── 팝업: 스레드 ──────────────────────────────────────────────────────── */

.inquiry-thread__head {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.45rem;
  padding-bottom: 0.6rem;
  margin-bottom: 0.6rem;
  border-bottom: 1px solid var(--border);
  color: var(--text-0);
  font-size: 0.95rem;
}
.inquiry-thread__char { color: var(--text-2); font-size: 0.78rem; }

.inquiry-thread { display: flex; flex-direction: column; gap: 0.6rem; }
.inquiry-msg {
  padding: 0.6rem 0.75rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-1);
}
/* 운영자 답변은 한눈에 갈려야 한다 — 이 팝업을 여는 이유가 대개 그것이다. */
.inquiry-msg--admin {
  background: rgba(var(--accent-rgb), 0.07);
  border-color: rgba(var(--accent-rgb), 0.3);
}
.inquiry-msg__who {
  display: flex;
  align-items: baseline;
  gap: 0.45rem;
  margin-bottom: 0.3rem;
  color: var(--accent);
  font-size: 0.78rem;
  font-weight: bold;
}
.inquiry-msg--user .inquiry-msg__who { color: var(--text-2); }
.inquiry-msg__time { color: var(--text-2); font-size: 0.72rem; font-weight: normal; }
.inquiry-msg__body { color: var(--text-1); font-size: 0.88rem; line-height: 1.65; white-space: pre-wrap; }

.inquiry-closed {
  margin: 0.9rem 0 0;
  padding: 0.6rem;
  border: 1px dashed var(--border);
  border-radius: var(--radius-sm);
  color: var(--text-2);
  font-size: 0.82rem;
  text-align: center;
}

/* ── 1:1 문의: 이미지 첨부 ─────────────────────────────────────────────── */

.inquiry-picker { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.inquiry-picker__hint { color: var(--text-2); font-size: 0.75rem; }

.inquiry-thumbs { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.inquiry-thumbs:empty { display: none; }

/* 고르는 중인 미리보기 — 빼기 버튼과 용량을 얹는다. */
.inquiry-thumb {
  position: relative;
  width: 72px;
  height: 72px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  overflow: hidden;
  background: var(--bg-0);
}
.inquiry-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.inquiry-thumb__x {
  position: absolute;
  top: 2px; right: 2px;
  width: 18px; height: 18px;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.7);
  color: var(--text-0);
  font-size: 0.7rem;
  line-height: 1;
  cursor: pointer;
}
.inquiry-thumb__x:hover { background: var(--danger); }
.inquiry-thumb__size {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  padding: 1px 3px;
  background: rgba(0, 0, 0, 0.65);
  color: var(--text-1);
  font-size: 0.62rem;
  text-align: center;
}

/* 답글 폼은 첨부가 붙으면서 한 줄에서 두 층이 됐다 — 입력+보내기를 한 줄로 묶는다. */
.inquiry-form--reply { flex-direction: column; align-items: stretch; }
.inquiry-form--reply__row { display: flex; align-items: flex-end; gap: 0.5rem; }
.inquiry-form--reply__row textarea { flex: 1 1 auto; min-width: 0; }

/* 이미 올라간 첨부(스레드 안). 누르면 원본이 새 창으로 열린다. */
.inquiry-msg__imgs { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-top: 0.5rem; }
.inquiry-msg__img {
  display: block;
  width: 96px;
  height: 96px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  overflow: hidden;
  background: var(--bg-0);
}
.inquiry-msg__img:hover { border-color: var(--accent); }
.inquiry-msg__img img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* ===== icons.css ===== */
/*
 * 게임 아이콘 베이스 스타일.
 * 규칙: 흰 실루엣 SVG 를 CSS mask 로 받아 background-color 로 색칠한다.
 *       (구 <img> 폴백도 .icon 클래스 사이즈 규칙은 그대로 받는다.)
 * 자세한 규약은 docs/icon-style-guide.md 참고.
 */

.icon {
  display: inline-block;
  width: 1.25em;
  height: 1.25em;
  vertical-align: -0.18em;
  user-select: none;
  -webkit-user-drag: none;
  /* mask 베이스: --icon-src 가 지정된 <span> 은 흰 실루엣을 mask 로 받아
     background-color (= 현재 color) 로 칠해진다. <img> 폴백은 --icon-src 가
     없으므로 mask 효과 무시되고 그대로 그림이 그려진다. */
  background-color: currentColor;
  -webkit-mask: var(--icon-src) center/contain no-repeat;
          mask: var(--icon-src) center/contain no-repeat;
  color: var(--icon-default, #ffffff);
  object-fit: contain;
}

/* ── 골드 마크 ─────────────────────────────────────────────────────────
 * 이모지 🪙 는 색을 바꿀 수 없어 금색 버튼(--accent) 위에서 배경에 묻힌다.
 * mask 아이콘은 currentColor 로 칠해지므로, 옆 숫자와 같은 색을 따라간다:
 *   어두운 배경 + 금색 숫자 → 금색 코인 / 금색 버튼 + 짙은 글자 → 짙은 코인.
 * 어디에 놓든 대비가 확보되므로 배경별 예외 규칙이 필요 없다.
 *
 * 크기·정렬: 골드 마크는 메뉴 아이콘(.icon 기본 1.25em)이 아니라 **숫자 옆에 붙는 인라인 마크**다.
 * 1.25em 은 옆 숫자보다 커서 글줄이 튀고, 기본 vertical-align 로는 중심이 1.5px 떠올랐다.
 * 1em + -0.15em 이 글자 상자 중심과 0.3px 이내로 맞는다(브라우저 실측). */
.icon--gold {
  color: currentColor;
  width: 1em;
  height: 1em;
  vertical-align: -0.15em;
}

/* ── 등급별 색상 (장비/소비/잡템 공통, 8단계) ── */
.icon[data-rarity="junk"]      { color: #7a7e89; }
.icon[data-rarity="common"]    { color: #cfd3df; }
.icon[data-rarity="uncommon"]  { color: #5d9b6a; }
.icon[data-rarity="rare"]      { color: #5b88c8; }
.icon[data-rarity="epic"]      { color: #a35cc7; }
.icon[data-rarity="legendary"] { color: #d9a441; }
.icon[data-rarity="artifact"]  { color: #e6cc80; }
.icon[data-rarity="ancient"]   { color: #e68a00; }
.icon[data-rarity="unique"]    { color: #ff8000; }

/* ── 재료 (rarity=material) — sub_category 로 세분화 ── */
.icon[data-rarity="material"]                        { color: #9cd0c8; }
.icon[data-rarity="material"][data-subcat="alchemy"] { color: #76c89a; }
.icon[data-rarity="material"][data-subcat="armor"]   { color: #b08a6a; }
.icon[data-rarity="material"][data-subcat="weapon"]  { color: #c4a26a; }
.icon[data-rarity="material"][data-subcat="general"] { color: #9cd0c8; }

.icon--lg { width: 2em; height: 2em; vertical-align: -0.35em; }
.icon--xl { width: 3em; height: 3em; vertical-align: middle; }

/* ── 컨테이너별 명시적 사이즈 ──
 * 부모 컨테이너 font-size 가 큰(이모지 시절) 경우 em 계산이 과대해지므로
 * .icon 자체를 절대 단위(rem) 로 강제 고정한다. 이모지 폴백은 부모 font-size 를
 * 그대로 따르므로 시각 비율이 호환된다.
 */
.exp-event-card__icon .icon  { width: 3rem;   height: 3rem; }
.exp-farm__icon .icon        { width: 3.6rem; height: 3.6rem; }
.exp-monster__icon .icon     { width: 3.6rem; height: 3.6rem; }
.equip-portrait__icon .icon  { width: 3rem;   height: 3rem; }
.hero-card__icon .icon       { width: 2rem;   height: 2rem; }
.equip-slot__icon .icon      { width: 1.6rem; height: 1.6rem; }
.menu-tab__icon .icon        { width: 1.4rem; height: 1.4rem; vertical-align: -0.3em; }
.section-head__icon .icon    { width: 1.6rem; height: 1.6rem; }
.goal__icon .icon            { width: 1.6rem; height: 1.6rem; }
.char-card__icon .icon       { width: 2.4rem; height: 2.4rem; }
.class-card__icon .icon      { width: 2rem;   height: 2rem; }
.home__res .icon             { width: 1.1rem; height: 1.1rem; vertical-align: -0.18em; }
.home__menu-btn .icon        { width: 1.2rem; height: 1.2rem; vertical-align: -0.2em; }
.chars__logout-btn .icon     { width: 1.2rem; height: 1.2rem; vertical-align: -0.2em; }
.char-create__close .icon    { width: 1.1rem; height: 1.1rem; }
.exp-region-card__lock .icon { width: 1rem;   height: 1rem; vertical-align: -0.15em; }
.exp-region-card__mob .icon  { width: 1.2rem; height: 1.2rem; vertical-align: -0.2em; }

/* 등급/카테고리별 색상은 위쪽 [data-rarity]/[data-subcat] 셀렉터로 적용된다.
   UI/메뉴/슬롯/클래스/몬스터/지역 아이콘은 data-rarity 가 없으므로 기본 흰색. */

/* ===== item-tooltip.css ===== */
/* 공통 아이템 툴팁 — body 자식, 단일 인스턴스. position: absolute + 좌표 직접 지정. */

.item-tooltip {
  position: absolute;
  z-index: 10090;
  min-width: 14rem;
  max-width: min(20rem, calc(100vw - 1rem)); /* 폰: 뷰포트보다 넓어 클립되는 것 방지. */
  padding: 0.7rem 0.85rem;
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: 0 0.6rem 1.4rem rgba(0, 0, 0, 0.55);
  pointer-events: none; /* 호버 영역 점유 X */
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  animation: item-tooltip-in 100ms ease-out;
}
@keyframes item-tooltip-in {
  from { opacity: 0; transform: translateY(-0.2rem); }
  to   { opacity: 1; transform: none; }
}
.item-tooltip[hidden] { display: none; }

/* 등급별 보더 강조 — 상하좌우 동일 색·두께. 색은 tokens.css 의 --rarity-edge 단일 출처(세트=녹색 포함). */
.item-tooltip[data-rarity] { border: 2px solid var(--rarity-edge); }

/* 인라인 패널 — 호버 툴팁과 같은 본문(gearTooltipHtml)을 화면 안에 박아 쓸 때(예: 제작 결과).
 * 부유(浮遊) 전용 속성만 무효화하고 카드 스타일(테두리·등급색·정점 글로우)은 그대로 물려받는다. */
.item-tooltip--inline {
  position: static;
  z-index: auto;
  pointer-events: auto; /* 호버 툴팁은 none — 인라인은 텍스트 선택·클릭 가능해야 한다. */
  animation: none;      /* 등장 연출은 오버레이 패널이 이미 수행. */
  width: 100%;
  max-width: 100%;
  box-shadow: none;     /* 화면 안 요소라 떠 있는 그림자는 부자연스럽다. */
}

/* 수동 닫기(X) — 컨테이너가 pointer-events:none 이라 버튼만 auto 로 되살린다. */
.item-tooltip__close {
  position: absolute;
  top: 0.3rem;
  right: 0.35rem;
  width: 1.1rem;
  height: 1.1rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: 0;
  padding: 0;
  margin: 0;
  line-height: 1;
  font-size: 1rem;
  color: var(--text-2);
  cursor: pointer;
  pointer-events: auto;
  border-radius: var(--radius-sm);
}
.item-tooltip__close:hover,
.item-tooltip__close:focus-visible {
  color: var(--text-0);
  background: var(--bg-2);
  outline: none;
}

.item-tooltip__head {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding-right: 1.1rem; /* 우상단 X 버튼과 이름 겹침 방지. */
}
.item-tooltip__icon {
  width: 1.8rem;
  height: 1.8rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.item-tooltip__icon .icon { width: 1.6rem; height: 1.6rem; }

.item-tooltip__name {
  font-weight: 700;
  color: var(--text-0);
  font-size: 0.95rem;
}
.item-tooltip__name[data-rarity] { color: var(--rarity-color, var(--text-0)); }

.item-tooltip__sub {
  display: flex;
  gap: 0.4rem;
  font-size: 0.75rem;
  color: var(--text-2);
}
.item-tooltip__rarity {
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.item-tooltip__rarity[data-rarity] { color: var(--rarity-color, inherit); }

.item-tooltip__desc {
  font-size: 0.82rem;
  line-height: 1.5;
  color: var(--text-1);
}

.item-tooltip__effect {
  font-size: 0.78rem;
  color: var(--accent-hi);
  line-height: 1.5;
}
.item-tooltip__effect b { color: var(--text-0); }

.item-tooltip__meta {
  display: flex;
  gap: 0.6rem;
  font-size: 0.72rem;
  color: var(--text-2);
  border-top: 1px dashed var(--border);
  padding-top: 0.35rem;
  margin-top: 0.1rem;
}

/* ── 획득 단서(지명 비노출, 라벨 + 분위기 묘사) ──
   「그 밖의 쓰임」(영혼 봉인·장비 강화) 블록도 같은 규칙을 그대로 쓴다 — 서버가 두 축을 같은
   {kind,label,hint} 형태로 내려 주므로 표시도 갈라지면 안 된다. 구분용 hook 만
   .item-tooltip__sources--use 로 붙어 있고 전용 규칙은 두지 않는다(색·간격은 한 벌). */
.item-tooltip__sources {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  border-top: 1px dashed var(--border);
  padding-top: 0.35rem;
  margin-top: 0.1rem;
}
.item-tooltip__sources-head {
  font-size: 0.7rem;
  letter-spacing: 0.04em;
  color: var(--text-2);
}
.item-tooltip__source {
  font-size: 0.76rem;
  line-height: 1.45;
  color: var(--text-1);
}
.item-tooltip__source b { color: var(--accent-hi); font-weight: 600; }
.item-tooltip__source i { color: var(--text-2); font-style: italic; }
/* 상한(종류당 2개)에 잘린 나머지 개수. 라벨이 없는 꼬리줄이라 묘사 쪽에 맞춰 들여쓴다. */
.item-tooltip__source-more {
  font-size: 0.72rem;
  line-height: 1.35;
  color: var(--text-2);
  opacity: 0.8;
  padding-left: 0.9rem;
}

/* ── 제작 쓰임(이 재료를 쓰는 제작물, 등급색 칩) ── */
.item-tooltip__uses {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  border-top: 1px dashed var(--border);
  padding-top: 0.35rem;
  margin-top: 0.1rem;
}
.item-tooltip__uses-head {
  font-size: 0.7rem;
  letter-spacing: 0.04em;
  color: var(--text-2);
}
.item-tooltip__use-list {
  display: flex;
  flex-wrap: wrap;
  gap: 0.2rem 0.4rem;
}
.item-tooltip__use {
  font-size: 0.76rem;
  line-height: 1.4;
  /* 등급색은 data-rarity → tokens.css 의 --rarity-color cascade. */
  color: var(--rarity-color, var(--text-1));
}
.item-tooltip__use:not(:last-child)::after {
  content: "·";
  margin-left: 0.4rem;
  color: var(--text-2);
}
.item-tooltip__use-more {
  font-size: 0.76rem;
  line-height: 1.4;
  color: var(--text-2);
}

/* 세트 등급(녹색)은 tokens.css 의 [data-grade="set"] 가 --rarity-color/--rarity-edge 를
 * 녹색으로 덮어 위 규칙들이 자동 적용한다(별도 override 불필요). */

/* ── 필요 재료(이 완성품을 만드는 재료, 등급색 + 수량) ── */
.item-tooltip__recipe {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  border-top: 1px dashed var(--border);
  padding-top: 0.35rem;
  margin-top: 0.1rem;
}
.item-tooltip__recipe-head {
  font-size: 0.7rem;
  letter-spacing: 0.04em;
  color: var(--text-2);
}
.item-tooltip__recipe-out {
  color: var(--accent-hi);
}
.item-tooltip__recipe-list {
  display: flex;
  flex-wrap: wrap;
  gap: 0.2rem 0.5rem;
}
.item-tooltip__recipe-mat {
  font-size: 0.76rem;
  line-height: 1.4;
  white-space: nowrap;
  /* 등급색은 data-rarity → tokens.css 의 --rarity-color cascade(제작 쓰임 칩과 같은 규칙). */
  color: var(--rarity-color, var(--text-1));
}
.item-tooltip__recipe-mat b {
  margin-left: 0.2rem;
  font-weight: 600;
  color: var(--text-2);
}

/* ── 방어구 카드 ── */
.item-tooltip__armor {
  display: flex;
  flex-direction: column;
  gap: 0.18rem;
  font-size: 0.8rem;
  line-height: 1.45;
}
.item-tooltip__def {
  color: var(--text-1);
}
.item-tooltip__def b { color: var(--text-0); font-weight: 700; }
.item-tooltip__affix {
  color: #93b7e8; /* 접사는 푸른 계열로 통일(와우식 옵션 라인). */
}
/* 정점/우수 롤 표식 — 상위권 굴림 접사 강조. */
.item-tooltip__affix.is-highroll { color: #bfe3a8; }
.item-tooltip__affix.is-godroll  { color: #ffd24f; text-shadow: 0 0 6px rgba(255, 210, 79, 0.45); }
.item-tooltip__roll {
  font-size: 0.66rem; font-weight: 700; vertical-align: middle;
  padding: 0 0.28em; border-radius: 0.5em;
  background: rgba(150, 200, 120, 0.18); color: #bfe3a8;
}
.item-tooltip__roll--god { background: rgba(255, 210, 79, 0.2); color: #ffd24f; }
.item-tooltip__godroll-badge {
  font-size: 0.66rem; font-weight: 700; color: #ffd24f;
  margin-left: 0.3em; text-shadow: 0 0 6px rgba(255, 210, 79, 0.5);
}
.item-tooltip[data-god-roll="true"] {
  box-shadow: 0 0 0 1px rgba(255, 210, 79, 0.55), 0 0 14px rgba(255, 210, 79, 0.28);
}
.item-tooltip__unique {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  margin-top: 0.25rem;
  padding-top: 0.25rem;
  border-top: 1px dashed var(--border);
}
.item-tooltip__unique-head { color: #ff8a3d; font-weight: 700; }
.item-tooltip__unique-desc { color: var(--text-1); font-size: 0.76rem; }
.item-tooltip__set {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  margin-top: 0.25rem;
  padding-top: 0.25rem;
  border-top: 1px dashed var(--border);
}
.item-tooltip__set-name { color: #5fd36b; font-weight: 700; }
.item-tooltip__set-source { color: var(--text-2); font-size: 0.72rem; }
.item-tooltip__set-bonus { color: #5fd36b; font-size: 0.76rem; }
.item-tooltip__set-bonus.is-inactive { color: var(--text-2); opacity: 0.7; }
.item-tooltip__set-note { color: var(--text-2); font-size: 0.7rem; font-style: italic; }

/* 강화(인스턴스당 1개) — 등급색·고유효과와 구분되는 청록 톤. */
.item-tooltip__enhance {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  margin-top: 0.25rem;
  padding-top: 0.25rem;
  border-top: 1px dashed var(--border);
}
.item-tooltip__enhance-head { color: #4fd6c8; font-weight: 700; }
.item-tooltip__enhance-stat { color: var(--text-1); font-size: 0.76rem; }

/* 제작 보너스 옵션(§5.5) — 기본 접사와 구분되는 전용 슬롯. */
.item-tooltip__craftbonus {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  margin-top: 0.25rem;
  padding-top: 0.25rem;
  border-top: 1px dashed var(--border);
}
.item-tooltip__craftbonus-head { color: #d8a84f; font-weight: 700; }
.item-tooltip__craftbonus-stat { color: var(--text-1); font-size: 0.76rem; }

/* ===== talents.css ===== */
/* 특성 — 노드/트리 시각화 (talents-modal.js 팝업에서 재사용) */

.talents-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; flex-wrap: wrap;
}
.talents-head__title { display: flex; flex-direction: column; gap: 2px; }
.talents-head__title strong { font-size: 1.1rem; }
.talents-head__sub { color: var(--text-muted, #9aa); font-size: 0.8rem; }
.talents-head__points { display: flex; align-items: center; gap: 12px; }
.talents-pt {
  display: inline-flex; align-items: baseline; gap: 4px;
  padding: 6px 12px; border-radius: 8px;
  background: rgba(120, 200, 255, 0.08);
  border: 1px solid rgba(120, 200, 255, 0.25);
}
.talents-pt__label { font-size: 0.75rem; color: var(--text-muted, #9aa); }
.talents-pt__num { font-size: 1.4rem; font-weight: 700; color: #7ec8ff; }
.talents-pt__unit { font-size: 0.8rem; color: var(--text-muted, #9aa); }

.talents-reset-btn {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 8px 12px; border-radius: 8px;
  border: 1px solid rgba(255, 100, 100, 0.4);
  background: rgba(255, 100, 100, 0.06);
  color: #ffb0b0; font-weight: 600; cursor: pointer;
}
.talents-reset-btn:hover { background: rgba(255, 100, 100, 0.14); }
.talents-reset-btn__cost { font-size: 0.75rem; color: #ffd080; }

/* 가지 설명 배너 — 트리 상단, 활성 가지의 정체성 안내 */
.talents-branch-banner {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px;
  margin-bottom: 10px; padding: 10px 12px;
  border-radius: 10px;
  background: rgba(120, 200, 255, 0.06);
  border: 1px solid rgba(120, 200, 255, 0.18);
  border-left: 3px solid rgba(120, 200, 255, 0.55);
}
.talents-branch-banner__name {
  font-size: 1rem; font-weight: 700; color: #7ec8ff;
}
.talents-branch-banner__desc {
  flex-basis: 100%; margin: 2px 0 0;
  font-size: 0.82rem; line-height: 1.4;
  color: var(--text-muted, #9aa);
}

/* 트리 — 코어(상단 가로전체) / 가지 2행 / 캡스톤(하단 가로전체) */
.talents-tree { display: flex; flex-direction: column; gap: 6px; }

/* 선행→후행 연결선: 좌측 세로 스파인(코어→가지→캡스톤) + 각 가지로 갈라지는 가로 가지선 */
.talents-tree__branches {
  position: relative; display: flex; flex-direction: column; gap: 6px;
  padding-left: 22px;
}
.talents-tree__branches::before { /* 세로 스파인 — 코어/캡스톤 쪽으로 살짝 연장 */
  content: ""; position: absolute; left: 8px; top: -6px; bottom: -6px;
  width: 2px; background: rgba(120, 200, 255, 0.4); border-radius: 1px;
}
.talents-tree__branch { position: relative; display: flex; gap: 6px; align-items: stretch; }
.talents-tree__branch::before { /* 스파인 → 가지 첫 노드 가로 연결선 */
  content: ""; position: absolute; left: -14px; top: 50%;
  width: 14px; height: 2px; background: rgba(120, 200, 255, 0.4);
  transform: translateY(-1px);
}
.talents-tree__branch > .talents-node { flex: 1 1 0; min-width: 0; }

/* 가지 내 tier1 → tier2 화살표 */
.talents-arrow {
  flex: 0 0 auto; align-self: center;
  color: rgba(120, 200, 255, 0.7); font-size: 0.95rem; line-height: 1;
}

/* 노드 버튼 — 투자할 수 있는 "특성 버튼"임이 드러나도록 입체감 부여 */
.talents-node {
  display: flex; flex-direction: column; gap: 4px;
  padding: 10px; border-radius: 10px;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.07), rgba(255, 255, 255, 0.02));
  border: 1px solid rgba(255, 255, 255, 0.16);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06), 0 2px 5px rgba(0, 0, 0, 0.38);
  cursor: pointer; color: var(--text, #d6d6d6);
  position: relative;
  transition: transform 110ms ease, background 120ms, border-color 120ms, box-shadow 120ms;
  text-align: left;
}
.talents-node:hover {
  background: linear-gradient(180deg, rgba(120, 200, 255, 0.18), rgba(120, 200, 255, 0.05));
  border-color: rgba(120, 200, 255, 0.55);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 5px 12px rgba(120, 200, 255, 0.2);
  transform: translateY(-1px);
}
.talents-node:active {
  transform: translateY(1px);
  box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.45);
}
/* 코어/캡스톤 — 가로 전체 폭(트리 column 의 직계 자식이라 기본 stretch), 살짝 강조 */
.talents-node--wide {
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.03));
}
.talents-node__top { display: flex; align-items: center; justify-content: space-between; }
.talents-node__rank {
  font-size: 0.7rem; font-weight: 600; color: var(--text-muted, #9aa);
  background: rgba(0, 0, 0, 0.3); border-radius: 999px; padding: 1px 8px;
}
/* 아이콘 = 원형 "슬롯" 칩 — 눌러서 찍는 특성 슬롯 느낌 */
.talents-node__icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; border-radius: 50%;
  font-size: 1.05rem; line-height: 1;
  background: rgba(120, 200, 255, 0.12);
  border: 1px solid rgba(120, 200, 255, 0.32);
  box-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.12);
}
.talents-node:hover .talents-node__icon {
  background: rgba(120, 200, 255, 0.22);
  border-color: rgba(120, 200, 255, 0.55);
}
.talents-node__name { font-size: 0.85rem; font-weight: 600; line-height: 1.2; }
.talents-node__lvl {
  align-self: flex-end; font-size: 0.7rem; color: #ffce8a; white-space: nowrap;
  background: rgba(255, 200, 120, 0.1);
  padding: 1px 4px; border-radius: 3px;
}
.talents-node__desc {
  margin: 2px 0 0; font-size: 0.8rem; line-height: 1.35;
  color: var(--text-muted, #9aa);
}

/* 상태별 색상 */
.talents-node.is-invested {
  background: linear-gradient(180deg, rgba(120, 200, 255, 0.22), rgba(120, 200, 255, 0.08));
  border-color: rgba(120, 200, 255, 0.65);
}
.talents-node.is-invested .talents-node__rank { color: #bfe4ff; }
.talents-node.is-maxed {
  background: linear-gradient(180deg, rgba(255, 220, 120, 0.24), rgba(255, 220, 120, 0.08));
  border-color: rgba(255, 220, 120, 0.75);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 0 10px rgba(255, 220, 120, 0.18);
}
.talents-node.is-maxed .talents-node__icon {
  background: rgba(255, 220, 120, 0.2);
  border-color: rgba(255, 220, 120, 0.55);
}
.talents-node.is-maxed .talents-node__rank { color: #ffce8a; }
/* 잠금 — 버튼 느낌 제거(입체감·호버·커서 없음) */
.talents-node.is-locked {
  opacity: 0.5; cursor: default; box-shadow: none;
  background: rgba(255, 255, 255, 0.02);
}
.talents-node.is-locked:hover {
  background: rgba(255, 255, 255, 0.02);
  border-color: rgba(255, 255, 255, 0.16);
  box-shadow: none; transform: none;
}
.talents-node.is-locked:hover .talents-node__icon {
  background: rgba(120, 200, 255, 0.12);
  border-color: rgba(120, 200, 255, 0.32);
}
.talents-node.is-selected {
  outline: 2px solid rgba(120, 200, 255, 0.85);
  outline-offset: 1px;
}

/* 캡스톤 택1 선택 행 — 같은 스킬의 캡스톤 3종 중 하나만 투자 가능(상호배타) */
.talents-cap-choice {
  margin-top: 6px; padding: 8px; border-radius: 10px;
  background: rgba(255, 220, 120, 0.05);
  border: 1px dashed rgba(255, 220, 120, 0.35);
}
.talents-cap-choice__label {
  display: block; font-size: 0.72rem; font-weight: 600; letter-spacing: 0.02em;
  color: #ffce8a; margin-bottom: 6px; text-align: center;
}
.talents-cap-choice__row { display: flex; gap: 6px; align-items: stretch; }
.talents-cap-choice__row > .talents-node { flex: 1 1 0; min-width: 0; }

/* 파라곤 보드 — 엔드게임 무한 성장(공/방/유틸 3분기) */
.paragon-loading { padding: 24px; text-align: center; color: var(--text-muted, #9aa); }
.paragon-board { display: flex; flex-direction: column; gap: 12px; }
.paragon-board__head {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
}
.paragon-board__pts { font-size: 0.85rem; color: var(--text-muted, #9aa); }
.paragon-board__pts strong { font-size: 1.3rem; color: #ffce8a; margin: 0 2px; }
.paragon-board__pts em { font-style: normal; }
.paragon-board__locked {
  padding: 10px 12px; border-radius: 8px; font-size: 0.85rem; line-height: 1.5;
  color: var(--text-muted, #9aa);
  background: rgba(255, 255, 255, 0.03);
  border: 1px dashed rgba(255, 255, 255, 0.15);
}
.paragon-board__grid {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px;
}
.paragon-card {
  display: flex; flex-direction: column; gap: 6px;
  padding: 12px; border-radius: 10px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.1);
}
.paragon-card__name { font-size: 0.95rem; font-weight: 700; }
.paragon-card__desc { font-size: 0.8rem; line-height: 1.4; color: var(--text-muted, #9aa); }
.paragon-card__spent { font-size: 0.8rem; color: var(--text-muted, #9aa); }
.paragon-card__spent strong { color: #ffce8a; }
.paragon-card__eff {
  font-size: 0.8rem; line-height: 1.4; color: #8fd0ff;
  background: rgba(120, 200, 255, 0.08); border-radius: 6px; padding: 4px 6px;
}
.paragon-card .talent-modal__btn { margin-top: auto; }

/* 종류별 아이콘 색상 */
.talents-node[data-kind="skill_core"] .talents-node__icon { color: #9ccfff; }
.talents-node[data-kind="skill_capstone"] .talents-node__icon { color: #ffd070; }
.talents-node[data-kind="passive_trunk"] .talents-node__icon { color: #ffce8a; }

/* ===== 특성 팝업 (talents-modal.js) ===== */
.talent-modal {
  position: fixed; inset: 0; z-index: 10040;
  display: flex; align-items: safe center; justify-content: safe center;
  overflow: auto;
}
.talent-modal__backdrop {
  position: fixed; inset: 0;
  background: rgba(0, 0, 0, 0.6); backdrop-filter: blur(2px);
}
.talent-modal__panel {
  position: relative;
  flex-shrink: 0;
  width: min(720px, calc(max(100vw, var(--app-min-w)) - 32px));
  max-height: min(88vh, 760px);
  display: flex; flex-direction: column;
  background: #1a1d23; color: var(--text, #d6d6d6);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 14px; overflow: hidden;
}
.talent-modal__loading,
.talent-modal__error { padding: 32px; text-align: center; color: var(--text-muted, #9aa); }

.talent-modal__header {
  display: flex; align-items: center; gap: 12px;
  padding: 14px 16px; border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}
.talent-modal__title { font-size: 1.05rem; font-weight: 700; color: #fff; margin-right: auto; }
.talent-modal__close {
  flex: 0 0 auto; width: 30px; height: 30px; border-radius: 8px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  background: rgba(255, 255, 255, 0.04); color: var(--text, #d6d6d6);
  cursor: pointer; font-size: 0.9rem;
}
.talent-modal__close:hover { background: rgba(255, 255, 255, 0.1); }

/* 탭 — 스킬/패시브 그룹 */
.talent-modal__tabs {
  display: flex; flex-direction: column; gap: 8px;
  padding: 12px 16px; border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  background: rgba(255, 255, 255, 0.015);
}
.talent-modal__tab-group { display: flex; align-items: flex-start; gap: 8px; }
.talent-modal__tab-group-label {
  flex: 0 0 auto; padding-top: 6px; min-width: 38px;
  font-size: 0.8rem; font-weight: 700; letter-spacing: 0.06em;
  color: var(--text-muted, #9aa);
}
.talent-modal__tab-row { display: flex; flex-wrap: wrap; gap: 6px; }
.talent-modal__tab {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 10px; border-radius: 8px;
  border: 1px solid rgba(255, 255, 255, 0.1);
  background: rgba(255, 255, 255, 0.03); color: var(--text, #d6d6d6);
  cursor: pointer; font-size: 0.88rem;
}
.talent-modal__tab:hover { background: rgba(120, 200, 255, 0.08); border-color: rgba(120, 200, 255, 0.35); }
.talent-modal__tab.is-active {
  background: rgba(120, 200, 255, 0.14); border-color: rgba(120, 200, 255, 0.55); color: #fff;
}
.talent-modal__tab.is-locked { opacity: 0.5; }
.talent-modal__tab-pts {
  font-size: 0.72rem; font-weight: 700; color: #7ec8ff;
  background: rgba(120, 200, 255, 0.15); border-radius: 8px; padding: 0 6px;
}

/* 본문 — 선택된 가지 트리 */
.talent-modal__body { padding: 16px; overflow-y: auto; flex: 1 1 auto; }

/* 하단 상세 패널 */
.talent-modal__footer {
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  padding: 12px 16px; background: rgba(255, 255, 255, 0.015);
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  min-height: 56px;
}
.talent-modal__detail-empty { color: var(--text-muted, #9aa); font-size: 0.88rem; }
.talent-modal__detail-info { flex: 1 1 240px; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.talent-modal__detail-name { font-size: 0.95rem; font-weight: 700; color: #fff; }
.talent-modal__detail-meta { font-size: 0.8rem; color: var(--text-muted, #9aa); }
.talent-modal__detail-desc { font-size: 0.9rem; line-height: 1.4; }
.talent-modal__detail-hint {
  margin-top: 4px; font-size: 0.8rem; padding: 5px 8px; border-radius: 6px;
  color: var(--text-muted, #9aa); background: rgba(255, 255, 255, 0.03);
}
.talent-modal__detail-hint.is-warning { color: #ffb0b0; background: rgba(255, 100, 100, 0.08); }
.talent-modal__detail-actions { display: flex; gap: 8px; flex: 0 0 auto; }
.talent-modal__btn {
  padding: 8px 14px; border-radius: 8px; cursor: pointer; font-weight: 600; font-size: 0.9rem;
  border: 1px solid rgba(255, 255, 255, 0.15);
  background: rgba(255, 255, 255, 0.04); color: var(--text, #d6d6d6);
}
.talent-modal__btn:hover { background: rgba(255, 255, 255, 0.08); }
.talent-modal__btn:disabled { opacity: 0.4; cursor: not-allowed; }
.talent-modal__btn--primary {
  background: rgba(120, 200, 255, 0.15); border-color: rgba(120, 200, 255, 0.45); color: #9ccfff;
}
.talent-modal__btn--primary:hover { background: rgba(120, 200, 255, 0.25); }
.talent-modal__btn--danger {
  background: rgba(255, 100, 100, 0.08); border-color: rgba(255, 100, 100, 0.35); color: #ffb0b0;
}
.talent-modal__btn--danger:hover { background: rgba(255, 100, 100, 0.18); }


/* 전투 슬롯 위젯의 skill 슬롯 활성 상태 */
.hero-slot--skill.is-empty .hero-slot__icon { opacity: 0.5; }
.hero-slot--skill.is-locked { cursor: default; }

/* combat-slots 모달의 스킬 탭 */
.cslot-modal__tabs { display: flex; gap: 4px; margin-bottom: 10px; }
.cslot-modal__tab {
  padding: 6px 12px; border-radius: 6px;
  border: 1px solid rgba(255, 255, 255, 0.1);
  background: transparent; cursor: pointer; color: var(--text, #d6d6d6);
}
.cslot-modal__tab.is-active {
  background: rgba(120, 200, 255, 0.12);
  border-color: rgba(120, 200, 255, 0.45);
  color: #fff;
}
.cslot-modal__skill-pool { display: grid; grid-template-columns: repeat(2, 1fr); gap: 6px; max-height: 50vh; overflow-y: auto; }
.cslot-modal__skill {
  display: flex; align-items: center; gap: 10px;
  padding: 8px; border-radius: 8px; cursor: pointer;
  border: 1px solid rgba(255, 255, 255, 0.08);
  background: rgba(255, 255, 255, 0.03);
}
.cslot-modal__skill:hover { background: rgba(120, 200, 255, 0.08); }
.cslot-modal__skill.is-selected { border-color: rgba(120, 200, 255, 0.55); background: rgba(120, 200, 255, 0.14); }
.cslot-modal__skill.is-locked { opacity: 0.4; cursor: not-allowed; }
.cslot-modal__skill-meta { display: flex; flex-direction: column; gap: 2px; flex: 1; }
.cslot-modal__skill-name { font-size: 0.9rem; font-weight: 600; }
.cslot-modal__skill-desc { font-size: 0.8rem; color: var(--text-muted, #9aa); }

/* 연계 역할 배지 — 점화(setup) / 기폭(payoff) / 제어(무관). 서버 tr1_skill_combo_role 이 판정. */
.cslot-role {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 6px;
  border-radius: 999px;
  border: 1px solid currentColor;
  font-size: 0.68rem;
  font-weight: 700;
  line-height: 1.5;
  white-space: nowrap;          /* 뱃지는 절대 줄바꿈하지 않는다(tokens.css 배지 규약). */
  vertical-align: middle;
}
.cslot-role--prime   { color: #ffab5e; background: rgba(255, 171, 94, 0.12); }   /* 점화 = 불씨(주황) */
.cslot-role--payoff  { color: #6fd3d0; background: rgba(111, 211, 208, 0.12); }  /* 기폭 = 폭발(청록) */
.cslot-role--control { color: #9aa4b2; background: rgba(154, 164, 178, 0.12); }  /* 제어 = 중립(회색) */
.cslot-role--chain   { color: #ff8ad4; background: rgba(255, 138, 212, 0.14); } /* 연쇄 = 다중 기폭(자홍) */

/* ===== mypage.css ===== */
/* 마이페이지(/mypage) — 계정·닉네임·캐릭터 요약·진행 위젯·활동 기록·비밀번호.
   읽기 데이터는 서버 렌더, 토큰(tokens.css)·패널(.panel.panel--section) 재사용. */

/* ── 공용 버튼 (마이페이지 한정) ─────────────────────────────── */
.mypage-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.5rem 1rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  font-weight: 600;
  font-size: 0.9rem;
  cursor: pointer;
  transition: background 140ms ease, border-color 140ms ease, color 140ms ease;
}
.mypage-btn--ghost { background: transparent; color: var(--text-1); }
.mypage-btn--ghost:hover { background: var(--bg-2); color: var(--text-0); }
.mypage-btn--primary { background: var(--accent); color: #1a1107; border-color: var(--accent-hi); }
.mypage-btn--primary:hover { background: var(--accent-hi); }
.mypage-btn:disabled { opacity: 0.5; cursor: not-allowed; }

/* ── 계정 정보 ──────────────────────────────────────────────── */
.mypage-account { margin: 0; display: grid; gap: 0.15rem; }
.mypage-account__row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  padding: 0.55rem 0.25rem;
  border-bottom: 1px solid var(--border);
}
.mypage-account__row:last-child { border-bottom: none; }
.mypage-account__label { margin: 0; color: var(--text-2); font-size: 0.86rem; }
.mypage-account__value { margin: 0; color: var(--text-0); font-weight: 600; text-align: right; word-break: break-all; }
.mypage-account__actions { margin-top: 0.9rem; display: flex; justify-content: flex-end; gap: 0.5rem; flex-wrap: wrap; }

/* ── 닉네임 변경 ────────────────────────────────────────────── */
.mypage-nickname { display: flex; flex-direction: column; align-items: flex-start; gap: 0.5rem; }
.mypage-nickname__current { color: var(--text-1); }
.mypage-nickname__current strong { color: var(--accent-hi); }
.mypage-nickname__remaining { color: var(--text-2); font-size: 0.88rem; }
.mypage-nickname__remaining strong { color: var(--text-0); }
.mypage-nickname__hint { margin: 0.1rem 0 0.5rem; color: var(--text-2); font-size: 0.82rem; line-height: 1.5; }

/* ── 캐릭터 요약 카드 ───────────────────────────────────────── */
.mypage-charcard {
  display: flex;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
  padding: 0.5rem 0.25rem;
}
.mypage-charcard__portrait {
  flex: none;
  display: grid;
  place-items: center;
  width: 4.5rem;
  height: 4.5rem;
  border-radius: var(--radius-md);
  background: var(--bg-0);
  border: 1px solid var(--border);
}
.mypage-charcard__id { flex: 1 1 auto; min-width: 0; }
.mypage-charcard__name { font-size: 1.15rem; font-weight: 700; color: var(--text-0); }
.mypage-charcard__meta { color: var(--text-2); font-size: 0.88rem; margin-top: 0.1rem; }
.mypage-charcard__power { margin-top: 0.3rem; color: var(--text-1); }
.mypage-charcard__power b { color: var(--accent-hi); }
.mypage-charcard__btn { flex: none; }

/* ── 진행 위젯 그리드 ───────────────────────────────────────── */
.mypage-widgets {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: 0.85rem;
}
.mypage-widget {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  padding: 0.9rem;
  border-radius: var(--radius-md);
  background: var(--bg-0);
  border: 1px solid var(--border);
}
.mypage-widget--locked { opacity: 0.7; }
.mypage-widget__title {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-weight: 600;
  color: var(--text-1);
  font-size: 0.92rem;
}
.mypage-widget__value { font-size: 1.25rem; font-weight: 700; color: var(--text-0); }
.mypage-widget__unit { font-size: 0.82rem; font-weight: 500; color: var(--text-2); }
.mypage-widget__sub { margin-top: 0.15rem; font-size: 0.82rem; color: var(--text-2); }
.mypage-widget__badge {
  margin-left: 0.4rem;
  padding: 0.05rem 0.4rem;
  border-radius: var(--radius-sm);
  background: var(--danger);
  color: var(--text-0);
  font-size: 0.7rem;
  font-weight: 700;
  vertical-align: middle;
  --fx-attn-rgb: var(--danger-rgb);
  animation: fx-attn-pulse var(--fx-attn-dur) ease-in-out infinite;
}
.mypage-widget__row { color: var(--text-1); font-size: 0.86rem; }
.mypage-widget__row--muted { color: var(--text-2); }

/* 진행도 바(도감 수집률 등) */
.mypage-progress {
  height: 0.4rem;
  border-radius: var(--radius-sm);
  background: var(--bg-1);
  border: 1px solid var(--border);
  overflow: hidden;
}
.mypage-progress__fill {
  height: 100%;
  border-radius: inherit;
  background: linear-gradient(90deg, var(--accent), var(--accent-hi));
  transition: width 240ms ease;
}
.mypage-widget__link {
  margin-top: auto;
  padding-top: 0.3rem;
  color: var(--accent-hi);
  font-size: 0.84rem;
  text-decoration: none;
}
.mypage-widget__link:hover { text-decoration: underline; }
.mypage-widget__locked-text { display: flex; align-items: center; gap: 0.4rem; color: var(--text-2); font-size: 0.88rem; }

/* ── 보급/최근 목록(위젯 내부) ──────────────────────────────── */
.mypage-supply { list-style: none; margin: 0.2rem 0 0; padding: 0; display: grid; gap: 0.3rem; }
.mypage-supply__item {
  display: flex;
  justify-content: space-between;
  gap: 0.6rem;
  font-size: 0.82rem;
  color: var(--text-1);
}
.mypage-supply__item--claimed { color: var(--text-2); }
.mypage-supply__label { color: var(--text-1); }
.mypage-supply__item--claimed .mypage-supply__label { color: var(--text-2); }
.mypage-supply__state { text-align: right; color: var(--text-2); }

/* ── 최근 활동 기록 ─────────────────────────────────────────── */
.mypage-activity__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.1rem; }
.mypage-activity__item {
  display: flex;
  gap: 0.75rem;
  padding: 0.45rem 0.25rem;
  border-bottom: 1px solid var(--border);
  font-size: 0.88rem;
}
.mypage-activity__item:last-child { border-bottom: none; }
.mypage-activity__time { flex: none; width: 5.5rem; color: var(--text-2); font-variant-numeric: tabular-nums; }
.mypage-activity__msg { color: var(--text-1); }
.mypage-activity__item[data-kind="levelup"] .mypage-activity__msg { color: var(--accent-hi); font-weight: 600; }
.mypage-activity__item[data-kind="loot"] .mypage-activity__msg,
.mypage-activity__item[data-kind="reward"] .mypage-activity__msg { color: var(--text-0); }
.mypage-activity__empty { color: var(--text-2); padding: 0.5rem 0.25rem; }

/* ── 비밀번호 변경 모달 폼 (password.js, community-modal 셸 재사용) ── */
/* 입력칸 3개뿐이라 기본 패널(min(46rem))은 과하게 넓다 → 좁게 재정의. */
.password-modal .community-modal__panel { width: min(26rem, 100%); }
.password-form { display: flex; flex-direction: column; gap: 0.75rem; }
.password-form .field { display: flex; flex-direction: column; gap: 0.3rem; }
.password-form .field label { color: var(--text-1); font-size: 0.85rem; }
.password-form .field input {
  background: var(--bg-0);
  border: 1px solid var(--border);
  color: var(--text-0);
  padding: 0.55rem 0.65rem;
  border-radius: var(--radius-sm);
  font-family: inherit;
  font-size: 0.95rem;
}
.password-form .field input:focus { outline: none; border-color: var(--accent); }
.password-form .notice {
  background: rgba(var(--accent-rgb), 0.06);
  border: 1px solid rgba(var(--accent-rgb), 0.25);
  border-radius: var(--radius-sm);
  padding: 0.6rem 0.75rem;
  color: var(--text-1);
  font-size: 0.85rem;
  line-height: 1.55;
}
.password-form .actions { display: flex; justify-content: flex-end; gap: 0.5rem; }
.password-form .actions button {
  padding: 0.5rem 1rem;
  border-radius: var(--radius-sm);
  cursor: pointer;
  border: 0;
  font-weight: bold;
}
.password-form .actions button[data-action="cancel"] {
  background: var(--bg-2);
  color: var(--text-1);
  border: 1px solid var(--border);
}
.password-form .actions button[type="submit"] { background: var(--accent); color: var(--bg-0); }
.password-form .actions button:disabled { opacity: 0.5; cursor: not-allowed; }

/* ── 활동 기록 "더보기" 버튼 ─────────────────────────────────── */
.mypage-activity__more {
  margin-top: 0.6rem;
  width: 100%;
  background: var(--bg-2);
  color: var(--text-1);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0.5rem;
  cursor: pointer;
  font-size: 0.85rem;
}
.mypage-activity__more:hover { color: var(--accent-hi); border-color: rgba(var(--accent-rgb), 0.4); }

/* ── 활동 기록 팝업 (activity-log-modal.js / major-log-modal.js — community-modal 셸 재사용) ── */
.activity-log-modal .community-modal__panel { width: min(36rem, 100%); }
.activity-log-feed { display: flex; flex-direction: column; gap: 0.1rem; }
.activity-log-row {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  padding: 0.45rem 0.25rem;
  border-bottom: 1px solid var(--border);
  font-size: 0.88rem;
}
.activity-log-row:last-child { border-bottom: none; }
.activity-log-row__time { flex: none; width: 5.5rem; color: var(--text-2); font-variant-numeric: tabular-nums; }
.activity-log-row__msg { color: var(--text-1); word-break: break-word; }

/* 주요 활동 행 — 카테고리 배지 + 강조. */
.major-log-row { gap: 0.5rem; }
.major-log-row__badge {
  flex: none;
  align-self: center;
  min-width: 3.6rem;
  text-align: center;
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--accent-hi);
  background: rgba(var(--accent-rgb), 0.1);
  border: 1px solid rgba(var(--accent-rgb), 0.3);
  border-radius: var(--radius-sm);
  padding: 0.1rem 0.4rem;
}
.major-log-row .activity-log-row__msg { color: var(--text-0); }

/* ── 비회원(게스트) 계정 안내 ──────────────────────────────────────────
   마이페이지가 게스트에게 보이는 유일한 계정 안내다(시작 모달은 한 번뿐이므로). */
.mypage-account__value--warn { color: var(--danger-soft); }

.mypage-guest {
  margin: 0.75rem 0 0;
  padding: 0.75rem 0.9rem;
  border: 1px solid var(--danger);
  border-radius: var(--radius-sm);
  background: rgba(var(--danger-rgb), 0.12);
  font-size: 0.84rem;
  line-height: 1.6;
  color: var(--text-1);
}
.mypage-guest b { color: var(--danger-soft); }

/* ===== combat-fx.css ===== */
/* 연계 반응(시너지) 연출 — combat-fx.js 가 document.body 에 부착하는 요소들.
   던전·첨탑·파티 전 전투 화면 공통(번들 로드). 순수 연출. */

/* 대상 노드 글로우 버스트(짧은 강조). */
.rx-burst {
  animation: rx-burst-glow 700ms ease-out;
}
@keyframes rx-burst-glow {
  0%   { filter: brightness(1); }
  25%  { filter: brightness(1.9) saturate(1.4); }
  100% { filter: brightness(1); }
}

/* 반응 이름 + 피해 팝(대상 위로 떠오름). */
.rx-pop {
  position: fixed;
  z-index: 11000; /* 탐험 오버레이(z10000) 위 — 연계 연출이 패널 뒤로 가려지지 않도록 */
  transform: translate(-50%, -50%);
  pointer-events: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.1rem;
  white-space: nowrap;
  animation: rx-pop-rise 1100ms cubic-bezier(0.2, 1, 0.3, 1) forwards;
  text-align: center;
}
.rx-pop__name {
  font-weight: 800;
  font-size: 1.05rem;
  color: var(--rx-color, #ffaa00);
  text-shadow: 0 0 0.5rem var(--rx-color, #ffaa00), 0 1px 2px rgba(0, 0, 0, 0.8);
}
.rx-pop__dmg {
  font-weight: 900;
  font-size: 1.5rem;
  color: #fff;
  text-shadow: 0 0 0.6rem var(--rx-color, #ffaa00), 0 2px 3px rgba(0, 0, 0, 0.9);
}
@keyframes rx-pop-rise {
  0%   { opacity: 0; transform: translate(-50%, -30%) scale(0.6); }
  20%  { opacity: 1; transform: translate(-50%, -60%) scale(1.15); }
  55%  { opacity: 1; transform: translate(-50%, -85%) scale(1); }
  100% { opacity: 0; transform: translate(-50%, -150%) scale(0.95); }
}

/* 파티클 버스트(중심에서 방사). */
.rx-particle {
  position: fixed;
  z-index: 10999;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  pointer-events: none;
  transform: translate(-50%, -50%);
  animation: rx-particle-fly 820ms ease-out forwards;
  box-shadow: 0 0 0.4rem currentColor;
}
@keyframes rx-particle-fly {
  0%   { opacity: 1; transform: translate(-50%, -50%) scale(1); }
  100% { opacity: 0; transform: translate(calc(-50% + var(--rx-dx, 0)), calc(-50% + var(--rx-dy, 0))) scale(0.2); }
}

/* 데미지 숫자 — 일러스트 곳곳에 무작위 각도(--dmg-rot)로 "빵" 터지며 제자리 소멸(combat-fx.js floatDamage). */
.dmg-pop {
  position: fixed;
  z-index: 11000; /* 탐험 오버레이(z10000)·뉴스티커(z10030) 위, 라이트박스(z12000) 아래 */
  transform: translate(-50%, -50%) rotate(var(--dmg-rot, 0deg));
  pointer-events: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.02rem;
  white-space: nowrap;
  text-align: center;
  animation: dmg-pop-burst 640ms cubic-bezier(0.2, 1.5, 0.35, 1) forwards;
}
.dmg-pop__num {
  font-weight: 900;
  font-size: 1.8rem;
  line-height: 1;
  color: var(--dmg-color, #fff);
  text-shadow:
    0 0 0.4rem rgba(0, 0, 0, 0.95),
    0 0 0.7rem var(--dmg-color, #fff),
    0 2px 3px rgba(0, 0, 0, 0.9);
}
.dmg-pop--crit {
  animation: dmg-pop-burst-crit 760ms cubic-bezier(0.18, 1.6, 0.3, 1) forwards;
}
.dmg-pop--crit .dmg-pop__num {
  font-size: 2.7rem;
  -webkit-text-stroke: 1px rgba(0, 0, 0, 0.5);
}
.dmg-pop__crit-tag {
  font-weight: 900;
  font-size: 0.92rem;
  letter-spacing: 0.06em;
  color: #fff;
  text-shadow: 0 0 0.5rem var(--dmg-color, #ffd166), 0 1px 2px rgba(0, 0, 0, 0.9);
}
/* 일반: 작게 → 큰 오버슈트(빵) → 안착 → 제자리 페이드(상승 없음, 기울기 유지). */
@keyframes dmg-pop-burst {
  0%   { opacity: 0; transform: translate(-50%, -50%) rotate(var(--dmg-rot, 0deg)) scale(0.2); }
  22%  { opacity: 1; transform: translate(-50%, -50%) rotate(var(--dmg-rot, 0deg)) scale(1.35); }
  40%  {            transform: translate(-50%, -50%) rotate(var(--dmg-rot, 0deg)) scale(0.92); }
  56%  { opacity: 1; transform: translate(-50%, -50%) rotate(var(--dmg-rot, 0deg)) scale(1.06); }
  72%  { opacity: 1; transform: translate(-50%, -50%) rotate(var(--dmg-rot, 0deg)) scale(1); }
  100% { opacity: 0; transform: translate(-50%, -50%) rotate(var(--dmg-rot, 0deg)) scale(1.04); }
}
/* 크리: 더 큰 폭발 + 좌우 흔들림(빵빵) 후 제자리 페이드. */
@keyframes dmg-pop-burst-crit {
  0%   { opacity: 0; transform: translate(-50%, -50%) rotate(var(--dmg-rot, 0deg)) scale(0.2); }
  18%  { opacity: 1; transform: translate(-50%, -50%) rotate(var(--dmg-rot, 0deg)) scale(1.7); }
  30%  {            transform: translate(-54%, -50%) rotate(var(--dmg-rot, 0deg)) scale(1.12); }
  42%  {            transform: translate(-46%, -50%) rotate(var(--dmg-rot, 0deg)) scale(1.3); }
  56%  {            transform: translate(-50%, -50%) rotate(var(--dmg-rot, 0deg)) scale(1); }
  72%  { opacity: 1; transform: translate(-50%, -50%) rotate(var(--dmg-rot, 0deg)) scale(1.07); }
  100% { opacity: 0; transform: translate(-50%, -50%) rotate(var(--dmg-rot, 0deg)) scale(1.1); }
}

/* 반응 발동 큰 글자 스탬프 — 반응명이 화면 중앙 상단에 속성색으로 "펑" 박혔다 사라진다.
   오버드라이브 텍스트(중앙 45%·4.5rem·11001)의 축소판: 상단 34%·작은 폰트·11000. */
.rx-stamp {
  position: fixed;
  top: 34%;
  left: 0;
  right: 0;
  z-index: 11000;
  pointer-events: none;
  display: flex;
  justify-content: center;
}
.rx-stamp__text {
  font-weight: 900;
  font-size: clamp(1.6rem, 5.5vw, 3.2rem);
  letter-spacing: 0.04em;
  color: var(--rx-stamp-color, #ffaa00);
  text-shadow: 0 0 1rem var(--rx-stamp-color, #ffaa00), 0 0 2rem rgba(0, 0, 0, 0.6), 0 3px 6px rgba(0, 0, 0, 0.9);
  -webkit-text-stroke: 1px rgba(0, 0, 0, 0.55);
  animation: rx-stamp-punch 850ms cubic-bezier(0.2, 1.5, 0.4, 1) forwards;
}
@keyframes rx-stamp-punch {
  0%   { transform: scale(0.4) rotate(-5deg); opacity: 0; }
  28%  { transform: scale(1.2) rotate(3deg); opacity: 1; }
  50%  { transform: scale(0.98) rotate(-1deg); opacity: 1; }
  72%  { transform: scale(1) rotate(0); opacity: 1; }
  100% { transform: scale(1.03) rotate(0); opacity: 0; }
}

/* 합동 폭발(OVERDRIVE) — 전체 화면 플래시 + 텍스트. */
.rx-overdrive {
  position: fixed;
  inset: 0;
  z-index: 11001;
  pointer-events: none;
  display: flex;
  align-items: center;
  justify-content: center;
  background: radial-gradient(circle at 50% 45%, rgba(255, 170, 0, 0.28) 0%, rgba(255, 90, 40, 0.12) 35%, transparent 70%);
  animation: rx-overdrive-fade 1300ms ease-out forwards;
}
.rx-overdrive__text {
  font-weight: 900;
  font-size: clamp(2rem, 8vw, 4.5rem);
  letter-spacing: 0.1em;
  color: #fff;
  text-shadow: 0 0 1.2rem #ffaa00, 0 0 2.4rem #ff5a28, 0 3px 6px rgba(0, 0, 0, 0.9);
  animation: rx-overdrive-pop 1300ms cubic-bezier(0.2, 1.5, 0.4, 1) forwards;
}
@keyframes rx-overdrive-fade {
  0%   { opacity: 0; }
  15%  { opacity: 1; }
  70%  { opacity: 1; }
  100% { opacity: 0; }
}
@keyframes rx-overdrive-pop {
  0%   { transform: scale(0.4) rotate(-6deg); opacity: 0; }
  30%  { transform: scale(1.18) rotate(3deg); opacity: 1; }
  55%  { transform: scale(0.96) rotate(-1deg); }
  100% { transform: scale(1) rotate(0); opacity: 1; }
}

.illust-lightbox {
  position: fixed;
  inset: 0;
  z-index: 12000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(1rem, 3vw, 2rem);
}
.illust-lightbox__backdrop {
  position: absolute;
  inset: 0;
  border: 0;
  background: rgba(2, 4, 9, 0.86);
  cursor: zoom-out;
}
.illust-lightbox__figure {
  position: relative;
  z-index: 1;
  display: grid;
  gap: 0.6rem;
  width: min(92vw, 68rem);
  max-height: 92vh;
  margin: 0;
  animation: illust-lightbox-in 160ms ease-out;
}
.illust-lightbox__image {
  display: block;
  width: 100%;
  max-height: min(82vh, 52rem);
  object-fit: contain;
  border-radius: var(--radius-md);
  box-shadow: 0 1.5rem 4rem rgba(0, 0, 0, 0.58);
}
.illust-lightbox__caption {
  justify-self: center;
  max-width: 100%;
  padding: 0.34rem 0.7rem;
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: 999px;
  color: var(--text-0);
  background: rgba(6, 10, 18, 0.78);
  font-weight: 700;
  line-height: 1.2;
}
.illust-lightbox__close {
  position: absolute;
  top: -0.85rem;
  right: -0.85rem;
  width: 2.3rem;
  height: 2.3rem;
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: 50%;
  background: rgba(8, 12, 20, 0.9);
  color: var(--text-0);
  font-size: 1.5rem;
  line-height: 1;
  cursor: pointer;
}
.illust-lightbox__close:hover {
  border-color: var(--accent-hi);
  color: var(--accent-hi);
}
/* 갤러리 모드: 좌우 이동 버튼 + 카운터(도감 등 여러 일러스트를 넘겨 볼 때). */
.illust-lightbox__nav {
  position: absolute;
  z-index: 2;
  top: 50%;
  transform: translateY(-50%);
  width: 3rem;
  height: 3rem;
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: 50%;
  background: rgba(8, 12, 20, 0.9);
  color: var(--text-0);
  font-size: 1.9rem;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
.illust-lightbox__nav:hover { border-color: var(--accent-hi); color: var(--accent-hi); }
.illust-lightbox__nav--prev { left: clamp(0.5rem, 2vw, 1.5rem); }
.illust-lightbox__nav--next { right: clamp(0.5rem, 2vw, 1.5rem); }
/* 등장 지역/타워 정보(도감 갤러리). 이름 캡션 아래 한 줄. */
.illust-lightbox__region {
  justify-self: center;
  max-width: 100%;
  padding: 0.22rem 0.66rem;
  border: 1px solid color-mix(in srgb, var(--accent) 38%, transparent);
  border-radius: 999px;
  background: rgba(6, 10, 18, 0.7);
  color: var(--accent-hi);
  font-size: 0.82rem;
  font-weight: 600;
  line-height: 1.2;
  text-align: center;
}
.illust-lightbox__region[hidden] { display: none; }
.illust-lightbox__counter {
  justify-self: center;
  padding: 0.2rem 0.6rem;
  border-radius: 999px;
  background: rgba(6, 10, 18, 0.78);
  color: var(--text-1);
  font-size: 0.8rem;
  font-weight: 700;
}

@keyframes illust-lightbox-in {
  from { opacity: 0; transform: scale(0.965); }
  to   { opacity: 1; transform: scale(1); }
}

@media (prefers-reduced-motion: reduce) {
  .rx-burst, .rx-pop, .rx-particle, .rx-stamp__text, .rx-overdrive, .rx-overdrive__text,
  .dmg-pop, .illust-lightbox__figure { animation-duration: 1ms; }
}

/* ===== news-ticker.css ===== */
/* 서버 전체 뉴스 티커 — 화면 상단 가운데 토스트.
   z-index 는 모달(10050)·유휴 경고(10100) 아래, 페이지 위(10030)로 둬
   소식이 모달을 가리지 않게 한다. 클릭은 카드에서만 받는다(컨테이너는 pass-through). */
.news-ticker {
  position: fixed;
  top: 20px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 10030;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  width: max-content;
  max-width: min(94vw, 720px);
  pointer-events: none; /* 빈 영역은 아래 UI 클릭을 막지 않는다. */
}

.news-ticker__item {
  pointer-events: auto; /* 카드 자체는 클릭(즉시 닫기) 가능. */
  display: flex;
  align-items: center;
  gap: 14px;
  max-width: 100%;
  padding: 16px 28px;
  border-radius: 999px;
  border: 2px solid rgba(var(--accent-hi-rgb), 0.6);
  background: linear-gradient(180deg, rgba(36, 44, 64, 0.97), rgba(26, 32, 48, 0.97));
  color: var(--text-0);
  font-size: 18px;
  font-weight: 700;
  line-height: 1.4;
  letter-spacing: 0.01em;
  box-shadow:
    0 12px 36px rgba(0, 0, 0, 0.5),
    0 0 26px rgba(var(--accent-hi-rgb), 0.3);
  cursor: pointer;
  /* 진입 전 상태(아래에서 떠오르며 페이드 인). */
  opacity: 0;
  transform: translateY(-14px) scale(0.95);
  transition: opacity 0.3s ease, transform 0.3s cubic-bezier(0.22, 1, 0.36, 1);
}

.news-ticker__item.is-in {
  opacity: 1;
  transform: translateY(0) scale(1);
}

.news-ticker__item.is-closing {
  opacity: 0;
  transform: translateY(-10px) scale(0.97);
  /* EXIT_MS(320ms, news-ticker.js)와 일치. */
  transition: opacity 0.3s ease, transform 0.3s ease;
}

.news-ticker__icon {
  flex: 0 0 auto;
  font-size: 22px;
  line-height: 1;
  filter: drop-shadow(0 0 8px rgba(var(--accent-hi-rgb), 0.55));
}

.news-ticker__text {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 전설 장비 획득 — 가장 화려한 골드 글로우. */
.news-ticker__item--gear_legendary {
  border-color: rgba(var(--accent-hi-rgb), 0.8);
  background: linear-gradient(180deg, rgba(54, 44, 24, 0.96), rgba(34, 28, 18, 0.96));
  color: var(--accent-hi);
  box-shadow:
    0 8px 28px rgba(0, 0, 0, 0.45),
    0 0 24px rgba(var(--accent-hi-rgb), 0.4);
}

/* 보스 최초 처치 — 붉은 승전 톤. */
.news-ticker__item--boss_first {
  border-color: rgba(224, 122, 95, 0.6);
  box-shadow:
    0 8px 28px rgba(0, 0, 0, 0.45),
    0 0 20px rgba(224, 122, 95, 0.28);
}

/* 첨탑 완등 — 차가운 청록 정상 톤. */
.news-ticker__item--spire_summit {
  border-color: rgba(159, 224, 255, 0.55);
  box-shadow:
    0 8px 28px rgba(0, 0, 0, 0.45),
    0 0 20px rgba(159, 224, 255, 0.26);
}

/* 뉴스 문장 속 아이템 이름 — 등급색(data-rarity→tokens.css --rarity-color) + 호버 툴팁 단서. */
.news-item-name {
  color: var(--rarity-color, var(--accent-hi));
  font-weight: 800;
  cursor: help;
  text-decoration: underline dotted rgba(var(--accent-hi-rgb), 0.5);
  text-underline-offset: 3px;
}
.news-item-name:hover { text-decoration-style: solid; }

/* "서버 소식" 목록 팝업(news-list-modal) 행 — mypage.css .activity-log-row 재사용 + 아이콘 칼럼. */
.news-log-row { align-items: center; gap: 0.5rem; }
.news-log-row__icon {
  flex: none;
  width: 1.5rem;
  text-align: center;
  font-size: 1rem;
  line-height: 1;
}


@media (prefers-reduced-motion: reduce) {
  .news-ticker__item,
  .news-ticker__item.is-closing {
    transition: opacity 0.2s ease;
    transform: none;
  }
  .news-ticker__item.is-in {
    transform: none;
  }
}

/* ===== system-hint.css ===== */
/* 시스템 안내 힌트 — 각 게임 페이지의 가운데 단(home__center) 메인 메뉴/콘텐츠 위 노란 배너.
   신규 유저의 "다음에 할 일" 1개를 강조한다. core.bundle.css 에 포함되어 모든 게임 화면에서 로드된다. */
.system-hint {
  background: linear-gradient(180deg, #ffe9a6 0%, #ffd35c 100%);
  border: 1px solid #e0a52a;
  border-radius: var(--radius-md);
  padding: 0.7rem 0.85rem;
  margin: 0 0 0.75rem;
  box-shadow: 0 2px 10px rgba(224, 165, 42, 0.25);
  color: #3a2c08;
}
.system-hint__head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 0.45rem;
}
.system-hint__chip {
  font-weight: 800; font-size: 0.82rem; letter-spacing: 0.02em;
  background: rgba(58, 44, 8, 0.12); color: #5a430c;
  padding: 0.12rem 0.5rem; border-radius: 999px;
}
.system-hint__progress { font-size: 0.78rem; font-weight: 700; color: #6b5212; }
.system-hint__body {
  display: flex; align-items: center; gap: 0.85rem; flex-wrap: wrap;
}
.system-hint__main { flex: 1 1 16rem; min-width: 0; }
.system-hint__title { font-weight: 800; font-size: 1rem; color: #2a2006; }
.system-hint__hint { font-size: 0.85rem; color: #5b4a1c; margin-top: 0.12rem; line-height: 1.35; }
.system-hint__action { flex: 0 0 auto; display: flex; flex-direction: column; gap: 0.4rem; align-items: flex-end; }
.system-hint__btn {
  display: inline-block; font-weight: 800; font-size: 0.9rem;
  padding: 0.5rem 0.95rem; border-radius: var(--radius-sm); border: none;
  cursor: pointer; text-decoration: none; white-space: nowrap;
}

/* "여기를 클릭" 유도 이펙트 — 활성 단계의 대상 요소/메뉴 탭에 부착(system-hint.js).
   outline 은 조상 overflow 에 클립되지 않아 어떤 컨테이너 안에서도 보인다. */
@keyframes gg-click-pulse {
  0%   { box-shadow: 0 0 0 0 rgba(0, 229, 255, 0.65), 0 0 10px 2px rgba(0, 229, 255, 0.35); }
  70%  { box-shadow: 0 0 0 16px rgba(0, 229, 255, 0), 0 0 20px 8px rgba(0, 229, 255, 0.55); }
  100% { box-shadow: 0 0 0 0 rgba(0, 229, 255, 0), 0 0 10px 2px rgba(0, 229, 255, 0.0); }
}
/* 위로 튀지 않고 아래로 "톡톡" 두드리는 모션 — 상단 모서리를 넘어가지 않는다. */
/* 클릭 유도 말풍선(툴팁) — 대상 버튼 위에 떠서 안내한다(전투 넛지의 물약 버튼 등). */

@media (prefers-reduced-motion: reduce) {
  
  
  
}

/* ===== notice.css ===== */
/* 공지사항 — 우측단 위젯 · 상단 고정 배너 · 전체보기 팝업(아코디언).
   core.bundle.css 에 포함되어 모든 게임 화면에서 로드된다.
   팝업 셸(.community-modal / .community-pager)은 community.css 를 그대로 빌려 쓴다. */

/* ── 분류 칩 · NEW 배지 (위젯·팝업 공용) ─────────────────────────── */
.notice-chip {
  display: inline-block;
  font-size: 0.68rem;
  font-weight: 700;
  line-height: 1;
  padding: 0.16rem 0.4rem;
  border-radius: 999px;
  border: 1px solid var(--border);
  color: var(--text-1);
  background: var(--bg-2);
  white-space: nowrap;
  vertical-align: middle;
}
.notice-chip--general     { border-color: #4a5570; color: #c6ccd9; background: rgba(74, 85, 112, 0.25); }
.notice-chip--maintenance { border-color: #a05252; color: #ffb3b3; background: rgba(160, 82, 82, 0.22); }
.notice-chip--update      { border-color: #3f7fa8; color: #9fd4f0; background: rgba(63, 127, 168, 0.22); }
.notice-chip--event       { border-color: #a07a3a; color: #f0c06a; background: rgba(160, 122, 58, 0.22); }

/* 뱃지는 줄바꿈되면 글자가 세로로 쪼개진다 — nowrap 이 규약이다. */
.notice-new {
  display: inline-block;
  font-size: 0.62rem;
  font-weight: 800;
  letter-spacing: 0.04em;
  line-height: 1;
  padding: 0.16rem 0.32rem;
  border-radius: 4px;
  background: var(--danger);
  color: #fff;
  white-space: nowrap;
  vertical-align: middle;
}

/* ── 우측단 위젯 ────────────────────────────────────────────────── */
/* 목록 골격(.union-widget__list)은 커뮤니티 것을 그대로 쓰고, 메타 줄만 가로 배치로 덮는다. */
[data-role="notice-widget"] .panel__title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
}
.notice-widget__unread {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.15rem;
  height: 1.15rem;
  padding: 0 0.3rem;
  border-radius: 999px;
  background: var(--danger);
  color: #fff;
  font-size: 0.68rem;
  font-weight: 800;
  line-height: 1;
  white-space: nowrap;
}
.notice-widget__list .meta {
  display: flex;
  align-items: center;
  gap: 0.3rem;
  flex-wrap: nowrap;
  overflow: hidden;
}
.notice-widget__time {
  margin-left: auto;
  flex: 0 0 auto;
  color: var(--text-2);
  font-size: 0.72rem;
  white-space: nowrap;
}
.notice-widget__pin { flex: 0 0 auto; font-size: 0.7rem; }

/* ── 상단 고정 배너 (가운데 단 맨 위, 💡 길잡이 바로 위) ────────────── */
/* 🔴 길잡이는 노란 카드다. 바로 아래 붙으므로 **색으로 확실히 갈라야** 둘이 한 덩어리로 안 보인다.
   그래서 남색 계열 + 좌측 강조선을 쓴다(분류마다 강조선 색만 달라진다). */
.notice-pin {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  background: linear-gradient(180deg, #2b3757 0%, #1e2740 100%);
  border: 1px solid #46598c;
  border-left: 4px solid #7aa2ff;
  border-radius: var(--radius-md);
  padding: 0.5rem 0.7rem;
  margin: 0 0 0.6rem;
  box-shadow: 0 2px 10px rgba(70, 89, 140, 0.25);
  color: var(--text-0);
}
.notice-pin--maintenance { border-left-color: #e08b8b; }
.notice-pin--update      { border-left-color: #6fc0ee; }
.notice-pin--event       { border-left-color: #f0c06a; }

.notice-pin__chip {
  flex: 0 0 auto;
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.02em;
  padding: 0.14rem 0.5rem;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.12);
  color: #dfe7ff;
  white-space: nowrap;
}
.notice-pin__title {
  flex: 1 1 auto;
  min-width: 0;
  text-align: left;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  color: var(--text-0);
  font-size: 0.92rem;
  font-weight: 700;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.notice-pin__title:hover { color: #cfe0ff; text-decoration: underline; }
.notice-pin__time {
  flex: 0 0 auto;
  font-size: 0.74rem;
  color: #9fabc9;
  white-space: nowrap;
}
.notice-pin__close {
  flex: 0 0 auto;
  background: none;
  border: 0;
  cursor: pointer;
  color: #9fabc9;
  font-size: 0.85rem;
  line-height: 1;
  padding: 0.2rem 0.1rem;
}
.notice-pin__close:hover { color: #fff; }

/* ── 전체보기 팝업 ──────────────────────────────────────────────── */
.notice-modal .community-modal__panel { width: min(46rem, 100%); }
.notice-feed { display: flex; flex-direction: column; gap: 0.4rem; }

.notice-row {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-1);
  overflow: hidden;
}
.notice-row.is-pinned { border-color: #46598c; }
.notice-row.is-open   { border-color: var(--accent); }

.notice-row__head {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  width: 100%;
  background: none;
  border: 0;
  cursor: pointer;
  padding: 0.55rem 0.65rem;
  text-align: left;
  color: inherit;
}
.notice-row__head:hover { background: var(--hover-bg); }
.notice-row__pin { flex: 0 0 auto; font-size: 0.75rem; }
.notice-row__title {
  flex: 1 1 auto;
  min-width: 0;
  color: var(--text-0);
  font-size: 0.92rem;
  font-weight: 700;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.notice-row__time {
  flex: 0 0 auto;
  color: var(--text-2);
  font-size: 0.74rem;
  white-space: nowrap;
}
.notice-row__caret {
  flex: 0 0 auto;
  color: var(--text-2);
  font-size: 0.7rem;
  transition: transform 0.15s ease;
}
.notice-row.is-open .notice-row__caret { transform: rotate(180deg); }

.notice-row__body {
  border-top: 1px solid var(--border);
  padding: 0.7rem 0.85rem 0.9rem;
  color: var(--text-1);
  font-size: 0.88rem;
  line-height: 1.65;
}

/* ── 마크다운 본문 ──────────────────────────────────────────────── */
/* 🔴 tr1_md_render 가 뱉는 클래스는 wiki-doc__* 인데 **wiki.css 는 게임 번들에 없다.**
   그래서 여기서 직접 최소한을 입힌다. 안 하면 제목·표·코드가 브라우저 기본 스타일로 떨어진다. */
.notice-row__body > :first-child { margin-top: 0; }
.notice-row__body > :last-child  { margin-bottom: 0; }
.notice-row__body p { margin: 0 0 0.6rem; }
.notice-row__body .wiki-doc__h2,
.notice-row__body .wiki-doc__h3,
.notice-row__body .wiki-doc__h4 {
  color: var(--text-0);
  margin: 1rem 0 0.45rem;
  line-height: 1.35;
}
.notice-row__body .wiki-doc__h2 { font-size: 1.05rem; border-bottom: 1px solid var(--border); padding-bottom: 0.25rem; }
.notice-row__body .wiki-doc__h3 { font-size: 0.98rem; }
.notice-row__body .wiki-doc__h4 { font-size: 0.92rem; color: var(--text-1); }

.notice-row__body .wiki-doc__list { margin: 0 0 0.6rem; padding-left: 1.2rem; }
.notice-row__body .wiki-doc__list--sub { margin: 0.2rem 0 0.2rem; }
.notice-row__body li { margin: 0.15rem 0; }

.notice-row__body .wiki-doc__link { color: var(--accent-hi); text-decoration: none; border-bottom: 1px dotted var(--accent); }
.notice-row__body .wiki-doc__link:hover { color: #fff; border-bottom-color: var(--accent-hi); }

.notice-row__body .wiki-doc__code {
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 0.05rem 0.3rem;
  font-size: 0.85em;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
.notice-row__body .wiki-doc__pre {
  background: var(--bg-0);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0.6rem 0.7rem;
  margin: 0 0 0.6rem;
  overflow-x: auto;
  font-size: 0.82rem;
  line-height: 1.5;
}
.notice-row__body .wiki-doc__pre code { background: none; border: 0; padding: 0; }

.notice-row__body .wiki-doc__quote {
  margin: 0 0 0.6rem;
  padding: 0.35rem 0.75rem;
  border-left: 3px solid var(--accent);
  background: rgba(var(--accent-rgb), 0.06);
  color: var(--text-1);
}

/* 표는 좁은 화면에서 페이지를 가로로 밀어내면 안 된다 — 자기 상자 안에서 스크롤한다. */
.notice-row__body .wiki-doc__table-wrap { overflow-x: auto; margin: 0 0 0.6rem; }
.notice-row__body .wiki-doc__table { border-collapse: collapse; width: 100%; font-size: 0.84rem; }
.notice-row__body .wiki-doc__table th,
.notice-row__body .wiki-doc__table td {
  border: 1px solid var(--border);
  padding: 0.3rem 0.5rem;
  text-align: left;
}
.notice-row__body .wiki-doc__table th { background: var(--bg-2); color: var(--text-0); }

.notice-row__body .wiki-doc__hr { border: 0; border-top: 1px solid var(--border); margin: 0.9rem 0; }
