:root { --bg: #ffffff; }
/* 한글 단어(어절) 중간이 잘리지 않고 띄어쓰기 단위로만 줄바꿈되게 한다.
   그래도 한 단어가 너무 길어 줄에 안 들어가는 경우(긴 URL 등)에는
   overflow-wrap이 안전망으로 그 단어만 잘라 넘친다. 모바일에서 버튼/링크를
   탭할 때 브라우저가 기본으로 씌우는 회색 하이라이트도 여기서 함께 없앤다. */
* { box-sizing: border-box; font-family: inherit; font-weight: inherit; word-break: keep-all; overflow-wrap: break-word; -webkit-tap-highlight-color: transparent; }

/* 스크롤은 되지만 스크롤바는 안 보이게(결과 화면처럼 내용이 길어 스크롤이 필요한 곳에 사용). */
.no-scrollbar {
  scrollbar-width: none; /* Firefox */
  -ms-overflow-style: none; /* 구형 Edge/IE */
}
.no-scrollbar::-webkit-scrollbar {
  display: none; /* Chrome/Safari */
}

body {
  margin: 0;
  min-height: 100vh;
  background: var(--bg);
  overflow: hidden;
  font-family: 'Space Mono', 'EB Garamond', 'Bitcount Grid Double', 'Jost', 'Geist Pixel', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  font-weight: 300;
}

.scene {
  position: fixed;
  top: var(--rest-top, 50%);
  left: 50%;
  transform: translate(-50%, -50%) scale(var(--rs, 1));
  width: 900px;
  height: 900px;
  perspective: 2000px;
  pointer-events: none;
}

/* 데스크톱(가로가 세로보다 넓은 화면)에서는 모빌을 살짝 아래로 낮춘다. */
@media (min-aspect-ratio: 1/1) {
  .scene {
    --rest-top: 53%;
  }
}

/* 확대→축소와 "제자리로 내려가기"(top)를 하나의 애니메이션으로 묶어 동시에 재생되게 한다.
   GPU에서 독립적으로 재생되는 CSS @keyframes라 메인 스레드 작업(회전 등)과도 무관하다. */
@keyframes introZoom {
  from {
    top: 46%;
    transform: translate(-50%, -50%) scale(var(--rs, 1)) scale(2.4);
  }
  to {
    top: var(--rest-top, 50%);
    transform: translate(-50%, -50%) scale(var(--rs, 1)) scale(1);
  }
}

/* 인트로에는 톤 버튼 텍스트가 아직 안 보이는 상태이므로, 버튼 자리를 비워두지 않고
   화면 정중앙(약간 더 위)에서 시작해 제자리로 내려온다. */
.scene.intro {
  animation: introZoom 1.4s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}

.tilt {
  width: 100%;
  height: 100%;
  transform-style: preserve-3d;
  transform: rotateX(0deg);
  position: relative;
}

.stage {
  position: absolute;
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
  transform-style: preserve-3d;
  cursor: grab;
  pointer-events: auto;
}
.stage:active { cursor: grabbing; }

.pivot {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 0;
  height: 0;
  transform-style: preserve-3d;
}

.arm {
  position: absolute;
  top: 0;
  left: 0;
  width: 0;
  height: 0;
  transform-style: preserve-3d;
  /* 화면 크기가 바뀔 때 개체 위치가 뚝뚝 끊기지 않고 부드럽게 이어지도록. */
  transition: transform 0.25s ease-out;
}

.card {
  position: absolute;
  transform: rotateY(180deg);
  transform-style: preserve-3d;

  transition: filter 0.15s linear, opacity 0.15s linear, transform 0.2s ease;
  overflow: hidden;
}

.card:hover {
  /* 옆으로 갸웃(rotateZ)이 아니라 세로축을 기준으로 좌우로 도리도리 돌아가게 rotateY를 더한다. */
  transform: rotateY(calc(180deg + var(--hover-twist, 8deg)));
}

.card-front {
  position: absolute;
  inset: 0;
  background: inherit;
  border-radius: inherit;
  overflow: hidden;
}

.card-back {
  position: absolute;
  inset: 0;
  background: inherit;
  border-radius: inherit;
  overflow: hidden;
  transform: rotateY(180deg) translateZ(6px);
  backface-visibility: hidden;
}

.card-side-left {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 6px;
  left: -6px;
  background: inherit;
  transform-origin: right;
  transform: rotateY(-90deg);
}

.card-side-right {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 6px;
  right: -6px;
  background: inherit;
  transform-origin: left;
  transform: rotateY(90deg);
}

.card-side-top {
  position: absolute;
  left: 0;
  right: 0;
  height: 6px;
  top: -6px;
  background: inherit;
  transform-origin: bottom;
  transform: rotateX(90deg);
}

.card-side-bottom {
  position: absolute;
  left: 0;
  right: 0;
  height: 6px;
  bottom: -6px;
  background: inherit;
  transform-origin: top;
  transform: rotateX(-90deg);
}

.card-side-top,
.card-side-bottom,
.card-side-left,
.card-side-right {
  display: none;
}

.controls {
  position: fixed;
  bottom: 28px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  gap: 14px;
}
.controls button {
  background: none;
  border: none;
  color: #333;
  padding: 8px 16px;
  border-radius: 20px;
  font-size: 13px;
  cursor: pointer;
}

.hint {
  position: fixed;
  top: 28px;
  left: 50%;
  transform: translateX(-50%);
  color: rgb(0, 0, 0);
  font-size: 12px;
}

.stage.animating .pivot {
  transition: transform 1.2s cubic-bezier(0.4, 0, 0.2, 1);
}

.stage.animating .card {
  transition: filter 1.2s cubic-bezier(0.4, 0, 0.2, 1),
              opacity 1.2s cubic-bezier(0.4, 0, 0.2, 1);
}

/* .card 자체(transform-style: preserve-3d)에 걸면 일부 브라우저(특히 태블릿)에서
   overflow: hidden 클리핑이 무시돼 발광이 카드 모양 밖 사각형으로 새어 나간다.
   preserve-3d가 없는 평평한 .card-front/.card-back에 각각 걸어 확실히 클리핑되게 한다. */
.card.lit .card-front::after,
.card.lit .card-back::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 160%;
  height: 500px;
  background: rgba(255, 255, 255, 0.241);
  transform: translate(-50%, -50%) rotate(-35deg);
  border-radius: 6px;
  mix-blend-mode: overlay;
  pointer-events: none;
}

.tone-buttons {
  position: fixed;
  /* 노치/다이나믹 아일랜드나 상태 표시줄(시간·배터리·와이파이)이 있는 기기(주로
     앱으로 감쌌을 때)에서 그 영역과 겹치지 않도록 안전 영역만큼 더 띄운다.
     일반 브라우저에서는 safe-area-inset-top이 0이라 기존과 동일하다. */
  top: calc(36px + env(safe-area-inset-top));
  left: 16px;
  right: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(2px, 0.6vw, 10px);
  z-index: 10;
  /* left/right를 고정폭으로 둬서 화면 크기와 무관하게 항상 좌우 16px 여백이 보장된다. */
  /* 인트로(확대→축소) 동안 겹치지 않도록 숨겨뒀다가 script.js에서 끝나면 opacity:1로 되돌린다. */
  opacity: 0;
  transition: opacity 0.6s ease;
}

.tone-buttons button {
  background: transparent;
  border: none;
  color: #111111;
  padding: clamp(4px, 1vw, 8px) clamp(6px, 1.6vw, 16px);
  border-radius: 999px;
  /* vw 계수를 낮춰 휴대폰 너비 전반에서 실제로 최솟값(8px) 근처를 쓰도록 한다. */
  font-size: clamp(8px, 2vw, 13px);
  font-weight: 400;
  cursor: pointer;
  white-space: nowrap;
}

/* 작은 화면(휴대폰)에서는 톤 버튼을 위로 살짝 올린다(글자 크기는 clamp가 처리). */
@media (max-width: 480px) {
  .tone-buttons {
    top: calc(16px + env(safe-area-inset-top));
  }
  .back-button {
    top: calc(16px + env(safe-area-inset-top)) !important;
    left: 16px !important;
    font-size: 11px !important;
    padding: 6px 12px !important;
  }
  /* back-button은 모바일에서 top/패딩이 줄어들어 세로 중심이 위로 올라가므로,
     우측 팔레트 아이콘도 같은 세로 중심에 오도록 top을 맞추고, 좌우 여백도
     back-button의 left: 16px과 대칭이 되도록 같은 값으로 맞춘다. */
  .palette-view-button {
    top: calc(14px + env(safe-area-inset-top)) !important;
    right: 16px !important;
  }
  /* "Next Step" 버튼(확정한 색 화면 우측 상단, 팔레트 아이콘과 같은 자리를 쓴다)도
     같은 세로 중심·여백에 맞추고, 글자 크기도 back-button의 11px과 맞춘다. */
  .stage-advance-button {
    top: calc(14px + env(safe-area-inset-top)) !important;
    right: 16px !important;
    font-size: 11px !important;
  }
  /* 모바일에서는 팔레트 바로 위 안내 문구를 조금 더 위로 띄운다(팔레트 확장
     화살표의 위쪽 끝이 164px 지점에 있으므로 그보다 확실히 위로). */
  .palette-drag-hint {
    bottom: 210px !important;
  }
  /* 튜토리얼 안내 문구(단계 1 세팅 등, 카드·단색 화면 제외) 화면은 모바일에서
     좌우 여백을 넉넉히 주고 글씨를 조금 줄인다. */
  .tutorial-overlay {
    padding: 24px 44px !important;
  }
  /* .tutorial-heading/.tutorial-body는 서류 화면 앞 인트로 막(.stage-intro-veil)에서도
     재사용되므로, 이 축소는 .tutorial-overlay 안으로만 한정해 카드 화면에 번지지 않게 한다. */
  .tutorial-overlay .tutorial-heading {
    font-size: 15px !important;
  }
  .tutorial-overlay .tutorial-body {
    font-size: 12px !important;
  }
  .tutorial-list li {
    font-size: 12px !important;
  }
  /* 서류(카드) 화면 앞 인트로 막(언더톤·명도·채도 등)도 튜토리얼 안내
     화면과 같은 글씨 크기·좌우 여백을 쓰게 한다. */
  .stage-intro-veil {
    padding: 24px 44px !important;
  }
  .stage-intro-veil .tutorial-heading {
    font-size: 15px !important;
  }
  .stage-intro-veil .tutorial-body {
    font-size: 12px !important;
  }
  /* 카드 없이 문구만 나오는 단계(종합 등)도 같은 글씨 크기·좌우 여백을 쓰게
     한다. stageHintHeading/Body는 카드 화면과 같은 컨테이너를 공유해서
     .tutorial-overlay/.stage-intro-veil 선택자로는 못 잡으므로 별도
     클래스로 한정한다. */
  .stage-hint-heading {
    font-size: 15px !important;
  }
  .stage-hint-body {
    font-size: 12px !important;
    padding: 0 20px !important;
    box-sizing: border-box !important;
  }
  /* 모바일에서는 아이콘 대신 "Tutorial" 텍스트 버튼으로 대체하고(script.js),
     상단 톤 버튼 줄과 겹치지 않도록 하단 중앙으로 옮긴다. */
  .tutorial-button {
    top: auto !important;
    right: auto !important;
    /* 홈 인디케이터가 있는 기기에서 겹치지 않도록 안전 영역만큼 더 띄우되,
       기본 여백은 줄여서 전체적으로 너무 떠 보이지 않게 한다. */
    bottom: calc(8px + env(safe-area-inset-bottom)) !important;
    left: 50% !important;
    transform: translateX(-50%) !important;
    /* 상단 톤 버튼 글자와 같은 크기(clamp)를 그대로 쓴다. */
    font-size: clamp(8px, 2vw, 13px) !important;
    padding: 6px 12px !important;
    letter-spacing: 0.02em;
  }
  .tutorial-back {
    top: calc(16px + env(safe-area-inset-top)) !important;
    left: 16px !important;
    font-size: 11px !important;
    padding: 6px 12px !important;
  }
  .tutorial-next {
    top: calc(16px + env(safe-area-inset-top)) !important;
    right: 16px !important;
    font-size: 11px !important;
    padding: 6px 12px !important;
  }
}

.tutorial-button {
  position: fixed;
  /* 상단 톤 버튼 줄과 높이를 맞춘다. */
  top: calc(36px + env(safe-area-inset-top));
  right: calc(28px + env(safe-area-inset-right));
  z-index: 1002;
  background: transparent;
  border: none;
  color: #111111;
  /* 상단 톤 버튼과 글자 크기/굵기/여백을 완전히 동일하게 맞춘다. */
  padding: clamp(4px, 1vw, 8px) clamp(6px, 1.6vw, 16px);
  font-size: clamp(8px, 2vw, 13px);
  font-weight: 400;
  white-space: nowrap;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  /* 톤 버튼 텍스트와 마찬가지로 인트로(확대→축소) 동안 숨겨뒀다가, 인트로가
     끝나는 시점에 자연스럽게 나타나게 한다. */
  opacity: 0;
  transition: opacity 0.6s ease;
}

.tutorial-overlay {
  position: fixed;
  inset: 0;
  z-index: 2000;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  padding: 24px;
  text-align: center;
  background: rgba(0, 0, 0, 0.45);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.4s ease;
  cursor: pointer;
}

.tutorial-overlay.active {
  opacity: 1;
  pointer-events: auto;
}

.tutorial-shortcut {
  margin: 0;
  font-size: 32px;
  font-weight: 700;
  color: #ffffff;
  letter-spacing: 0.02em;
}

.tutorial-hint {
  margin: 0;
  font-size: 15px;
  font-weight: 400;
  color: rgba(255, 255, 255, 0.8);
}

.tutorial-slide {
  display: none;
  flex-direction: column;
  align-items: center;
  gap: 24px;
  max-width: 640px;
}

.tutorial-slide.active {
  display: flex;
}

.tutorial-eyebrow {
  margin: 0;
  font-size: 13px;
  font-weight: 400;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.65);
}

/* 단계 카드 화면(STAGE_HINTS)과 마찬가지로, "단계 N · ..." 문구는 튜토리얼
   슬라이드 안에서도 가운데 정렬된 본문과 분리해 화면 맨 아래로 떨어뜨린다. */
.tutorial-overlay .tutorial-eyebrow {
  position: absolute;
  left: 50%;
  bottom: calc(28px + env(safe-area-inset-bottom));
  transform: translateX(-50%);
}

.tutorial-heading {
  margin: 0;
  font-size: 24px;
  font-weight: 700;
  color: #ffffff;
}

.tutorial-body {
  margin: 0;
  font-size: 17px;
  line-height: 1.7;
  color: rgba(255, 255, 255, 0.92);
}

/* 단계 1 안내처럼 여러 조건을 나열할 때 쓰는 불릿 리스트. */
.tutorial-list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 10px;
  text-align: left;
}

.tutorial-list li {
  position: relative;
  padding-left: 1.1em;
  font-size: 17px;
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.92);
}

.tutorial-list li::before {
  content: '•';
  position: absolute;
  left: 0;
  color: rgba(255, 255, 255, 0.55);
}

/* 카드(서류)가 있는 단계 화면이 열릴 때, 화면을 잠깐 어둡게 가리고 그 위에
   헤딩+설명 문구를 보여줬다가 몇 초 뒤 스르륵 사라지는 인트로 막. */
.stage-intro-veil {
  position: absolute;
  inset: 0;
  z-index: 5;
  display: none;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 16px;
  padding: 24px;
  text-align: center;
  background: rgba(0, 0, 0, 0.7);
  pointer-events: none;
}

/* 명도/언더톤/채도 단계 안내에서 쓰는 콘텐츠 컨테이너. 데스크탑은 무채색
   서류 문서(.hint-doc) 한 개, 모바일은 카드 스택(.hint-card-stack)을 담는다. */
.hint-cards {
  display: none;
  width: 100%;
  max-width: 92vw;
  box-sizing: border-box;
  gap: 32px;
  flex-wrap: wrap;
  align-items: stretch;
  justify-content: center;
  margin-top: 4px;
}

.hint-card-label {
  align-self: center;
  margin: 0;
  font-size: 20px;
  font-weight: 500;
  color: #171717;
}

.hint-card-illustration {
  width: 176px;
  height: 176px;
  object-fit: contain;
  /* 사진(폴라로이드) 원본에 그림자가 그려져 있었으나, 크기별로 그림자
     비율이 안 맞아 코드(필터)로 옮김 — 알파 채널을 따라가는 실제 카드
     테두리 모양대로 그림자가 지도록 box-shadow 대신 drop-shadow를 쓴다. */
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.22)) drop-shadow(0 1px 1px rgba(0, 0, 0, 0.16));
}

/* 모바일 카드 스택 안의 사람 이미지만 더 크게, 조금 더 아래로 내려서 보여준다. */
.hint-stack-card .hint-card-illustration {
  width: 240px;
  height: 240px;
  margin-top: 10px;
  margin-bottom: -8px;
}

/* 클립이 사진 위쪽에 꽂혀 있는 것처럼 겹쳐 보여주는 감싸개. 클립은 이
   감싸개 기준 절대 위치라, 감싸개를 위로 올리면 사진과 클립이 함께
   따라 올라가 맨 밑 회색 표지 위쪽 가장자리에 클립이 걸쳐진 것처럼
   보이게 된다. */
.hint-doc-photo {
  position: relative;
  align-self: center;
  display: flex;
  justify-content: center;
  margin-top: -32px;
}

/* 클립은 기울이지 않고 똑바로, 서류 위쪽 가장자리에 걸터앉은 것처럼 더
   위로 올려둔다. */
.hint-doc-clip {
  position: absolute;
  top: -23px;
  left: 50%;
  width: 62px;
  height: auto;
  transform: translateX(-50%);
  z-index: 2;
  pointer-events: none;
  filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.28));
}

/* 클립의 뒷다리. clip.png(앞 클립)와 완전히 같은 위치·크기로 겹쳐두고,
   포토샵 레이어 순서로 치면 맨 아래로 보내듯 z-index만 서류 표지
   (.hint-doc-cover, z-index: -1)보다도 더 낮게 줘서 맨 뒤에 깔리게 한다. */
.hint-doc-clip-back {
  position: absolute;
  top: -23px;
  left: 50%;
  width: 62px;
  height: auto;
  transform: translateX(-50%);
  z-index: -2;
  pointer-events: none;
  filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.28));
}

/* 서류 안 이미지는 카드 스택(모바일)보다 훨씬 크게 보여주되, 세로 기준으로
   최대 높이를 잡아 서류가 화면 밖으로 넘칠 만큼 커지지 않게 한다(이미지이
   세로로 긴 인물 사진이라 폭을 기준으로 키우면 높이가 감당 안 될 만큼
   커진다). 그 안에서 폭은 원본 비율 그대로 최대한 채운다. 클립에 꽂힌
   사진처럼 살짝 기울여두고, 클릭하면 라이트박스로 크게 볼 수 있다. */
.hint-doc-page-blank .hint-card-illustration {
  width: auto;
  max-width: 98%;
  height: auto;
  max-height: 130vh;
  /* 클립은 그대로 두고 사진만 위로 당긴다(클립은 감싸개 기준 절대 위치라
     이 마진의 영향을 받지 않는다). 이미지가 훨씬 커진 만큼 당기는 양은
     줄여서 클립과 안 부딪히게 살짝 내려준다. */
  margin-top: 22px;
  transform: rotate(-3deg);
  cursor: zoom-in;
  /* 서류에서는 사진이 훨씬 크게 보이므로 그림자도 비례해 더 크고 넓게. */
  filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.26)) drop-shadow(0 1px 1px rgba(0, 0, 0, 0.18));
}

/* 화면을 어둡게 가리고 그 위에 클릭한 얼굴 사진을 크게 보여주는 라이트박스.
   배경이 완전히 불투명하지 않으면(예전엔 0.82 + blur) 뒤에 있던 흰 서류/
   사진이 은은하게 비쳐서 확대된 사진 둘레에 얼룩 같은 그림자가 생겼다 —
   완전 불투명으로 바꿔 그 비침을 없앤다. */
.hint-image-lightbox {
  position: fixed;
  inset: 0;
  z-index: 3000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 32px;
  background: #000;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.4s ease;
  cursor: zoom-out;
}

.hint-image-lightbox img {
  max-width: min(560px, 88vw);
  max-height: 88vh;
  object-fit: contain;
}

.hint-card-text {
  margin: 0;
  font-size: 14px;
  line-height: 2;
  color: rgba(23, 23, 23, 0.78);
}

/* 서류 안 본문은 위로 당겨 올리고, 페이지 좌우 패딩 위에 추가로 좌우
   여백을 더 줘서 살짝 안쪽으로 들여 쓴다. */
.hint-doc-page .hint-card-text {
  margin-top: -14px;
  padding: 0 12px;
  box-sizing: border-box;
}

/* 데스크탑 전용: Good/Bad 뒤집기 카드 두 장 대신, 무채색 서류철처럼 생긴
   문서 한 개. 클릭하면 라벨×Good/Bad 조합 4페이지가 한 장씩 넘어가고,
   우측에 튀어나온 색인 탭으로 원하는 페이지로 바로 건너뛸 수 있다. */
.hint-doc {
  position: relative;
  /* 오른쪽 페이지(실제 내용, 기존과 같은 폭)와 왼쪽 빈 페이지를 나란히
     두려고 폭을 기존의 두 배로 잡는다 — 오른쪽 페이지 자체의 폭/레이아웃은
     그대로 유지된다. 갈피가 차지할 폭까지 감안해 화면 안에 항상 들어오게
     하되, 너무 좁아져 타이틀/본문이 잘리지 않도록 최소 폭을 지킨다. */
  width: min(1140px, max(680px, calc(200vw - 560px)));
  margin: 4px auto 0;
}

/* 서류 뒤에 깔리는 회색 표지. 펼쳐진 두 페이지보다 사방으로 조금 더 커서
   가장자리가 표지처럼 삐져나와 보인다. 실제로 눈에 보이는 부분은 서류
   밖으로 삐져나온 얇은 테두리뿐이라, 중심에서부터 옅어지는 radial-gradient는
   전부 서류 밑에 가려져 티가 안 났다. 그래서 배경을 아예 투명하게 비우고,
   inset box-shadow로 테두리 안쪽에서만 옅어지는 그림자를 그려 넣어 —
   가장자리는 불투명하고 안쪽(서류에 가까운 쪽)으로 갈수록 투명해져 뒤의
   배경이 비쳐 보이게 만든다. */
.hint-doc-cover {
  position: absolute;
  top: -16px;
  bottom: -16px;
  left: -50px;
  /* 우측 갈피(탭)는 자리(slot)에 따라 최대 3단(39px)까지 더 밀려나서
     튀어나오므로, 왼쪽보다 오른쪽을 더 넉넉히 잡아 가장 깊이 튀어나온
     갈피까지 표지 안에 들어오게 한다. */
  right: -85px;
  background: transparent;
  border-radius: 14px;
  box-shadow: inset 0 0 36px rgba(156, 156, 152, 0.85), 0 26px 44px rgba(0, 0, 0, 0.32);
  z-index: -1;
}

.hint-doc-spread {
  display: flex;
  align-items: stretch;
}

/* 왼쪽의 빈 페이지. 오른쪽 페이지와 같은 종이 질감이지만 내용은 없다.
   사진이 실제로 커질 폭 여유를 주려고 오른쪽 페이지보다 살짝 더 넓게
   잡는다(사진은 세로로 긴 인물 사진이라 max-height보다 폭이 먼저
   병목이 되기 때문). */
.hint-doc-page-blank {
  flex: 1 1 50%;
  box-sizing: border-box;
  min-height: 560px;
  /* 오른쪽 페이지와 똑같이 위쪽 여백(24px)을 줘서, 사람 사진·클립이 이
     페이지로 옮겨와도 세로 위치(높이)는 그대로 유지되게 한다. */
  padding-top: 24px;
  display: flex;
  flex-direction: column;
  align-items: center;
  background: #f5f5f3 url('../envelope-letter-card.png');
  background-size: cover;
  border: 1px solid rgba(17, 17, 17, 0.1);
  border-right: none;
  border-radius: 4px 0 0 4px;
}

.hint-doc-page {
  position: relative;
  flex: 1 1 50%;
  box-sizing: border-box;
  min-height: 560px;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  justify-content: flex-start;
  gap: 24px;
  /* 이미지 위(padding-top)와 이미지 아래(다음 요소까지의 gap)가 같은 24px가
     되도록 맞춰서, 이미지 상하 여백이 동일해 보이게 한다. */
  padding: 24px 20px 44px;
  /* 결과 편지지와 같은 종이 질감 이미지를 깔아, 서류도 실제 종이처럼 보이게
     한다. css/ 안에서 참조하는 거라 루트에 있는 이미지로 가려면 ../가 필요하다. */
  background: #f5f5f3 url('../envelope-letter-card.png');
  background-size: cover;
  border: 1px solid rgba(17, 17, 17, 0.1);
  border-radius: 0 4px 4px 0;
  /* 우측으로 어긋난 회색 종이 세 겹(+ 맨 앞의 본체 = 총 4장, 갈피 4개와
     맞춤)이 겹쳐 있는 것처럼 보이게 하는 그림자. 이 간격은 갈피의 계단식
     간격(TAB_STEP_PX, script.js)과는 별개로 여기서 직접 조절한다. */
  box-shadow:
    13.5px 0 0 -1px #e4e4e1,
    27px 0 0 -2px #d6d6d3,
    40.5px 0 0 -3px #c8c8c5,
    0 20px 34px rgba(0, 0, 0, 0.2);
  text-align: left;
  cursor: pointer;
}

/* 몇 번째 페이지인지 보여주는 숫자는 서류 하단 중앙에 고정된다. */
.hint-doc-page-index {
  position: absolute;
  bottom: 24px;
  left: 50%;
  transform: translateX(-50%);
  margin: 0;
  font-size: 11px;
  letter-spacing: 0.08em;
  color: rgba(23, 23, 23, 0.4);
}

/* 타이틀(라벨)과 Good/Bad 텍스트를 콜론으로 이어 한 줄에 나란히, 같은
   크기로 놓는다. */
.hint-doc-title-row {
  display: flex;
  align-items: baseline;
  gap: 8px;
  /* 본문 좌측 여백(12px)과 맞춘다. */
  padding-left: 12px;
  /* 오른쪽 페이지에는 이제 사진이 없으므로(왼쪽 페이지로 옮김), 페이지
     자체의 위쪽 패딩(24px)에 더해 상단 여백을 넉넉히 준다. */
  margin-top: 32px;
}

/* 서류 타이틀(라벨)만 따로 줄인다. .hint-card-label은 모바일 카드
   스택에도 쓰이므로 여기서 서류 쪽만 범위를 좁혀 크기를 줄인다. */
.hint-doc-title-row .hint-card-label {
  font-size: 16px;
}

.hint-doc-title-separator {
  margin: 0;
  font-size: 16px;
  font-weight: 500;
  color: #171717;
}

.hint-doc-badge {
  margin: 0;
  font-size: 16px;
  font-weight: 500;
  letter-spacing: 0.02em;
  color: #171717;
}

/* 문서 우측에 튀어나와 있는 서류철 갈피. 실제 파일 폴더 인덱스처럼 세로로
   길쭉하고, 서로 다른 깊이로 어긋나게 튀어나와 겹쳐 쌓인 것처럼 보이게
   한다. 각 갈피는 해당 페이지의 라벨·Good/Bad를 제목으로 보여주고,
   클릭하면 그 페이지로 바로 건너뛴다. */
.hint-doc-tabs {
  position: absolute;
  top: 26px;
  left: 100%;
  /* 갈피 묶음 전체 위치(우측으로 밀린 정도)를 조정하는 값. */
  margin-left: -1.4px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.hint-doc-tab {
  /* 왼쪽(서류에 맞닿는 면)만 테두리를 없애 종이와 이어지는 부분에 선이
     보이지 않게 하고, 나머지 세 면만 테두리를 그린다. */
  position: relative;
  border-style: solid;
  border-color: rgba(17, 17, 17, 0.15);
  border-width: 1px 1px 1px 0;
  /* 배경색은 자리(slot)에 따라 script.js가 인라인으로 지정한다(서류 종이
     계단층과 같은 무채색, 맨 앞이 밝고 뒤로 갈수록 어두워짐). 종이
     질감(텍스처)은 맨 앞(active) 갈피에만 아래 .active 규칙에서 덧입힌다. */
  background-color: #f5f5f3;
  color: rgba(23, 23, 23, 0.6);
  font-family: inherit;
  font-size: 11px;
  font-weight: 400;
  letter-spacing: 0.02em;
  line-height: 1.3;
  width: 36px;
  min-height: 128px;
  box-sizing: border-box;
  padding: 10px 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  /* 좁아진 갈피 폭에 맞춰 글씨를 세로 방향으로 회전해서(줄이 위→아래로
     흐르게) 한 줄로만 보여준다. */
  writing-mode: vertical-rl;
  white-space: nowrap;
  cursor: pointer;
  /* 오른쪽 끝(바깥으로 튀어나온 쪽)만 모서리를 살짝 둥글리고, 왼쪽(서류에
     맞닿는 쪽) 위아래 모서리는 안으로 깎이는 대신 ::before/::after로
     밖으로 펼쳐지듯 둥글린다(아래 참고). */
  border-radius: 0 10px 10px 0;
  /* 그림자의 흐림 반경(blur)이 가로 이동 거리(x)보다 크면 왼쪽(서류에
     맞닿는 면) 쪽으로도 그림자가 살짝 번져 나가 이음매처럼 보인다. x를
     blur보다 크게 잡아 왼쪽으로는 그림자가 전혀 번지지 않게 한다. */
  box-shadow: 7px 5px 5px rgba(0, 0, 0, 0.14);
}

/* 키보드로 갈피에 포커스가 가면 브라우저 기본 파란 아웃라인이 테두리
   바깥쪽에 그려지는데, 맨 앞(0번) 갈피는 표지 가장자리와 거의 붙어 있어
   그 아웃라인만 표지 밖으로 삐져나와 보인다. 안쪽으로 파고들게 옮겨서
   표지 밖으로 나가지 않게 한다. */
.hint-doc-tab:focus-visible {
  outline-offset: -3px;
}

/* 갈피 왼쪽 위/아래 모서리가 안으로 깎이지 않고, 위/아래(세로) 방향으로
   밖으로 펼쳐지듯 둥글게 이어지는 부분. radial-gradient로 사분원을
   그려서 탭의 사각 모서리(0,0)·(0,H)에서 시작해 위/아래 바깥쪽으로
   곡선을 그리다가 위·아래 평평한 변에 자연스럽게 붙는다(이 모양 자체는
   더 손대지 않는다). 탭 배경색(자리별로 달라짐)과 정확히 같은 색을
   --tab-flare-color로 전달받아 이어붙인 티가 나지 않게 한다. */
.hint-doc-tab::before,
.hint-doc-tab::after {
  content: '';
  position: absolute;
  left: 0;
  width: 14px;
  height: 14px;
  pointer-events: none;
}

/* 곡선 "바깥"(반지름 14px 안쪽)은 완전히 투명하게 비워서 흰 단색 덩어리가
   보이지 않게 한다. 맨 앞(active) 갈피만 곡선 윤곽에 테두리 링을 두고,
   나머지는 링 없이 민무늬로 둔다. */
.hint-doc-tab::before {
  top: -14px;
  background: radial-gradient(circle at top right, transparent 14px, var(--tab-flare-color, #f5f5f3) 14px);
}

.hint-doc-tab::after {
  bottom: -14px;
  background: radial-gradient(circle at bottom right, transparent 14px, var(--tab-flare-color, #f5f5f3) 14px);
}

/* 갈피마다 튀어나온 깊이(margin-left)와 쌓임 순서(z-index)는 서류의 겹쳐진
   종이 층 간격에 맞춰 script.js가 인라인으로 직접 지정한다(선택된 갈피가
   0번 자리로 당겨질 때도 인라인이라야 이 기본값을 확실히 덮어쓴다). */
.hint-doc-tab.active {
  color: #171717;
  /* 여기서도 x(9px)를 blur(7px)보다 크게 잡아 왼쪽으로는 그림자가 번지지
     않게 한다. */
  box-shadow: 9px 6px 7px rgba(0, 0, 0, 0.2);
  /* 맨 앞(0번) 갈피에만 왼쪽 종이(.hint-doc-page)와 같은 종이 질감을
     덧입혀, 뒤에 깔린 갈피들과 구분되게 한다. */
  background-image: url('../envelope-letter-card.png');
  background-size: cover;
}

/* 맨 앞 갈피의 위/아래 플레어는 --tab-flare-color(민무늬 단색)만 채워지면
   본체의 종이 질감과 달리 밋밋하게 떠 보인다. 채움 구간(반지름 14px
   밖)만 투명하게 비워서 그 뒤에 깐 종이 질감이 비치게 한다. 곡선
   바깥(반지름 13px 안쪽)은 gradient에서도 투명이지만, 그 뒤에 텍스처
   레이어가 통째로 깔려 있어서 gradient만으로는 안 비고 텍스처가 그대로
   채워져 흰 면처럼 보였다 — mask-image로 상자 자체를 잘라내야 진짜로
   빈다. */
.hint-doc-tab.active::before,
.hint-doc-tab.active::after {
  background-size: 14px 14px, cover;
}

.hint-doc-tab.active::before {
  background-image: radial-gradient(
      circle at top right,
      transparent 13px,
      rgba(17, 17, 17, 0.15) 13px,
      rgba(17, 17, 17, 0.15) 14px,
      transparent 14px
    ),
    url('../envelope-letter-card.png');
  -webkit-mask-image: radial-gradient(circle at top right, transparent 13px, #000 13px);
  mask-image: radial-gradient(circle at top right, transparent 13px, #000 13px);
}

.hint-doc-tab.active::after {
  background-image: radial-gradient(
      circle at bottom right,
      transparent 13px,
      rgba(17, 17, 17, 0.15) 13px,
      rgba(17, 17, 17, 0.15) 14px,
      transparent 14px
    ),
    url('../envelope-letter-card.png');
  -webkit-mask-image: radial-gradient(circle at bottom right, transparent 13px, #000 13px);
  mask-image: radial-gradient(circle at bottom right, transparent 13px, #000 13px);
}

/* 모바일 전용: 카드 두 장을 뒤집는 대신, Good/Bad 얼굴 4장을 카드 더미로 겹쳐두고
   맨 앞 카드만 드래그해서 넘기면 뒤에 살짝 기울어져 있던 카드가 앞으로 올라오는
   셔플형 카드 스택. 스택 전체는 제자리에 고정되어 있고 카드만 앞뒤로 넘어간다. */
.hint-card-stack {
  position: relative;
  width: 100%;
  height: 520px;
  margin: 0 auto;
}

.hint-stack-card {
  position: absolute;
  top: 50%;
  left: 50%;
  width: min(290px, 74vw);
  min-height: 420px;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  padding: 18px 16px;
  border-radius: 22px;
  background: #ffffff;
  box-shadow: 0 14px 30px rgba(0, 0, 0, 0.28);
  text-align: center;
  transition: transform 0.2s cubic-bezier(0.22, 1, 0.36, 1), opacity 0.2s ease;
  touch-action: pan-y;
}

/* 라벨(Warm)과 Good/Bad를 서류(데스크탑) 타이틀과 같은 모양으로 — 줄바꿈
   없이 한 줄에, 콜론으로 이어 나란히 놓는다. */
.hint-stack-title-row {
  display: flex;
  align-items: baseline;
  gap: 8px;
}

/* .hint-card-label은 데스크탑 서류에서도 재사용되므로, 굵기·크기 축소는
   모바일 카드 스택 타이틀 행 안으로만 한정한다. */
.hint-stack-title-row .hint-card-label {
  font-weight: 400;
  font-size: 16px;
}

.hint-stack-title-separator {
  margin: 0;
  font-size: 16px;
  font-weight: 400;
  color: #171717;
}

.hint-stack-badge {
  margin: 0;
  font-size: 16px;
  font-weight: 400;
  color: #171717;
}

/* .hint-card-text는 데스크탑 서류 본문에도 쓰이므로, 축소는 모바일 카드
   스택 안으로만 한정한다. */
.hint-stack-card .hint-card-text {
  font-size: 12px;
  padding: 0 8px;
  box-sizing: border-box;
}

/* 단계 6(결과 안내) 화면 중앙에 놓는 봉투 그래픽. 카드/폼폼/스티커/팔찌가 이미
   하나로 합성된 단일 이미지(envelope.png)를 그대로 보여준다. */
.result-envelope {
  width: 100%;
  max-width: 675px;
  margin: 8px auto 0;
}

.result-envelope img {
  display: block;
  width: 100%;
  height: auto;
  pointer-events: none;
  -webkit-user-drag: none;
}

/* 봉투 클릭 시 뜨는 "편지 확대" 화면. 플랩(lr-flap)/몸통(lr-body)/편지지 기준점
   (lr-paper-anchor, 안에 lr-paper)을 절대 위치로 겹쳐놓는다. 아래 left/top/
   width/height(%)를 직접 바꾸면 각 레이어의 위치·크기가 바뀐다. 쌓임 순서
   (뒤→앞)는 편지지 → 몸통 → 플랩. */
.letter-reveal {
  position: relative;
  width: 100%;
  max-width: 1404px;
  aspect-ratio: 1189 / 1129;
}

.letter-reveal img {
  position: absolute;
  object-fit: contain;
  pointer-events: none;
  -webkit-user-drag: none;
}

/* 편지지 "기준점"(lr-paper-anchor). 예전 lr-card와 같은 안전한 자리(30%~136.28%,
   다른 버튼과 안 겹치고 화면 밖으로 안 밀려나는 자리)에 고정돼 있지만, overflow를
   자르지 않는다(visible) — 그래서 안의 lr-paper가 이보다 위로 솟아올라도 잘리지
   않고 계속 보인다. */
.letter-reveal .lr-paper-anchor {
  left: 10.48%;
  top: 30%;
  width: 79.06%;
  height: 106.28%;
  z-index: 1;
  position: absolute;
}

/* 편지지 본체. 기준점의 top에 붙어 아래로 늘어난다(텍스트 길이만큼). 배경 이미지를
   이 요소의 전체 높이에 꽉 채워 늘려서 반복 타일 없이 "종이 한 장"처럼 보이게 한다.
   translateY는 script.js가 스크롤 값을 그대로 옮겨 적용한다 — 그래서 스크롤하면
   이 편지지 자체가 화면에서 실제로 위로 이동한다. */
.letter-reveal .lr-paper {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  min-height: 100%;
  /* background-size:100% 100%로 이미지를 텍스트 길이만큼(수천 px) 늘려 그리면
     GPU가 매 프레임 그 큰 텍스처를 다시 리샘플링해야 해서 무겁다. 고정 크기
     타일을 세로로 반복하는 방식이 훨씬 가볍다(그냥 같은 작은 텍스처를 복사).
     background-image는 CSS에 안 넣고 script.js가 필요한 시점에 인라인으로 지연
     할당한다 — CSS에 있으면 이 클래스를 쓰는 엘리먼트가 생성되는 즉시(첫 화면
     로딩 시점) 브라우저가 미리 받아버린다. */
  background-repeat: repeat-y;
  background-size: 100% 640px;
  box-shadow: 0 6px 8px rgba(0, 0, 0, 0.22);
  will-change: transform;
  backface-visibility: hidden;
}

/* 안 보이는 스크롤 입력 전용 레이어. lr-paper-anchor와 같은 자리를 덮고 있다가,
   휠/트랙패드/터치 스크롤을 네이티브로 받아서(브라우저가 가장 안정적으로 처리하는
   방식) 그 scrollTop을 위 lr-paper의 translateY로 그대로 옮긴다. */
.letter-reveal .lr-scroll-capture {
  position: absolute;
  inset: 0;
  z-index: 2;
  overflow-y: auto;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-y: contain;
  opacity: 0;
}

.letter-reveal .lr-scroll-spacer {
  width: 1px;
}

.letter-reveal .lr-body {
  left: 5.78%;
  top: 68.56%;
  width: 88.4%;
  height: 70.44%;
  z-index: 2;
  filter: drop-shadow(0 8px 10px rgba(0, 0, 0, 0.25));
}

.letter-reveal .lr-flap {
  left: 6.11%;
  top: 42%;
  width: 87.9%;
  height: 37.22%;
  z-index: 0;
  transform: translateY(-0.8px);
}

/* 모바일에서는 편지 봉투(몸통+플랩)를 조금 더 크게, 훨씬 더 아래로 내린다.
   lr-body와 lr-flap을 같은 폭(+25%p)만큼 같이 내려서 봉투 몸통과 플랩의 상대
   위치(겹치는 부분)가 유지되게 한다. */
@media (max-width: 480px) {
  /* 봉투(몸통+플랩)는 %/aspect-ratio 대신 고정 px 크기·위치를 쓴다 — 화면 폭에
     따라 .letter-reveal 컨테이너 자체의 크기가 달라지므로, %로 두면 화면마다
     봉투 높이가 다르게 보인다. 그 값을 %/top이 아니라 position:fixed +
     bottom(뷰포트 기준)으로 앵커한다 — .letter-reveal은 화면에 세로 중앙
     정렬되어 있어서, top으로 앵커하면 기기 화면 "높이"가 다를 때(같은 폭이라도)
     중앙 정렬 위치 자체가 달라져 봉투가 화면마다 다르게 보였다. bottom은
     뷰포트 바닥 기준 절대 거리라 화면 폭·높이와 무관하게 항상 같은 위치에
     온다. */
  .letter-reveal .lr-body {
    position: fixed;
    left: 50%;
    top: auto;
    bottom: -164px;
    width: 400px;
    height: 302px;
    margin-left: -200px;
    transform: scale(1.15);
  }
  .letter-reveal .lr-flap {
    position: fixed;
    left: 50%;
    top: auto;
    bottom: 75px;
    width: 397px;
    height: 160px;
    margin-left: -198.5px;
    transform: scale(1.15);
  }
  /* 편지지 가로폭을 더 넓히고, 늘어난 만큼 좌우로 균등하게 걸치도록
     왼쪽으로 절반만큼 당긴다. */
  .letter-reveal .lr-paper {
    width: calc(100% + 60px);
    left: -30px;
  }
}

/* 편지지 위에 적히는 결과 텍스트(뷰티팁 내용). lr-paper 안의 일반 문서 흐름으로
   들어가, 내용이 길어지면 lr-paper 자체의 높이가 늘어나고(= 스크롤 범위가 늘어남).
   아래쪽 여백을 크게 둔 이유: lr-body(봉투 몸통)가 이 창의 아래쪽 일부를 항상
   덮고 있어서, 그 정도 여유가 없으면 맨 마지막 줄이 끝까지 스크롤해도 봉투에
   가려진 채로 남는다. */
.letter-reveal .lr-text {
  box-sizing: border-box;
  padding: 13% 13% 25%;
  text-align: left;
}

.lr-text-title {
  margin: 0 0 20px;
  font-size: 26px;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: rgba(17, 17, 17, 0.9);
}

.lr-text-section {
  margin: 0 0 22px;
}

/* 결과(뷰티팁) 화면과 같은 방식으로, 첫 섹션을 뺀 나머지 항목 사이를 얇은 선으로 구분한다. */
.lr-text-section + .lr-text-section {
  border-top: 1px solid rgba(17, 17, 17, 0.14);
  padding-top: 20px;
}

.lr-text-label {
  margin: 0 0 6px;
  font-size: 17px;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: rgba(17, 17, 17, 0.85);
}

.lr-text-body {
  margin: 0 0 10px;
  font-size: 15px;
  line-height: 1.6;
  color: rgba(17, 17, 17, 0.75);
}

/* 모바일에서는 편지지 안 텍스트를 전체적으로 조금 작게 줄인다. */
@media (max-width: 480px) {
  .lr-text-title {
    font-size: 21px;
  }
  .lr-text-label {
    font-size: 14px;
  }
  .lr-text-body {
    font-size: 12.5px;
  }
}

/* 데스크탑에서는 "End"를 화면 우측 상단(다른 화면들의 top-right 버튼과 같은
   자리)에 둔다. 모바일에서는 아래 미디어쿼리가 하단 중앙 스택으로 되돌린다. */
.lr-end-button {
  position: fixed;
  top: calc(28px + env(safe-area-inset-top));
  right: calc(28px + env(safe-area-inset-right));
  left: auto;
  bottom: auto;
  transform: none;
  z-index: 10;
  background: transparent;
  border: none;
  font-size: 13px;
  letter-spacing: 0.02em;
  color: #111111;
  cursor: pointer;
}

/* "컬러 팔레트 보기" 버튼. 편지 화면(letterRevealOverlay) 하단 중앙에 화면
   기준으로 고정돼 있다 — 편지지 스크롤 레이어와 쌓임 순서가 절대 안 꼬이도록,
   일부러 스크롤되는 영역 밖에 둔 것이다. 데스크탑에서는 End가 우측 상단으로
   빠지므로 혼자 남아 조금 더 아래로 내려온다. */
.lr-palette-button {
  position: absolute;
  left: 50%;
  bottom: calc(30px + env(safe-area-inset-bottom));
  transform: translateX(-50%);
  z-index: 10;
  background: transparent;
  border: none;
  padding: 0;
  color: #111111;
  font-size: 13px;
  letter-spacing: 0.02em;
  cursor: pointer;
}

@media (max-width: 480px) {
  .lr-end-button {
    position: absolute;
    top: auto;
    right: auto;
    left: 50%;
    bottom: calc(28px + env(safe-area-inset-bottom));
    transform: translateX(-50%);
  }
  .lr-palette-button {
    bottom: calc(56px + env(safe-area-inset-bottom));
  }
}

/* "컬러 팔레트 보기"는 새 화면을 그리지 않고, 앱에 이미 있는 "확정한 색 보기"
   화면(colorOverlay/paletteBar/paletteToneTabs/backButton)을 그대로
   재사용한다 — 그 화면들 CSS는 이 파일 다른 곳에 이미 있다. */

/* 화면이 열리는 순간, 편지가 화면 아래에서 회전하며 떠올라 정위치에 안착한다. */
@keyframes envelopeDropIn {
  from {
    transform: translateY(60%) rotate(-18deg);
    opacity: 0;
  }
  to {
    transform: translateY(0) rotate(0deg);
    opacity: 1;
  }
}

.result-envelope.envelope-enter {
  animation: envelopeDropIn 0.9s cubic-bezier(0.22, 1, 0.36, 1) both;
}


.tutorial-back {
  position: fixed;
  top: calc(28px + env(safe-area-inset-top));
  left: calc(28px + env(safe-area-inset-left));
  z-index: 2001;
  background: transparent;
  border: none;
  color: #ffffff;
  padding: 8px 16px;
  border-radius: 999px;
  font-size: 12px;
  /* line-height: normal은 글자마다(특히 ←/→ 화살표처럼 폰트에 없어
     대체 글꼴로 넘어가는 글자) 줄 높이가 미세하게 달라질 수 있다.
     고정값으로 둬서 Back/Next 버튼 높이가 항상 똑같게 한다. */
  line-height: 1;
  cursor: pointer;
}

.tutorial-next {
  position: fixed;
  top: calc(28px + env(safe-area-inset-top));
  right: calc(28px + env(safe-area-inset-right));
  z-index: 2001;
  background: transparent;
  border: none;
  color: #ffffff;
  padding: 8px 16px;
  border-radius: 999px;
  font-size: 12px;
  line-height: 1;
  cursor: pointer;
}

/* 팔레트에서 색을 확정할 때마다 우측 상단 팔레트 아이콘이 벨이 울리듯 짧게 흔들린다. */
@keyframes paletteIconBell {
  0%, 100% { transform: rotate(0deg); }
  15% { transform: rotate(-18deg); }
  35% { transform: rotate(14deg); }
  55% { transform: rotate(-10deg); }
  75% { transform: rotate(6deg); }
  90% { transform: rotate(-3deg); }
}

.bell {
  animation: paletteIconBell 0.6s ease;
  transform-origin: 50% 15%;
}

/* 아이콘 뒤에 깔리는 넓고 연한 발광. box-shadow 대신 실제 원(blur된 원)을 써서
   각지거나 이상한 모양 없이 매끈하게 퍼지도록 한다. */
.icon-glow {
  position: absolute;
  width: 210px;
  height: 210px;
  border-radius: 50%;
  background: var(--glow-color, rgba(255, 255, 255, 0.55));
  filter: blur(34px);
  transform: translate(-50%, -50%) scale(0.6);
  opacity: 0;
  pointer-events: none;
  /* position:absolute인 이 엘리먼트는 음수 z-index를 줘야 일반 흐름 요소인
     아이콘(SVG)보다 뒤에 그려진다. DOM 순서만으로는 위치가 있는 요소가
     항상 나중에(위에) 칠해지기 때문. */
  z-index: -1;
}

@keyframes iconGlowPulse {
  0%, 100% { opacity: 0; transform: translate(-50%, -50%) scale(0.6); }
  40% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}

.icon-glow.pulse {
  animation: iconGlowPulse 0.9s ease;
}

/* 팔레트/색 확인 힌트가 뜰 때 각각 하단 중앙 팔레트 스와치와 우측 상단 팔레트
   아이콘을 은은하게 발광시켜 시선을 끈다. icon-glow(짧게 반짝하고 마는 keyframe
   pulse)와 달리, 이 발광들은 힌트 문구와 같은 타이밍에 나타나고(짧게) 사라지도록
   (느리게) opacity 트랜지션으로 직접 켜고 끈다 — 문구가 사라지는 속도에 맞춘다. */
.palette-center-glow,
.palette-icon-hint-glow {
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.55);
  filter: blur(20px);
  opacity: 0;
  pointer-events: none;
  z-index: 999;
  transition: opacity 0.35s ease;
}

.palette-center-glow {
  position: fixed;
  bottom: 36px;
  left: 50%;
  width: 90px;
  height: 90px;
  transform: translate(-50%, 0);
}

.palette-icon-hint-glow {
  position: fixed;
  top: calc(44px + env(safe-area-inset-top));
  right: calc(36px + env(safe-area-inset-right));
  width: 90px;
  height: 90px;
  transform: translate(50%, -50%);
}

/* 종합 단계 색 구름: 원 배치 한 주기를 좌우로 이어붙여 두고, -50%(둘째 주기가 보이는
   지점)에서 0(첫 주기가 보이는 지점)으로 되돌아가듯 흘려서 왼쪽→오른쪽으로 흐르게
   한다. 두 주기가 완전히 같은 그림이라 이 구간을 반복해도 이음매 없이 이어진다. */
@keyframes synthesisDrift {
  from { transform: translateX(-50%); }
  to { transform: translateX(0); }
}

@media (prefers-reduced-motion: reduce) {
  .synthesis-track { animation: none !important; }
}

/* 팔레트 아이콘을 눌러 확정 색 화면으로 들어갈 때, 아이콘 자리에서 빛이 확 퍼지듯
   커지면서 투명해지고 그 뒤로 다음 화면이 드러나는 전환 효과. */
.palette-transition-glow {
  position: fixed;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(255, 255, 255, 0.95) 0%, rgba(255, 255, 255, 0.75) 45%, rgba(255, 255, 255, 0) 72%);
  transform: translate(-50%, -50%) scale(0.6);
  opacity: 0;
  pointer-events: none;
  z-index: 3000;
  /* 밝은(파스텔) 배경 위에서도 그냥 흰 원으로 뭉개지지 않고 "빛이 밝아진다"는
     느낌이 나도록 항상 밝게만 더해지는 screen 블렌드를 쓴다. */
  mix-blend-mode: screen;
}

@keyframes paletteTransitionBurst {
  0% { opacity: 0.95; transform: translate(-50%, -50%) scale(0.6); }
  100% { opacity: 0; transform: translate(-50%, -50%) scale(48); }
}

.palette-transition-glow.burst {
  animation: paletteTransitionBurst 0.75s cubic-bezier(0.22, 0.61, 0.36, 1) forwards;
}

/* 팔레트 아이콘 바로 아래 뜨는 짧은 안내("색을 선택해주세요"). 배경이 어떤
   색이든 항상 읽히도록 스스로 어두운 배경 + 흰 글씨를 쓴다. */
.palette-empty-toast {
  position: fixed;
  top: calc(68px + env(safe-area-inset-top));
  right: calc(28px + env(safe-area-inset-right));
  margin: 0;
  padding: 7px 14px;
  background: rgba(23, 20, 18, 0.85);
  color: #ffffff;
  font-size: 12px;
  border-radius: 999px;
  white-space: nowrap;
  z-index: 1600;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s ease;
}

.site-footer {
  position: fixed;
  left: calc(14px + env(safe-area-inset-left));
  bottom: calc(10px + env(safe-area-inset-bottom));
  z-index: 500;
  color: #111111;
  /* 홈 화면 인트로(확대→축소) 동안에는 숨겨뒀다가, 인트로가 끝나는 시점에
     톤 버튼/튜토리얼 아이콘과 함께 나타난다(script.js). */
  opacity: 0;
  pointer-events: none;
  transition: color 0.4s ease, opacity 0.6s ease;
}

.site-footer-toggle {
  display: block;
  background: none;
  border: none;
  padding: 4px 2px;
  margin: 0;
  font-family: inherit;
  font-size: 9px;
  letter-spacing: 0.02em;
  color: inherit;
  opacity: 0.5;
  cursor: pointer;
}

.site-footer-details {
  max-height: 0;
  overflow: hidden;
  opacity: 0;
  transform: translateY(4px);
  transition: max-height 0.3s ease, opacity 0.25s ease, transform 0.3s ease;
  font-size: 9px;
  line-height: 1.7;
  color: inherit;
}

.site-footer-details.expanded {
  max-height: 140px;
  opacity: 0.8;
  transform: translateY(0);
}

.site-footer .nowrap {
  white-space: nowrap;
}

.site-footer a {
  color: inherit;
  text-decoration: underline;
}

/* 모바일에서는 화면 하단 중앙에 "Tutorial" 버튼이 따로 있어서, 펼쳐진 사업자
   정보가 옆으로 넓게 퍼지면 그 버튼과 겹친다. 폭을 좁혀 왼쪽에만 머물게 하고,
   대신 줄바꿈으로 세로가 늘어나는 만큼 max-height도 넉넉히 늘려준다. */
@media (max-width: 480px) {
  .site-footer-details {
    max-width: 128px;
  }
  .site-footer-details.expanded {
    max-height: 190px;
  }
  /* 하단 중앙 "Tutorial" 버튼과 같은 글자 크기로 맞춘다(같은 clamp 식). */
  .site-footer-toggle {
    font-size: clamp(8px, 2vw, 13px);
  }
}

/* 봉투를 눌렀을 때 편지를 열기 전에 먼저 뜨는 결제 화면. */
.payment-overlay {
  position: fixed;
  inset: 0;
  z-index: 1700;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: rgba(20, 16, 14, 0.55);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.35s ease;
}

.payment-card {
  position: relative;
  width: 100%;
  max-width: 520px;
  background: rgba(255, 253, 251, 0.55);
  border-radius: 22px;
  padding: 60px 48px 48px;
  text-align: center;
  box-shadow: 0 20px 40px rgba(0, 0, 0, 0.25);
}

.payment-title {
  font-size: 24px;
  font-weight: 700;
  color: #171412;
  margin: 0 0 22px;
}

.payment-description {
  font-size: 14.5px;
  line-height: 1.7;
  color: #666666;
  margin: 0 0 32px;
}

.payment-pay-button {
  display: block;
  width: 100%;
  padding: 17px;
  border: none;
  border-radius: 999px;
  background: #171412;
  color: #ffffff;
  font-size: 16px;
  font-weight: 400;
  letter-spacing: 0.02em;
  cursor: pointer;
  transition: opacity 0.2s ease;
}

.payment-pay-button:disabled {
  opacity: 0.5;
  cursor: default;
}

.payment-products {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.payment-product {
  display: block;
  width: 100%;
  padding: 16px 20px;
  border: 1px solid rgba(23, 20, 18, 0.15);
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.5);
  cursor: pointer;
  text-align: left;
  transition: border-color 0.15s ease, background 0.15s ease;
}

.payment-product:hover {
  border-color: #171412;
  background: rgba(255, 255, 255, 0.85);
}

.payment-product-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.payment-product-name {
  font-size: 15px;
  font-weight: 500;
  color: #171412;
}

.payment-product-price {
  font-size: 15px;
  font-weight: 600;
  color: #171412;
  white-space: nowrap;
}

.payment-error {
  display: none;
  margin: 14px 0 0;
  font-size: 12px;
  color: #c0392b;
}