@charset "UTF-8";
/* ═══════════════════════════════════════════════════════════
   coin laundry · window seat — 스타일시트
   ───────────────────────────────────────────────────────────
   두 세계관(laundry / airplane)이 이 스타일시트를 공유합니다.
   테마별로만 달라야 하는 규칙은 body[data-theme="..."]로 감쌉니다.

   목차
   1. 🎨 테마 토큰  ← 색을 바꾸려면 여기만 수정하면 됩니다
   2. 공통 (리셋 / 그레인 / 화면 전환)
   3. 화면 0 · 입구 (사진 전체 화면 + 입장 버튼)
   4. 종이 카드 공통 (주문 플로우)
   5. 화면 -1 · 세계관 선택   ← 이 화면만 규칙이 다름 (흰 배경 · 세리프 제목)
   6. 화면 1 · 뽑기 — 공통
   7. 화면 1 · 뽑기 — board 모드 (전광판)
   8. 화면 2 · 시간 선택
   9. 화면 3 · 티켓 / 탑승권
   10. 화면 4 · 포스트잇
   11. 버튼 공통
   12. 화면 5 · 타이머 (focus / social / 자리비움)
   13. 화면 6 · 완료
   14. 모바일 대응
   ═══════════════════════════════════════════════════════════ */

/* ═══ 1. 🎨 테마 토큰 ═══
   구아슈(과슈) 페인팅 느낌의 팔레트 — 두 세계관이 같은 색을 씁니다.
   색만 바꾸고 싶다면 이 블록만 수정하면 됩니다.
   (단, assets/*.svg 안에도 같은 색이 하드코딩되어 있으니 톤을 맞추려면
    함께 수정하세요.) */
:root {
  --ink: #1c1a17;                         /* 텍스트 · 잉크 선 */
  --paper: #f4ede0;                       /* 크림 배경 */
  --navy: #24345c;                        /* 간판 · 포인트 남색 · 전광판 테두리 */
  --navy-soft: rgba(36, 52, 92, 0.22);    /* 옅은 남색 (그림자) */
  --red: #c2402f;                         /* 진행률 바 · 정지 버튼 빨강 */
  --yellow: #d9a441;                      /* 머스타드 (로고 · 전광판 글자) */

  /* ── 커스텀 커서 ──
     세계관마다 커서가 다릅니다. 실제로 쓰이는 것은 --cursor(배경 위)와
     --cursor-pointer(클릭 가능한 요소 위) 두 개뿐이고, 아래 body 규칙이
     테마에 따라 이 둘의 값을 갈아끼웁니다. 그래서 새 커서를 넣고 싶으면
     ① 여기에 그림 두 줄을 추가하고 ② body[data-theme=...]에서 --cursor /
     --cursor-pointer에 연결하면 끝입니다. */

  /* 🧺 laundry — 비눗방울 */
  --cursor-bubble:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3E%3Ccircle cx='15' cy='15' r='11.5' fill='rgba(207,224,238,0.5)' stroke='%2324345c' stroke-width='1.6'/%3E%3Ccircle cx='10.5' cy='10.5' r='3' fill='%23ffffff' opacity='0.95'/%3E%3Ccircle cx='20' cy='19' r='1.5' fill='%23ffffff' opacity='0.75'/%3E%3C/svg%3E")
    15 15, auto;
  --cursor-bubble-pointer:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3E%3Ccircle cx='15' cy='15' r='11.5' fill='rgba(207,224,238,0.65)' stroke='%2324345c' stroke-width='1.8'/%3E%3Ccircle cx='10.5' cy='10.5' r='3' fill='%23ffffff'/%3E%3Ccircle cx='20' cy='19' r='1.5' fill='%23ffffff' opacity='0.8'/%3E%3C/svg%3E")
    15 15, pointer;

  /* ✈️ airplane — 종이비행기. 기수(오른쪽 위)가 실제 포인터 지점입니다 */
  --cursor-plane:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3E%3Cpath d='M26.5 3.5 L4 14.5 L13 17.5 L16 26.5 Z' fill='%23ffffff' stroke='%2324345c' stroke-width='1.7' stroke-linejoin='round'/%3E%3Cpath d='M13 17.5 L26.5 3.5' fill='none' stroke='%2324345c' stroke-width='1.3'/%3E%3C/svg%3E")
    26 4, auto;
  --cursor-plane-pointer:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3E%3Cpath d='M26.5 3.5 L4 14.5 L13 17.5 L16 26.5 Z' fill='%23e9b247' stroke='%2324345c' stroke-width='1.9' stroke-linejoin='round'/%3E%3Cpath d='M13 17.5 L26.5 3.5' fill='none' stroke='%2324345c' stroke-width='1.4'/%3E%3C/svg%3E")
    26 4, pointer;

  /* 세계관 선택 화면은 커스텀 커서를 쓰지 않습니다 — 아직 어느 세계관에도
     들어가지 않은 화면이라 브라우저 기본 커서가 맞습니다 (아래 #screen-world). */

  /* 기본값 (테마가 아직 안 정해졌을 때) */
  --cursor: var(--cursor-bubble);
  --cursor-pointer: var(--cursor-bubble-pointer);
}

/* ── 세계관별 커서 · 글꼴 ──
   여기 두 블록이 "비행기와 세탁소의 분위기를 다르게" 만드는 핵심입니다.
   커서와 본문 글꼴을 통째로 갈아끼우므로, 모든 화면이 함께 바뀝니다. */
body[data-theme='laundry'] {
  --cursor: var(--cursor-bubble);
  --cursor-pointer: var(--cursor-bubble-pointer);
  font-family: 'Shantell Sans', sans-serif;
}
body[data-theme='airplane'] {
  --cursor: var(--cursor-plane);
  --cursor-pointer: var(--cursor-plane-pointer);
  /* 각지고 건조한 공항 사인 느낌 — 둥근 마커 글꼴과 정반대 */
  font-family: 'Work Sans', sans-serif;
  letter-spacing: 0.01em;
}

/* ═══ 2. 공통 ═══ */
* { margin: 0; padding: 0; box-sizing: border-box; }

html, body { height: 100%; }

body {
  font-family: 'Shantell Sans', sans-serif;
  color: var(--ink);
  background: var(--paper);
  overflow: hidden;
  -webkit-font-smoothing: antialiased;
  cursor: var(--cursor);
}

/* 글자를 직접 입력하는 곳은 거품 대신 진짜 텍스트 커서가 필요합니다 */
.ticket-name,
.postit-body {
  cursor: text;
}

/* 화면 전체에 얇게 깔리는 필름 그레인 (종이 질감) */
.grain-svg {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0.08;
  pointer-events: none;
  z-index: 999;
  mix-blend-mode: multiply;
}
/* 세계관 선택 화면은 순백이어야 깔끔하므로 그레인을 거의 걷어냅니다.
   (곱하기 블렌드라서 그레인이 남으면 흰 배경이 회색으로 탁해집니다) */
body:has(#screen-world.active) .grain-svg { opacity: 0.02; }

.art { display: block; }

/* ⚠ hidden 속성이 항상 먹히게 만드는 안전장치.
   HTML의 hidden은 브라우저 기본 스타일시트에서 display:none이지만,
   우리가 .draw-dock 등에 display:flex를 직접 지정하면 그게 이겨서
   hidden이 무시됩니다 (실제로 전광판 위에 바구니가 남는 버그가 있었음).
   그래서 hidden에는 !important를 붙여 우선권을 확실히 줍니다. */
[hidden] { display: none !important; }

/* 화면(스크린) 전환: .active가 붙은 화면만 보입니다 */
.screen {
  position: fixed;
  inset: 0;
  display: none;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  background: var(--paper);
}
.screen.active { display: flex; }

/* ═══ 3. 화면 0 · 입구 (실제 사진, 화면 전체) ═══
   assets/splash-photo.webp가 화면을 가득 채우고, 버튼은 사진 속
   인도(빈 바닥) 위에 겹쳐 놓았습니다. */
.entrance {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
  background: var(--paper);
}

.entrance-photo {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  cursor: var(--cursor-pointer);
}

/* 입장 버튼: 가만히 있을 때도 살짝 숨쉬듯 움직여서 눈에 띄고,
   호버하면 화살표만 스르륵 앞으로 나갑니다 */
.poster-enter {
  position: absolute;
  left: 50%;
  bottom: 7%;
  transform: translateX(-50%);
  z-index: 2;
  animation: enterBreathe 2.6s ease-in-out infinite;
  transition: transform 0.25s cubic-bezier(0.34, 1.56, 0.64, 1), box-shadow 0.25s ease;
}
@keyframes enterBreathe {
  0%, 100% { transform: translateX(-50%) scale(1); }
  50% { transform: translateX(-50%) scale(1.04); }
}
.poster-enter:hover {
  animation-play-state: paused;
  transform: translateX(-50%) scale(1.08);
  box-shadow: 5px 6px 0 rgba(17, 17, 17, 0.22);
}
.poster-enter:active {
  animation-play-state: paused;
  transform: translateX(-50%) scale(0.96);
}
.enter-arrow {
  display: inline-block;
  transition: transform 0.25s ease;
}
.poster-enter:hover .enter-arrow { transform: translateX(5px); }

/* ═══ 4. 종이 카드 공통 (주문 플로우) ═══ */
.paper {
  position: relative;
  width: min(600px, 92vw);
  max-height: 94vh;
  background: #fff;
  padding: clamp(1.1rem, 3vh, 3rem) clamp(1.4rem, 4vw, 3rem);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(0.9rem, 2.4vh, 1.6rem);
  border: 3px solid var(--navy);
  border-radius: 22px;
  box-shadow: 8px 9px 0 var(--navy-soft);
  overflow-y: auto;
}

.paper-logo { width: 46px; }

.paper-q {
  font-size: clamp(1.05rem, 2.6vw, 1.35rem);
  font-weight: 800;
  color: var(--navy);
  letter-spacing: 0.01em;
}

/* ═══ 5. 화면 -1 · 세계관 선택 ═══
   ⚠ 이 화면만 앱의 다른 규칙을 따르지 않습니다.
   나머지 화면은 크림 배경 + 남색 테두리 종이 카드(.paper)를 쓰지만,
   여기는 "표지"라서 순백 배경에 넓은 여백, 세리프 제목(Instrument Serif),
   테두리 없는 얇은 헤어라인만 씁니다. 두 세계관 어디에도 속하지 않는
   자리이므로 커서도 중립적인 링을 씁니다.

   각 카드는 자기 세계관을 미리 보여줍니다 — 이름의 글꼴과 --accent 색이
   그 테마의 것이라, 고르기 전에 분위기를 짐작할 수 있습니다.
   카드를 추가하려면 index.html에 .world-card를 하나 복사하고,
   아래에 그 data-theme의 --accent와 이름 글꼴을 한 줄씩 지정하세요. */
#screen-world {
  background: #fff;
  /* 아직 세계관을 고르기 전이라 브라우저 기본 커서를 씁니다.
     (body의 거품/종이비행기 커서는 cursor가 상속 속성이라 여기까지
      내려오므로, 이렇게 명시적으로 되돌려야 합니다) */
  cursor: auto;
}

.world {
  width: min(940px, 92vw);
  max-height: 96vh;
  overflow-y: auto;
  padding: clamp(1rem, 4vh, 2.6rem) clamp(0.5rem, 2vw, 1.5rem);
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}

/* 아주 작은 대문자 + 넓은 자간 — 표지의 "부제" 같은 한 줄 */
.world-eyebrow {
  font-family: 'Work Sans', sans-serif;
  font-size: clamp(0.58rem, 1.5vw, 0.7rem);
  font-weight: 500;
  letter-spacing: 0.44em;
  text-transform: uppercase;
  color: rgba(28, 26, 23, 0.42);
  margin-left: 0.44em; /* 자간 때문에 오른쪽으로 치우치는 것 보정 */
}

/* 제목만 세리프(Instrument Serif). 두 번째 줄은 이탤릭으로만 강조합니다.
   ⚠ Instrument Serif는 굵기가 400 하나뿐입니다. font-weight를 300이나 600으로
   주면 브라우저가 가짜 볼드/라이트를 합성해서 글자가 뭉개지므로, 굵기는
   건드리지 않고 이탤릭과 크기로만 강약을 만듭니다. */
.world-title {
  font-family: 'Instrument Serif', Georgia, serif;
  font-weight: 400;
  font-size: clamp(1.9rem, 6.2vw, 3.7rem);
  line-height: 1.04;
  letter-spacing: -0.012em;
  color: var(--ink);
  margin-top: clamp(0.7rem, 2vh, 1.1rem);
}
.world-title em { font-style: italic; }

.world-rule {
  width: 46px;
  height: 1px;
  background: rgba(28, 26, 23, 0.22);
  margin: clamp(1.1rem, 3.4vh, 2rem) 0 clamp(1.2rem, 3.6vh, 2.2rem);
}

.world-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: clamp(1rem, 3.5vw, 3rem);
  width: 100%;
}

/* 카드: 테두리 상자가 아니라 "위쪽 헤어라인 아래 놓인 항목"입니다.
   호버하면 그 선이 그 세계관의 색으로 굵어집니다. */
.world-card {
  --accent: var(--navy);
  position: relative;
  background: none;
  border: none;
  border-top: 1px solid rgba(28, 26, 23, 0.16);
  padding: clamp(1rem, 3vh, 1.9rem) clamp(0.4rem, 1.5vw, 1rem) clamp(0.7rem, 2vh, 1.2rem);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(0.4rem, 1.2vh, 0.7rem);
  cursor: pointer; /* 기본 손가락 커서 — 이 화면은 커스텀 커서를 안 씁니다 */
  transition: border-top-color 0.22s ease;
}
/* 호버 시 위쪽 선이 색을 입고 두꺼워지는 효과 (레이아웃은 흔들리지 않게
   border 대신 별도 선을 겹쳐 그립니다) */
.world-card::before {
  content: '';
  position: absolute;
  top: -1px;
  left: 0;
  width: 0;
  height: 2px;
  background: var(--accent);
  transition: width 0.32s cubic-bezier(0.4, 0, 0.2, 1);
}
.world-card:hover::before,
.world-card:focus-visible::before { width: 100%; }

.world-num {
  font-family: 'Work Sans', sans-serif;
  font-size: 0.66rem;
  font-weight: 500;
  letter-spacing: 0.22em;
  color: rgba(28, 26, 23, 0.3);
  transition: color 0.22s ease;
}
.world-card:hover .world-num { color: var(--accent); }

.world-art {
  width: clamp(96px, 17vh, 168px);
  height: clamp(96px, 17vh, 168px);
  object-fit: contain;
  margin: clamp(0.2rem, 1vh, 0.6rem) 0;
  filter: drop-shadow(3px 6px 8px rgba(28, 26, 23, 0.13));
  transition: transform 0.32s cubic-bezier(0.34, 1.4, 0.64, 1);
}
.world-card:hover .world-art { transform: translateY(-7px) scale(1.04); }

/* 이름은 그 세계관의 글꼴로 — 고르기 전에 분위기가 먼저 보입니다 */
.world-name {
  font-size: clamp(1.05rem, 2.9vw, 1.45rem);
  color: var(--ink);
}
.world-card[data-theme='laundry'] {
  --accent: var(--red);
}
.world-card[data-theme='laundry'] .world-name {
  font-family: 'Shantell Sans', sans-serif;
  font-weight: 700;
}
.world-card[data-theme='airplane'] {
  --accent: #2f6f9f;
}
.world-card[data-theme='airplane'] .world-name {
  font-family: 'Work Sans', sans-serif;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-size: clamp(0.92rem, 2.4vw, 1.2rem);
}

/* 카드 설명은 세리프가 아니라 본문 산세리프로 — 제목만 세리프여야
   "제목이 특별하다"가 살아납니다 (시안 B 기준) */
.world-sub {
  font-family: 'Work Sans', sans-serif;
  font-weight: 400;
  font-size: clamp(0.82rem, 2vw, 0.98rem);
  color: rgba(28, 26, 23, 0.5);
  line-height: 1.4;
}

/* 평소엔 숨어 있다가 호버하면 올라오는 안내 */
.world-go {
  font-family: 'Work Sans', sans-serif;
  font-size: 0.66rem;
  font-weight: 500;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--accent);
  margin-top: clamp(0.2rem, 1vh, 0.5rem);
  opacity: 0;
  transform: translateY(5px);
  transition: opacity 0.24s ease, transform 0.24s ease;
}
.world-card:hover .world-go,
.world-card:focus-visible .world-go {
  opacity: 1;
  transform: translateY(0);
}

/* ═══ 6. 화면 1 · 뽑기 (공통) ═══
   두 세계관이 같은 구조를 씁니다: 소스(#drawSource)를 누르면 항목이 하나씩
   .draw-stage에 쌓이고, 쌓인 것 중 하나를 눌러 고릅니다.
     laundry  → 바구니를 누르면 빨랫감이 튀어나옴  (toss 모드, 이 섹션)
     airplane → 전광판을 누르면 행선지가 떠오름    (board 모드, 섹션 7)
   아래 규칙은 toss 모드 기준이고, board 모드는 섹션 7에서 덮어씁니다. */
.paper-draw { gap: clamp(0.7rem, 2vh, 1.3rem); }

/* 뽑힌 항목들이 쌓이는 무대 (소스 버튼 위쪽) */
.draw-stage {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: flex-end;
  gap: clamp(0.3rem, 1.4vw, 0.9rem);
  width: 100%;
  min-height: clamp(96px, 22vh, 190px);
}

/* 뽑힌 항목 하나 (버튼). 기울기·호버는 안쪽 .pick-inner에 걸어서,
   바깥에 걸린 "튀어나오는" 애니메이션의 transform과 부딪히지 않게
   분리했습니다 (둘 다 transform이라 한 요소에 걸면 서로를 덮어씁니다). */
.pick {
  background: none;
  border: none;
  padding: 0.2rem 0.35rem;
  font-family: inherit;
  cursor: var(--cursor-pointer);
  transform-origin: bottom center;
  animation: pickToss 0.5s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
}
.pick-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.35rem;
  transform: rotate(var(--tilt, 0deg));
  transition: transform 0.16s ease;
}
.pick:hover .pick-inner { transform: translateY(-5px) rotate(0deg); }
.pick .art {
  width: clamp(64px, 12vh, 116px);
  height: clamp(64px, 12vh, 116px);
  object-fit: contain;
  filter: drop-shadow(2px 4px 4px rgba(36, 52, 92, 0.16));
  transition: transform 0.16s ease;
}
.item-label {
  font-size: 0.85rem;
  font-weight: 500;
  color: var(--navy);
  background: var(--paper);
  border: 2px solid transparent;
  border-radius: 8px;
  padding: 0.15rem 0.65rem;
}
/* 하나를 고르면 나머지는 흐려집니다 */
.draw-stage.has-pick .pick:not(.selected) { opacity: 0.32; filter: grayscale(0.7); }
.pick.selected .item-label { border-color: var(--navy); font-weight: 800; background: #fff; }
.pick.selected .art { transform: scale(1.06); }

/* 소스에서 튀어나오는 연출: 아래쪽에서 작게 시작해 통 튀어오름 */
@keyframes pickToss {
  0%   { opacity: 0; transform: translateY(64px) scale(0.5); }
  55%  { opacity: 1; }
  100% { opacity: 1; transform: translateY(0) scale(1); }
}

/* 소스 버튼이 놓이는 자리 (버튼 + 안내 문구) */
.draw-dock {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.3rem;
}
.draw-source {
  background: none;
  border: none;
  padding: 0;
  cursor: var(--cursor-pointer);
  animation: basketNudge 2.8s ease-in-out infinite;
  transition: transform 0.12s ease;
}
.draw-source:hover { animation-play-state: paused; transform: translateY(-3px) scale(1.03); }
.draw-source:active { transform: translateY(2px) scale(0.97); }
/* 눌렀을 때 살짝 짜부 → 원상복귀 (하나 꺼낼 때의 반동) */
.draw-source.pop { animation: basketPop 0.32s ease; }
.draw-source.spent { animation: none; cursor: default; }
.draw-source-img {
  width: clamp(116px, 21vh, 196px);
  filter: drop-shadow(3px 6px 5px rgba(36, 52, 92, 0.18));
}
@keyframes basketNudge {
  0%, 86%, 100% { transform: rotate(0deg); }
  90% { transform: rotate(-3deg); }
  95% { transform: rotate(3deg); }
}
@keyframes basketPop {
  0% { transform: scale(1); }
  35% { transform: scale(1.06, 0.9) translateY(3px); }
  100% { transform: scale(1); }
}
.draw-hint {
  font-family: 'Caveat', cursive;
  font-size: clamp(1rem, 2.4vh, 1.35rem);
  color: var(--navy);
  opacity: 0.72;
}

/* ═══ 7. 화면 1 · board 모드 (airplane 출발 전광판) ═══
   실제 전광판 사진(assets/air-board.webp) 위에 글자 행을 얹습니다.
   사진에 이미 "DEPARTURES" 헤더와 time·to·gate·info 열 제목, 그리고
   빈 도트매트릭스 칸 10개가 그려져 있으므로, 우리가 하는 일은 그 칸 위에
   글자를 정확히 앉히는 것뿐입니다.

   ⚠ 아래 %는 assets/air-board.webp(1070×857)에서 실측한 값입니다:
       도트 칸 영역   y 213~813  → top 24.85% ~ 94.87%
       한 칸 높이     60px       → 7.001%
       열 시작 x      time 55 / to 225 / gate 582 / info 704
                      → 5.14% / 21.03% / 54.39% / 65.79%
   사진을 바꾸면 이 값들을 다시 재야 합니다 (README의 "전광판 좌표
   재는 법" 참고). 행 수(10)도 사진 칸 수와 맞아야 하므로, 항목을
   늘리려면 THEMES.airplane.items와 사진을 함께 바꿔야 합니다. */
.draw-stage[data-mode='board'] {
  display: block;
  min-height: 0;
}

/* 전광판 사진 + 그 위에 얹히는 행들의 기준 박스.
   container-type을 주면 글자 크기를 cqw(이 박스 너비의 %)로 지정할 수 있어,
   화면이 커지든 작아지든 사진과 글자가 항상 같은 비율로 붙어 있습니다. */
.board {
  position: relative;
  width: 100%;
  container-type: inline-size;
  filter: drop-shadow(4px 6px 6px rgba(36, 52, 92, 0.22));
}
.board-img {
  width: 100%;
  height: auto;
}

/* 전광판 한 행 — 사진의 도트 칸 하나에 정확히 겹칩니다.
   --row는 몇 번째 칸인지(0부터). app.js의 makePick()이 넣어줍니다. */
.pick.dest {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(24.85% + var(--row) * 7.001%);
  height: 7.001%;
  padding: 0;
  background: none;
  border: none;
  cursor: var(--cursor-pointer);
  /* 스플릿플랩처럼 위에서 딱 떨어지는 연출 (행마다 조금씩 늦게) */
  animation: destFlap 0.4s cubic-bezier(0.3, 1.4, 0.5, 1) backwards;
  animation-delay: calc(var(--row) * 0.055s);
  transform-origin: top center;
  transition: filter 0.15s ease;
}

/* 네 칸의 글자. 왼쪽 위치는 사진의 열 시작점 실측값. */
.dest-time,
.dest-city,
.dest-gate,
.dest-info {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  white-space: nowrap;
  /* 전광판이니 등폭 글꼴 — 별도 폰트를 받지 않고 시스템 것을 씁니다 */
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 2.85cqw;
  letter-spacing: 0.02em;
  line-height: 1;
}
.dest-time { left: 5.14%;  color: #c4beb2; }
.dest-city { left: 21.03%; color: #e9b247; font-weight: 700; }
.dest-gate { left: 54.39%; color: #c4beb2; }
.dest-info { left: 65.79%; color: #8cbe78; }

/* 호버: 그 행만 살짝 밝아집니다 (사진 위라서 배경을 덮지 않고 밝기만 올림) */
.pick.dest:hover { filter: brightness(1.35); }
.pick.dest:focus-visible {
  outline: 2px solid rgba(233, 178, 71, 0.7);
  outline-offset: -2px;
}

/* 고른 행만 밝게, 나머지는 흐리게 */
.draw-stage[data-mode='board'].has-pick .pick.dest:not(.selected) { opacity: 0.32; filter: none; }
.pick.dest.selected .dest-city { color: #ffd66e; }
.pick.dest.selected .dest-time,
.pick.dest.selected .dest-gate { color: #efe9dd; }

@keyframes destFlap {
  0%   { opacity: 0; transform: rotateX(-88deg); }
  60%  { opacity: 1; }
  100% { opacity: 1; transform: rotateX(0deg); }
}

/* 전광판은 가로로 넓으니 카드도 살짝 넓혀 줍니다 */
body[data-theme='airplane'] .paper-draw { width: min(680px, 94vw); }

/* ═══ 8. 화면 2 · 시간 선택 ═══ */
.cycle-list {
  display: flex;
  flex-direction: column;
  gap: clamp(0.7rem, 2vh, 1.2rem);
  width: min(380px, 100%);
  margin: 1rem 0;
}
.cycle {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  background: none;
  border: 2.5px solid transparent;
  border-radius: 12px;
  padding: 0.55rem 0.95rem;
  font-family: inherit;
  font-size: 1rem;
  cursor: var(--cursor-pointer);
  text-align: left;
}
.cycle-name { font-weight: 800; color: var(--ink); }
.cycle-dots { flex: 1; border-bottom: 2.5px dotted var(--navy-soft); transform: translateY(-4px); }
.cycle-time { font-weight: 500; color: var(--navy); }
.cycle.selected { border-color: var(--navy); background: var(--paper); }

/* ── airplane: 같은 목록을 공항 안내판처럼 ──
   세탁소는 "quick wash ······ 25 minutes"처럼 점선으로 잇는 손글씨 영수증
   느낌이지만, 비행기는 대문자·넓은 자간·등폭 숫자·실선으로 건조하게
   바꿉니다. 구조(HTML)는 그대로고 글꼴과 선만 갈아입습니다. */
body[data-theme='airplane'] .cycle {
  border-radius: 4px;
  border-width: 0 0 0 2.5px;
  border-left-color: transparent;
  padding: 0.6rem 0.9rem;
}
body[data-theme='airplane'] .cycle-name {
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-size: 0.92em;
}
body[data-theme='airplane'] .cycle-dots {
  border-bottom: 1px solid rgba(36, 52, 92, 0.22);
  transform: translateY(-3px);
}
body[data-theme='airplane'] .cycle-time {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.86em;
  letter-spacing: 0.02em;
  color: var(--navy);
}
body[data-theme='airplane'] .cycle.selected {
  border-left-color: var(--navy);
  background: rgba(47, 111, 159, 0.07);
}
body[data-theme='airplane'] .cycle.selected .cycle-name { font-weight: 700; }

/* airplane 화면 제목도 같은 목소리로 (둥근 마커 → 각진 사인) */
body[data-theme='airplane'] .paper-q {
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: lowercase;
}
/* 티켓·포스트잇의 라벨류도 각지게 */
body[data-theme='airplane'] .ticket-head,
body[data-theme='airplane'] .postit-head,
body[data-theme='airplane'] .ticket-foot {
  letter-spacing: 0.14em;
}

/* ═══ 9. 화면 3 · 티켓 / 탑승권 ═══ */
.ticket {
  position: relative;
  width: min(340px, 100%);
  background: #e8e2d4;               /* 크라프트지 색 */
  border: 1.5px solid #c9c2b0;
  padding: 1.4rem 1.5rem 1.1rem;
  margin: 1.2rem 0;
  box-shadow: 4px 6px 0 var(--navy-soft);
  transform: rotate(-1.2deg);
}
.ticket-holes {
  position: absolute;
  top: 10px; left: 0; right: 0;
  display: flex;
  justify-content: space-between;
  padding: 0 14px;
}
.ticket-holes i {
  width: 9px; height: 9px;
  border-radius: 50%;
  background: var(--paper);
  border: 1.5px solid #b3ab97;
}
.ticket-head {
  text-align: center;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.22em;
  color: #6b6350;
}
.ticket-name {
  font-family: 'Caveat', cursive;
  font-size: 2.6rem;
  font-weight: 600;
  text-align: center;
  color: var(--navy);
  margin: 0.8rem 0 0.4rem;
  outline: none;
  min-height: 3.2rem;
}
.ticket-name:focus { color: var(--red); }
.ticket-rule { border-top: 1.5px solid #b3ab97; margin-bottom: 0.55rem; }
.ticket-foot {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  color: #6b6350;
}

/* ═══ 10. 화면 4 · 포스트잇 ═══ */
.postit {
  position: relative;
  width: auto;
  height: min(300px, 44vh);
  aspect-ratio: 1 / 0.96;
  background: linear-gradient(180deg, #f7ecab, #f2e394);
  box-shadow: 4px 8px 14px rgba(0, 0, 0, 0.16);
  padding: 2rem 1.6rem;
  margin: 1rem 0;
  transform: rotate(1deg);
  display: flex;
  flex-direction: column;
  align-items: center;
}
.postit-tape {
  position: absolute;
  top: -12px; left: 50%;
  width: 84px; height: 26px;
  transform: translateX(-50%) rotate(-2deg);
  background: rgba(255, 255, 255, 0.55);
  border-left: 1px dashed rgba(0, 0, 0, 0.12);
  border-right: 1px dashed rgba(0, 0, 0, 0.12);
}
.postit-head {
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.2em;
  color: #7c7040;
}
.postit-body {
  flex: 1;
  width: 100%;
  margin-top: 1.2rem;
  font-family: 'Caveat', cursive;
  font-size: 1.9rem;
  font-weight: 500;
  color: var(--navy);
  text-align: center;
  outline: none;
  line-height: 1.25;
}
.postit-body:empty::before {
  content: attr(data-placeholder);
  color: #b0a86f;
}

/* ═══ 11. 버튼 공통 ═══ */
.btn {
  font-family: inherit;
  font-size: 0.95rem;
  font-weight: 700;
  padding: 0.7rem 1.9rem;
  background: var(--navy);
  color: #fff;
  border: none;
  border-radius: 12px;
  cursor: var(--cursor-pointer);
  box-shadow: 3px 4px 0 rgba(17, 17, 17, 0.18);
  transition: transform 0.12s ease, opacity 0.2s;
}
.btn:hover:not(:disabled) { transform: scale(1.05); }
.btn:disabled {
  background: #cfd4e2;
  color: #8b90a1;
  box-shadow: none;
  cursor: default;
}

.back {
  font-size: 0.85rem;
  color: var(--navy);
  text-decoration: underline;
  cursor: var(--cursor-pointer);
  opacity: 0.75;
}
.back:hover { opacity: 1; }

/* ═══ 12. 화면 5 · 타이머 (focus / social / 자리비움) ═══ */
.timer-scene {
  position: relative;
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  background: #efe8d8;   /* 세탁소 벽 색 (살롱 배경과 톤 맞춤) */
}

/* 천장에 매달린 간판 2개 */
.hang-sign {
  position: absolute;
  top: 0;
  width: clamp(54px, 8vw, 76px);
  background: none;
  border: none;
  cursor: var(--cursor-pointer);
  padding: 0;
  transition: transform 0.2s ease;
  transform-origin: top center;
  z-index: 6;
}
.hang-sign:hover { transform: rotate(3deg); }
.hang-sign.left { left: 3vw; }
.hang-sign.right { right: 3vw; }
.hang-sign img { width: 100%; }

/* 간판이 무슨 기능인지 아주 간단하게 알려주는 호버 안내.
   간판이 화면 맨 위에 있어서 말풍선은 항상 아래쪽으로 뜹니다. */
.sign-tip {
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translate(-50%, 2px);
  background: var(--navy);
  color: #fff;
  font-size: 0.66rem;
  font-weight: 700;
  white-space: nowrap;
  padding: 0.3rem 0.6rem;
  border-radius: 6px;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.15s ease, transform 0.15s ease;
}
/* 오른쪽 간판은 화면 끝에 붙어 있어서, 말풍선 기준점을 오른쪽으로
   맞춰야 화면 밖으로 넘치지 않습니다 */
.hang-sign.right .sign-tip {
  left: auto;
  right: 0;
  transform: translate(0, 2px);
}
.hang-sign.right:hover .sign-tip,
.hang-sign.right:focus-visible .sign-tip {
  transform: translate(0, 6px);
}
.hang-sign:hover .sign-tip,
.hang-sign:focus-visible .sign-tip {
  opacity: 1;
  transform: translate(-50%, 6px);
}

/* 큰 카운트다운 숫자
   뒤에 실제 사진이 깔리므로, 흰 후광(text-shadow)으로 어떤 사진 위에서도
   읽히게 합니다. */
.timer-big {
  font-family: 'Shantell Sans', sans-serif;
  font-weight: 800;
  font-size: clamp(3.6rem, 12vh, 7rem);
  letter-spacing: 0.02em;
  line-height: 1;
  margin-top: clamp(0.4rem, 2vh, 1.4rem);
  z-index: 5;
  color: var(--navy);
  text-shadow:
    0 0 14px var(--paper), 0 0 14px var(--paper),
    0 0 6px var(--paper), 0 0 6px var(--paper);
  font-variant-numeric: tabular-nums;
  pointer-events: none; /* 글자 박스가 커서 아래 호버 핫스팟을 가리기 쉬움 */
}
/* airplane: 카운트다운도 각진 숫자로 (둥근 마커 숫자는 기내 느낌이 아님) */
body[data-theme='airplane'] .timer-big {
  font-family: 'Work Sans', sans-serif;
  font-weight: 700;
  letter-spacing: 0.04em;
}
body[data-theme='airplane'] .timer-big.finished { letter-spacing: 0.06em; }
/* 종료 직전 "done!" 깜빡임 */
.timer-big.finished {
  animation: doneFlash 0.6s steps(2, jump-none) infinite;
}
@keyframes doneFlash {
  0% { opacity: 1; }
  100% { opacity: 0.25; }
}

.timer-goal {
  font-family: 'Caveat', cursive;
  font-size: 1.5rem;
  font-weight: 600;
  color: var(--navy);
  z-index: 5;
  min-height: 1.8rem;
  text-shadow: 0 0 10px var(--paper), 0 0 10px var(--paper), 0 0 4px var(--paper);
  pointer-events: none;
}

/* focus / social 뷰 전환 */
.view {
  position: absolute;
  inset: 0;
  display: none;
  pointer-events: none;
}
.view.active { display: block; }

/* ── 배경 사진 공통 (social 배경, stop 화면 POV 둘 다) ──
   가만히 정지된 사진 그대로 둡니다 (예전엔 은은하게 맥동하는 효과가
   있었지만 제거했습니다). */
.view-photo {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 1;
}

/* 사진 상단(간판 글자 등)이 타이머 숫자와 겹쳐 지저분해지지 않도록,
   화면 비율에 상관없이 항상 위쪽을 옅게 눌러주는 크림색 그라데이션.
   사진 자체를 자르는 대신 이 스크림으로 대비를 확보합니다. */
.timer-scrim {
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 44%;
  background: linear-gradient(
    to bottom,
    rgba(244, 237, 224, 0.9) 0%,
    rgba(244, 237, 224, 0.5) 60%,
    rgba(244, 237, 224, 0) 100%
  );
  z-index: 3;
  pointer-events: none;
}

/* ── focus 뷰의 "무대" (공통 뼈대) ──
   테마마다 무대가 하나씩 있고, 지금 테마의 것만 .active 입니다.
     laundry  → .focus-machine  (세탁기 창문이 회전)
     airplane → .focus-window   (창밖 하늘이 흐름)

   두 무대 모두 같은 구조를 씁니다:
     .focus-stage  화면 전체를 채우고 안쪽을 가운데 정렬 (여백은 배경색)
       └ .focus-frame  ⚠ 사진과 정확히 같은 비율의 박스 — 좌표(%)의 기준
           ├ .focus-base   정지된 사진 (몸체·창틀·벽)
           └ 움직이는 부분 (.focus-drum / .focus-sky)

   ⚠ .focus-frame의 비율이 사진 비율과 같아야 하는 이유: 움직이는 부분의
   위치·크기를 전부 %로 잡았기 때문에, 기준 박스 비율이 사진과 다르면
   사진은 object-fit:contain으로 레터박스가 생기는데 %는 박스 기준이라
   마스크가 사진의 창문과 어긋납니다. (실제로 프레임 비율이 안 맞아서
   원이 타원으로 찌그러진 버그가 있었습니다.)
   기본값은 정사각형이고, 사진 비율이 다른 테마는 아래에서 덮어씁니다. */
.focus-stage {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: none;
  align-items: center;
  justify-content: center;
  z-index: 1;
}
.focus-stage.active { display: flex; }

.focus-frame {
  position: relative;
  /* 기본: 정사각형 사진 기준 (화면의 짧은 쪽에 맞춤) */
  width: min(100vw, 100vh);
  height: min(100vw, 100vh);
}
.focus-base {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

/* ── focus 뷰 (laundry): 실제 세탁기 사진 + 진짜로 돌아가는 창문 ──
   assets/focus-machine.webp(1254×1254 정사각형) 기준 실측값:
   창문 중심 = (50.76%, 51.12%), 회전시킬 반지름 = 이미지 너비의 15.55%.
   다른 세탁기 사진으로 바꾸면 이 숫자들을 다시 재야 합니다
   (README의 "세탁기 사진 좌표 재는 법" 참고). */
.focus-machine {
  /* assets/focus-machine.webp 자체의 배경색과 정확히 맞춘 값입니다
     (사진 모서리 픽셀 실측: rgb(252,248,240)). 화면이 정사각형이 아니어서
     사진 위아래(또는 좌우)에 여백이 생겨도, 이 색이 사진 배경과 이어져
     경계선이 보이지 않습니다. 사진을 바꾸면 이 값도 다시 맞춰야 합니다. */
  background: #fcf8f0;
}
/* 회전하는 원형 창: 같은 사진을 배경으로 삼아, 창문 자리에 딱 맞게
   확대·이동시킨 뒤 통째로 빙글빙글 돌립니다. */
.focus-drum {
  position: absolute;
  left: 50.76%;
  top: 51.12%;
  width: 31.1%;
  height: 31.1%;
  border-radius: 50%;
  overflow: hidden;
  background-image: url('assets/focus-machine.webp');
  background-repeat: no-repeat;
  background-size: 321.55% 321.55%;
  background-position: 51.10% 51.62%;
  transform: translate(-50%, -50%) rotate(0deg);
  animation: focusDrumSpin 2.4s linear infinite;
  animation-play-state: paused;
}
.focus-machine.running .focus-drum { animation-play-state: running; }
.focus-machine.running .focus-base { animation: focusShake 0.55s ease-in-out infinite; }
@keyframes focusDrumSpin {
  from { transform: translate(-50%, -50%) rotate(0deg); }
  to { transform: translate(-50%, -50%) rotate(360deg); }
}
@keyframes focusShake {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(-0.3%) rotate(-0.15deg); }
  75% { transform: translateX(0.3%) rotate(0.15deg); }
}

/* ── focus 뷰 (airplane): 기내 창가 사진 + 지나가는 구름 ──
   세탁기는 창문이 "원형"이라 같은 사진을 회전시켜 창 안을 진짜로 돌릴 수
   있었지만, 이 창가 사진에는 ⚠ 날개가 있습니다. 날개는 비행기에 고정된
   것이라 사진 일부를 옆으로 밀면 날개까지 끌려가서 즉시 어색해집니다.

   [이전 시도와 실패 이유]
   처음엔 "날개 아래 구름 띠"만 잘라 옆으로 밀었습니다. 그런데 바로 위의
   똑같은 구름은 정지해 있어서 그 경계에 직선 이음매가 생기고, 띠를 칸
   크기에 맞추려 확대하면서 주변 구름과 결이 안 맞아 글리치처럼 보였습니다.
   → 사진의 구름을 "대체"하려 한 게 잘못이었습니다.

   [현재 방식]
   사진은 그대로 두고, 그 위로 반투명한 구름 결(air-wisp-*.webp)을 두 겹
   천천히 지나가게 합니다.
     · 경계선이 아예 없습니다 (알파가 사방으로 부드럽게 빠짐)
     · 날개 앞을 스쳐 지나가는 것도 실제 비행과 같습니다
     · 사진의 구름 색을 직접 뽑아 톤을 맞췄고, 위쪽 파란 하늘로 갈수록
       알파가 0이 되어 높은 고도엔 구름이 없는 것처럼 보입니다
     · 두 겹의 속도(132s / 84s)와 농도를 달리해 원근감을 줍니다

   ⚠ 아래 %는 assets/air-window.webp(1086×1448) 실측값입니다:
       유리면  x 274~670, y 446~1046, 코너 반지름 196px
       → left 25.23% top 30.80% 36.46%×41.44%
         border-radius 196/396=49.5%(가로) / 196/600=32.7%(세로)
   새 창가 사진으로 바꾸면 이 값들과 .focus-frame의 aspect-ratio를 다시
   재야 합니다 (README의 "창문 좌표 재는 법" 참고). */
.focus-window {
  /* assets/air-window.webp의 기내 벽 색(모서리 픽셀 실측). 사진 비율과
     화면 비율이 달라 여백이 생겨도 이어져 보이게 맞춘 값입니다. */
  background: #9aa0a6;
}
/* 이 사진은 세로로 긴 3:4라서 프레임 비율을 사진에 맞춥니다 */
body[data-theme='airplane'] .focus-frame {
  width: min(100vw, calc(100vh * 1086 / 1448));
  height: auto;
  aspect-ratio: 1086 / 1448;
}

/* 유리면 전체 모양 = 지나가는 구름을 곡선으로 잘라주는 틀 */
.focus-sky {
  position: absolute;
  left: 25.23%;
  top: 30.80%;
  width: 36.46%;
  height: 41.44%;
  border-radius: 49.5% / 32.7%;
  overflow: hidden;
  pointer-events: none;
}

/* 지나가는 구름 결 한 겹.
   칸 2개 + 각 칸에 "가로로 이음매 없는" 텍스처를 정확히 칸 크기로 깔고
   translateX를 0 → -50%까지 움직입니다. -50% 지점에서 2번째 칸이 1번째
   칸과 완전히 같은 그림이라 루프가 튀지 않습니다.
   background-size를 100% 100%로 고정하는 게 중요합니다 — cover로 두면
   칸 크기에 따라 텍스처가 잘려 이음매가 드러납니다. */
.sky-drift {
  position: absolute;
  inset: 0;
  display: flex;
  width: 200%;
  animation: skyDrift 90s linear infinite;
  animation-play-state: paused;
  will-change: transform;
}
.sky-drift i {
  flex: 0 0 50%;
  height: 100%;
  background-repeat: no-repeat;
  background-size: 100% 100%;
}
/* 두 겹의 속도·농도·그림을 달리해서 원근감을 줍니다.
   너무 느리면 멈춘 것처럼 보이고 너무 빠르면 지상 저공비행처럼 보입니다 —
   순항 고도에서 구름 갑판이 천천히 지나가는 정도로 맞춘 값입니다. */
.sky-drift.far {
  animation-duration: 82s;
  opacity: 0.38;
}
.sky-drift.far i { background-image: url('assets/air-wisp-b.webp'); }
.sky-drift.near {
  animation-duration: 50s;
  opacity: 0.46;
}
.sky-drift.near i { background-image: url('assets/air-wisp-a.webp'); }

.focus-window.running .sky-drift { animation-play-state: running; }
/* 비행 중 아주 미세한 진동 (세탁기 흔들림보다 훨씬 약하게) */
.focus-window.running .focus-base { animation: focusSway 3.4s ease-in-out infinite; }

@keyframes skyDrift {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}
@keyframes focusSway {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-0.25%); }
}

/* ── stop 화면: 우측 상단 간판을 누르면 focus/social 뷰 위로 덮입니다 ──
   assets/paused-photo.webp (POV) — cafe pomodoro의 화장실 아이콘과
   같은 역할("잠깐 자리 비움"). .view-focus/.view-social의 형제
   요소라서 어느 뷰를 보고 있었든 상관없이 그 위를 덮습니다.
   기본은 숨겨져 있고 .active일 때만 보입니다. */
.focus-away {
  position: absolute;
  inset: 0;
  display: none;
  z-index: 2;
}
.focus-away.active { display: block; }
.focus-away-label {
  position: absolute;
  left: 50%;
  bottom: clamp(6.5rem, 15vh, 9rem);
  transform: translateX(-50%);
  background: #fff;
  border: 2.5px solid var(--navy);
  border-radius: 10px;
  color: var(--navy);
  padding: 0.4rem 1.1rem;
  font-size: 0.85rem;
  font-weight: 700;
  white-space: nowrap;
  z-index: 3;
}

/* 작동 상태 램프 (초록 = 작동 중 / 빨강 = 종료)
   z-index를 focus-away(2)보다 낮게 둬서, stop 화면이 떠 있을 때는
   완전히 가려지고 비쳐 보이지 않게 합니다. */
.status-lamp {
  position: absolute;
  top: clamp(0.8rem, 2vh, 1.4rem);
  right: clamp(0.8rem, 2vh, 1.4rem);
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: #7db46c;
  border: 2.5px solid #fff;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);
  z-index: 1;
}

/* ── social 뷰: 장면 곳곳에 숨겨둔 호버 한 줄 ──
   assets/social-photo.webp(1672×941) 기준 좌표입니다. 정보(이름·시간)
   대신 그 자리에 어울리는 장난스러운 한 줄이 손글씨 메모처럼 뜹니다.
   위치·문구는 app.js의 THEMES.<테마>.hotspots 설정에서 채워집니다.
   같은 이유로 focus-away보다 낮은 z-index. */
.scene-hotspots {
  position: absolute;
  inset: 0;
  z-index: 1;
  /* .view 자체가 pointer-events:none이라 (뒤에 숨은 뷰가 클릭을 가로채지
     않도록) 이 레이어에서 다시 켜주지 않으면 호버가 전혀 먹지 않습니다. */
  pointer-events: auto;
}
.hotspot {
  position: absolute;
  cursor: var(--cursor-pointer);
}
/* 손글씨 메모 느낌의 말풍선. --tip-tilt는 app.js에서 핫스팟마다
   조금씩 다르게 줘서 아무렇게나 붙여놓은 듯한 느낌을 냅니다. */
/* 말풍선의 위치는 변수 3개로만 정해집니다. 아래 .below / .edge-* 클래스는
   이 변수만 덮어쓰므로, 조합(위/아래 × 왼쪽/가운데/오른쪽)마다 규칙을
   따로 쓰지 않아도 됩니다.
     --tip-x     가로 정렬 기준점 (가운데 -50% / 가장자리 0)
     --tip-dir   -1 = 위로 뜸, 1 = 아래로 뜸
     --tip-lift  떠 있는 거리 (평소 6px → 호버 11px, 이 값만 바뀌며 애니메이션) */
.hotspot-tip {
  --tip-x: -50%;
  --tip-dir: -1;
  --tip-lift: 6px;

  position: absolute;
  left: 50%;
  bottom: 100%;
  max-width: min(78vw, 30rem);
  transform: translate(var(--tip-x), calc(var(--tip-lift) * var(--tip-dir)))
             rotate(var(--tip-tilt, -2deg));
  transform-origin: bottom center;
  background: #fdfcf7;
  border: 2px solid var(--navy);
  border-radius: 10px 26px 12px 24px / 24px 12px 26px 10px;
  padding: 0.3rem 0.85rem;
  font-family: 'Caveat', cursive;
  font-size: clamp(1rem, 2.6vh, 1.4rem);
  font-weight: 600;
  color: var(--navy);
  white-space: nowrap;
  box-shadow: 2px 3px 0 rgba(36, 52, 92, 0.18);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.18s ease, transform 0.18s ease;
}
.hotspot:hover .hotspot-tip,
.hotspot:focus-visible .hotspot-tip {
  opacity: 1;
  --tip-lift: 11px;
}

/* 화면 맨 위쪽 핫스팟(예: 간판 셔츠)은 말풍선이 위로 뜨면 잘리므로
   아래쪽으로 뒤집습니다. */
.hotspot.below .hotspot-tip {
  bottom: auto;
  top: 100%;
  --tip-dir: 1;
}

/* 화면 좌우 가장자리에 붙은 핫스팟은 말풍선을 가운데 정렬하면 화면 밖으로
   잘립니다. 그래서 왼쪽 끝은 왼쪽에, 오른쪽 끝은 오른쪽에 맞춰 붙입니다.
   이 클래스는 app.js의 makeHotspot()이 핫스팟의 가로 위치를 보고 자동으로
   붙여줍니다 — 좌표만 바꿔도 알아서 처리됩니다. */
.hotspot.edge-left .hotspot-tip {
  left: 0;
  --tip-x: 0;
}
.hotspot.edge-right .hotspot-tip {
  left: auto;
  right: 0;
  --tip-x: 0;
}

/* 좌우 뷰 전환 화살표 — 유니코드 글자 대신 둥근 SVG 셰브런 아이콘 */
.arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 2.5px solid var(--navy);
  background: #fff;
  box-shadow: 2px 3px 0 var(--navy-soft);
  cursor: var(--cursor-pointer);
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.arrow svg {
  width: 20px;
  height: 20px;
  stroke: var(--navy);
  transition: transform 0.15s ease;
}
.arrow:hover {
  transform: translateY(-50%) scale(1.1);
  box-shadow: 3px 4px 0 var(--navy-soft);
}
.arrow.left:hover svg { transform: translateX(-2px); }
.arrow.right:hover svg { transform: translateX(2px); }
.arrow.left { left: 2.5vw; }
.arrow.right { right: 2.5vw; }

/* 일시정지 / 정지 버튼 */
.timer-controls {
  position: absolute;
  bottom: clamp(3rem, 8vh, 4.4rem);
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  gap: 0.55rem;
  z-index: 10;
}
.ctrl {
  width: 42px;
  height: 36px;
  border: 2.5px solid var(--navy);
  border-radius: 8px;
  background: #fff;
  color: var(--navy);
  font-size: 0.7rem;
  cursor: var(--cursor-pointer);
  transition: transform 0.12s;
}
.ctrl:hover { transform: scale(1.08); }
.ctrl-stop { background: var(--navy); color: #fff; font-size: 0.85rem; }

/* 볼륨 슬라이더 */
.volume-row {
  position: absolute;
  bottom: clamp(0.9rem, 3vh, 1.6rem);
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 0.5rem;
  z-index: 10;
}
.vol-ico { font-size: 0.75rem; opacity: 0.55; }
#volSlider {
  width: 110px;
  accent-color: var(--navy);
}

/* 하단 진행률 바 */
.progress-line {
  position: absolute;
  bottom: 0;
  left: 0;
  height: 5px;
  width: 0%;
  background: var(--red);
  transition: width 1s linear;
  z-index: 10;
}

/* ═══ 13. 화면 6 · 완료 ═══ */
.done-title {
  font-family: 'Shantell Sans', sans-serif;
  font-weight: 800;
  font-size: clamp(1.9rem, 5vw, 2.8rem);
  color: var(--navy);
}
.done-art { width: min(230px, 55vw); }

.done-sub {
  font-family: 'Caveat', cursive;
  font-size: 1.6rem;
  color: var(--navy);
  text-align: center;
}
.done-detail {
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  color: #6b6350;
  text-align: center;
}

/* 뒤에서 떠오르는 비눗방울 */
.done-bubbles {
  position: absolute;
  inset: 0;
  pointer-events: none;
  overflow: hidden;
}
.done-bubbles i {
  position: absolute;
  bottom: -60px;
  width: 26px;
  height: 26px;
  border: 2.5px solid var(--navy);
  border-radius: 50%;
  background:
    radial-gradient(circle at 32% 30%, rgba(255, 255, 255, 0.95) 0 22%, transparent 30%),
    radial-gradient(circle at 50% 50%, rgba(36, 52, 92, 0.08), rgba(36, 52, 92, 0.02));
  opacity: 0.7;
  animation: floatUp 7s linear infinite;
}
.done-bubbles i:nth-child(1)  { left: 6%;  width: 30px; height: 30px; animation-duration: 8s; }
.done-bubbles i:nth-child(2)  { left: 15%; width: 18px; height: 18px; animation-duration: 6.2s; animation-delay: 1.4s; }
.done-bubbles i:nth-child(3)  { left: 26%; width: 38px; height: 38px; animation-duration: 9.5s; animation-delay: 0.6s; }
.done-bubbles i:nth-child(4)  { left: 38%; width: 16px; height: 16px; animation-duration: 5.6s; animation-delay: 2.4s; }
.done-bubbles i:nth-child(5)  { left: 49%; width: 24px; height: 24px; animation-duration: 7.4s; animation-delay: 3.1s; }
.done-bubbles i:nth-child(6)  { left: 60%; width: 34px; height: 34px; animation-duration: 8.8s; animation-delay: 1.1s; }
.done-bubbles i:nth-child(7)  { left: 70%; width: 20px; height: 20px; animation-duration: 6.6s; animation-delay: 2.0s; }
.done-bubbles i:nth-child(8)  { left: 80%; width: 28px; height: 28px; animation-duration: 7.8s; animation-delay: 0.3s; }
.done-bubbles i:nth-child(9)  { left: 89%; width: 16px; height: 16px; animation-duration: 5.9s; animation-delay: 3.6s; }
.done-bubbles i:nth-child(10) { left: 95%; width: 24px; height: 24px; animation-duration: 8.2s; animation-delay: 1.9s; }
@keyframes floatUp {
  0% { transform: translateY(0) translateX(0); opacity: 0; }
  8% { opacity: 0.7; }
  50% { transform: translateY(-55vh) translateX(-14px); }
  92% { opacity: 0.6; }
  100% { transform: translateY(-110vh) translateX(10px); opacity: 0; }
}

/* ── airplane: 완료 화면을 통째로 착륙 삽화로 ──
   세탁소는 종이 카드 + 작은 스티커 + 비눗방울이지만, 비행기는
   air-done.webp(착륙하는 비행기, 활주로) 한 장이 화면 전체를 채우고
   그 위에 문구만 얹습니다. 사진 속 하늘의 빈 공간(구름과 활주로 사이)에
   글이 자연스럽게 놓이도록, .paper의 카드 껍데기(배경·테두리·그림자)만
   벗기고 가운데 정렬은 그대로 둡니다. */
body[data-theme='airplane'] .done-bubbles { display: none; }

/* air-done.webp는 세로로 긴 포스터 구도라 cover로 채우면 넓은 화면에서
   비행기가 화면 밖으로 잘려 나갑니다. 그래서 contain으로 전체 구도를
   지키고, 남는 좌우 여백은 사진 하늘과 같은 파란색으로 채워 이음매를
   숨깁니다. */
body[data-theme='airplane'] #screen-done { background: #357cc4; }

body[data-theme='airplane'] .done-art {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  z-index: 0;
}

/* 사진 중앙의 빈 하늘 띠(대략 이미지 높이의 25~63%)에만 글이 들어가야
   구름·기체와 겹치지 않습니다. .paper는 화면(=사진) 정중앙에 놓이므로
   그 띠의 가운데와 이미 맞아떨어지지만, 안에 들어가는 글줄 5개를 기본
   간격대로 쌓으면 띠보다 훌쩍 커져 위아래로 삐져나갑니다. 그래서 간격과
   글자 크기를 눈에 띄게 줄여 전체 블록을 그 띠 안에 욱여넣습니다. */
body[data-theme='airplane'] #screen-done .paper {
  position: relative;
  z-index: 1;
  width: min(380px, 84vw);
  max-height: none;
  padding: 0;
  margin-top: -24px;
  gap: clamp(0.25rem, 1vh, 0.5rem);
  background: none;
  border: none;
  border-radius: 0;
  box-shadow: none;
  overflow: visible;
}

/* 파란 하늘 위에 얹히는 글이라 흰 글씨 + 그림자로 대비를 확보합니다 */
body[data-theme='airplane'] .done-title,
body[data-theme='airplane'] .done-sub,
body[data-theme='airplane'] .done-detail {
  color: #fff;
  text-shadow: 0 2px 14px rgba(15, 34, 66, 0.45);
}
body[data-theme='airplane'] .done-title {
  font-family: 'Work Sans', sans-serif;
  font-weight: 600;
  font-size: clamp(1.3rem, 3.6vw, 1.8rem);
  letter-spacing: 0.02em;
  text-transform: lowercase;
}
body[data-theme='airplane'] .done-sub {
  font-family: 'Work Sans', sans-serif;
  font-size: clamp(0.82rem, 2.2vw, 0.98rem);
  font-weight: 500;
}
body[data-theme='airplane'] .done-detail {
  color: rgba(255, 255, 255, 0.82);
  text-shadow: 0 1px 8px rgba(15, 34, 66, 0.5);
}
body[data-theme='airplane'] #screen-done .btn {
  font-size: 0.85rem;
  padding: 0.5rem 1.5rem;
}
body[data-theme='airplane'] #screen-done .back {
  color: #fff;
  opacity: 0.85;
  font-size: 0.78rem;
}
body[data-theme='airplane'] #screen-done .back:hover { opacity: 1; }

/* ═══ 14. 모바일 대응 ═══ */
@media (max-width: 560px) {
  .pick .art { width: clamp(56px, 20vw, 92px); height: clamp(56px, 20vw, 92px); }
  .draw-source-img { width: clamp(104px, 34vw, 160px); }
  .arrow.left { left: 2vw; }
  .arrow.right { right: 2vw; }
  .timer-big { font-size: 3.4rem; }
}
