/*
 * map.css — 인연 지도(/map) 전용 스타일.
 * ============================================================
 * tokens.css 변수만 사용한다(라이트/다크 자동 전환). 하드코딩 색은 SVG 인코딩용 rgba 뿐이고
 * 그마저도 토큰 색 위에 얹는 투명도라 테마를 따라간다.
 * 공용 표면(GNB=nav.css, 푸터=legal.css, 로그인 시트=coin-ui.css)은 그대로 재사용하고
 * 여기에는 지도 고유 스타일만 둔다.
 */

/* display 를 지정하는 클래스가 hidden 속성을 이기는 사고 방지(코드베이스 관용구). */
[hidden] { display: none !important; }

.mp-page { margin: 0; word-break: keep-all; overflow-wrap: break-word; }
/* overflow-x 는 clip 이 정답 — hidden 은 스크롤포트를 만들어 GNB 의 sticky top:0 을 뷰포트에서 떼어낸다. */
html, body.mp-page { overflow-x: hidden; overflow-x: clip; max-width: 100vw; }

/* 코인칩(coin-ui.css)의 잔액/충전 표기는 지도에서 감춘다 — 지도 화면에는 결제 표면을 두지 않는다.
   계정 칩(로그인/마이 진입)은 남겨 로그인 동선은 유지한다. */
.mp-page .coin-acct .ca-coin,
.mp-page .coin-acct .ca-charge { display: none !important; }

/* GNB(sticky) 아래로 내려온 계정 칩(top: gnb-h + 8, 높이 44)과 첫 콘텐츠가 겹치지 않게 확보한 여백. */
.mp-wrap {
  max-width: 560px;
  margin: 0 auto;
  padding: 64px max(16px, env(safe-area-inset-left)) 8px max(16px, env(safe-area-inset-right));
}

.mp-boot { padding: 88px 0 120px; text-align: center; color: var(--color-text-tertiary); font-size: .9rem; }

/* ── 머리말 ── */
.mp-head { margin-bottom: 22px; }
.mp-eyebrow {
  display: inline-flex; align-items: center; padding: 6px 12px; border-radius: var(--r-pill);
  background: var(--color-accent-mist); color: var(--color-accent-deep);
  font-size: .74rem; font-weight: 800; letter-spacing: .02em;
}
.mp-title {
  margin: 14px 0 0; font-family: var(--font-serif); font-weight: 600;
  font-size: clamp(1.55rem, 6vw, 2.1rem); line-height: 1.34; color: var(--color-text-primary);
}
.mp-lead { margin: 12px 0 0; font-size: .94rem; line-height: 1.75; color: var(--color-text-secondary); }

.mp-h2 {
  margin: 0 0 6px; font-family: var(--font-serif); font-weight: 600;
  font-size: 1.18rem; line-height: 1.4; color: var(--color-text-primary);
}
.mp-sec-sub { margin: 0 0 14px; font-size: .84rem; line-height: 1.7; color: var(--color-text-tertiary); }

.mp-card {
  padding: 20px 18px; margin-top: 18px;
  border: 1px solid var(--color-border-default); border-radius: var(--r-lg);
  background: var(--color-bg-elevated); box-shadow: var(--shadow-soft);
}

/* ── 랜딩 안내 ── */
.mp-steps { list-style: none; margin: 24px 0 0; padding: 0; display: grid; gap: 14px; }
.mp-steps li {
  display: flex; gap: 13px; align-items: flex-start;
  padding: 15px 16px; border: 1px solid var(--color-border-subtle); border-radius: var(--r-lg);
  background: var(--color-bg-elevated);
}
.mp-step-n {
  flex: none; width: 26px; height: 26px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--color-accent-mist); color: var(--color-accent-deep);
  font-size: .82rem; font-weight: 800;
}
.mp-steps strong { display: block; font-size: .95rem; font-weight: 700; color: var(--color-text-primary); }
.mp-steps p { margin: 5px 0 0; font-size: .86rem; line-height: 1.7; color: var(--color-text-secondary); }

.mp-free-note {
  margin: 18px 0 0; padding: 12px 14px; border-radius: var(--r-sm);
  background: var(--color-bg-sunken); color: var(--color-text-secondary);
  font-size: .86rem; line-height: 1.65;
}

.mp-note { margin: 12px 2px 0; font-size: .8rem; line-height: 1.7; color: var(--color-text-tertiary); }

/* ── 버튼 ── */
.mp-go {
  display: block; width: 100%; min-height: 52px; margin-top: 20px; padding: 14px 18px;
  border: 0; border-radius: var(--r-md);
  background: linear-gradient(135deg, var(--color-accent), var(--color-deco-peach));
  color: var(--color-text-inverse); font-family: inherit; font-size: 1rem; font-weight: 800;
  text-align: center; text-decoration: none; cursor: pointer; box-shadow: var(--shadow-soft);
}
.mp-go:hover { box-shadow: var(--shadow-medium); }
.mp-go:focus-visible { outline: 2px solid var(--color-accent-deep); outline-offset: 2px; }
.mp-go[disabled] { opacity: .55; cursor: default; box-shadow: none; }
.mp-go-link { line-height: 24px; }

.mp-btn {
  flex: 1 1 160px; min-height: 48px; padding: 12px 16px;
  border: 1px solid var(--color-border-default); border-radius: var(--r-md);
  background: var(--color-bg-sunken); color: var(--color-text-primary);
  font-family: inherit; font-size: .92rem; font-weight: 700; cursor: pointer;
}
.mp-btn:hover { border-color: var(--color-border-strong); }
.mp-btn:focus-visible { outline: 2px solid var(--color-accent-deep); outline-offset: 2px; }
.mp-btn[disabled] { opacity: .55; cursor: default; }
.mp-btn.primary {
  border-color: transparent; color: var(--color-text-inverse);
  background: linear-gradient(135deg, var(--color-accent), var(--color-accent-deep));
}

/* ── 폼 ── */
.mp-form-head { margin-bottom: 18px; }
.mp-form-head h2 { margin: 0; font-size: 1.02rem; font-weight: 800; color: var(--color-text-primary); }
.mp-form-head p { margin: 7px 0 0; font-size: .84rem; line-height: 1.7; color: var(--color-text-tertiary); }

.mp-field { margin-bottom: 18px; }
.mp-field:last-of-type { margin-bottom: 0; }
.mp-label { display: block; margin-bottom: 8px; font-size: .84rem; font-weight: 700; color: var(--color-text-primary); }
.mp-label .mp-opt { margin-left: 5px; font-weight: 500; color: var(--color-text-tertiary); }
.mp-hint { margin-top: 7px; font-size: .76rem; line-height: 1.6; color: var(--color-text-tertiary); }

.mp-form input[type="text"], .mp-form select {
  width: 100%; min-height: 46px; padding: 11px 13px; box-sizing: border-box;
  border: 1px solid var(--color-border-default); border-radius: var(--r-sm);
  background: var(--color-bg-sunken); color: var(--color-text-primary);
  font-family: inherit; font-size: .96rem;
}
.mp-form input[type="text"]::placeholder { color: var(--color-text-tertiary); }
.mp-form input[type="text"]:focus, .mp-form select:focus {
  outline: 2px solid var(--color-accent); outline-offset: 1px; border-color: transparent;
}
.mp-form input.mp-bad { border-color: var(--color-warning); }
.mp-form input:disabled { opacity: .5; }

.mp-pills { display: flex; gap: 8px; }
.mp-pill {
  flex: 1; min-height: 46px; padding: 8px 10px;
  border: 1px solid var(--color-border-default); border-radius: var(--r-sm);
  background: var(--color-bg-sunken); color: var(--color-text-secondary);
  font-family: inherit; font-size: .9rem; font-weight: 700; line-height: 1.35; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.mp-pill span { display: block; margin-top: 3px; font-size: .7rem; font-weight: 500; color: var(--color-text-tertiary); }
.mp-pill.on { border-color: var(--color-border-strong); background: var(--color-accent-mist); color: var(--color-text-primary); }

.mp-ymd { display: grid; grid-template-columns: 1.35fr 1fr 1fr; gap: 8px; }
.mp-hm { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.mp-check {
  display: flex; align-items: center; gap: 9px; min-height: 44px; margin-top: 10px;
  font-size: .86rem; color: var(--color-text-secondary); cursor: pointer;
}
.mp-check input { width: 20px; height: 20px; margin: 0; flex: none; cursor: pointer; accent-color: var(--color-accent-deep); }

.mp-err {
  display: none; margin-top: 16px; padding: 11px 14px; border-radius: var(--r-sm);
  background: var(--color-bg-sunken); border: 1px solid var(--color-warning);
  color: var(--color-warning); font-size: .85rem; line-height: 1.6;
}
.mp-err.on { display: block; }

/* ── 주인 카드 ── */
.mp-owner {
  position: relative; margin-bottom: 4px; padding: 22px 18px 20px; text-align: center;
  border: 1px solid var(--color-border-default); border-radius: var(--r-lg);
  background:
    radial-gradient(120% 80% at 50% 0%, var(--color-accent-mist), transparent 70%),
    var(--color-bg-elevated);
  box-shadow: var(--shadow-soft);
}
.mp-owner-fig { display: block; width: 108px; height: 108px; margin: 0 auto 4px; object-fit: contain; }
.mp-owner-emoji { display: block; font-size: 3.2rem; line-height: 1.1; margin-bottom: 4px; }
.mp-owner-title {
  margin: 6px 0 0; font-family: var(--font-serif); font-weight: 600;
  font-size: clamp(1.35rem, 5.4vw, 1.8rem); line-height: 1.35; color: var(--color-text-primary);
}
.mp-owner-sub {
  display: inline-flex; margin-top: 10px; padding: 5px 12px; border-radius: var(--r-pill);
  background: var(--color-bg-sunken); color: var(--color-text-secondary);
  font-size: .8rem; font-weight: 700;
}
.mp-owner-hook { margin: 12px 0 0; font-size: .9rem; line-height: 1.75; color: var(--color-text-secondary); }
.mp-owner-count {
  display: inline-flex; align-items: center; gap: 6px; margin-top: 14px;
  padding: 7px 14px; border-radius: var(--r-pill);
  background: var(--color-accent-mist); color: var(--color-accent-deep);
  font-size: .84rem; font-weight: 800;
}

/* ── 방사형 지도 ── */
.mp-map-card { padding: 12px 10px 16px; }
.mp-map-canvas { width: 100%; }
.mp-map-canvas svg { display: block; width: 100%; height: auto; }
.mp-map-caption { margin: 6px 12px 0; text-align: center; font-size: .82rem; line-height: 1.65; color: var(--color-text-tertiary); }
.mp-zoom-open {
  display: block; margin: 12px auto 0; padding: 9px 16px; min-height: 40px;
  border: 1px solid var(--color-border-default); border-radius: var(--r-pill);
  background: var(--color-bg-sunken); color: var(--color-text-secondary);
  font-family: inherit; font-size: .82rem; font-weight: 700; cursor: pointer;
}
.mp-zoom-open:hover { border-color: var(--color-border-strong); color: var(--color-text-primary); }

.mp-node { cursor: pointer; }
.mp-node-name { font-family: var(--font-sans); font-weight: 700; fill: var(--color-text-secondary); }
.mp-sector-label { font-family: var(--font-sans); font-weight: 800; fill: var(--color-text-secondary); }
.mp-center-name { font-family: var(--font-serif); font-weight: 600; fill: var(--color-text-primary); }
.mp-spoke { stroke: var(--color-border-default); }
.mp-ring { fill: none; stroke: var(--color-border-subtle); }
.mp-sector-chip { fill: var(--color-bg-sunken); stroke: var(--color-border-default); }
.mp-node.is-new .mp-node-halo { animation: mpPulse 1.6s ease-out 3; }
@keyframes mpPulse { 0% { opacity: .85; } 60% { opacity: .15; } 100% { opacity: .85; } }

/* ── 관계 카운트 칩 ── */
.mp-counts { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 16px; }
.mp-count-chip {
  display: inline-flex; align-items: center; gap: 6px; padding: 7px 12px;
  border: 1px solid var(--color-border-default); border-radius: var(--r-pill);
  background: var(--color-bg-elevated); font-size: .81rem; font-weight: 700;
  color: var(--color-text-secondary);
}
.mp-count-chip b { font-size: .84rem; color: var(--color-text-primary); }
.mp-count-dot { width: 9px; height: 9px; border-radius: 50%; flex: none; }

/* ── 케미 랭킹 ── */
.mp-rank-sec { margin-top: 26px; }
.mp-rank { display: grid; gap: 12px; }
.mp-rank-row {
  display: grid; grid-template-columns: 34px 52px 1fr auto; gap: 10px; align-items: start;
  padding: 14px 14px; border: 1px solid var(--color-border-default); border-radius: var(--r-lg);
  background: var(--color-bg-elevated); box-shadow: var(--shadow-soft);
}
.mp-rank-row.is-new { border-color: var(--color-border-strong); box-shadow: var(--shadow-lift); }
.mp-rank-n {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; border-radius: 50%;
  background: var(--color-bg-sunken); color: var(--color-text-tertiary);
  font-size: .84rem; font-weight: 800;
}
.mp-rank-n.medal-1 { background: rgba(201, 162, 75, .2); color: var(--color-butter); }
.mp-rank-n.medal-2 { background: rgba(126, 135, 155, .18); color: var(--stem-metal); }
.mp-rank-n.medal-3 { background: rgba(246, 181, 143, .24); color: var(--color-deco-peach); }
/* 아바타: 오행 틴트 원(::before) 위에 캐릭터 일러스트. 이미지가 실패해도 원은 남습니다. */
.mp-rank-ava { position: relative; width: 52px; height: 52px; flex: none; }
.mp-rank-ava::before {
  content: ''; position: absolute; inset: 0; border-radius: 50%;
  background: var(--mp-oh, var(--color-accent)); opacity: .16;
}
.mp-rank-ava img { position: relative; display: block; width: 52px; height: 52px; object-fit: contain; }
.mp-rank-mid { min-width: 0; }
.mp-rank-name { font-size: 1rem; font-weight: 800; color: var(--color-text-primary); }
.mp-rank-sub { margin-top: 2px; font-size: .76rem; color: var(--color-text-tertiary); }
.mp-rel-line { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 8px; }
.mp-rel-chip {
  display: inline-flex; padding: 5px 11px; border-radius: var(--r-pill);
  background: var(--color-accent-mist); color: var(--color-accent-deep);
  font-size: .8rem; font-weight: 800;
}
.mp-rel-principle { font-size: .78rem; font-weight: 700; color: var(--color-text-tertiary); }
.mp-badges { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 7px; }
.mp-badge {
  display: inline-flex; padding: 4px 9px; border-radius: var(--r-pill);
  border: 1px solid var(--color-border-default); background: var(--color-bg-sunken);
  font-size: .72rem; font-weight: 700; color: var(--color-text-secondary);
}
.mp-rank-desc { margin: 9px 0 0; font-size: .85rem; line-height: 1.75; color: var(--color-text-secondary); }
.mp-rank-right { display: flex; flex-direction: column; align-items: flex-end; gap: 8px; }
.mp-chemi { text-align: right; line-height: 1; }
.mp-chemi b { font-family: var(--font-serif); font-size: 1.35rem; font-weight: 600; color: var(--color-text-primary); }
.mp-chemi span { display: block; margin-top: 4px; font-size: .68rem; font-weight: 700; color: var(--color-text-tertiary); }
.mp-del {
  min-height: 34px; padding: 6px 11px; border: 1px solid var(--color-border-default);
  border-radius: var(--r-pill); background: transparent; color: var(--color-text-tertiary);
  font-family: inherit; font-size: .74rem; font-weight: 700; cursor: pointer; white-space: nowrap;
}
.mp-del:hover { border-color: var(--color-warning); color: var(--color-warning); }

.mp-rank-empty {
  padding: 26px 18px; text-align: center; border: 1px dashed var(--color-border-default);
  border-radius: var(--r-lg); color: var(--color-text-tertiary); font-size: .88rem; line-height: 1.75;
}

/* ── 공유 ── */
.mp-share-btns { display: flex; flex-wrap: wrap; gap: 10px; }
.mp-share-url {
  margin-top: 12px; padding: 10px 12px; border-radius: var(--r-sm);
  background: var(--color-bg-sunken); color: var(--color-text-tertiary);
  font-size: .76rem; line-height: 1.6; overflow-wrap: anywhere; word-break: break-all;
}
.mp-share-note {
  margin: 12px 0 0; font-size: .78rem; line-height: 1.75;
  color: var(--color-text-tertiary); word-break: keep-all;
}

/* ── 기존 기능 연결 ── */
.mp-cross { display: grid; gap: 10px; margin-top: 24px; }
.mp-cross-item {
  display: block; padding: 15px 16px; border-radius: var(--r-lg);
  border: 1px solid var(--color-border-default); background: var(--color-bg-elevated);
  text-decoration: none; box-shadow: var(--shadow-soft);
}
.mp-cross-item:hover { box-shadow: var(--shadow-medium); }
.mp-cross-item strong { display: block; font-size: .95rem; font-weight: 800; color: var(--color-text-primary); }
.mp-cross-item span { display: block; margin-top: 4px; font-size: .82rem; line-height: 1.7; color: var(--color-text-tertiary); }

.mp-disclaimer { margin: 22px 2px 0; font-size: .76rem; line-height: 1.75; color: var(--color-text-tertiary); }

/* ── 확대 뷰 ── */
.mp-zoom {
  position: fixed; inset: 0; z-index: 10020; display: flex; align-items: center; justify-content: center;
  padding: 16px; background: var(--color-bg-overlay);
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  overflow: auto; -webkit-overflow-scrolling: touch;
}
.mp-zoom-inner {
  width: 100%; max-width: 720px; margin: auto; padding: 12px;
  border-radius: var(--r-lg); background: var(--color-bg-elevated); box-shadow: var(--shadow-float);
  overflow-x: auto; -webkit-overflow-scrolling: touch;
}
/* 좁은 화면에서는 확대가 곧 가로 스크롤입니다 — 폭을 못 박아 실제로 크게 보이게 하고 좌우로 밀게 합니다.
   오버레이 안쪽 스크롤이라 본문 가로 스크롤과는 무관합니다. */
.mp-zoom-inner svg { display: block; width: 100%; min-width: 520px; height: auto; }
.mp-zoom-hint { margin: 8px 0 2px; text-align: center; font-size: .76rem; color: var(--color-text-tertiary); }
.mp-zoom-x {
  position: fixed; top: max(14px, env(safe-area-inset-top)); right: max(14px, env(safe-area-inset-right));
  width: 40px; height: 40px; border: 0; border-radius: 50%;
  background: var(--color-bg-elevated); color: var(--color-text-secondary);
  font-size: 1rem; line-height: 1; cursor: pointer; box-shadow: var(--shadow-medium);
}

/* ── 토스트 ── */
.mp-toast {
  position: fixed; left: 50%; bottom: calc(24px + env(safe-area-inset-bottom)); transform: translateX(-50%);
  z-index: 10030; max-width: min(90vw, 420px); padding: 12px 18px; border-radius: var(--r-pill);
  background: var(--color-text-primary); color: var(--color-text-inverse);
  font-size: .86rem; font-weight: 700; text-align: center;
  opacity: 0; pointer-events: none; transition: opacity var(--motion-base) ease;
}
.mp-toast.show { opacity: 1; }

/* ══ 9:16 공유 카드(화면 밖 캡처 자리) ══════════════════════════════════════════
   카드는 두 장이다. .mp-story = 주인용 지도 카드(map-client.js), .mp-duo = 참여자용 2인 카드
   (map-join.js). 둘 다 1080x1920 이고 html2canvas 로 굽는다.

   ⚠️ 세이프존이 1급 규칙이다 — 상단 250px / 하단 340px 은 인스타 스토리 UI(프로필 줄, 답장창)가
      덮는 자리라 브랜드와 주소 말고는 아무것도 두지 않는다. 두 카드의 padding 이 그 규칙의 정본이고,
      브랜드/워터마크만 absolute 로 그 안에 들어간다.
   ⚠️ 색은 테마 변수를 쓰지 않고 값을 못 박는다. 카드는 라이트 모드에서도 어두운 그림으로 나가야
      하는데, var(--stem-*) 을 쓰면 화면 테마의 라이트 값이 그대로 구워져 대비가 무너진다.
   ⚠️ html2canvas 는 인라인 SVG 안의 외부 <image> 를 못 그린다. 그래서 배치도를 SVG 가 아니라
      절대 배치 <img> 로 다시 그린다(map-client.js buildStoryPlot). */
#mapStoryRoot, #mapDuoRoot { position: fixed; left: -99999px; top: 0; width: 1080px; height: 0; overflow: hidden; }
.mp-story, .mp-duo {
  position: relative; width: 1080px; height: 1920px; box-sizing: border-box;
  padding: 250px 84px 340px;
  display: flex; flex-direction: column; align-items: center;
  background: linear-gradient(165deg, #1A1830 0%, #241F45 52%, #34255A 100%);
  color: #F0EDE6; font-family: var(--font-sans); text-align: center; word-break: keep-all;
}
/* 브랜드만 상단 세이프존 안에 산다(카드 두 장 공통). */
.mp-story-brand, .mp-duo-brand {
  position: absolute; top: 104px; left: 0; right: 0;
  font-family: var(--font-serif); font-size: 44px; font-weight: 600; letter-spacing: .06em; color: #E0BA6A;
}
/* ⚠️ 워터마크는 카드 두 장 모두 하단 세이프존 "밖"(bottom <= 1560)에 있어야 한다. 예전에는 둘 다
   세이프존 안에 앉아, 인스타 스토리 답장창이 덮으면서 출처와 유입 경로가 통째로 가려졌다.
   2인 카드는 세로 가운데 정렬이라 흐름 안에 두면 저절로 세이프존 위에 앉는다.
   ⚠️ 단 한 줄로 눕혀야 한다. 주인 카드처럼 브랜드를 블록으로 쌓으면 이 자리가 138px 을 먹고,
      가운데 정렬이라 그 절반만큼 카드가 위로도 자라 상단 세이프존을 넘는다(실측 top=240 < 250). */
.mp-duo-mark {
  margin-top: 22px;
  font-size: 32px; line-height: 1.5; color: rgba(240, 237, 230, .74);
}
.mp-duo-mark b {
  margin-right: 14px;
  font-family: var(--font-serif); font-size: 36px; font-weight: 600; letter-spacing: .08em; color: #F0EDE6;
}
/* 주인 카드 푸터는 margin-top:auto 로 아래에 붙인다(패딩 340px 이 세이프존 경계를 만든다).
   margin-bottom 이 그 경계에서 20px 을 더 띄운다 — 경계에 딱 붙이면 여유가 0 이라, 폰트 대체나
   반올림 1px 만 어긋나도 QR 이 답장창 밑으로 들어간다. */
.mp-story-foot {
  margin-top: auto; margin-bottom: 20px;
  display: flex; align-items: center; justify-content: center; gap: 30px;
}
.mp-story-qr { flex: none; padding: 14px; border-radius: 20px; background: #FFFFFF; line-height: 0; }
.mp-story-mark { text-align: left; font-size: 30px; line-height: 1.5; color: rgba(240, 237, 230, .74); }
.mp-story-mark span { display: block; margin-top: 6px; }
.mp-story-mark i {
  display: block; margin-top: 10px; font-style: normal; font-size: 26px; color: rgba(240, 237, 230, .52);
}
.mp-story-mark b {
  display: block; margin-bottom: 12px;
  font-family: var(--font-serif); font-size: 52px; font-weight: 600; letter-spacing: .08em; color: #F0EDE6;
}
/* 면책 한 줄(2인 카드) — 워터마크 위에 붙는다. 2030 캐릭터 카드 푸터 정책과 같은 결이다. */
.mp-duo-note { margin-top: 26px; font-size: 26px; color: rgba(240, 237, 230, .52); }

/* ── 주인용: 캐릭터 배치도가 주인공 ── */
.mp-story-title { font-family: var(--font-serif); font-size: 68px; font-weight: 600; line-height: 1.26; }
.mp-story-count { margin-top: 16px; font-size: 36px; font-weight: 800; color: #A292F5; }
.mp-story-plot { position: relative; margin-top: 18px; flex: none; }
.mp-story-orbit {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  border: 2px solid rgba(255, 255, 255, .1); border-radius: 50%;
}
/* 크기는 map-client.js buildStoryPlot 이 배치도 한 변에 비례해 인라인으로 박습니다(겹침 방지). */
.mp-story-pin { position: absolute; transform: translate(-50%, -50%); text-align: center; }
.mp-story-pin-halo {
  position: absolute; left: 50%; transform: translate(-50%, -50%); border-radius: 50%;
}
.mp-story-pin-fig { position: relative; object-fit: contain; }
.mp-story-pin-dot { position: relative; display: block; border-radius: 50%; }
.mp-story-pin-name {
  position: relative; display: block; margin-top: 2px;
  font-weight: 700; color: rgba(240, 237, 230, .88); text-shadow: 0 2px 6px rgba(20, 16, 40, .85);
}
.mp-story-hub {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); text-align: center;
}
.mp-story-hub-fig { object-fit: contain; }
.mp-story-hub-name { display: block; margin-top: 4px; font-weight: 800; color: #E0BA6A; text-shadow: 0 2px 6px rgba(20, 16, 40, .85); }
.mp-story-chips { margin-top: 16px; display: flex; flex-wrap: wrap; justify-content: center; gap: 12px; }
.mp-story-chip {
  display: inline-flex; align-items: center; gap: 9px; padding: 10px 18px; border-radius: 999px;
  background: rgba(255, 255, 255, .08); font-size: 26px; font-weight: 700;
}
.mp-story-chip i { width: 18px; height: 18px; border-radius: 50%; }
/* 세로 여백은 카드 예산이다 — QR 을 키우면서(스캔 마진 확보) 이 블록에서 18px 을 돌려받았다.
   가로 여백은 그대로 둔다(줄바꿈에 영향을 준다). */
.mp-story-best {
  margin-top: 14px; width: 100%; padding: 12px 28px; box-sizing: border-box; border-radius: 34px;
  background: rgba(255, 255, 255, .07); border: 2px solid rgba(255, 255, 255, .12);
}
.mp-story-best-lbl { font-size: 24px; font-weight: 700; letter-spacing: .04em; color: #E0BA6A; }
.mp-story-best-row { margin-top: 10px; display: flex; align-items: center; gap: 22px; text-align: left; }
.mp-story-best-fig { width: 100px; height: 100px; object-fit: contain; flex: none; }
.mp-story-best-mid { flex: 1; min-width: 0; }
.mp-story-best-name { font-size: 42px; font-weight: 800; }
.mp-story-best-rel { margin-top: 8px; font-size: 30px; color: #B9ACF8; }
.mp-story-best-score { font-family: var(--font-serif); font-size: 56px; font-weight: 600; }

/* ── 참여자용 2인 카드: 관계 라벨 한 단어가 화면을 먹는다 ── */
/* 2인 카드는 내용이 짧아 위로 몰리면 아래가 텅 빈다 — 세이프존 사이에서 세로 가운데로 앉힌다. */
.mp-duo { justify-content: center; }
.mp-duo-eyebrow { font-size: 34px; color: rgba(240, 237, 230, .74); }
.mp-duo-label {
  margin-top: 18px; font-family: var(--font-serif); font-size: 140px; font-weight: 600; line-height: 1.14;
  letter-spacing: -.02em;
}
/* 열 글자짜리 관계 이름("서로를 벼리는 인연" / "기운을 나누는 인연")은 140px 로는 글자 칸(912px)을
   넘어 두 줄이 된다. 카드는 세이프존 사이에서 세로 가운데 정렬이라 두 줄이 되는 순간 위아래로 함께
   자라 양쪽 세이프존을 다 침범한다(실측 top 203 / bottom 1627). 그 이름만 한 단계 줄여 한 줄로
   세운다 — 붙이는 쪽은 map-join.js 이고 기준은 글자 수다. */
.mp-duo-label-long { font-size: 108px; }
.mp-duo-principle { margin-top: 22px; font-size: 42px; font-weight: 700; color: #E0BA6A; }
.mp-duo-hook {
  margin-top: 20px; padding: 16px 30px; border-radius: 999px;
  background: rgba(162, 146, 245, .18); font-size: 40px; font-weight: 700; color: #DCD5FA;
}
.mp-duo-pair { margin-top: 34px; display: flex; align-items: flex-start; justify-content: center; gap: 20px; }
.mp-duo-one { width: 300px; }
.mp-duo-fig { width: 240px; height: 240px; object-fit: contain; }
.mp-duo-figdot { display: block; width: 160px; height: 160px; margin: 40px auto; border-radius: 50%; background: rgba(255, 255, 255, .16); }
.mp-duo-name { margin-top: 4px; font-size: 38px; font-weight: 800; }
.mp-duo-sub { margin-top: 8px; font-size: 26px; color: rgba(240, 237, 230, .62); }
.mp-duo-amp { align-self: center; font-family: var(--font-serif); font-size: 56px; color: rgba(240, 237, 230, .5); }
.mp-duo-chemi { margin-top: 26px; font-size: 30px; color: rgba(240, 237, 230, .74); }
.mp-duo-chemi b { font-family: var(--font-serif); font-size: 44px; font-weight: 600; color: #F0EDE6; margin: 0 6px; }
/* QR 은 모듈 한 변이 정수 픽셀이어야 캡처에서 경계가 안 흐려진다(qr-vendor.js __roumQrSvg 가
   요청 크기를 내림해 정수 배율을 맞춘다). 그래서 상자에 크기를 강제하지 않고 svg 가 자기 크기로
   앉게 두고, 상자는 여백만 준다. */
.mp-duo-qr { margin-top: 56px; display: flex; align-items: center; justify-content: center; gap: 24px; }
.mp-duo-qr-box { padding: 14px; border-radius: 20px; background: #FFFFFF; flex: none; line-height: 0; }
.mp-duo-qr-cap { font-size: 28px; line-height: 1.55; color: rgba(240, 237, 230, .74); text-align: left; }

/* ── 좁은 화면 ── */
@media (max-width: 400px) {
  .mp-wrap { padding-left: max(13px, env(safe-area-inset-left)); padding-right: max(13px, env(safe-area-inset-right)); }
  .mp-rank-row { grid-template-columns: 30px 44px 1fr; padding: 12px 12px; }
  .mp-rank-n { width: 30px; height: 30px; font-size: .8rem; }
  .mp-rank-ava, .mp-rank-ava img { width: 44px; height: 44px; }
  /* 점수/삭제는 3열 그리드 밖으로 내려 이름 열을 좁히지 않는다(가로 스크롤 방지).
     row-reverse 라 지우기는 왼쪽, 점수는 오른쪽 — 넓은 화면의 배치 감각을 유지한다. */
  .mp-rank-right {
    grid-column: 1 / -1; flex-direction: row-reverse; align-items: center; justify-content: space-between;
    margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--color-border-subtle);
  }
  .mp-chemi { display: flex; align-items: baseline; gap: 6px; }
  .mp-chemi span { margin-top: 0; }
  .mp-btn { flex-basis: 100%; }
}
