/* ============================================================
   연봉닥터 — 통합 디자인 시스템
   SOMIN의 CSS 변수 체계를 계승하고, sangmi의 팔레트·히어로 감각을 얹었다.
   ============================================================ */

*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
html { scroll-behavior: smooth; }

body {
  font-family: system-ui, -apple-system, "Apple SD Gothic Neo", "Segoe UI", "Malgun Gothic", sans-serif;
  background: var(--page-plane);
  color: var(--text-primary);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

/* ---------- 팔레트 (라이트 기본) ---------- */
:root {
  color-scheme: light;
  /* v34: 기존 값(#f7f7f4 등)이 살짝 누런 아이보리 톤이라는 피드백 —
     같은 정도의 명도 차이(카드 흰색과 구분되는 폭)는 유지하면서
     따뜻한 톤 대신 아주 옅은 그레이·블루 쪽으로 축을 바꿨다. */
  --page-plane:     #f7f8fa;
  --surface-1:      #fbfcfd;
  --surface-2:      #ffffff;
  --surface-sunk:   #eef1f5;
  --text-primary:   #0b0b0b;
  --text-secondary: #52514e;
  --text-muted:     #8b8983;
  --gridline:       #e3e2db;
  --baseline:       #c3c2b7;
  --border:         rgba(11, 11, 11, .10);
  --border-strong:  rgba(11, 11, 11, .18);

  /* v33: 초록 계열 브랜드 컬러를 파란 계열(토스 블루 계통)로 전면
     전환했다 — "닥터/처방전" 컨셉과 어울리는 청량한 병원/의료 톤을
     원한다는 요청. --brand=#2563EB는 흰 텍스트 대비 5.17:1로 AA를
     여유 있게 통과한다(#3182F6 원안은 white-on-bg 기준 3.7:1로
     소형 텍스트 AA에는 부족해 한 단계 더 짙게 조정). */
  --brand:          #2563eb;
  --brand-soft:     #e5eefc;
  --accent:         #b76442;

  /* 도넛(지출 5항목)·자산 타임머신(6종목)이 함께 쓰는 다색 팔레트 —
     하나의 색으로 통일할 수 없는 자리라 "블루 패밀리"(네이비→블루→
     스카이블루→틸→그레이블루) + 보조색 1개(인디고, 6번째 항목용)로
     재구성했다. 원색 빨강/노랑처럼 완전히 동떨어진 색은 쓰지 않았다. */
  --series-1:       #1e3a8a;  /* 저축·예금 — 네이비 */
  --series-2:       #2563eb;  /* 투자      — 블루(브랜드와 동일 축) */
  --series-3:       #0ea5e9;  /* 부수입    — 스카이블루 */
  --series-4:       #14b8a6;  /* 자기계발  — 틸 */
  --series-5:       #64748b;  /* 실물      — 그레이블루 */
  --series-6:       #6366f1;  /* 암호자산  — 인디고(보조색) */

  /* good도 브랜드와 마찬가지로 파란 계열로 옮겼다 — 이 서비스는
     "초록=성공"이 아니라 브랜드 컬러 자체가 곧 긍정 신호였어서,
     good만 초록으로 남기면 브랜드와 어긋나 보인다. brand(indigo
     쪽 블루)와는 다른 축(사이언 쪽 블루)을 써서 그 둘은 여전히
     구분된다. good-text(#075985)는 흰 배경 대비 7.57:1로 AA를
     넉넉히 통과한다. */
  --good:           #0284c7;
  --good-text:      #075985;
  /* v22 "닥터" 컨셉: 경고색을 덜 자극적인 톤으로 낮췄다(원색 빨강/
     쨍한 주황 → 차분한 러스트/앰버) — 유효성 검사 오류처럼 진짜
     "주의"가 필요한 곳에서도 위협적으로 느껴지지 않게 한다. */
  --warning:        #e8a23d;
  --warning-text:   #92661f;
  --critical:       #c1594a;
  --critical-text:  #a3452f;
  /* "물가 유지선"처럼 나쁜 소식이 아니라 그냥 기준선을 나타내는
     자리에 쓴다 — critical(빨강)을 쓰면 "이겨야 할 상대"처럼 보인다. */
  --reference:      #5c7f97;

  /* v36: "병원 안내 자료/차트" 느낌을 살리려면 소비자 앱 특유의
     둥글둥글한 곡률보다는 절제된 각을 쓰는 편이 더 정돈돼 보인다 —
     모든 카드·버튼·입력창이 이 토큰 하나를 공유해서 값만 낮추면
     전체에 일괄 반영된다(22px→16px, 14px→10px). */
  --radius:         16px;
  --radius-sm:      10px;
  --shadow:         0 1px 2px rgba(11,11,11,.04), 0 8px 24px rgba(11,11,11,.05);
  --maxw:           1180px;
}

@media (prefers-color-scheme: dark) {
  :root:where(:not([data-theme="light"])) {
    color-scheme: dark;
    --page-plane:     #0d0d0d;
    --surface-1:      #171716;
    --surface-2:      #201f1e;
    --surface-sunk:   #121211;
    --text-primary:   #f7f7f5;
    --text-secondary: #b9b8b1;
    --text-muted:     #85837d;
    --gridline:       #2c2c2a;
    --baseline:       #3a3a37;
    --border:         rgba(255,255,255,.11);
    --border-strong:  rgba(255,255,255,.2);

    --brand:          #5b8def;
    --brand-soft:     #16283d;
    --accent:         #d9825f;

    --series-1:       #4c6fdc;
    --series-2:       #5b8def;
    --series-3:       #38bdf8;
    --series-4:       #2dd4bf;
    --series-5:       #94a3b8;
    --series-6:       #818cf8;

    --good-text:      #7dd3fc;
    --warning-text:   #e0a94f;
    --critical-text:  #d97e68;
    --reference:      #7fa6bf;
    --shadow:         0 1px 2px rgba(0,0,0,.3), 0 8px 24px rgba(0,0,0,.35);
  }
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --page-plane:     #0d0d0d;
  --surface-1:      #171716;
  --surface-2:      #201f1e;
  --surface-sunk:   #121211;
  --text-primary:   #f7f7f5;
  --text-secondary: #b9b8b1;
  --text-muted:     #85837d;
  --gridline:       #2c2c2a;
  --baseline:       #3a3a37;
  --border:         rgba(255,255,255,.11);
  --border-strong:  rgba(255,255,255,.2);
  --brand:          #5b8def;
  --brand-soft:     #16283d;
  --accent:         #d9825f;
  --series-1:       #4c6fdc;
  --series-2:       #5b8def;
  --series-3:       #38bdf8;
  --series-4:       #2dd4bf;
  --series-5:       #94a3b8;
  --series-6:       #818cf8;
  --good-text:      #7dd3fc;
  --warning-text:   #e0a94f;
  --critical-text:  #d97e68;
  --reference:      #7fa6bf;
  --shadow:         0 1px 2px rgba(0,0,0,.3), 0 8px 24px rgba(0,0,0,.35);
}

/* ---------- 단계별 테마 (v34) ----------
   진단 단계(리포트 카드1~4, "내 연봉 vs 물가"까지)는 :root 기본값
   (블루)을 그대로 쓴다. 진찰(설문 전체)과 처방(카드5~6·연봉 협상
   가이드·목표 자산·자산 타임머신)만 body에 .stage-checkup/
   .stage-prescription 클래스가 붙어(app.js setStage()) 이 블록이
   --brand 등을 덮어쓴다. 컴포넌트 CSS는 여전히 var(--brand)만
   참조하므로 이 토큰 재정의 말고는 손댈 곳이 없다 — v33에서
   확인한 "전부 토큰화되어 있다"는 전제가 여기서도 그대로 통한다. */
body.stage-checkup {
  --brand:          #db2777;
  --brand-soft:     #fce7f3;
  --series-1:       #831843;
  --series-2:       #db2777;
  --series-3:       #f472b6;
  --series-4:       #c026d3;
  --series-5:       #6b7280;
}
body.stage-prescription {
  --brand:          #15803d;
  --brand-soft:     #dcfce7;
  --series-1:       #14532d;
  --series-2:       #15803d;
  --series-3:       #22c55e;
  --series-4:       #0d9488;
  --series-5:       #6b7280;
  --series-6:       #84cc16;
  --good:           #16a34a;
  --good-text:      #166534;
}
/* v36 버그 수정: data-theme는 <body>가 아니라 <html>(:root)에 붙는다
   (initTheme()/themeToggle 참고). 아래 두 블록이 원래
   "body[data-theme=dark].stage-X"/"body.stage-X:not([data-theme=light])"
   로 body 자신의 data-theme을 찾고 있어서, 사용자가 테마 토글
   버튼으로 다크를 켠 경우(시스템이 아니라 명시적 토글) 이 규칙이
   전혀 매치되지 않았다 — 그 결과 다크에서도 라이트용 --brand-soft
   (밝은 파스텔)가 그대로 남고, 본문 텍스트만 다크모드 규칙
   (:root[data-theme=dark]가 올바르게 적용됨)을 타서 흰색이 되며
   "밝은 배경 + 흰 글자"로 뒤집혀 보였다(v35 캐릭터·연봉 협상 가이드
   박스 버그가 전부 이 원인). :root의 data-theme을 확인하고, 커스텀
   프로퍼티는 그대로 body에 선언해 자손에게 내려가게 한다. */
@media (prefers-color-scheme: dark) {
  :root:where(:not([data-theme="light"])) body.stage-checkup {
    --brand:          #f472b6;
    --brand-soft:     #4a1942;
    --series-1:       #f9a8d4;
    --series-2:       #f472b6;
    --series-3:       #fbcfe8;
    --series-4:       #e879f9;
    --series-5:       #94a3b8;
  }
  :root:where(:not([data-theme="light"])) body.stage-prescription {
    --brand:          #4ade80;
    --brand-soft:     #14291c;
    --series-1:       #86efac;
    --series-2:       #4ade80;
    --series-3:       #bbf7d0;
    --series-4:       #2dd4bf;
    --series-5:       #94a3b8;
    --series-6:       #bef264;
    --good:           #4ade80;
    --good-text:      #86efac;
  }
}
:root[data-theme="dark"] body.stage-checkup {
  --brand:          #f472b6;
  --brand-soft:     #4a1942;
  --series-1:       #f9a8d4;
  --series-2:       #f472b6;
  --series-3:       #fbcfe8;
  --series-4:       #e879f9;
  --series-5:       #94a3b8;
}
:root[data-theme="dark"] body.stage-prescription {
  --brand:          #4ade80;
  --brand-soft:     #14291c;
  --series-1:       #86efac;
  --series-2:       #4ade80;
  --series-3:       #bbf7d0;
  --series-4:       #2dd4bf;
  --series-5:       #94a3b8;
  --series-6:       #bef264;
  --good:           #4ade80;
  --good-text:      #86efac;
}

/* ---------- 레이아웃 ---------- */
.wrap { width: min(100% - 2.5rem, var(--maxw)); margin-inline: auto; }
@media (max-width: 640px) { .wrap { width: min(100% - 1.5rem, var(--maxw)); } }

section { scroll-margin-top: 5rem; }

/* ---------- 상단바 ---------- */
.topbar {
  position: sticky; top: 0; z-index: 50;
  background: color-mix(in srgb, var(--page-plane) 88%, transparent);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--border);
}
.topbar-inner { display: flex; align-items: center; gap: 1rem; padding: .85rem 0; }
/* v34: 헤더가 "연봉닥터" + 서브텍스트(SNU 핀테크...) 2줄이었는데,
   서브텍스트를 빼고 로고 텍스트 하나만 남기면서 1줄이 됐다. 팀
   크레딧은 이미 footer(.credits)에 그대로 남아있어 정보가
   사라지지 않는다. 줄어든 만큼 로고 자체를 크고 단단하게 키운다. */
.brand { display: flex; align-items: center; font-weight: 800; font-size: 1.35rem; letter-spacing: -.02em; text-decoration: none; color: var(--text-primary); }

/* ---------- 단계 스테퍼(진찰/진단/처방) ---------- */
/* 점 색은 어느 단계에 있든 고정(핑크/블루/그린) — 사이트 전체가
   단계별로 갈아입는 --brand 토큰과는 별개로, 이 3개 점만은 항상
   같은 색을 보여줘야 "지금 이 단계"라는 위치를 기준점처럼 읽을 수
   있다. 그래서 토큰이 아니라 고정 hex를 직접 쓴다. */
.stage-tracker { display: flex; align-items: center; gap: .3rem; }
/* v61: 표지(설문 시작 전)에서는 세 pill 중 어느 것도 활성화되지
   않는데, 그 상태로 계속 보여주면 "지금 진찰 단계"로 오해할 수
   있다 — 표지에서만 탭 자체를 숨긴다(app.js setStage()가 이 클래스를
   붙인다). 좌우 grid-column을 명시로 고정해 둔 .brand/.theme-toggle
   덕분에(아래 861px 이상 규칙) 탭이 사라져도 로고는 왼쪽, 테마
   버튼은 오른쪽에 그대로 남는다 — 별도 여백 보정이 필요 없었다. */
body.stage-cover .stage-tracker { display: none; }
.stage-pill {
  display: inline-flex; align-items: center; gap: .35rem;
  font-size: .68rem; font-weight: 700; padding: .32rem .6rem; border-radius: 999px;
  color: var(--text-muted); background: transparent; border: 1px solid var(--border);
  white-space: nowrap; user-select: none;
  transition: background-color .25s ease, color .25s ease, border-color .25s ease, transform .2s ease;
}
.stage-dot { width: 6px; height: 6px; border-radius: 50%; flex: 0 0 auto; transition: background-color .25s ease; }
.stage-pill[data-stage="checkup"] .stage-dot { background: #db2777; }
.stage-pill[data-stage="diagnosis"] .stage-dot { background: #2563eb; }
.stage-pill[data-stage="prescription"] .stage-dot { background: #15803d; }
.stage-pill.is-active { transform: scale(1.06); border-color: transparent; }
.stage-pill.is-active .stage-dot { background: #fff; }
.stage-pill[data-stage="checkup"].is-active { color: #fff; background: #db2777; }
.stage-pill[data-stage="diagnosis"].is-active { color: #fff; background: #2563eb; }
.stage-pill[data-stage="prescription"].is-active { color: #fff; background: #15803d; }
/* v67: 표지 카피의 "진찰/진단/처방" 세 단어를 위 스테퍼와 같은 고정
   hex(핑크/블루/그린)로 강조한다. v66은 형광펜 띠만 두고 글자색은
   기본색으로 바꿨는데, "글자색은 그대로(색 유지) 두라"는 피드백 —
   글자색도 다시 고정 hex로 칠하고, 얇은 형광펜 밑줄(글자 아래쪽
   32%, background-image 그라디언트 트릭 — background-color는 세로
   일부만 칠할 수 없어서)도 그대로 유지한다. 색 글자 위에 같은 색
   형광펜이 너무 진하면 서로 눌러버리므로, 형광펜 알파를 살짝
   낮춰(라이트 .5→.22, 다크 .58→.38) 균형을 맞췄다. padding을 안 써서
   이 span의 박스 높이가 글자 자체보다 커지지 않으니 v65의 줄 겹침
   문제는 여전히 생기지 않는다. */
.lede-word {
  font-weight: 800;
  background-repeat: no-repeat; background-position: 0 90%; background-size: 100% 32%;
}
.lede-word-checkup { color: #db2777; background-image: linear-gradient(rgba(219, 39, 119, .22), rgba(219, 39, 119, .22)); }
.lede-word-diagnosis { color: #2563eb; background-image: linear-gradient(rgba(37, 99, 235, .2), rgba(37, 99, 235, .2)); }
.lede-word-prescription { color: #15803d; background-image: linear-gradient(rgba(21, 128, 61, .2), rgba(21, 128, 61, .2)); }
@media (prefers-color-scheme: dark) {
  :root:where(:not([data-theme="light"])) .lede-word-checkup { background-image: linear-gradient(rgba(219, 39, 119, .38), rgba(219, 39, 119, .38)); }
  :root:where(:not([data-theme="light"])) .lede-word-diagnosis { background-image: linear-gradient(rgba(37, 99, 235, .34), rgba(37, 99, 235, .34)); }
  :root:where(:not([data-theme="light"])) .lede-word-prescription { background-image: linear-gradient(rgba(21, 128, 61, .34), rgba(21, 128, 61, .34)); }
}
:root[data-theme="dark"] .lede-word-checkup { background-image: linear-gradient(rgba(219, 39, 119, .38), rgba(219, 39, 119, .38)); }
:root[data-theme="dark"] .lede-word-diagnosis { background-image: linear-gradient(rgba(37, 99, 235, .34), rgba(37, 99, 235, .34)); }
:root[data-theme="dark"] .lede-word-prescription { background-image: linear-gradient(rgba(21, 128, 61, .34), rgba(21, 128, 61, .34)); }
@media (max-width: 480px) {
  /* 아주 좁은 화면에서는 글자를 지우고 점만 남겨 한 줄을 지킨다.
     라벨은 별도 태그 없이 텍스트 노드라 부모의 font-size:0을
     그대로 상속해서 사라진다 — .stage-dot만 px 단위라 영향 없다. */
  .stage-pill { font-size: 0; padding: .45rem; gap: 0; }
  .stage-dot { width: 8px; height: 8px; }
}

.theme-toggle {
  /* 탭이 숨겨진 첫 화면에서도 오른쪽 끝에 붙어 있도록 — 탭이 보이면
     탭의 flex:1이 이미 남는 공간을 다 차지해서 이 margin은 그냥 0이 된다. */
  margin-left: auto;
  display: grid; place-items: center; width: 34px; height: 34px; padding: 0;
  border: 1px solid var(--border); background: var(--surface-2); color: var(--text-secondary);
  border-radius: 999px; cursor: pointer; font-family: inherit;
}
.theme-toggle:hover { border-color: var(--border-strong); color: var(--text-primary); }
.theme-icon { width: 18px; height: 18px; grid-area: 1 / 1; }
/* 라이트 모드에서는 달(누르면 어두워짐), 다크 모드에서는 해(누르면
   밝아짐) 아이콘을 보여준다 — 색상 변수와 같은 다크모드 판별 규칙이다. */
.theme-icon-moon { display: none; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .theme-icon-sun { display: none; }
  :root:not([data-theme="light"]) .theme-icon-moon { display: block; }
}
:root[data-theme="dark"] .theme-icon-sun { display: none; }
:root[data-theme="dark"] .theme-icon-moon { display: block; }

/* ---------- 실시간 지표 스트립 ---------- */
/* 스켈레톤(자리표시자)과 실제 값(원/달러 유무, 델타 표시 유무 등으로
   내용이 조금씩 달라짐) 사이에 높이가 흔들리지 않도록 min-height를
   명시한다 — 내용에 따라 우연히 높이가 맞는 걸 기대하지 않는다. */
.ticker {
  display: flex; gap: .5rem; overflow-x: auto; padding: .55rem 0; scrollbar-width: none;
  min-height: 3.2rem; box-sizing: border-box;
  margin-top: 1rem; border-top: 1px solid var(--border);
}
.ticker::-webkit-scrollbar { display: none; }
/* v20: 카드 덱 전체 아래(마지막 카드 뒤)로 옮겼다 — 점수·결론을 먼저
   보여주고, 시세는 다 본 뒤 참고하는 보조 정보로 내렸다. 모바일은
   항목이 넘칠 때 overflow-x:auto로 가로 스크롤해야 하는데, 가운데
   정렬 상태에서 넘치면 시작 지점을 스크롤로 못 찾아가는 경우가 있어
   좁은 화면은 기존 왼쪽 정렬을 유지한다 (탭 중앙 정렬과 같은 이유). */
@media (min-width: 861px) { .ticker { justify-content: center; } }
/* display:flex는 [hidden]의 기본 display:none과 명시도가 같아 나중에
   선언된 이 규칙이 이겨버린다. 설문 중엔 티커 자체를 숨겨야 하므로 명시한다. */
.ticker[hidden] { display: none; }
.tick {
  flex: 0 0 auto; display: flex; align-items: baseline; gap: .45rem;
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: 999px; padding: .3rem .8rem; font-size: .78rem; white-space: nowrap;
}
.tick b { font-variant-numeric: tabular-nums; font-size: .85rem; }
.tick .lbl { color: var(--text-muted); }
.tick .delta { font-size: .72rem; font-variant-numeric: tabular-nums; }
.up { color: var(--critical-text); }
.down { color: var(--series-1); }

.live-dot {
  width: 7px; height: 7px; border-radius: 50%; background: var(--good);
  box-shadow: 0 0 0 0 color-mix(in srgb, var(--good) 60%, transparent);
  animation: pulse 2.4s infinite;
}
.live-dot.stale { background: var(--warning); animation: none; }
.live-dot.err { background: var(--text-muted); animation: none; }
@keyframes pulse {
  0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--good) 55%, transparent); }
  70%  { box-shadow: 0 0 0 7px transparent; }
  100% { box-shadow: 0 0 0 0 transparent; }
}
@media (prefers-reduced-motion: reduce) { .live-dot { animation: none; } }

@media (min-width: 861px) {
  .topbar-inner { display: grid; grid-template-columns: 1fr auto 1fr; }
  .brand { grid-column: 1; justify-self: start; }
  .stage-tracker { grid-column: 2; justify-self: center; }
  .theme-toggle { grid-column: 3; justify-self: end; }
}

.panel { padding: 1.1rem 0 0; }
.panel[hidden] { display: none; }
/* 리포트 섹션 사이 구분선 — 첫 섹션(홈)은 그대로 두고, 그다음부터는
   챕터가 바뀐다는 걸 보여주는 선을 준다. 예전엔 위아래 3rem씩 비워서
   포트폴리오를 내려볼 때 빈 공간이 너무 크다는 피드백이 있어 줄였다. */
.panel + .panel { margin-top: 1rem; padding-top: 1rem; border-top: 1px solid var(--border); }
.report-heading {
  font-size: clamp(1.5rem, 3.2vw, 1.95rem); font-weight: 800; letter-spacing: -.02em;
  margin: 0 0 .9rem; color: var(--text-primary);
}
/* 각 리포트 섹션 진입부에 짧게 "이제 이걸 볼게요"를 걸어, 요약 화면의
   풀이가 아래로 계속 이어지는 느낌을 준다. */
.report-heading + .report-intro {
  margin: -.5rem 0 1.1rem; font-size: .88rem; color: var(--text-muted);
}

/* ---------- 홈 · 온보딩 → 로딩 → 요약 ---------- */
/* 뷰포트를 꽉 채운다 — 그 아래 리포트 내용이 로드 시점에 살짝 보이면
   "홈"이 아니라 그냥 리포트 맨 위 여백처럼 느껴진다. 상단바 + 실시간
   지표 스트립 높이(대략 9rem)만큼만 빼서 스크롤 신호 없이 시작한다. */
.home-hero {
  min-height: calc(100vh - 9rem);
  min-height: calc(100dvh - 9rem);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; gap: 1.1rem; padding: 2rem 1rem;
}
/* display:flex는 [hidden]의 기본 display:none과 명시도가 같아 나중에
   선언된 이 규칙이 이겨버린다. 그래서 hidden이어도 안 숨겨지는 걸 막는다. */
.home-hero[hidden], .onboarding-step[hidden] { display: none; }

/* 요약 화면은 온보딩 표지가 아니라 포트폴리오의 시작이다 — 화면을
   꽉 채우면 리포트를 보기까지 스크롤이 한 번 더 필요해져서 빈 공간처럼
   느껴진다. 짧게 두고 바로 아래 리포트로 이어지게 한다. */
#homeSummary { min-height: auto; padding: 2.4rem 1rem 1.6rem; gap: .9rem; }

.home-hero h1 {
  font-size: clamp(2rem, 5vw, 3.2rem); line-height: 1.16; letter-spacing: -.03em;
  margin: 0; font-weight: 800; color: var(--text-primary);
}
.home-hero h1 em { font-style: normal; color: var(--brand); }
.home-hero .lede { font-size: clamp(.95rem, 2vw, 1.1rem); color: var(--text-secondary); margin: 0; max-width: 32rem; word-break: keep-all; }
.home-hero .kicker { margin: 0; }
/* 카드1(결론부터)의 kicker는 이 리포트의 첫인상 역할을 하는데도 다른
   자잘한 kicker(Q1·내 물가 같은 문항 안내, 카드7의 "마지막으로")와
   같은 톤이면 존재감이 없다. 카드1 전용으로 더 크고 진하게, 브랜드색을
   줘서 확실히 눈에 띄게 한다(다른 카드의 .kicker는 손대지 않는다). */
#card-1 > .kicker {
  margin: 0; font-size: 1.05rem; font-weight: 800; color: var(--brand); letter-spacing: -.01em;
}

/* v21: 카드1에 결론이 그대로 들어오면서 갭 막대그래프만 필요해졌다
   (점수 링·등급·풀이 문단은 삭제 — 안 쓰이는 채로 남겨두지 않는다). */
.home-gap-chart { margin-top: 1rem; }
.home-gap-chart[hidden] { display: none; }

/* ---------- 마스코트 캐릭터 (v22) ----------
   실제 일러스트 전까지 쓰는 자리표시자 SVG(mascot.js) + 말풍선.
   is-large는 카드1(진단 결과)·카드6(마무리 인사, v44부터 카드1과 같은
   크기)처럼 세로로 크게 쓰는 자리에 붙인다. v44 이전엔 카드6에서만
   is-small.is-inline(옆으로 작게)을 썼는데, 그 자리를 감싸던 점선
   상자(.prescription-box)를 없애면서 크기도 카드1과 맞춰 더는 안
   쓴다 — 죽은 규칙이라 함께 지웠다. */
.mascot-wrap { display: flex; flex-direction: column; align-items: center; gap: .6rem; }
.mascot-svg { display: block; }
.mascot-bubble {
  margin: 0; background: var(--surface-2); border: 1px solid var(--border);
  border-radius: 999px; padding: .5rem 1.15rem; font-size: .84rem; font-weight: 700;
  color: var(--text-primary); word-break: keep-all; text-align: center;
}

@media (min-width: 641px) {
  .final-body { white-space: pre; max-width: none; }
}
/* 클릭하면 바로 전체 문장이 보이므로, 타이핑 중에는 클릭 가능하다는
   힌트로 커서 모양을 바꿔 둔다. */
.typing-cursor { cursor: pointer; }
.typing-cursor::after {
  content: ""; display: inline-block; width: 2px; height: 1em; margin-left: 2px;
  background: var(--brand); vertical-align: -.15em; animation: caretBlink 1s step-end infinite;
}
@keyframes caretBlink { 50% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .typing-cursor::after { animation: none; } }

.home-start-btn {
  appearance: none; border: 0; cursor: pointer; margin-top: .5rem;
  background: var(--brand); color: #fff; font-family: inherit; font-weight: 700;
  font-size: 1rem; padding: .85rem 2.1rem; border-radius: var(--radius-sm);
  /* v34: 진찰→진단→처방 단계가 바뀔 때 --brand가 즉시 스냅되지 않고
     부드럽게 넘어가도록. 값이 바뀌는 커스텀 프로퍼티 자체는 트랜지션
     대상이 될 수 없지만, 이걸 참조하는 background-color 속성 자체에
     transition을 걸면 새로 계산된 색으로 정상적으로 보간된다. */
  transition: filter .15s ease, transform .05s ease, background-color .3s ease;
}
.home-start-btn:hover { filter: brightness(1.08); }
.home-start-btn:active { transform: translateY(1px); }

/* v55: 바로 위 설명 문구("필요하면 펼쳐서…")를 없앴다 — 원래 이
   margin-top(.6rem)은 그 문구 아래 여백이었는데, 지금은 제목
   바로 아래라 그만큼으로는 붙어 보인다. 제목-버튼 사이 여백을
   자연스럽게 넓힌다(.next-step-actions는 이 카드에서만 쓰는 클래스). */
.next-step-actions { display: flex; flex-wrap: wrap; gap: .7rem; margin-top: 1rem; }
.next-step-actions .home-start-btn { margin-top: 0; }

/* PDF 다운로드는 카드7 맨 마지막(재입력 링크 바로 위)에 둔다 — 리포트를
   다 보고 난 뒤의 마무리 동작이라는 자리를 그대로 지킨다. */
.pdf-download-wrap { display: flex; justify-content: center; margin-top: 1.1rem; }

.onboarding-back {
  appearance: none; border: 0; background: none; cursor: pointer; font: inherit;
  color: var(--text-muted); font-size: .83rem; padding: .5rem;
}
.onboarding-back:hover { color: var(--text-secondary); }
/* 위쪽 "리포트 보기" 버튼과 붙어 있으면 오클릭으로 입력값이 초기화될
   위험이 있어, 기본 여백(#homeSummary의 flex gap) 위에 추가로 더
   띄운다. confirm 다이얼로그와 함께 이중으로 방지한다. */
.home-summary-links { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: .3rem 1rem; margin-top: 1.1rem; }

/* 문항 하나가 화면 하나 — 답이 바뀔 때마다 살짝 밀려 들어오게 해서
   "설문" 대신 "경험"처럼 느껴지게 한다. */
@keyframes stepIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
.onboarding-step {
  display: flex; flex-direction: column; align-items: center; gap: 1.1rem;
  animation: stepIn .35s ease;
  /* home-hero도 flex column + align-items:center라서, 이 스텝을 그
     align-items로 가로 방향을 맡기면(기본값 stretch가 아님) 스텝 자신의
     폭이 "내용에 맞춰 줄어드는" shrink-to-fit이 된다. 그 안의
     .onboarding-card는 width: min(100%, 920px)처럼 부모의 %로 폭을
     정하는데, 부모(이 스텝) 자체가 shrink-to-fit이면 그 %가 순환
     참조가 되어 브라우저가 임의로 작은 값을 골라버린다(실측:
     920px를 넣어도 카드가 457px로만 렌더링됨 — v49 확대가 사실상
     무효화됐던 원인). align-self:stretch로 스텝 폭을 home-hero
     전체 폭으로 고정해 이 순환을 끊는다 — 카드는 여전히 스텝 자신의
     align-items:center로 가운데 정렬된다. */
  align-self: stretch;
}
.onboarding-step h2 {
  font-size: clamp(1.4rem, 3.4vw, 2rem); line-height: 1.25; letter-spacing: -.02em;
  margin: 0; font-weight: 750; color: var(--text-primary);
}
/* 카드로 감싸는 이유: input-wrap/persona-grid/seg는 채움색이 --surface-1인데
   페이지 배경(--page-plane)과 같은 색이라, 카드(--surface-2) 없이 페이지에
   바로 놓으면 입력 필드 경계가 안 보인다. */
.onboarding-card { width: min(100%, 620px); text-align: left; }
.onboarding-card .field-note { text-align: center; }
/* v49: 데스크톱에서 카드가 화면 대비 너무 작아 보인다는 피드백 —
   리포트 카드덱(.deck-viewport, 데스크톱 최대 1000px)에 맞춰 설문
   카드도 넓혔다. is-wide(Q2 카테고리별 탭+퀴즈 화면)는 기존 640px에서
   더 크게(920px), 그 외 스텝(Q1 생활유형·Q3 연봉)도 비례해서
   440→620px로 같이 넓혔다 — "설문 전체 스텝에 동일한 기준"이라는
   요청. 모바일은 min(100%, …)이라 이 값을 넓혀도 좁은 화면에서는
   여전히 100%로 자동 축소된다. */
.onboarding-card.is-wide { width: min(100%, 920px); }
.onboarding-nav { display: flex; align-items: center; justify-content: center; gap: 1rem; flex-wrap: wrap; }

.onboarding-progress-wrap {
  display: flex; align-items: center; gap: .6rem; width: min(90%, 300px);
  position: absolute; top: 1.2rem; left: 50%; transform: translateX(-50%);
}
/* display:flex와 [hidden]은 특정성이 같아서(0,0,1,0) 나중에 선언된 쪽이
   이긴다 — 이 클래스가 뒤에 있으면 hidden 속성이 true여도 계속 보인다.
   이 코드베이스에서 반복된 버그라 항상 이렇게 명시적으로 덮어써야 한다. */
.onboarding-progress-wrap[hidden] { display: none; }
.onboarding-progressbar { flex: 1; height: 4px; border-radius: 999px; background: var(--surface-sunk); overflow: hidden; }
.onboarding-progressbar-fill { height: 100%; background: var(--brand); border-radius: 999px; transition: width .25s ease; }
.onboarding-progress-text { font-size: .72rem; color: var(--text-muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
#homeOnboarding { position: relative; }

.loading-ring {
  width: 40px; height: 40px; border-radius: 50%;
  border: 3px solid var(--surface-sunk); border-top-color: var(--brand);
  animation: loadingSpin .8s linear infinite;
}
@keyframes loadingSpin { to { transform: rotate(360deg); } }
.loading-msg { color: var(--text-secondary); font-size: .95rem; font-weight: 600; }

@media (prefers-reduced-motion: reduce) {
  .onboarding-step { animation: none; }
  .loading-ring { animation: none; }
}

/* ---------- 카드 / 그리드 ---------- */
.card {
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 1.2rem 1.3rem; box-shadow: var(--shadow);
}
/* 패널 안의 박스(카드/워크스페이스/결과그리드 등)는 종류와 무관하게
   전부 1rem 간격으로 통일한다. 개별 요소마다 margin-top을 따로 주면
   .card 뒤에 .workspace가 오는 경우처럼 규칙이 안 걸려 간격이 들쭉날쭉해진다. */
.panel > * + * { margin-top: 1rem; }
/* minmax(0, …)를 쓰는 이유: 그냥 1fr은 minmax(auto, 1fr)이라
   자식의 min-content(숫자 input의 기본 폭)만큼 컬럼이 늘어나 모바일에서
   페이지 전체에 가로 스크롤이 생긴다. */
.workspace { display: grid; grid-template-columns: minmax(0, 340px) minmax(0, 1fr); gap: 1rem; align-items: start; }
.workspace > * { min-width: 0; }
@media (max-width: 900px) { .workspace { grid-template-columns: minmax(0, 1fr); } }

/* ---------- 카드뉴스 덱 (v8) ----------
   내 물가·실질임금 진단·결론을 세로 스크롤 대신 카드 7장을 좌우로
   넘기며 보는 방식. 온보딩 위저드(.onboarding-step)가 이미 "한 화면에
   하나씩, 상단 진행바"를 검증해 둔 패턴이라 같은 시각 언어(스텝인
   애니메이션·진행 표시·카드 배경)를 재사용한다. */
.deck { padding: .3rem 0 1rem; }
.deck[hidden] { display: none; }

/* ---------- 한눈에 보기 토글 (v20 항목8) ---------- */
.deck-toolbar { display: flex; justify-content: flex-end; max-width: 1000px; margin: 0 auto .5rem; padding-inline: .2rem; }
.deck-view-toggle {
  appearance: none; cursor: pointer; font: inherit;
  border: 1px solid var(--border); background: var(--surface-2); color: var(--text-secondary);
  border-radius: 999px; padding: .35rem .9rem; font-size: .78rem; font-weight: 600;
}
.deck-view-toggle:hover { border-color: var(--border-strong); color: var(--text-primary); }
.deck-view-toggle[aria-pressed="true"] { background: var(--brand); border-color: var(--brand); color: #fff; }

/* 카드뉴스(스와이프) 대신 카드 전부를 세로로 이어 붙여 스크롤 한 번에
   다 보여준다 — 인쇄용 @media print 블록이 이미 만들어 둔 "덱을
   문서처럼 펼치는" 레이아웃을 화면에서도 토글로 쓸 수 있게 재사용한다.
   점 인디케이터·화살표는 스와이프 전용이라 이 모드에서는 의미가
   없어 숨긴다. */
.deck.is-full-view .deck-dots,
.deck.is-full-view .deck-arrow { display: none; }
.deck.is-full-view .deck-shell { display: block; }
.deck.is-full-view .deck-viewport {
  width: auto; max-width: 640px; height: auto; min-height: 0; overflow: visible; margin-inline: auto;
}
.deck.is-full-view .deck-track { display: block; transform: none !important; transition: none !important; }
.deck.is-full-view .deck-card {
  flex: none; width: auto; height: auto; overflow: visible;
  padding: 0 0 1.4rem;
}
.deck.is-full-view .deck-card + .deck-card { border-top: 1px dashed var(--border-strong); padding-top: 1.4rem; }
.deck.is-full-view .deck-card.is-cover { min-height: 0; }

.deck-dots { display: flex; justify-content: center; align-items: center; gap: .45rem; margin-bottom: .9rem; }
.deck-dot {
  appearance: none; padding: 0; cursor: pointer;
  width: 8px; height: 8px; border-radius: 999px;
  border: 1.5px solid var(--border-strong); background: transparent;
  transition: width .2s ease, background .2s ease, border-color .2s ease;
}
.deck-dot.is-done { background: var(--brand); border-color: var(--brand); }
.deck-dot.is-current { width: 22px; background: var(--brand); border-color: var(--brand); }

.deck-shell { display: flex; align-items: center; justify-content: center; gap: 1rem; }

.deck-arrow {
  flex: 0 0 auto; width: 42px; height: 42px; padding: 0;
  display: grid; place-items: center;
  border: 1px solid var(--border); background: var(--surface-2); color: var(--text-secondary);
  border-radius: 999px; font-size: 1.4rem; line-height: 1; cursor: pointer; font-family: inherit;
}
.deck-arrow:hover { border-color: var(--border-strong); color: var(--text-primary); }
.deck-arrow:disabled { opacity: .3; cursor: default; }
/* 화살표는 데스크톱 전용 — 모바일은 스와이프·좌우 탭으로 넘긴다.
   상단바가 grid로 바뀌는 861px 기준을 그대로 재사용한다. */
@media (max-width: 860px) { .deck-arrow { display: none; } }

/* 카드 한 장 = 화면 한 장. 상단바+티커+점 인디케이터 높이를 뺀
   나머지를 뷰포트 높이로 쓴다. calc(100dvh - 13rem)은 JS가 실제
   측정값으로 덮어쓰기 전까지의 초기값일 뿐이다 — 고정 rem 상수는
   상단바 부제목이 줄바꿈되는 화면 폭(약 861~950px) 등에서 실제
   헤더 높이와 어긋나 카드 위쪽이 sticky 헤더에 가려지는 문제가 있었다
   (setupCardDeck의 syncViewportHeight 참고). 콘텐츠가 그래도 넘치면
   카드 안에서만 세로 스크롤된다. */
.deck-viewport {
  width: 100%; max-width: 540px; min-height: 420px;
  height: calc(100dvh - 13rem); height: calc(100svh - 13rem);
  overflow: hidden; border-radius: var(--radius); position: relative;
  touch-action: pan-y;
}
/* 데스크톱은 모바일 폭(540px)을 그대로 쓰면 좌우 여백이 불필요하게
   넓다. 가로 배치(.deck-split)와 함께 화면을 더 활용하되, 텍스트
   줄 길이가 늘어져 가독성이 떨어지지 않도록 1000px에서 제한한다. */
@media (min-width: 861px) {
  .deck-viewport { max-width: 1000px; }
}

/* 카드 안 요소를 데스크톱에서 2단으로 배치해 세로 길이를 줄인다
   (카드 2의 정보+그래프, 카드 5의 소득 조건+진단 카드). 모바일은
   화면이 좁아 강제하지 않고 기존처럼 세로로 쌓는다. */
.deck-split { display: block; }
.deck-split > * + * { margin-top: 1rem; }
@media (min-width: 861px) {
  .deck-split {
    display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 1.4rem; align-items: start;
  }
  .deck-split > * + * { margin-top: 0; }
}
.deck-track {
  display: flex; height: 100%;
  transition: transform .32s cubic-bezier(.22, .61, .36, 1);
}
.deck-card {
  flex: 0 0 100%; width: 100%; height: 100%; box-sizing: border-box;
  overflow-y: auto; -webkit-overflow-scrolling: touch;
  padding: 1.3rem 1.2rem 2rem;
}
.deck-card > * + * { margin-top: 1rem; }
.deck-card .report-heading { margin-bottom: 0; }

/* 카드 1(표지)만 세로 가운데 정렬 — 나머지 카드는 위에서부터 읽는
   일반 카드 레이아웃(기존 리포트와 같은 흐름)을 유지한다. */
/* justify-content:center인 채로 콘텐츠가 카드 높이보다 길어지면(모바일
   처럼 뷰포트가 낮을 때 특히), 넘치는 만큼이 위/아래로 반씩 나뉘어
   밀려나면서 "위로 밀려난 절반"이 화면 밖(#deckViewport의
   overflow:hidden)으로 잘려나가 스크롤로도 다시 볼 수 없는 문제가
   있었다(카드1 맨 위 마스코트 얼굴 위쪽이 잘려 보이던 원인). safe
   center는 넘칠 경우 자동으로 맨 위 정렬로 대체해 항상 스크롤로
   전체 콘텐츠에 닿을 수 있게 한다 — 미지원 브라우저는 이 줄이
   무효화되어 그냥 앞의 center로 남는다(점진적 향상, JS 불필요). */
.deck-card.is-cover {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  justify-content: safe center;
  text-align: center; gap: 1rem; min-height: 100%;
}
/* 점 인디케이터·화살표·스와이프로도 이미 이동할 수 있는 보조
   버튼(카드 6의 목표/타임머신 진입 버튼 등)은 화면의 유일한 CTA처럼
   크게 보일 필요가 없다 — 다른 텍스트 요소와 비슷한 비중으로 줄인다. */
.home-start-btn.is-compact { font-size: .82rem; padding: .55rem 1.3rem; }

@media (prefers-reduced-motion: reduce) {
  .deck-track { transition: none; }
  .deck-dot { transition: none; }
}

/* 목표 자산/타임머신은 카드뉴스가 아니라 예전처럼 독립된 스크롤
   페이지다 — 덱에서 벗어났다는 걸 알리고 돌아갈 방법을 준다. */
.deck-back-btn {
  appearance: none; border: 0; background: none; cursor: pointer; font: inherit;
  color: var(--brand); font-weight: 600; font-size: .85rem; padding: 0 0 .9rem; display: block;
}
.deck-back-btn:hover { text-decoration: underline; }

/* 결과 카드는 나란히 놓는다. 세로로 쌓으면 평가자가 스크롤을 안 해서
   아래 내용을 아예 못 본다. */
.result-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 420px), 1fr));
  gap: 1rem; align-items: start;
}
.result-grid > * { min-width: 0; margin-top: 0; }

/* 부가 입력은 접어 둔다 — 12개를 한 번에 보여주면 입력 벽처럼 보인다 */
.more-fields { margin-top: .3rem; }
.more-fields summary {
  cursor: pointer; font-size: .78rem; color: var(--text-muted);
  padding: .4rem 0; user-select: none;
}
.more-fields summary:hover { color: var(--text-secondary); }
.more-fields summary::marker { color: var(--brand); }
.more-fields[open] summary { margin-bottom: .4rem; }

/* "나와 가까운 생활 유형"/"나의 소득 조건"/"목표 설정" 같은 답변 요약
   블록의 제목 — 결과 블록 제목(h3.block-title)과 크기를 맞춰서 같은
   무게로 읽히게 한다. 예전엔 1.02rem으로 유난히 작아서 이 블록만
   밋밋해 보였다. */
.section-head { display: flex; gap: .7rem; align-items: flex-start; margin-bottom: .7rem; }
.section-head h2 { margin: 0; font-size: 1.2rem; font-weight: 800; letter-spacing: -.01em; }
.section-head p { margin: .15rem 0 0; font-size: .8rem; color: var(--text-muted); }

h3.block-title { font-size: 1.2rem; font-weight: 800; margin: 0 0 .2rem; letter-spacing: -.01em; }
p.block-q { margin: 0 0 .6rem; font-size: .8rem; color: var(--text-muted); }

/* ---------- 폼 ---------- */
.field-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: .7rem; }
.field-grid > * { min-width: 0; }
.field-grid > .field-span2 { grid-column: 1 / -1; }
@media (max-width: 480px) { .field-grid { grid-template-columns: minmax(0, 1fr); } }
/* 목표 기간의 년·개월을 한 라벨 아래 두 입력칸으로 나란히 둔다(예:
   "목표 기간(년)"/"목표 기간(개월)"을 별개 필드로 두면 같은 값을 두
   군데로 쪼갠 것처럼 보인다는 피드백). */
.duo-input { display: flex; gap: .5rem; }
.duo-input > .input-wrap { flex: 1; min-width: 0; }
/* label.field(입력칸을 감싸는 라벨)뿐 아니라 div.field(세그먼트·체크박스
   그룹을 감싸는 라벨, 예: "투자 성향", "비교할 자산")도 같이 잡아야
   한다 — label.field만 잡으면 div.field 쪽은 라벨 스타일을 못 받아서
   기본 텍스트 크기로 나오고, 그 아래 값(예: "균형형")과 크기·굵기
   차이가 없어 라벨-값 위계가 안 보였다. */
.field { display: block; font-size: .8rem; font-weight: 600; color: var(--text-secondary); margin-bottom: .5rem; }
.input-wrap {
  display: flex; align-items: center; gap: .4rem; margin-top: .32rem;
  border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  background: var(--surface-1); padding: .05rem .6rem .05rem .1rem;
}
.input-wrap:focus-within { border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-soft); }
.input-wrap input {
  flex: 1; min-width: 0; border: 0; background: none; font: inherit; color: var(--text-primary);
  padding: .5rem .6rem; font-variant-numeric: tabular-nums; text-align: right;
}
.input-wrap input:focus { outline: none; }
.input-wrap span { font-size: .78rem; color: var(--text-muted); flex: 0 0 auto; }
/* v46: 세부질문의 select(대중교통/자차, 알뜰폰 여부 등) — 숫자 입력과
   같은 .input-wrap 틀을 그대로 쓴다. */
.input-wrap select {
  flex: 1; min-width: 0; border: 0; background: none; font: inherit; color: var(--text-primary);
  padding: .5rem .6rem; cursor: pointer;
}
.input-wrap select:focus { outline: none; }
.range-label { display: block; font-size: .8rem; font-weight: 600; color: var(--text-secondary); margin-bottom: .9rem; }
.range-label .val { color: var(--brand); font-variant-numeric: tabular-nums; }
.range-label input[type="range"] { width: 100%; margin: .45rem 0 .1rem; }
.range-scale { display: flex; justify-content: space-between; font-size: .68rem; color: var(--text-muted); }

/* 슬라이더 핸들 — 기본 브라우저 핸들(대략 12~16px)은 모바일 터치로는
   정밀 조작이 어렵다는 피드백이 있어, 24px 원으로 키우고 트랙도 두껍게 했다.
   accent-color 대신 트랙·핸들을 직접 그려야 크기를 제어할 수 있다. */
input[type="range"] {
  -webkit-appearance: none; appearance: none;
  width: 100%; height: 28px; background: transparent; cursor: pointer;
  margin: 0; padding: 0;
}
input[type="range"]::-webkit-slider-runnable-track {
  height: 5px; border-radius: 999px; background: var(--gridline);
}
input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 24px; height: 24px; margin-top: -9.5px; border-radius: 50%;
  background: var(--slider-color, var(--brand));
  border: 3px solid var(--surface-2);
  box-shadow: 0 1px 3px rgba(0, 0, 0, .25);
}
input[type="range"]::-moz-range-track {
  height: 5px; border-radius: 999px; background: var(--gridline);
}
input[type="range"]::-moz-range-thumb {
  width: 24px; height: 24px; border-radius: 50%;
  background: var(--slider-color, var(--brand));
  border: 3px solid var(--surface-2);
  box-shadow: 0 1px 3px rgba(0, 0, 0, .25);
}
input[type="range"]:focus-visible::-webkit-slider-thumb { outline: 2px solid var(--brand); outline-offset: 2px; }
input[type="range"]:focus-visible::-moz-range-thumb { outline: 2px solid var(--brand); outline-offset: 2px; }

.seg { display: flex; gap: .25rem; background: var(--surface-sunk); border-radius: var(--radius-sm); padding: .22rem; }
.seg button {
  flex: 1; appearance: none; border: 0; background: none; font-family: inherit; font-size: .8rem;
  font-weight: 600; color: var(--text-muted); padding: .45rem .3rem; border-radius: 7px; cursor: pointer;
}
.seg button[aria-pressed="true"] { background: var(--surface-2); color: var(--brand); box-shadow: var(--shadow); }

.persona-grid { display: grid; gap: .42rem; }
.persona-grid button {
  appearance: none; width: 100%; text-align: left; cursor: pointer;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--surface-1); color: var(--text-primary); padding: .68rem .75rem;
  font-family: inherit;
}
.persona-grid button b { display: block; font-size: 1.1rem; font-weight: 800; line-height: 1.35; }
.persona-grid button span { display: block; margin-top: .12rem; font-size: .68rem; color: var(--text-muted); }
.persona-grid button[aria-pressed="true"] {
  border-color: var(--brand); background: var(--brand-soft); box-shadow: 0 0 0 2px var(--brand-soft);
}
.persona-grid button[aria-pressed="true"] b { color: var(--brand); }
.total-field { margin-top: .1rem; }

/* v47: 설문 Q2 세부질문 — 숫자 직접 입력 대신 구간 버튼을 고른다.
   Q1(.persona-grid)과 같은 카드형 버튼 언어를 쓰되, 짧은 라벨이 여러
   개(3~4개) 나열되는 자리라 2열로 압축한다.
   v48: 하위 항목(배달/외식·장보기·카페/음료 등)을 세로로 쭉 늘어놓으면
   스크롤이 길어진다는 피드백 — 탭으로 분리해 한 번에 하나만 보여준다.
   빈도·1회금액 두 질문은 좁은 화면(480px 이하)에서만 세로로 접힌다 —
   그 아래에서는 구간 버튼 2열(.range-grid)이 이미 화면 폭을 다 쓰고
   있어서 나란히 배치하면 버튼이 지나치게 좁아진다. */
.quiz-tabs { display: flex; gap: .4rem; margin-bottom: 1rem; overflow-x: auto; }
.quiz-tab {
  flex: 0 0 auto; appearance: none; cursor: pointer; font-family: inherit; white-space: nowrap;
  border: 1px solid var(--border); border-radius: 999px; background: var(--surface-1);
  color: var(--text-secondary); font-size: .82rem; font-weight: 700; padding: .5rem .95rem;
}
.quiz-tab[aria-selected="true"] { border-color: var(--brand); background: var(--brand); color: #fff; }
/* v51: "(월 기준)" 같은 대제목 표기 대신, 실제 입력 단위를 이 라벨과
   버튼 아래 힌트(.range-grid button span)가 직접 안내하도록 했다 —
   안내 역할이 커진 만큼 text-muted보다 대비가 확실한 text-secondary로
   올리고 굵기를 준다. */
.quiz-question-label { margin: .6rem 0 .35rem; font-size: .74rem; font-weight: 700; color: var(--text-secondary); }
.quiz-question-pair { display: grid; grid-template-columns: 1fr 1fr; gap: 1.2rem; }
.quiz-question-pair .quiz-question-label { margin-top: 0; }
/* v56: 놓치면 "억지로 아무 버튼이나 눌러야 한다"고 오해할 수 있는,
   무시하면 안 되는 안내라서 다른 보조 텍스트(.field-note류)보다
   눈에 띄는 브랜드색 텍스트 + 아이콘으로 표시한다. 카테고리마다
   색을 다르게 하면 "동일한 스타일을 일관되게" 유지하기 어려워
   5개 카테고리 전부 같은 브랜드색으로 통일한다. v57: 특정 필드에만
   조건부로 붙이던 것을(noZeroOption) 모든 freq-avg·direct 질문에
   항상 붙이는 방식으로 단순화했다. v58: 박스(배경·테두리)는 다른
   보조 텍스트에 비해 위계가 너무 세다는 피드백 — 배경·테두리를
   걷어내고 아이콘+색 텍스트만 남긴, 다른 .field-note류와 같은
   "줄글" 형태로 낮췄다. */
.quiz-no-usage-note {
  display: flex; align-items: flex-start; gap: .35rem; text-align: left;
  margin: .5rem 0 0;
  font-size: .78rem; font-weight: 600; color: var(--brand); line-height: 1.45;
}
.quiz-no-usage-icon { flex: 0 0 auto; font-size: .85rem; line-height: 1.5; }
@media (max-width: 480px) {
  .quiz-question-pair { grid-template-columns: 1fr; gap: 0; }
}
/* v58: "거의 안 함"처럼 일부 버튼에만 보조 설명(span)이 붙으면 그
   버튼이 있는 행만 콘텐츠가 커져, 행마다 각자 auto로 높이가 정해지는
   기본 그리드에서는 행끼리 높이가 달라 보였다(설명 없는 행은 짧고,
   있는 행은 김). grid-auto-rows: 1fr로 모든 행을 같은 높이(가장 큰
   행 기준)로 맞추고, 버튼 자체도 flex column + justify-content:center로
   바꿔서 설명이 없는 버튼은 늘어난 셀 안에서 텍스트가 세로 중앙에
   오도록 한다 — 버튼그룹 컴포넌트(.range-grid) 하나만 고치면 모든
   카테고리·모든 질문에 그대로 적용된다. */
.range-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); grid-auto-rows: 1fr; gap: .35rem; }
.range-grid button {
  appearance: none; width: 100%; text-align: center; cursor: pointer;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--surface-1); color: var(--text-primary); padding: .5rem .4rem;
  font-family: inherit;
  display: flex; flex-direction: column; justify-content: center;
}
.range-grid button b { display: block; font-size: .82rem; font-weight: 700; line-height: 1.3; }
.range-grid button span { display: block; margin-top: .15rem; font-size: .7rem; font-weight: 600; color: var(--text-secondary); }
.range-grid button[aria-pressed="true"] {
  border-color: var(--brand); background: var(--brand-soft); box-shadow: 0 0 0 2px var(--brand-soft);
}
.range-grid button[aria-pressed="true"] b { color: var(--brand); }
.range-grid button[aria-pressed="true"] span { color: var(--brand); }

/* v49: 카드 폭을 넓힌 만큼 데스크톱에서는 안 요소도 비례해서 키운다 —
   모바일은 이미 화면이 좁아 카드가 상대적으로 커 보이므로 기존 크기
   그대로 둔다(기존 .deck-viewport 등과 같은 861px 기준선 재사용). */
@media (min-width: 861px) {
  .onboarding-step h2 { font-size: 2.2rem; }
  .quiz-tabs { gap: .6rem; margin-bottom: 1.3rem; }
  .quiz-tab { font-size: .92rem; padding: .65rem 1.3rem; }
  .quiz-question-label { font-size: .82rem; }
  .quiz-question-pair { gap: 2rem; }
  .range-grid { gap: .6rem; }
  .range-grid button { padding: .85rem .7rem; }
  .range-grid button b { font-size: .95rem; }
  .range-grid button span { font-size: .78rem; margin-top: .2rem; }
}
/* 가구 유형(#personaLabel)은 인풋이 아닌 텍스트라 input[readonly]의
   "설문에서 이미 답한 값" 스타일을 못 물려받는다 — 같은 무게로 맞춘다. */
.field-value {
  margin: .32rem 0 0; font-size: clamp(1.4rem, 2.6vw, 1.7rem); font-weight: 800;
  letter-spacing: -.02em; color: var(--text-primary);
}

.field-note { font-size: .73rem; color: var(--text-muted); margin: .35rem 0 0; }
/* 실시간 물가 출처 문구(#inflSource)는 스켈레톤일 때 한 줄 높이만
   차지하는데, 실제 문장("실시간 · OECD 기준 ...")은 좁은 화면에서
   두 줄로 넘어갈 수 있어 값이 도착하는 순간 아래 내용이 밀린다.
   항상 두 줄 높이를 미리 잡아 둔다. */
#inflSource { line-height: 1.4; min-height: 2.8em; }
/* 색만으로 표시하던 경고문을 배경 있는 알림 칩으로 — 색약 사용자도
   구분되고, 눈에도 훨씬 잘 띈다. display:flex는 [hidden]과 명시도가
   같아서 나중 선언이 이기므로, 숨김 상태를 명시적으로 다시 덮어써야
   한다(이 코드베이스에서 반복된 패턴). */
.err-text {
  display: flex; align-items: center; gap: .4rem;
  font-size: .78rem; font-weight: 700; color: var(--critical-text);
  margin: .5rem 0 0; padding: .55rem .75rem;
  background: color-mix(in srgb, var(--critical) 10%, transparent);
  border-left: 3px solid var(--critical); border-radius: var(--radius-sm);
}
.err-text::before { content: "⚠️"; flex: 0 0 auto; }
.err-text[hidden] { display: none; }
.input-wrap.invalid { border-color: var(--critical); }
/* 입력 범위 경고문(field-guard-err)은 .spend-row 같은 grid 컨테이너
   안에 인풋의 형제로 꽂힐 수 있다 — 항상 전체 폭으로 펼쳐서 2번째
   그리드 칸에 눌려 찌그러지지 않게 한다. grid가 아닌 곳에서는 무시된다. */
.field-guard-err { grid-column: 1 / -1; }

/* ---------- 설문에서 이미 답한 값 (읽기 전용) ----------
   readonly는 타이핑만 막고 JS의 .value 읽기/쓰기는 그대로 허용한다 —
   자산 타임머신 → 목표 자산 브릿지, 지출 세부수정 → 월 생활비 합산처럼
   다른 탭/위젯이 이 값을 코드로 계속 갱신해야 하기 때문이다. 폼 필드가
   아니라 그냥 값을 보여주는 것처럼 테두리·배경·스핀 버튼을 없앤다. */
.input-wrap:has(input[readonly]) {
  border-color: transparent; background: none; padding-left: 0;
}
.input-wrap:has(input[readonly]):focus-within { box-shadow: none; }
/* 값 자체(180, 3600만원 등)가 이 블록에서 가장 중요한 정보인데 폼
   기본 크기(1rem)로 남아 있어서 라벨과 구분이 안 되고 밋밋해 보였다.
   .stat .v와 같은 "크고 굵은 숫자" 언어로 맞춘다. */
input[readonly] {
  font-size: clamp(1.4rem, 2.6vw, 1.7rem); font-weight: 800; letter-spacing: -.02em;
  color: var(--text-primary); cursor: default;
}
input[readonly]::-webkit-outer-spin-button,
input[readonly]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
input[readonly] { -moz-appearance: textfield; }

/* ---------- KPI ----------
   같은 줄의 카드끼리 캡션(.s) 줄 수가 다르면(1줄 vs 2줄), 그리드가
   기본으로 카드 높이를 맞추면서(align-items:stretch) 짧은 카드 하단에
   빈 공간이 남아 불균형해 보인다. 카드를 세로 flex로 만들고 캡션에
   margin-top:auto를 줘서, 제목+숫자는 항상 위쪽에 나란히 붙고 캡션은
   줄 수와 무관하게 카드 맨 아래에 정렬되게 한다. .stat을 쓰는 모든
   섹션(내 물가·실질임금 진단·목표 자산·자산 타임머신)에 공통 적용된다. */
/* grid auto-fit는 카드 개수가 열 수의 배수가 아니면(예: 4열에 카드 6개)
   마지막 줄이 같은 열 폭을 그대로 물려받아 오른쪽이 비어 보인다 —
   grid의 트랙 구조는 모든 줄에 공통이라 줄마다 다르게 배치할 수 없다.
   flex-wrap은 줄 단위로 배치하므로 justify-content:center로 마지막 줄만
   자연스럽게 가운데 모을 수 있다. max-width는 카드가 없는 줄에서 남는
   공간을 혼자 다 먹어 커지지 않도록 꽉 찬 줄과 비슷한 폭으로 잡아준다. */
.stat-grid { display: flex; flex-wrap: wrap; justify-content: center; gap: .7rem; }
.stat {
  background: var(--surface-1); border-radius: var(--radius-sm);
  padding: .8rem .9rem;
  display: flex; flex-direction: column;
  flex: 1 1 150px; max-width: 220px;
  container-type: inline-size;
}
.stat .k { font-size: .74rem; color: var(--text-muted); display: block; margin-bottom: .3rem; }
/* v26: "내년 연봉으로 실제 살 수 있는 만큼" 같이 자릿수가 큰 값
   ("3,643만원")은 다른 카드보다 글자 수가 많은데 폭은 같은
   .stat-grid 아래서 정해져서, 고정 크기(vw 기준)로는 이 카드만
   두 줄로 줄바꿈됐다. 뷰포트가 아니라 이 박스 자신의 실제 너비를
   기준으로 글자 크기가 줄어들게(cqw, container-type:inline-size
   필요) 바꿔, 어떤 값이 와도 박스 폭에 맞춰 자동으로 줄어들며 항상
   한 줄을 유지한다 — 카드 개수·값 자릿수가 바뀌어도 다시 손댈
   필요가 없다. white-space:nowrap으로 줄바꿈 자체를 막아둔다. */
.stat .v {
  font-size: clamp(1.3rem, 17cqw, 2.15rem); font-weight: 800; letter-spacing: -.02em;
  font-variant-numeric: tabular-nums; display: block; white-space: nowrap;
}
.stat .s { font-size: .72rem; color: var(--text-muted); margin-top: auto; padding-top: .3rem; }
.stat.is-good .v { color: var(--good-text); }
.stat.is-warn .v { color: var(--warning-text); }
.stat.is-bad  .v { color: var(--critical-text); }

/* 조작하면 같이 바뀌는 결론 문장 */
.verdict {
  margin: .8rem 0 0; padding: .75rem .9rem; border-radius: var(--radius-sm);
  background: var(--brand-soft); border: 1px solid color-mix(in srgb, var(--brand) 22%, transparent);
  font-size: .9rem; line-height: 1.55;
}
.verdict b { color: var(--brand); }
.verdict.warn { background: color-mix(in srgb, var(--warning) 13%, transparent); border-color: color-mix(in srgb, var(--warning) 35%, transparent); }
.verdict.warn b { color: var(--warning-text); }
.verdict.bad { background: color-mix(in srgb, var(--critical) 10%, transparent); border-color: color-mix(in srgb, var(--critical) 30%, transparent); }
.verdict.bad b { color: var(--critical-text); }

/* v13: 공식 물가·내 물가 %가 작은 보조 텍스트(.vs-figures)라 헤드라인
   문장에 묻혀 보인다는 피드백 — 카드의 시각적 중심이 되도록 큰 숫자로
   뺐다(아이스 아메리카노 콜아웃을 없앤 자리). "내 물가" 쪽은 브랜드
   색으로 강조하고, 그 옆 %p 차이는 유불리에 따라 경고/양호 색을 쓴다. */
.price-compare { display: flex; gap: 1rem; justify-content: center; flex-wrap: wrap; }
.price-compare-item {
  display: flex; flex-direction: column; align-items: center; gap: .2rem;
  padding: .7rem 1.4rem; border-radius: var(--radius-sm); background: var(--surface-1);
}
.price-compare-label { font-size: .78rem; font-weight: 600; color: var(--text-muted); }
.price-compare-value {
  font-size: clamp(1.9rem, 4vw, 2.5rem); font-weight: 800; letter-spacing: -.02em;
  line-height: 1.1; font-variant-numeric: tabular-nums; color: var(--text-primary);
}
.price-compare-item.is-mine {
  background: var(--brand-soft); border: 1px solid color-mix(in srgb, var(--brand) 25%, transparent);
}
.price-compare-item.is-mine .price-compare-value { color: var(--brand); }
.price-compare-diff { font-size: .82rem; font-weight: 700; color: var(--text-muted); }
.price-compare-diff.is-warn { color: var(--warning-text); }
.price-compare-diff.is-good { color: var(--good-text); }

/* ---------- 베이토 그리드 ----------
   카드를 세로로 쌓으면 높이가 내용에 끌려다녀 크기가 제각각으로 보인다.
   격자에 맞춰 배치하면 크기 차이가 "들쭉날쭉"이 아니라 "의도된 위계"가 된다. */
/* 기사처럼 위에서 아래로 읽히는 단일 칼럼. 예전엔 12열 그리드로 입력
   패널을 왼쪽에, 결과를 오른쪽 2단으로 짰지만(카드 테두리가 있을 땐
   대시보드처럼 훑어보기 좋았다), 카드 장식을 없앤 뒤로는 시선이
   좌우로 갈라져서 오히려 읽기 산만하다는 피드백이 있었다. 모바일
   전용이었던 "DOM 순서 그대로 세로 스택" 규칙(예전엔 780px 이하에서만
   적용)을 전체 폭 기본값으로 올렸다 — 이 순서(입력요약 → 핵심 결과 →
   차트 → 세부 통계 → 설명/버튼)는 이미 모바일에서 자연스럽게 읽힌다고
   확인된 순서라 그대로 재사용한다. 폭은 기사 본문처럼 제한해서
   가운데 정렬한다. */
.bento {
  display: flex; flex-direction: column;
  /* 블록에 배경·패딩이 있어서 구분은 충분히 되니, 공간을 쓸데없이 많이
     차지한다는 피드백을 반영해 더 좁힌다 — 토스 리스트처럼 카드끼리
     붙어서 흐르게. */
  gap: 1rem;
  max-width: 820px; margin-inline: auto;
}
.bento > * { min-width: 0; margin-top: 0 !important; }
.bento .chart-box svg, .deck-card .chart-box svg { width: 100%; }

/* 스크롤하며 섹션이 하나씩 나타나는 연출 — stepIn 키프레임(온보딩 문항
   전환에도 쓰는 것과 같은 모양)을 재사용한다. JS(setupScrollReveal)가
   뷰포트에 처음 들어온 블록에 is-visible을 붙인다. reduced-motion에서는
   처음부터 다 보이는 상태로 시작해서 애니메이션 자체가 의미 없어진다 —
   이 파일의 다른 애니메이션(캐럿 깜빡임, 로딩 스피너 등)과 같은 처리. */
.bento > * { opacity: 0; transform: translateY(10px); }
.bento > *.is-visible { animation: stepIn .4s ease forwards; }
@media (prefers-reduced-motion: reduce) {
  .bento > * { opacity: 1; transform: none; }
  .bento > *.is-visible { animation: none; }
}

/* 리포트 결과가 네모칸 여러 개로 나뉘어 번잡스럽다는 피드백 → 테두리와
   그림자를 없앤 완전 플랫 버전으로 바꿨더니 이번엔 섹션 구분이 아예 안
   보여 가독성이 떨어진다는 피드백. 토스 스타일로 절충한다 — 윤곽선
   대신 옅은 색 블록으로 구분하고(테두리·그림자는 계속 없음), 모서리는
   크게 둥글리고, 안쪽 여백은 넉넉하게 준다.
   (v8: 카드뉴스 덱 카드도 같은 톤 — .deck-card 안 .card도 같이 적용) */
.bento .card, .deck-card .card {
  background: var(--surface-2); border: 0; box-shadow: none;
  border-radius: var(--radius); padding: 1.3rem 1.4rem;
}
.bento .src-note, .deck-card .src-note { font-size: .66rem; padding: .12rem .45rem; margin-top: .45rem; }
.bento .stat, .deck-card .stat { padding: .8rem .9rem; border-radius: var(--radius-sm); }
.bento .block-q, .deck-card .block-q { margin-bottom: .6rem; }

/* "당신이 답한 내용" 블록 — 예전엔 옅은 브랜드색(--brand-soft)으로 채워
   구분했는데, 그 색이 페이지 배경(--page-plane)과 명도가 비슷해서
   경계가 잘 안 보인다는 피드백. 배경은 다른 결과 블록과 똑같이 밝게
   맞추고, 대신 브랜드색 테두리 + 옅은 그림자로 "이건 당신 답변"이라는
   구분을 준다 — 배경색보다 테두리가 경계를 훨씬 또렷하게 만든다.
   (v8: 카드뉴스 덱 안의 카드는 .bento 대신 .deck-card로 감싸므로 같이 적용) */
.bento .card.bento-input, .deck-card .card.bento-input {
  background: var(--surface-2);
  border: 1px solid color-mix(in srgb, var(--brand) 32%, var(--border-strong));
  box-shadow: var(--shadow);
}
.answer-bridge {
  margin: .8rem 0 0; padding-top: .6rem; border-top: 1px dashed color-mix(in srgb, var(--brand) 30%, transparent);
  font-size: .82rem; font-weight: 700; color: var(--brand); text-align: center;
}

/* ---------- 지출 구성 슬라이더 ---------- */
.total-field {
  display: flex; align-items: center; justify-content: space-between;
  gap: .6rem; margin-bottom: .8rem; font-size: .84rem; font-weight: 600;
  color: var(--text-secondary);
}
.total-field .input-wrap { margin-top: 0; width: 132px; flex: 0 0 auto; }

/* 구성 비율을 한 줄에 보여주는 누적 막대 */
.mix-bar {
  display: flex; height: 15px; border-radius: 999px; overflow: hidden;
  margin: .9rem 0 .8rem; background: var(--surface-sunk);
}
.mix-bar span { transition: width .12s ease; }
.mix-bar span:first-child { border-radius: 999px 0 0 999px; }
.mix-bar span:last-child { border-radius: 0 999px 999px 0; }

.mix-row { margin-bottom: .52rem; }
.mix-head {
  display: flex; align-items: baseline; gap: .35rem; font-size: .76rem;
  color: var(--text-secondary); margin-bottom: .1rem;
}
.mix-name { font-weight: 600; }
.mix-head .spacer { flex: 1; }
.mix-pct { font-variant-numeric: tabular-nums; font-weight: 700; color: var(--text-primary); }
.mix-won { font-variant-numeric: tabular-nums; color: var(--text-muted); font-size: .72rem; }

.mix-row input[type="range"] {
  width: 100%; margin: 0; height: 16px; cursor: pointer;
  accent-color: var(--slider-color, var(--brand));
}

/* ---------- 내 물가: 대비 헤드라인 ---------- */
.headline-card { text-align: center; padding: 1.1rem 1.3rem 1rem; }
.kicker { margin: 0 0 .7rem; font-size: .8rem; color: var(--text-muted); }
.bento-hero .verdict { margin-top: .8rem; }

/* 지출 입력 */
.spend-details-label { color: var(--brand); font-size: .8rem; font-weight: 700; margin: 0 0 .65rem; }
/* v51: 카테고리 5개 응답을 다 마친 뒤 보여주는 "전체 요약" 독립 스텝 —
   카드2("내 물가란?")의 완성된 리포트용 도넛과 달리 아직 답을
   채워가는 중간 화면이라 차트 없이 텍스트 목록으로만 구성한다
   (v50에서 카드6 하단에 있던 요약을 이 스텝이 더 자세한 버전으로
   흡수했다). */
.onb-summary-group { padding: .85rem 0; border-bottom: 1px solid var(--border); }
.onb-summary-group:first-child { padding-top: 0; }
.onb-summary-group:last-of-type { border-bottom: none; }
.onb-summary-group-title {
  display: flex; align-items: center; gap: .45rem; margin: 0 0 .5rem;
  font-size: .92rem; font-weight: 800; color: var(--text-primary);
}
.onb-summary-fields { margin: 0 0 .5rem; padding-left: 1.15rem; display: flex; flex-direction: column; gap: .3rem; }
.onb-summary-fields li { font-size: .84rem; color: var(--text-secondary); line-height: 1.5; }
/* v52: 미답 카테고리가 답한 카테고리와 톤이 비슷해 눈에 안 띈다는
   피드백 — .verdict.warn과 같은 --warning 토큰으로 옅은 배경 + 왼쪽
   포인트 바를 주고, 답한 카테고리(위 기본 스타일)와 명확히 구분한다. */
.onb-summary-group.is-unanswered {
  margin: .3rem 0; padding: .85rem .9rem; border: none;
  border-left: 3px solid var(--warning); border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--warning) 12%, transparent);
}
.onb-summary-warn-note {
  display: flex; align-items: flex-start; gap: .4rem; margin: 0 0 .5rem;
  font-size: .83rem; font-weight: 600; color: var(--warning-text); line-height: 1.5;
}
.onb-summary-warn-icon { flex: 0 0 auto; font-size: .95rem; line-height: 1.4; }
.onb-summary-group.is-unanswered .onb-summary-group-total { color: var(--warning-text); }
.onb-summary-group.is-unanswered .onb-summary-group-total b { color: var(--warning-text); }
/* 페이지 상단의 "N개 카테고리는 아직 답하지 않아…" 한 줄 — 카드 밖,
   h2 바로 아래라 .onboarding-card .field-note의 가운데 정렬을 그대로
   물려받지 않는다. */
.onb-summary-unanswered-count { margin: 0; font-size: .82rem; font-weight: 700; color: var(--warning-text); text-align: center; }
.onb-summary-group-total { margin: 0; font-size: .86rem; font-weight: 700; color: var(--text-primary); }
.onb-summary-group-total b { color: var(--brand); }
.onb-summary-grand-total {
  margin: 1rem 0 0; padding-top: 1rem; border-top: 2px solid var(--border);
  font-size: 1.2rem; font-weight: 800; color: var(--text-primary);
}
.spend-row {
  display: grid; grid-template-columns: minmax(0, 1fr) 130px;
  gap: .5rem; align-items: center; margin-bottom: .42rem;
}
.spend-row > label { font-size: .8rem; color: var(--text-secondary); min-width: 0; }
.spend-row > label small { display: block; font-size: .68rem; color: var(--text-muted); }
.spend-row .rate-chip {
  font-size: .66rem; font-variant-numeric: tabular-nums; padding: .05rem .32rem;
  border-radius: 999px; margin-left: .3rem; white-space: nowrap;
}
.rate-hot  { background: color-mix(in srgb, var(--critical) 13%, transparent); color: var(--critical-text); }
.rate-mild { background: var(--surface-sunk); color: var(--text-muted); }
.rate-cool { background: color-mix(in srgb, var(--good) 14%, transparent); color: var(--good-text); }

.spend-total {
  display: flex; justify-content: space-between; align-items: baseline;
  margin-top: .6rem; padding-top: .6rem; border-top: 1px solid var(--border);
  font-size: .84rem; color: var(--text-secondary);
}
.spend-total b { font-size: 1.35rem; font-weight: 800; font-variant-numeric: tabular-nums; }

/* ---------- 처방전 (카드1 결론 문단) ----------
   v21 전에는 .final-card라는 그라디언트 박스 안에 감싸 카드7 맨
   아래에 있었다 — 카드1로 옮기면서 카드1이 이미 .is-cover로 가운데
   정렬·여백을 처리하므로 별도 박스 스타일은 없앴다. v22 "닥터"
   컨셉에서 다시 점선 테두리 박스(.prescription-box)로 감싸 실제
   처방전 용지를 은유한다 — 과하지 않게 점선 테두리 하나만 쓴다.
   (v23: "Rx 처방전" 텍스트 라벨 자체는 카드1에서 뺐다 — 박스와
   점선만으로도 처방전 느낌은 남아 있어서 과했다는 판단.) */
.prescription-box {
  margin-top: .8rem; padding: 1.3rem 1.4rem;
  border: 1.5px dashed color-mix(in srgb, var(--brand) 45%, var(--border-strong));
  border-radius: var(--radius-sm); background: var(--surface-2);
}
.final-body {
  max-width: 34rem; margin: 0 auto; text-align: center;
  font-size: 1rem; line-height: 1.8; color: var(--text-secondary); white-space: pre-line;
  min-height: 6em;
  word-break: keep-all;
}

/* ---------- 차트 ---------- */
/* flex-shrink:0 — 카드1(.deck-card.is-cover)처럼 세로 flex 컬럼 안에서
   쓰일 때, overflow-x:auto가 있는 요소는 flexbox의 "콘텐츠 기준 자동
   최소 크기" 보호를 받지 못해 형제 요소들과 세로 공간을 다투다가
   높이가 0으로 눌려버리는 문제가 있었다(모바일처럼 뷰포트가 낮아
   카드 내용이 다 안 들어갈 때 재현 — 축·막대·값 라벨이 전부 통째로
   사라져 보였다). 이 차트만은 절대 눌리지 않게 고정한다. */
.chart-box { margin-top: .3rem; overflow-x: auto; flex-shrink: 0; }
.chart-box svg { display: block; width: 100%; height: auto; min-width: 300px; }
/* 막대 3개짜리 비교 차트처럼 세로:가로 비율이 낮은 차트는 카드
   전체 폭으로 늘어나면 그만큼 세로로도 길어진다(v13 — 카드 4의
   스탯을 다른 카드로 옮기고 나니 차트 혼자 전체 폭을 다 쓰면서
   불필요하게 커졌다). 이런 차트는 폭을 제한해 세로 길이를 줄인다. */
.chart-box.is-compact-bar { max-width: 480px; margin-inline: auto; }
.axis-line { stroke: var(--baseline); stroke-width: 1; }
.grid-line { stroke: var(--gridline); stroke-width: 1; stroke-dasharray: 2 3; }
.axis-text { fill: var(--text-muted); font-size: 11px; font-family: inherit; }
.series-label { font-size: 11px; font-weight: 600; font-family: inherit; }
.bar-value { fill: var(--text-primary); font-size: 11px; font-weight: 700; font-family: inherit; }
/* 기여도 그래프(contributionChart) 전용 — 다른 차트(막대·꺾은선)와
   .axis-text/.bar-value를 공유하면 거기도 같이 커져서 이 두 클래스를
   따로 둔다. 12개 항목이 5개 그룹으로 줄면서 세로 여유가 생겨 글자를
   더 키울 수 있게 됐다. */
.contrib-label { font-size: 13px; }
.contrib-value { font-size: 12.5px; font-weight: 800; }
/* barChart() 전용(카드1 갭 그래프·카드6 협상 가이드) — 막대 위 값이
   이 그래프에서 가장 중요한 정보인데 기본 .bar-value(11px)로는 너무
   작아 안 보인다는 피드백. contrib-*와 같은 이유로 .bar-value/
   .axis-text를 공유하는 다른 차트(hBarChart, lineChart)까지 같이
   커지지 않게 전용 클래스로 분리했다. */
.gap-value { font-size: 20px; }
.gap-axis-label { font-size: 15px; fill: var(--text-secondary); }

.legend { display: flex; flex-wrap: wrap; gap: .5rem .95rem; margin-top: .7rem; font-size: .78rem; color: var(--text-secondary); }
.legend-item { display: inline-flex; align-items: center; gap: .35rem; }
.legend-swatch { width: 10px; height: 10px; border-radius: 3px; flex: 0 0 auto; }

.donut-row { display: flex; gap: 1.3rem; align-items: center; flex-wrap: wrap; }
/* 도넛 옆에 나란히 놓을 다른 요소(입력 목록 등)가 없는 자리에서는
   기본 flex-start 정렬 때문에 도넛이 카드 왼쪽으로 치우쳐 보인다 —
   카드 2의 세부 품목 그래프처럼 도넛 혼자 있는 칸에서만 가운데로 맞춘다. */
.spend-chart-col { text-align: center; }
.donut-row.is-centered { justify-content: center; }
.legend.is-centered { justify-content: center; }
/* mask는 그 엘리먼트가 그려낸 전체(자식 포함)를 하나로 합성한 뒤에
   잘라낸다 — 안쪽 원을 뚫으려고 .donut에 mask를 걸면, 자식인
   .donut-center에 mask:none을 줘도 가운데 텍스트까지 같이 사라진다
   (실제로 이 버그로 기대수익률 숫자가 안 보이고 있었다). 그래서
   가운데 텍스트는 .donut의 자식이 아니라 형제로 두고, 같은
   .donut-wrap 위에 절대좌표로 겹쳐서 mask의 영향을 아예 안 받게 한다. */
.donut-wrap { width: 156px; height: 156px; flex: 0 0 auto; position: relative; }
.donut {
  position: absolute; inset: 0; border-radius: 50%;
  -webkit-mask: radial-gradient(circle, transparent 52%, #000 53%);
          mask: radial-gradient(circle, transparent 52%, #000 53%);
}
.donut-center {
  position: absolute; inset: 0; display: grid; place-content: center; text-align: center;
}

/* ---------- 표 ----------
   나머지 화면은 다 숫자를 크고 굵게 키웠는데(토스 스타일) 표만 예전
   그대로 작은 스프레드시트 글씨로 남아 있어서 유독 촘촘하고 읽기
   힘들어 보였다 — 포트폴리오 표(자산배분·시나리오 비교 등)가 가장
   눈에 띄는 곳이라 특히 두드러졌다. 본문 글자를 키우고, 숫자 칸은
   굵게 강조하고, 줄 간격도 넉넉하게 한다. */
.table-scroll { overflow-x: auto; margin-top: 1rem; }
table { width: 100%; border-collapse: collapse; font-size: 1rem; min-width: 440px; }
th, td { text-align: left; padding: .7rem .7rem; border-bottom: 1px solid var(--border); }
th { font-size: .8rem; color: var(--text-muted); font-weight: 700; }
td { font-weight: 600; }
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; }
td.num { font-weight: 800; font-size: 1.05rem; }
tr.cat-row td { background: var(--surface-sunk); }
.risk-badge { display: inline-block; font-size: .68rem; padding: .1rem .45rem; border-radius: 999px; font-weight: 700; }
.risk-low  { background: color-mix(in srgb, var(--good) 15%, transparent); color: var(--good-text); }
.risk-mid  { background: color-mix(in srgb, var(--warning) 20%, transparent); color: var(--warning-text); }
.risk-high { background: color-mix(in srgb, var(--critical) 13%, transparent); color: var(--critical-text); }

/* ---------- 자산 선택 ---------- */
.asset-picks { display: flex; flex-wrap: wrap; gap: .45rem; margin: .2rem 0 1rem; }
.pick {
  display: inline-flex; align-items: center; gap: .4rem; cursor: pointer;
  border: 1px solid var(--border-strong); border-radius: 999px; padding: .32rem .75rem;
  font-size: .8rem; background: var(--surface-1); user-select: none;
}
.pick input { accent-color: var(--brand); margin: 0; }
.pick:has(input:checked) { border-color: var(--brand); background: var(--brand-soft); color: var(--brand); font-weight: 600; }
.pick .dot { width: 9px; height: 9px; border-radius: 50%; }

/* ---------- 데이터 출처 배지 ---------- */
.src-note {
  display: inline-flex; align-items: center; gap: .35rem; font-size: .7rem; color: var(--text-muted);
  border: 1px solid var(--border); border-radius: 999px; padding: .18rem .55rem; margin-top: .7rem;
}

.disclosure { margin-top: 2.5rem; }
.disclosure summary { cursor: pointer; font-weight: 700; font-size: .93rem; padding: .5rem 0; }
.disclosure summary::marker { color: var(--brand); }
.disclosure .body { font-size: .85rem; color: var(--text-secondary); }
.disclosure h4 { margin: 1.1rem 0 .35rem; font-size: .85rem; color: var(--text-primary); }
.disclosure ul { margin: .3rem 0; padding-left: 1.1rem; }
.disclosure li { margin: .22rem 0; }
.disclosure a, .src-note a { color: var(--text-secondary); text-underline-offset: 2px; }
.disclosure code { background: var(--surface-sunk); padding: .08rem .3rem; border-radius: 4px; font-size: .93em; }

.table-sub { display: block; margin-top: .12rem; font-size: .66rem; font-weight: 400; color: var(--text-muted); }

footer {
  margin-top: 3rem; padding: 1.8rem 0 2.6rem; border-top: 1px solid var(--border);
  font-size: .78rem; color: var(--text-muted);
}
footer a { color: var(--text-secondary); }

/* ---------- 툴팁 ---------- */
#tooltip {
  position: fixed; z-index: 100; pointer-events: none; transform: translate(-50%, -100%);
  background: var(--text-primary); color: var(--page-plane);
  padding: .4rem .6rem; border-radius: 7px; font-size: .76rem; line-height: 1.45;
  white-space: nowrap; box-shadow: var(--shadow);
}
#tooltip[hidden] { display: none; }

/* ---------- 맨 위로 버튼 ---------- */
/* 상단 탭 내비게이션이 없어진 뒤로, 리포트를 내려가다 처음으로
   돌아가려면 계속 스크롤해야 하는 불편이 있다 — 일정 이상 내려갔을
   때만 뜨는 플로팅 버튼으로 보완한다. safe-area-inset은 iOS 하단
   홈 인디케이터 영역에 버튼이 가려지지 않게 한다. */
.scroll-top-btn {
  position: fixed; z-index: 60;
  right: max(1.1rem, env(safe-area-inset-right));
  bottom: max(1.1rem, env(safe-area-inset-bottom));
  width: 44px; height: 44px; padding: 0;
  display: grid; place-items: center;
  border: 0; border-radius: 999px; cursor: pointer;
  background: var(--brand); color: #fff; box-shadow: var(--shadow);
  transition: filter .15s ease, transform .05s ease;
}
.scroll-top-btn[hidden] { display: none; }
.scroll-top-btn:hover { filter: brightness(1.08); }
.scroll-top-btn:active { transform: translateY(1px); }
.scroll-top-btn svg { width: 20px; height: 20px; }

/* ---------- 처음부터 다시 입력하기 확인 다이얼로그 ----------
   window.confirm() 대신 페이지 안 <dialog>를 쓴다 — 인앱 브라우저에서
   네이티브 confirm()이 안 뜨거나 화면 밖으로 나가버리면 confirm()의
   동기 실행 특성 때문에 사용자 눈엔 페이지가 완전히 멈춘 것처럼
   보인다. <dialog>는 그냥 페이지 안 엘리먼트라 항상 그려지고 스타일도
   디자인 시스템 그대로 맞춘다. */
.restart-dialog {
  border: 0; padding: 1.4rem 1.5rem; border-radius: var(--radius);
  background: var(--surface-1); color: var(--text-primary);
  box-shadow: var(--shadow); max-width: min(90vw, 22rem);
}
.restart-dialog .block-title { margin: 0 0 .4rem; }
.restart-dialog .block-q { margin: 0; color: var(--text-secondary); }
.restart-dialog::backdrop { background: rgba(0, 0, 0, .45); }
.restart-dialog-actions {
  display: flex; justify-content: flex-end; align-items: center;
  gap: .6rem; margin-top: 1.2rem;
}

/* ---------- 로딩 / 에러 ---------- */
.skeleton { color: var(--text-muted); font-size: .85rem; padding: 1.4rem 0; text-align: center; }

/* 데이터를 불러오는 동안 "—"나 안내 문구만 떠 있으면 사이트가 덜 완성된
   것처럼 보인다는 피드백이 있어, 값이 들어올 자리에 반짝이는 자리표시자를
   넣는다. 실제 값이 오면 JS가 이 클래스를 지운다. */
@keyframes skeletonShimmer {
  0%   { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}
.skeleton-bar {
  display: inline-block; color: transparent !important; pointer-events: none;
  background: linear-gradient(90deg,
    var(--surface-sunk) 35%, var(--border-strong) 50%, var(--surface-sunk) 65%);
  background-size: 250% 100%;
  animation: skeletonShimmer 1.5s ease-in-out infinite;
  border-radius: 6px;
}
/* 문단형 자리표시자(푸터의 데이터 갱신 안내, 실시간 물가 출처 표기 등) —
   실제 텍스트 폭과 비슷하게 잡아야 값이 채워질 때 레이아웃이 덜 튄다. */
p.skeleton-bar { display: block; width: min(26em, 90%); height: 1em; }
/* height:1em은 line-height를 1로 가정하는데, 본문 줄간격은 그보다
   넉넉해서(실측 약 1.6배) 실제 문장이 채워지는 순간 살짝 더 커 보이는
   틈이 있었다. 비트코인 시세처럼 아이콘이 같이 들어가는 한 줄짜리
   자리표시자는 실측 줄높이에 맞춰 min-height로 덮어쓴다. */
#btcLiveNote.skeleton-bar { height: auto; min-height: 1.6em; }
.tick.skeleton-tick { border-color: transparent; }
.tick.skeleton-tick .skeleton-bar { height: .9em; border-radius: 999px; }
@media (prefers-reduced-motion: reduce) { .skeleton-bar { animation: none; } }

.load-error {
  border: 1px solid color-mix(in srgb, var(--critical) 35%, transparent);
  background: color-mix(in srgb, var(--critical) 8%, transparent);
  border-radius: var(--radius-sm); padding: .9rem 1rem; font-size: .85rem; color: var(--critical-text);
}

.visually-hidden {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---------- 푸터 크레딧 ---------- */
.credits { font-weight: 600; color: var(--text-secondary); }
.credits .sep { font-weight: 400; color: var(--text-muted); font-size: .92em; }
.copyright { color: var(--text-muted); font-size: .92em; }

/* 통계 기준 시점 — 수동 갱신 값이라 언제 것인지 밝힌다 */
.vintage {
  display: inline-block; font-size: .72rem; color: var(--text-muted);
  border: 1px solid var(--border); border-radius: 999px; padding: .04rem .42rem;
}

/* ---------- "내 물가" 개념 설명 ----------
   처음 보는 사람은 이 지표가 뭔지 모른다. 결과 숫자를 보여주기 전에
   왜 평균이 내 물가가 아닌지를 실제 값으로 한 번 보여 준다. */
.concept-note {
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 1.1rem 1.2rem; margin-bottom: .9rem;
}
.concept-note p { margin: 0; font-size: .88rem; color: var(--text-secondary); line-height: 1.65; }
.concept-note p + p { margin-top: .8rem; }
.concept-note b { color: var(--text-primary); }

/* 다른 탭의 해설은 막대 없이 글만이라 조금 더 조인다 */
.concept-note.is-compact { padding: .9rem 1.1rem; }
.concept-note.is-compact p { font-size: .85rem; }
.concept-note.is-compact p + p { margin-top: .55rem; }

/* ---------- 투자 성향 비교 · 비중 직접 조정 ---------- */
.mix-compare { margin: .2rem 0 .9rem; display: grid; gap: .25rem; }
.mix-head-row,
.mix-row-btn {
  display: grid; grid-template-columns: 4.2rem 4.4rem 4.4rem 1fr;
  align-items: center; gap: .5rem; text-align: left;
}
.mix-head-row { font-size: .68rem; color: var(--text-muted); padding: 0 .6rem; }
.mix-row-btn {
  appearance: none; font-family: inherit; cursor: pointer;
  background: var(--surface-1); border: 1px solid var(--border);
  border-radius: var(--radius-sm); padding: .5rem .6rem;
}
.mix-row-btn:hover { border-color: var(--border-strong); }
.mix-row-btn.is-active { border-color: var(--brand); background: var(--brand-soft); }
.mix-label { font-weight: 700; font-size: .82rem; color: var(--text-primary); }
.mix-num { font-size: .82rem; font-variant-numeric: tabular-nums; font-weight: 700; }
.mix-num.good { color: var(--good-text); }
.mix-num.bad { color: var(--critical-text); }
.mix-desc-col { font-size: .74rem; color: var(--text-muted); }
.mix-foot { margin: .35rem 0 0; }

/* v32: 이 토글(비중 직접 조정)은 "상세 계산 보기" 같은 얕은 부연
   토글과 달리 실제로 값을 바꾸는 핵심 조작 진입점인데, 그동안
   ▶ 표시 하나만 있는 작은 텍스트 링크라 있는지도 모르고 지나치기
   쉬웠다. 다른 disclosure류(.calc-detail, .disclosure 등)는
   의도적으로 얕게 남겨두고, 이 토글만 배경·테두리가 있는 초록
   버튼 + 아이콘으로 위계를 분명히 다르게 준다. */
.mix-tuner { margin-bottom: 1rem; }
.mix-tuner summary {
  display: inline-flex; align-items: center; gap: .5rem;
  cursor: pointer; font-size: .88rem; font-weight: 700;
  color: var(--brand); background: var(--brand-soft);
  border: 1.5px solid var(--brand); border-radius: 999px;
  padding: .68rem 1.2rem; min-height: 2.75rem; box-sizing: border-box;
  user-select: none; list-style: none; transition: background-color .15s;
}
.mix-tuner summary::-webkit-details-marker { display: none; }
.mix-tuner summary::marker { content: ""; }
.mix-tuner summary:hover { background: color-mix(in srgb, var(--brand) 16%, var(--brand-soft)); }
.mix-tuner-icon { width: 17px; height: 17px; flex: 0 0 auto; }
.mix-tuner-chevron { width: 14px; height: 14px; flex: 0 0 auto; margin-left: -.15rem; transition: transform .2s; }
.mix-tuner[open] .mix-tuner-chevron { transform: rotate(180deg); }
.mix-reset {
  appearance: none; border: 1px solid var(--border-strong); background: var(--surface-1);
  color: var(--text-secondary); font-family: inherit; font-size: .78rem;
  border-radius: 999px; padding: .34rem .8rem; cursor: pointer; margin-top: .5rem;
}
.mix-reset:hover { border-color: var(--brand); color: var(--brand); }

@media (max-width: 640px) {
  .mix-head-row, .mix-row-btn { grid-template-columns: 3.6rem 3.9rem 3.9rem; }
  .mix-desc-col { display: none; }
}

/* ---------- 내 물가 계산 과정 따라가기 ----------
   전에는 이 박스 배경이 부모 카드(.card)와 같은 --surface-2라 테두리
   왼쪽 선 하나로만 구분됐는데, 그러다 보니 ①②③ 단계가 위 설명
   문단·아래 차트와 뭉쳐 보인다는 피드백이 있었다. 눌러앉은 톤
   (--surface-sunk, 다른 중첩 박스들과 같은 톤)으로 실제 배경 대비를
   주고, 위아래 여백과 단계 사이 간격을 넉넉히 늘려 하나의 "계산
   과정" 블록으로 또렷하게 읽히게 했다. */
.calc-walk {
  margin: .9rem 0 1.1rem; padding: 1rem 1.1rem;
  background: var(--surface-sunk); border-radius: var(--radius-sm);
}
.calc-step {
  margin: 0 0 .7rem; font-size: .82rem; line-height: 1.6;
  color: var(--text-secondary); display: flex; gap: .6rem; align-items: baseline;
}
.calc-step:last-child { margin-bottom: 0; }
.calc-step b { color: var(--text-primary); font-weight: 700; }
.calc-no {
  flex: 0 0 1.25rem; height: 1.25rem; border-radius: 50%;
  background: var(--brand-soft); color: var(--brand);
  font-size: .7rem; font-weight: 700; line-height: 1.25rem;
  text-align: center; align-self: flex-start;
}
.calc-last { margin-top: .2rem; padding-top: .7rem; border-top: 1px dashed var(--border-strong); }
.calc-last .calc-no { background: transparent; color: var(--text-muted); font-size: .9rem; }
.tip-ex { color: var(--text-muted); font-size: .72rem; }

/* ---------- 내 물가를 밀어올린 범인: 순위 요약 + 상세 토글 ---------- */
.contrib-rank { list-style: none; margin: 0 0 .7rem; padding: 0; display: flex; flex-direction: column; gap: .4rem; }
.rank-row {
  display: flex; align-items: center; gap: .6rem;
  padding: .55rem .75rem; border-radius: var(--radius-sm); background: var(--surface-1);
  font-size: .86rem;
}
.rank-no { flex: 0 0 auto; font-weight: 800; color: var(--text-muted); font-size: .78rem; min-width: 2.2em; }
.rank-name { flex: 1; font-weight: 600; }
.calc-detail { margin: 0 0 .6rem; }
.calc-detail summary { cursor: pointer; color: var(--brand); font-size: .8rem; font-weight: 700; padding: .3rem 0; }
.calc-detail summary::marker { color: var(--brand); }
.calc-detail[open] summary { margin-bottom: .5rem; }

/* v46: 설문 Q2 그룹 총액 아래 "자세히 입력하기"(소비 습관 세부질문).
   .calc-detail을 그대로 얹어 쓰고, 필드 레이아웃만 여기서 정의한다.
   온보딩 Q2는 #onbSpendFields가 도넛차트와 폭을 나눠 쓰는(min-width
   230px) 좁은 칸이라, 횟수·1회평균 입력 두 개를 가로로 나란히 두면
   안 들어가 카드 전체가 옆으로 밀려나며 왼쪽이 잘려 보이는 문제가
   있었다(실측: .onboarding-card가 컨테이너보다 넓어져 flex 중앙정렬로
   양쪽이 잘림). 가로 공간이 애초에 좁은 자리라 반응형 줄바꿈 대신
   아예 세로로 쌓는다 — 어떤 폭에서도 넘칠 일이 없다. */
.spend-detail-toggle { margin: -.2rem 0 .8rem; }
.spend-detail-fields { display: flex; flex-direction: column; gap: .7rem; }
.spend-detail-field .spend-detail-label { margin: 0 0 .3rem; font-size: .78rem; font-weight: 700; color: var(--text-secondary); }
.spend-detail-inputs { display: flex; flex-direction: column; gap: .35rem; }
.spend-detail-field > .field-note { margin: .3rem 0 0; font-size: .68rem; }

/* ---------- 카테고리별 절약 팁 (v20) ----------
   카드3(범인)·카드7(격차 추이)·시나리오 카드가 공유하는 팁 라이브러리의
   화면 표현. 조언 톤이라 경고(critical/warning)가 아니라 브랜드 톤으로
   구분한다. */
.tip-box {
  background: var(--brand-soft); border: 1px solid color-mix(in srgb, var(--brand) 30%, var(--border));
  border-radius: var(--radius-sm); padding: .9rem 1.1rem; margin: .7rem 0;
}
.tip-box .tip-title { margin: 0 0 .5rem; font-size: .82rem; font-weight: 700; color: var(--brand); }
.tip-box ul { margin: 0; padding-left: 1.1rem; display: flex; flex-direction: column; gap: .4rem; }
.tip-box li { font-size: .85rem; color: var(--text-secondary); line-height: 1.5; }
/* v48: 설문에서 실제로 답한 값으로 만든 맞춤 팁 — 아래 고정 팁 목록과
   구분되게 살짝 강조하고, 그 아래 일반 팁과는 얇은 구분선으로 나눈다. */
.tip-box .tip-personalized-label { margin: 0 0 .4rem; font-size: .72rem; font-weight: 700; color: var(--brand); }
.tip-box ul.tip-personalized {
  margin: 0 0 .8rem; padding-bottom: .8rem; border-bottom: 1px solid color-mix(in srgb, var(--brand) 25%, transparent);
}
.tip-box ul.tip-personalized li { color: var(--text-primary); font-weight: 600; }

/* ---------- 조언 수용 시나리오 3가지 (v20 항목5) ---------- */
.scenario-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); gap: .7rem; margin-top: .3rem; }
@media (max-width: 640px) { .scenario-grid { grid-template-columns: 1fr; } }
.scenario-card {
  background: var(--surface-1); border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: .9rem .95rem; text-align: center;
}
.scenario-card .scenario-label { display: block; font-size: .78rem; font-weight: 700; color: var(--text-secondary); margin-bottom: .5rem; }
.scenario-card .scenario-rate { display: block; font-size: 1.05rem; font-variant-numeric: tabular-nums; }
.scenario-card .scenario-rate b { color: var(--good-text); }
.scenario-card .scenario-rate .arrow { color: var(--text-muted); font-weight: 400; margin: 0 .15rem; }
/* v44: 마무리 인사 마스코트를 감싸던 .prescription-box를 없애면서 그
   박스가 주던 margin-top(.8rem)도 같이 사라졌다 — 시나리오 카드 바로
   아래 붙지 않도록 직접 챙긴다. */
#scenarioCard .mascot-wrap { margin-top: 1rem; }

/* ---------- PDF 다운로드 버튼 (v18) ---------- */
/* 별도 라이브러리 없이 브라우저 네이티브 인쇄(window.print())를 쓴다 —
   사용자가 인쇄 대화상자에서 "대상: PDF로 저장"을 고르면 그게 곧
   다운로드다. 버튼 자체는 기존 next-step-actions 버튼과 같은 톤. */
.pdf-download-btn:disabled { opacity: .6; cursor: default; }

/* 화면에서는 항상 숨김 — 인쇄 전용 문서 헤더·표 등, .no-print와 반대
   역할(그쪽은 "화면 전용", 이쪽은 "인쇄 전용"). */
.print-only { display: none; }

/* ---------- 인쇄(=PDF 저장) 전용 스타일 (v18~v19) ----------
   화면에는 전혀 영향이 없다 — @media print 안의 규칙만 인쇄 렌더링에
   적용된다. 다크모드로 보고 있어도 인쇄물은 늘 라이트 팔레트로
   고정한다(보관·인쇄용 자료라 가독성·잉크 절약이 우선).

   v19: "카드뉴스 화면을 그대로 캡처한 느낌"이라는 피드백 — 실제로는
   html2canvas 캡처가 아니라 매번 새로 그려지는 텍스트/SVG라
   선택·복사도 되지만(pdftotext로 확인), 카드 특유의 그림자·둥근
   모서리·그라디언트 배경이 화면 UI 그대로라 "문서"보다 "카드 화면"
   처럼 보였다. --radius/--shadow를 0으로 눌러 카드 상자 느낌을 걷어
   내고, 상단에 문서 헤더(제목·생성일·요약), 연봉 협상 가이드에는
   실제 <table>을 추가해 문서 형식에 더 가깝게 만든다. */
@media print {
  :root, :root[data-theme="dark"] {
    color-scheme: light !important;
    --page-plane:     #f7f8fa !important;
    --surface-1:      #fbfcfd !important;
    --surface-2:      #ffffff !important;
    --surface-sunk:   #eef1f5 !important;
    --text-primary:   #0b0b0b !important;
    --text-secondary: #52514e !important;
    --text-muted:     #8b8983 !important;
    --gridline:       #e3e2db !important;
    --baseline:       #c3c2b7 !important;
    --border:         rgba(11, 11, 11, .10) !important;
    --border-strong:  rgba(11, 11, 11, .18) !important;
    --brand:          #2563eb !important;
    --brand-soft:     #e5eefc !important;
    --accent:         #b76442 !important;
    --series-1:       #1e3a8a !important;
    --series-2:       #2563eb !important;
    --series-3:       #0ea5e9 !important;
    --series-4:       #14b8a6 !important;
    --series-5:       #64748b !important;
    --series-6:       #6366f1 !important;
    --good:           #0284c7 !important;
    --good-text:      #075985 !important;
    --warning:        #e8a23d !important;
    --warning-text:   #92661f !important;
    --critical:       #c1594a !important;
    --critical-text:  #a3452f !important;
    --reference:      #5c7f97 !important;
    --shadow:         none !important;
    /* 화면용 카드 상자의 그림자·둥근 모서리를 눌러서, .card/.stat 등
       var(--radius[-sm])를 쓰는 모든 상자가 인쇄에서는 각진 문서
       구획으로 보이게 한다(클래스를 일일이 나열할 필요 없이 토큰
       하나로 전부 적용된다). */
    --radius:         0 !important;
    --radius-sm:      0 !important;
  }
  body { background: #fff !important; }
  .print-only { display: block; }

  /* 인쇄물에서는 의미 없는 조작용 UI를 뺀다 — 상단바, 점 인디케이터,
     화살표, 되돌아가기/재입력 링크, PDF 버튼 자신 등. */
  .no-print, .topbar, .ticker, .deck-dots, .deck-arrow, .deck-back-btn,
  .next-step-actions, .home-summary-links, .pdf-download-btn,
  .pdf-download-wrap, .scroll-top-btn, #restartConfirmDialog, #tooltip {
    display: none !important;
  }

  /* 문서 맨 위에만 붙는 제목·생성일·요약 한 줄 — JS(renderPrintMeta)가
     내용을 채운다. 화면에서는 .print-only가 항상 숨긴다. */
  .print-doc-header { margin-bottom: 1.4rem; padding-bottom: .8rem; border-bottom: 2px solid var(--text-primary); }
  .print-doc-title { margin: 0 0 .3rem; font-size: 1.3rem; font-weight: 800; }
  .print-doc-meta { margin: 0; font-size: .82rem; color: var(--text-secondary); }

  /* 연봉 협상 가이드처럼 숫자 3개를 나란히 비교하는 곳은 막대 그래프
     대신(정적 인쇄물에서 막대는 축 없이 크기만으론 비교가 어렵다)
     같은 값을 실제 <table>로도 병기한다 — 화면엔 없고 인쇄에만 보인다. */
  .print-only-table { width: 100%; border-collapse: collapse; font-size: .85rem; }
  .print-only-table th, .print-only-table td { border: 1px solid var(--border-strong); padding: .5rem .6rem; text-align: left; }
  .print-only-table th { background: var(--surface-1); font-weight: 700; }
  .print-only-table td.num { text-align: right; font-variant-numeric: tabular-nums; }

  /* 카드뉴스 덱 — 한 장씩 넘기며 보던 걸 인쇄에서는 카드 1~7을 순서대로
     세로로 펼쳐서 전부 담는다. */
  .deck { padding: 0; }
  .deck-shell { display: block; }
  .deck-viewport {
    width: auto; max-width: none; height: auto; min-height: 0; overflow: visible;
  }
  /* .deck-track에 걸린 transition(카드 넘김 애니메이션)이 인쇄 순간과
     겹치면 transform이 "none"으로 다 바뀌기 전 중간값에서 캡처될 수
     있다 — transition 자체를 꺼서 즉시 반영되게 한다. */
  .deck-track { display: block; transform: none !important; transition: none !important; }
  .deck-card {
    flex: none; width: auto; height: auto; overflow: visible;
    page-break-inside: avoid; break-inside: avoid;
    padding: 0 0 1.4rem;
  }
  .deck-card + .deck-card { border-top: 1px dashed var(--border-strong); padding-top: 1.4rem; }
  .deck-card.is-cover { min-height: 0; }

  /* 목표 자산/타임머신 화면의 스크롤 리브일 애니메이션 — 사용자가
     아직 스크롤을 안 내려 본 카드는 opacity:0로 DOM에 남아 있을 수
     있어, 인쇄 시점에는 전부 강제로 보이게 한다. */
  .bento > * { opacity: 1 !important; transform: none !important; }
  .bento > .card { page-break-inside: avoid; break-inside: avoid; }

  a { color: var(--text-primary); }
}
