/* Task 13: block-challenge(귀입딱 챌린지)에서 이식.
   원본: /root/block-challenge-dev/public_html/assets/css/app.css (44,989 bytes)
   내용은 그대로 유지한다 — 5days 에서 안 쓰는 클래스도 지우지 않는다
   (원본과 대조 가능해야 하고, 나중에 쓸 수도 있다). 이 주석 블록만 추가됨. */

/* 귀입딱 챌린지 — 디자인 시스템 v1.0 구현
   docs/design-system.md 의 토큰·컴포넌트 규칙을 따른다. */

:root {
  --color-brand-500: #fe6400;
  --color-brand-600: #e55a00;
  --color-brand-700: #c84e00;
  --color-brand-100: #ffe7d5;
  --color-brand-050: #fff3ea;
  --color-ink: #17171c;
  --color-ink-soft: #55555f;
  --color-muted: #85858f;
  --color-line: #e4e5e8;
  --color-surface-soft: #f5f6f8;
  --color-surface: #ffffff;
  --color-success: #168a57;
  --color-success-bg: #e8f7ef;
  --color-success-line: #a9dcc0;
  --color-danger: #d93d47;
  --color-danger-bg: #fdecee;
  --color-danger-line: #e6a3a3;
  --color-warning: #b56a00;
  --color-warning-bg: #fff3d6;
  --color-info: #2563b9;
  --color-focus: #1d4ed8;

  --space-1: 4px;   --space-2: 8px;   --space-3: 12px;  --space-4: 16px;
  --space-5: 20px;  --space-6: 24px;  --space-8: 32px;  --space-10: 40px;
  --space-12: 48px; --space-14: 56px; --space-16: 64px; --space-20: 80px;

  --radius-sm: 10px; --radius-md: 13px; --radius-lg: 16px;
  --radius-xl: 20px; --radius-2xl: 28px; --radius-pill: 999px;

  --shadow-float: 0 12px 30px rgb(23 23 28 / 12%);
  --shadow-hover: 0 8px 24px rgb(23 23 28 / 8%);
  --content-max: 1200px;
  --challenge-max: 720px;
  --header-h: 56px;

  /* 모션 — design-system.md §전환(160ms ease-out)을 기준으로 세 단계만 둔다. */
  --motion-fast: 120ms;
  --motion-base: 200ms;
  --motion-slow: 320ms;
  --ease-out: cubic-bezier(0.2, 0.8, 0.3, 1);
  --ease-in: cubic-bezier(0.5, 0, 0.75, 0);
  /* 온보딩처럼 미끄러지듯 붙어야 하는 곳에만 쓰는 긴 감속 곡선(iOS 계열 감각). */
  --ease-soft: cubic-bezier(0.22, 0.85, 0.3, 1);
}

/* ── 페이지 전환 ────────────────────────────────────────────
   여러 장의 PHP 페이지라 이동할 때마다 화면이 통째로 갈린다.
   지원 브라우저에서는 크로스페이드로, 아닌 곳에서는 본문 fade-in 으로 받는다. */

@view-transition { navigation: auto; }

::view-transition-old(root) { animation: fade-out var(--motion-fast) var(--ease-in) both; }
::view-transition-new(root) { animation: fade-in var(--motion-base) var(--ease-out) both; }

/* View Transitions 가 없는 브라우저용. 헤더·하단탭은 고정된 채 본문만 들어온다. */
.main { animation: page-in var(--motion-base) var(--ease-out) both; }

@keyframes page-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}
@keyframes fade-in  { from { opacity: 0; } to { opacity: 1; } }
@keyframes fade-out { from { opacity: 1; } to { opacity: 0; } }

/* ── 등장 ───────────────────────────────────────────────────
   .reveal 은 한 덩어리, .stagger 는 자식들을 조금씩 늦춰 순서대로 들어오게 한다.
   DAY 목록은 60개까지 길어질 수 있어 앞 8개만 늦춘다 — 전부 늦추면 아래쪽이 늦게 떠서 답답하다. */

.reveal { animation: rise-in var(--motion-slow) var(--ease-out) both; }
.stagger > * { animation: rise-in var(--motion-base) var(--ease-out) both; }
.stagger > *:nth-child(1) { animation-delay: 0ms; }
.stagger > *:nth-child(2) { animation-delay: 40ms; }
.stagger > *:nth-child(3) { animation-delay: 80ms; }
.stagger > *:nth-child(4) { animation-delay: 120ms; }
.stagger > *:nth-child(5) { animation-delay: 160ms; }
.stagger > *:nth-child(6) { animation-delay: 200ms; }
.stagger > *:nth-child(7) { animation-delay: 240ms; }
.stagger > *:nth-child(n + 8) { animation-delay: 280ms; }

@keyframes rise-in {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}

*, *::before, *::after { box-sizing: border-box; }

/* .btn 등 display 를 지정한 요소는 [hidden] 을 덮어써서 그냥 보인다. 전역으로 막는다. */
[hidden] { display: none !important; }

/* 목록이 짧아져 세로 스크롤바가 사라지는 순간 본문 폭이 넓어지며 화면이 좌우로 튄다.
   자리를 미리 비워 두면 스크롤바 유무와 상관없이 폭이 고정된다. */
html { -webkit-text-size-adjust: 100%; scrollbar-gutter: stable; }

body {
  margin: 0;
  font-family: "Pretendard Variable", Pretendard, "Apple SD Gothic Neo",
    "Malgun Gothic", system-ui, sans-serif;
  font-size: 16px; font-weight: 500; line-height: 1.6;
  color: var(--color-ink);
  background: var(--color-surface);
  word-break: keep-all;
}

h1, h2, h3, p, figure { margin: 0; }
ul, ol { margin: 0; padding: 0; list-style: none; }
a { color: inherit; text-decoration: none; }
button, input, textarea, select { font: inherit; color: inherit; }
img, video { max-width: 100%; }

:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

.tnum { font-variant-numeric: tabular-nums; }
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ── 타이포 ─────────────────────────────────────────────── */

.t-display { font-size: 36px; font-weight: 800; line-height: 1.12; letter-spacing: -0.02em; }
.t-h1      { font-size: 30px; font-weight: 800; line-height: 1.2; letter-spacing: -0.02em; }
.t-h2      { font-size: 26px; font-weight: 750; line-height: 1.25; letter-spacing: -0.01em; }
.t-h3      { font-size: 20px; font-weight: 700; line-height: 1.35; }
.t-challenge { font-size: 24px; font-weight: 600; line-height: 1.5; }
.t-body-l  { font-size: 17px; line-height: 1.65; }
.t-body    { font-size: 16px; line-height: 1.6; }
.t-label   { font-size: 14px; font-weight: 700; line-height: 1.4; }
.t-caption { font-size: 12px; line-height: 1.45; color: var(--color-muted); }

.t-soft  { color: var(--color-ink-soft); }
.t-muted { color: var(--color-muted); }
.t-en    { font-family: inherit; }

@media (min-width: 1024px) {
  .t-display { font-size: 54px; }
  .t-h1 { font-size: 44px; }
  .t-h2 { font-size: 36px; }
  .t-h3 { font-size: 24px; }
  .t-challenge { font-size: 30px; }
  .t-body-l { font-size: 18px; }
  .t-caption { font-size: 13px; }
}

/* ── 셸 ─────────────────────────────────────────────────── */

.shell {
  max-width: var(--content-max);
  margin: 0 auto;
  padding: 0 var(--space-4);
}
@media (max-width: 359px) { .shell { padding: 0 14px; } }
@media (min-width: 600px) { .shell { padding: 0 var(--space-6); } }
@media (min-width: 1024px) { .shell { padding: 0 var(--space-8); } }

.app-header {
  position: sticky; top: 0; z-index: 30;
  height: var(--header-h);
  display: flex; align-items: center;
  background: rgb(255 255 255 / 92%);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--color-line);
}
.app-header__inner {
  max-width: var(--content-max); width: 100%;
  margin: 0 auto; padding: 0 var(--space-4);
  display: flex; align-items: center; gap: var(--space-3);
}
.app-header__brand { font-size: 17px; font-weight: 800; letter-spacing: -0.02em; }
.app-header__brand b { color: var(--color-brand-500); }
.app-header__spacer { flex: 1; }

.icon-btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 44px; min-height: 44px;
  background: none; border: 0; cursor: pointer;
  border-radius: var(--radius-md);
}
.icon-btn:hover { background: var(--color-surface-soft); }

@media (min-width: 1024px) {
  :root { --header-h: 64px; }
  .app-header__inner { padding: 0 var(--space-8); }
}

.main { padding: var(--space-6) 0 var(--space-20); }
.main--learn { padding-bottom: 120px; }

.stack   { display: flex; flex-direction: column; gap: var(--space-4); }
/* 🔴 .stack-2 는 템플릿 9곳(관리자 명단·기수 폼·말하기·홈·진단)이 쓰고 있었는데
   **정의가 없었다**(2026-09-03 발견). 이 저장소는 p·ul 의 margin 을 0 으로 리셋하므로,
   정의가 없으면 간격이 0 이 되어 문단이 붙어 버린다 — 그동안은 "좀 촘촘하네" 정도로
   보였다. 그런데 자식이 <label> 같은 **인라인 요소**면 세로로 쌓이지도 않아서
   선택지 카드가 서로 겹쳐 보였다(Day5 진단 문항에서 실제로 깨졌다). */
.stack-2 { display: flex; flex-direction: column; gap: var(--space-2); }
.stack-6 { display: flex; flex-direction: column; gap: var(--space-6); }
.stack-8 { display: flex; flex-direction: column; gap: var(--space-8); }
.row     { display: flex; align-items: center; gap: var(--space-3); }
.row-between { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); }
/* 버튼 두 개가 나란히 있을 때 좁은 화면에서 글자가 두 줄로 접히는 걸 막는다. */
.row--wrap { flex-wrap: wrap; }
.row--wrap > * { flex: 1 1 200px; }

.learn-col { max-width: var(--challenge-max); margin: 0 auto; }

.section-title { margin-bottom: var(--space-4); }

/* ── 버튼 ───────────────────────────────────────────────── */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
  min-height: 54px; min-width: 120px; padding: 0 var(--space-6);
  border: 0; border-radius: var(--radius-md);
  font-size: 16px; font-weight: 700; line-height: 1;
  cursor: pointer;
  transition: background-color 160ms ease-out, transform 160ms ease-out;
}
.btn:active:not(:disabled) { transform: translateY(1px); }
.btn--block { width: 100%; }
.btn--sm { min-height: 44px; min-width: 0; padding: 0 var(--space-4); font-size: 14px; }

.btn--primary { background: var(--color-brand-500); color: #fff; }
.btn--primary:hover:not(:disabled) { background: var(--color-brand-600); }
.btn--primary:active:not(:disabled) { background: var(--color-brand-700); }

.btn--secondary { background: var(--color-ink); color: #fff; }
.btn--secondary:hover:not(:disabled) { background: #2b2b33; }

.btn--tertiary { background: transparent; color: var(--color-brand-600); min-width: 0; padding: 0 var(--space-3); }
.btn--tertiary:hover:not(:disabled) { background: var(--color-brand-050); }

.btn--ghost { background: var(--color-surface); color: var(--color-ink); border: 1px solid var(--color-line); }
.btn--ghost:hover:not(:disabled) { background: var(--color-surface-soft); }

.btn:disabled { background: var(--color-line); color: var(--color-muted); cursor: not-allowed; }

/* ── 카드 ───────────────────────────────────────────────── */

.card {
  background: var(--color-surface);
  border: 1px solid var(--color-line);
  border-radius: var(--radius-xl);
  padding: var(--space-5);
}
@media (min-width: 1024px) { .card { padding: var(--space-8); } }

.card--soft { background: var(--color-surface-soft); border-color: transparent; }
.card--hero { background: linear-gradient(180deg, var(--color-brand-050) 0%, var(--color-surface) 100%); }

/* ── 배지 · 칩 ──────────────────────────────────────────── */

.badge {
  display: inline-flex; align-items: center; gap: var(--space-1);
  padding: 4px var(--space-3);
  border-radius: var(--radius-pill);
  font-size: 12px; font-weight: 700; line-height: 1.45;
  background: var(--color-surface-soft); color: var(--color-ink-soft);
}
.badge--brand   { background: var(--color-brand-100); color: var(--color-brand-700); }
.badge--success { background: var(--color-success-bg); color: var(--color-success); }
.badge--danger  { background: var(--color-danger-bg); color: var(--color-danger); }
.badge--warning { background: var(--color-warning-bg); color: var(--color-warning); }
.badge--lock    { background: var(--color-surface-soft); color: var(--color-muted); }
/* 큰 칩 — Day5 진단 결과의 유형명("블록 빌더 🧱") 전용.
   🔑 유형명은 제목이 아니라 칩으로 두기로 했다(2026-09-10). 대신 12px 칩은 결과
      화면에서 부속품처럼 보여서, 이 화면에서만 한 단계 키운다.
   ⛔ .badge 자체를 키우지 않는다 — 같은 칩을 홈·완료·랭킹이 전부 쓰고 있어
      한 줄 고치면 다섯 화면이 같이 커진다. */
.badge--lg {
  padding: 6px var(--space-4);
  font-size: 16px; line-height: 1.4;
}

/* 세로 stack 안에서 배지가 가로로 늘어나지 않게 한다. */
.stack > .badge, .stack-2 > .badge, .stack-6 > .badge, .stack-8 > .badge { align-self: flex-start; }

/* ── 안내 토글([?]) ───────────────────────────────────────
   라벨 옆에 붙어, 눌러야 펼쳐지는 부가 설명을 여닫는다.
   🔑 카드에 늘 펼쳐 두면 정작 봐야 할 숫자가 문장에 묻힌다 — 접어 둔다.
   ⛔ 내용을 fetch 로 가져오지 않는다. 서버가 이미 그려 둔 문단의 hidden 만
      토글하므로, JS 가 죽어도 정보가 사라지지 않는다(개발자도구로도 읽힌다). */
.info-dot {
  position: relative;                     /* ::after 로 터치 영역을 넓히기 위해 */
  display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px; margin-left: var(--space-1);
  padding: 0; border: 0; border-radius: var(--radius-pill);
  background: var(--color-surface-soft); color: var(--color-muted);
  font-size: 11px; font-weight: 700; line-height: 1;
  cursor: pointer; vertical-align: middle;
}
/* ── 텍스트 링크형 버튼 ───────────────────────────────────
   기능은 버튼인데(=JS 가 처리) 생김새는 링크여야 하는 자리. 블록 버튼으로 두면
   주 CTA 와 크기가 같아 서로 경쟁한다.
   🔑 <a> 가 아니라 <button> 을 쓴다 — 이동이 아니라 화면 안의 동작이라
      키보드·스크린리더에 그렇게 알려야 한다.
   🔑 글자는 작지만 누르는 영역은 패딩으로 넓힌다. */
.link-btn {
  padding: 4px 0;
  border: 0; background: none;
  font-family: inherit; font-size: 13px; font-weight: 700; line-height: 1.4;
  color: var(--color-brand-700);
  cursor: pointer;
}
.link-btn:hover { text-decoration: underline; }

/* ── 구역 제목(eyebrow) ───────────────────────────────────
   한 카드 안에서 구역의 머리 역할을 하는 작은 제목.

   🔴 왜 .t-label(14px, 검정)을 안 쓰나: 바로 아래 본문이 .t-body-l(17px, 굵게)라
      **제목이 본문보다 작고 색까지 같아** 위계가 뒤집혀 있었다(2026-09-03 검수).
      크기로 이기려 들면 본문까지 키워야 하므로, **색과 표시**로 가른다.
   ⛔ 형광펜(배경)을 쓰지 않는다 — 이 화면엔 이미 연한 브랜드 배경 블록이 있고,
      Day3 에서 밑줄 강조를 이미 쓰고 있어 강조 방식이 두 벌이 된다. */
.section-label {
  display: flex; align-items: center; gap: var(--space-2);
  font-size: 12px; font-weight: 800; letter-spacing: 0.04em;
  color: var(--color-brand-700);
}
/* 왼쪽 액센트 바 — "여기서 새 구역이 시작된다"를 구분선보다 가깝게 알린다. */
.section-label::before {
  content: '';
  flex: none;
  width: 3px; height: 14px;
  border-radius: 2px;
  background: var(--color-brand-500);
}

/* ── 한 카드 안의 구역 나누기 ─────────────────────────────
   카드를 쪼개지 않고 얇은 선으로만 구역을 나눈다 — 박스를 나누면 "서로 다른 안내"로
   읽히고, 선으로 나누면 "한 덩어리 안의 문단"으로 읽힌다. */
.section-line {
  padding-top: var(--space-4);
  border-top: 1px solid var(--color-line);
}

/* ── 유의사항 목록 ────────────────────────────────────────
   ⛔ list-style 을 되살리지 않는다 — 이 저장소는 ul 의 목록 표시를 전역으로 껐고,
      여기서 켜면 다른 화면 목록까지 같이 바뀐다. 대신 '-' 를 문자로 붙이고
      들여쓰기로 둘째 줄을 맞춘다(hanging indent). */
.caution-list > li {
  padding-left: 12px;
  text-indent: -12px;
}
.caution-list > li::before { content: '- '; }

/* ── CTA 말풍선 ───────────────────────────────────────────
   버튼 위에 얹는 짧은 부담 낮추기 문구("1분 소요!"). Day5 완료 화면의 진단 진입로.

   🔑 버튼 **밖**에 둔다 — 버튼 안에 넣으면 글자가 두 줄이 되면서 CTA 높이가 아래
      버튼들과 어긋나고, 정작 눌러야 할 문구가 작아 보인다.
   🔑 꼬리는 border 로 만든 삼각형이다(가상 요소). 이미지·SVG 를 쓰지 않는다 —
      배경색이 바뀌면 같이 안 바뀌는 자산이 하나 더 생긴다.
   ⚠️ 말풍선은 중앙 정렬이다. 버튼 왼쪽 끝에 붙이면 폭이 좁은 화면에서 꼬리가
      버튼 모서리 밖으로 나간다(실측 360px). */
.bubble-cta {
  display: flex; flex-direction: column; align-items: center;
  gap: var(--space-2);
}
.bubble-cta > .btn { width: 100%; }
.bubble-tip {
  position: relative;
  padding: 6px 12px;
  border-radius: var(--radius-pill);
  background: var(--color-brand-100);
  color: var(--color-brand-700);
  font-size: 13px; font-weight: 800; line-height: 1.3;
}
/* 아래를 향한 꼬리 — 말풍선과 버튼 사이의 gap 만큼만 내려간다. */
.bubble-tip::after {
  content: '';
  position: absolute; top: 100%; left: 50%;
  transform: translateX(-50%);
  border: 5px solid transparent;
  border-top-color: var(--color-brand-100);
  border-bottom: 0;
}

/* ── 진단 선택지 ──────────────────────────────────────────
   Day5 진단 문항의 보기 4개(3기 개편 2026-10-08 — 데모 HTML 의 번호 배지·체크 형태).
   🔑 라디오는 **시각적으로만** 감춘다(display:none 이 아니다) — 키보드·스크린리더가
      그대로 라디오로 다룬다. 상태는 번호 배지 색·체크·테두리로 보인다.
   🔑 글은 배지 옆 칸에 둔다 — 두 줄로 넘어가도 배지 밑으로 파고들지 않는다.
   🔑 라벨 전체가 누르는 영역이다. */
.diag-opt {
  position: relative;
  display: flex; align-items: center; gap: var(--space-3);
  min-height: 76px;
  padding: var(--space-4);
  background: var(--color-surface);
  border: 1px solid var(--color-line);
  border-radius: var(--radius-lg);
  cursor: pointer;
  transition: border-color var(--motion-fast) var(--ease-out), background var(--motion-fast) var(--ease-out);
}
.diag-opt input[type="radio"] {
  position: absolute; opacity: 0; width: 1px; height: 1px; margin: 0; pointer-events: none;
}
.diag-opt__no {
  flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; border-radius: var(--radius-pill);
  background: var(--color-surface-soft); color: var(--color-ink-soft);
  font-size: 13px; font-weight: 800;
}
.diag-opt__text { flex: 1; font-size: 15px; line-height: 1.5; }
.diag-opt__check { flex: none; color: var(--color-brand-500); font-weight: 800; visibility: hidden; }
/* 🔑 :has() 와 .is-checked(JS)를 **둘 다** 건다 — :has() 를 모르는 브라우저는 셀렉터 목록
      전체를 버리므로 한 규칙에 묶지 않고 따로 쓴다. */
.diag-opt.is-checked {
  border: 2px solid var(--color-brand-500);
  padding: calc(var(--space-4) - 1px);
  background: var(--color-brand-050);
}
.diag-opt.is-checked .diag-opt__no { background: var(--color-brand-500); color: #fff; }
.diag-opt.is-checked .diag-opt__check { visibility: visible; }
.diag-opt:has(input:checked) {
  border: 2px solid var(--color-brand-500);
  padding: calc(var(--space-4) - 1px);         /* 테두리가 두꺼워져도 글자가 밀리지 않게 */
  background: var(--color-brand-050);
}
.diag-opt:has(input:checked) .diag-opt__no { background: var(--color-brand-500); color: #fff; }
.diag-opt:has(input:checked) .diag-opt__check { visibility: visible; }
.diag-opt:has(input:focus-visible) { outline: 2px solid var(--color-focus); outline-offset: 2px; }

/* ── 모달 ─────────────────────────────────────────────────
   [?] 같은 작은 버튼으로 여는 짧은 안내용. 인트로 오버레이(.io)와 달리 카드 한 장만
   띄운다.
   🔴 반드시 <main> **바깥**(템플릿의 overlay 블록)에 둘 것 — .main 의 transform
      애니메이션이 position:fixed 의 containing block 을 만들어서, main 안에 있으면
      헤더·푸터가 모달 위로 삐져나온다(2026-08-25 실측). */
.modal { position: fixed; inset: 0; z-index: 8000; display: flex; align-items: center; justify-content: center; }
.modal[hidden] { display: none; }
.modal__backdrop { position: absolute; inset: 0; background: rgba(17, 17, 20, 0.5); }
.modal__panel {
  position: relative; z-index: 1;
  width: min(100% - var(--space-8), 420px);
  max-height: 80vh; overflow-y: auto;
  display: flex; flex-direction: column; gap: var(--space-4);
  padding: var(--space-6);
  border-radius: var(--radius-xl);
  background: var(--color-surface);
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.24);
  animation: modal-in var(--motion-base) var(--ease-out) both;
}
@keyframes modal-in {
  from { opacity: 0; transform: translateY(12px) scale(0.98); }
  to   { opacity: 1; transform: none; }
}

/* 🔴 보이는 원은 18px 이지만 **누르는 영역은 40px** 로 넓힌다 — 손가락으로 18px 를
   정확히 맞추기는 어렵다(모바일 터치 타깃 권장치는 44px 안팎이다). 원을 키우면
   라벨보다 커져서 시선을 뺏으므로, 투명 영역만 넓힌다. */
.info-dot::after { content: ''; position: absolute; inset: -11px; }
.info-dot:hover { background: var(--color-brand-100); color: var(--color-brand-700); }
.info-dot[aria-expanded="true"] { background: var(--color-brand-500); color: #fff; }
/* ── 카운트 말풍선 ────────────────────────────────────────
   Day3 인터뷰 블록 머리에서 "미션 N번 완료"를 띄운다.

   ⚠️ 이름을 `.bubble` 로 하지 않는다 — 그건 이미 대화형 말풍선(.bubble--ai/--me)이
      쓰고 있는 이름이라, 겹치면 한쪽을 고칠 때 다른 쪽이 조용히 따라 바뀐다.
   🔑 포인트 컬러(brand-500) + 흰 글씨. 배지(.badge)보다 강하게 눈에 걸려야 하는
      자리라 배지 변형이 아니라 별도 컴포넌트로 둔다.
   🔑 꼬리는 ::after 로 그린다(아래를 가리킨다 — 바로 밑 문장에 붙는 말이라는 표시). */
.count-bubble {
  position: relative;
  align-self: flex-start;
  display: inline-flex; align-items: center; gap: var(--space-1);
  margin-bottom: var(--space-2);          /* 꼬리 높이만큼 아래 문장과 띄운다 */
  padding: 6px var(--space-3);
  border-radius: var(--radius-pill);
  background: var(--color-brand-500);
  color: #fff;
  font-size: 13px; font-weight: 700; line-height: 1.45;
  box-shadow: 0 6px 16px rgba(254, 100, 0, 0.28);
  animation: count-bubble-float 2.8s var(--ease-soft) infinite;
  will-change: transform;
}
.count-bubble::after {
  content: '';
  position: absolute; left: var(--space-4); bottom: -5px;
  width: 12px; height: 8px;
  background: inherit;
  clip-path: polygon(0 0, 100% 0, 50% 100%);
}
/* 위아래로 아주 얕게. 6px 이상 움직이면 읽는 눈이 따라가느라 피곤해진다. */
@keyframes count-bubble-float {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-5px); }
}

/* ── 버튼 바로 아래 한 줄 설명 ────────────────────────────
   말풍선으로도 만들어 봤지만(2026-09-03), 이 화면엔 이미 연한 브랜드 배경
   (.notice 두 개)이 많아 배경을 하나 더 얹으니 지저분했다 — 배경 없이 글자만 둔다.
   🔑 .stack 의 기본 간격(16px)만큼 벌어지면 버튼과 따로 노는 문단으로 읽힌다.
      음수 마진으로 8px 까지 당겨 버튼과 한 덩어리로 보이게 한다. */
.btn-caption {
  margin-top: calc(var(--space-2) - var(--space-4));
  text-align: center;
  font-size: 13px; line-height: 1.6;
  color: var(--color-muted);
}

/* ── 그어지는 밑줄 강조 ───────────────────────────────────
   문장 안의 한 구절에만 포인트 컬러 밑줄을 긋는다. 요소가 보이는 순간
   왼쪽에서 오른쪽으로 그어진다(CSS 애니메이션은 display:none 동안 돌지 않으므로,
   숨겨진 카드가 열릴 때 자연히 시작된다 — 별도 JS 가 필요 없다).

   🔑 밑줄을 background 로 그린다(::after + scaleX 가 아니라). 구절이 두 줄로
      나뉘어도 box-decoration-break:clone 덕에 줄마다 밑줄이 따로 그어진다.
      ::after 로 하면 두 줄일 때 한 줄만 그어지거나 엉뚱한 폭이 된다. */
.mark-draw {
  background-image: linear-gradient(var(--color-brand-500), var(--color-brand-500));
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 0 4px;
  padding-bottom: 3px;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}
/* 🔴 애니메이션은 **화면에 들어왔을 때** 시작한다(assets/js/interview.js 가 클래스를 단다).
   예전에는 카드가 열리는 순간 바로 그어졌는데, 모바일에서는 이 문장이 한참 아래에
   있어서 **다 그어진 뒤에야 눈에 들어왔다**(실사용 확인, 2026-09-03). 스크롤해서
   읽는 순간에 그어져야 강조가 보인다. */
.mark-draw.is-drawn { animation: mark-draw 620ms var(--ease-out) 120ms forwards; }
@keyframes mark-draw {
  to { background-size: 100% 4px; }
}

/* ── 진행률 ─────────────────────────────────────────────── */

.progress {
  height: 8px; border-radius: var(--radius-pill);
  background: var(--color-line); overflow: hidden;
}
.progress__fill {
  height: 100%; background: var(--color-brand-500);
  border-radius: var(--radius-pill);
  transition: width var(--motion-slow) var(--ease-out);
  /* 너비는 인라인 스타일로 정해지므로, 채워지는 느낌은 scaleX 로 낸다. */
  transform-origin: left center;
  animation: progress-in 480ms var(--ease-out) both;
}
@keyframes progress-in {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}

/* ── Day별 완료 달력 (홈 내 리워드 카드 상단, 2026-09-07) ──────────────
   둥근 띠 하나를 세로선으로 나눈 모양(09-07 스케치 반영) — 칸마다 따로 테두리를
   두지 않는다. 칸 수는 cohort.day_count 를 따르므로 5 로 고정하지 않는다(auto-fit).
   높이를 최소로: 라벨 한 줄 + 도장 하나. 날짜·'오늘' 글자 없음(요청).
   상태 클래스는 views/home.njk 주석 참조(is-today/is-past/is-future 는 서버,
   is-done 은 home.js 가 얹는다). */
.daycal {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
  border: 1.5px solid var(--color-line); border-radius: var(--radius-lg);
  overflow: hidden; background: var(--color-surface);
}
.daycal__cell {
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  padding: 7px 0 6px; min-width: 0;
}
.daycal__cell + .daycal__cell { border-left: 1.5px solid var(--color-line); }
/* 양끝 칸은 띠의 곡률을 그대로 따른다(바깥 반지름 − 테두리 두께). 이게 없으면 오늘 칸의
   inset 테두리·바닥색이 네모로 그려진 뒤 overflow:hidden 에 잘려 모서리가 깨져 보인다
   (Day 1·Day 5 가 오늘일 때, 2026-09-07 지적). */
.daycal__cell:first-child { border-radius: calc(var(--radius-lg) - 1.5px) 0 0 calc(var(--radius-lg) - 1.5px); }
.daycal__cell:last-child  { border-radius: 0 calc(var(--radius-lg) - 1.5px) calc(var(--radius-lg) - 1.5px) 0; }
.daycal__label { font-size: 11px; font-weight: 700; line-height: 1.2; color: var(--color-muted); white-space: nowrap; }
.daycal__mark {
  width: 30px; height: 30px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  border: 2px dashed var(--color-line);
}
.daycal__stamp { display: none; }

/* 지난 날(놓침): 라벨만 흐리게 — X 를 찍지 않는다. 앞으로: 살짝 어두운 바닥. */
.daycal__cell.is-past   .daycal__label { color: var(--color-muted); }
.daycal__cell.is-future { background: var(--color-surface-soft); }
.daycal__cell.is-future .daycal__label { color: var(--color-muted); }
/* 오늘: 바닥색 + 안쪽 테두리(띠가 overflow:hidden 이라 바깥 테두리 대신 inset). */
.daycal__cell.is-today  { background: var(--color-brand-050); box-shadow: inset 0 0 0 1.5px var(--color-brand-500); }
.daycal__cell.is-today .daycal__label { color: var(--color-brand-700); }
.daycal__cell.is-today .daycal__mark  { border-color: var(--color-brand-500); }

/* 완료 도장: 이중 테두리 원 안에 '완료', 살짝 기울여 찍힌 느낌. */
.daycal__cell.is-done .daycal__label { color: var(--color-ink); }
.daycal__cell.is-done.is-today .daycal__label { color: var(--color-brand-700); }
.daycal__cell.is-done .daycal__mark {
  border: 2px solid var(--color-brand-600);
  box-shadow: inset 0 0 0 2px var(--color-surface), inset 0 0 0 3px var(--color-brand-600);
  transform: rotate(-14deg);
}
.daycal__cell.is-done.is-today .daycal__mark {
  box-shadow: inset 0 0 0 2px var(--color-brand-050), inset 0 0 0 3px var(--color-brand-600);
}
.daycal__cell.is-done .daycal__stamp {
  display: block; font-size: 10px; font-weight: 700; line-height: 1; color: var(--color-brand-600);
}

/* 도장 내리찍기 (미션 완료 화면 전용, 2026-09-07 — done.js 가 is-stamping 을 붙인다. 홈은 안 쓴다).
   크게 떠 있던 도장이 0.42s 에 내리꽂혀 살짝 눌렸다 튕기고(-34°→-14°), 칸이 1.5px 눌렸다
   올라오며, 도장 둘레에서 얇은 파문이 퍼진다. 최종 상태는 위 is-done 규칙과 정확히 같다. */
.daycal__cell.is-stamping { animation: daycal-press 300ms ease-out 200ms both; }
.daycal__cell.is-stamping .daycal__mark {
  position: relative;
  animation: daycal-slam 420ms cubic-bezier(0.2, 0.7, 0.3, 1) both;
}
.daycal__cell.is-stamping .daycal__mark::after {
  content: ''; position: absolute; inset: -4px; border-radius: 50%;
  border: 2px solid var(--color-brand-500); opacity: 0;
  animation: daycal-ripple 500ms ease-out 220ms both;
}
@keyframes daycal-slam {
  0%   { opacity: 0; transform: rotate(-34deg) scale(2.4); }
  55%  { opacity: 1; transform: rotate(-14deg) scale(0.88); }
  75%  { transform: rotate(-14deg) scale(1.06); }
  100% { transform: rotate(-14deg) scale(1); }
}
@keyframes daycal-press {
  0%   { transform: none; }
  35%  { transform: translateY(1.5px) scale(0.97); }
  100% { transform: none; }
}
@keyframes daycal-ripple {
  0%   { opacity: 0.7; transform: scale(0.8); }
  100% { opacity: 0; transform: scale(1.9); }
}
@media (prefers-reduced-motion: reduce) {
  .daycal__cell.is-stamping, .daycal__cell.is-stamping .daycal__mark { animation: none; }
  .daycal__cell.is-stamping .daycal__mark::after { display: none; }
}

/* 축하 연출 '미리 감춤' (views/_celebrate_pre.njk, 2026-09-07). celebrate.js 의 시작 상태와 같다 —
   본문(.cel-run 의 celViewIn 이 .45 에서 시작) 45%, 연출 대상([data-cel]) 숨김. 첫 페인트가
   이 모습이어야 연출이 늦게 시작해도 화면이 "지웠다 다시 뜨지" 않는다. */
.cel-pre [data-cel-id] { opacity: 0.45; }
.cel-pre [data-cel] { opacity: 0; }

.stepdots { display: flex; gap: var(--space-1); }
.stepdots span {
  width: 8px; height: 8px; border-radius: var(--radius-pill);
  background: var(--color-line);
  transition: background-color var(--motion-base) var(--ease-out),
              transform var(--motion-base) var(--ease-out);
}
.stepdots span[data-on="1"] { background: var(--color-brand-500); transform: scale(1.15); }

/* ── DAY 목록 ───────────────────────────────────────────── */

.filter-tabs { display: flex; gap: var(--space-2); flex-wrap: wrap; }
.filter-tabs a {
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-md);
  background: var(--color-surface-soft);
  font-size: 14px; font-weight: 700; color: var(--color-ink-soft);
  transition: background-color var(--motion-base) var(--ease-out),
              color var(--motion-base) var(--ease-out);
}
.filter-tabs a[aria-current="page"] { background: var(--color-brand-100); color: var(--color-brand-700); }

/* 필터는 페이지를 다시 불러오지 않고 감추기만 한다(days.php). 카드가 통째로 다시 그려지면
   스크롤 위치·페이지 높이가 함께 튀어 화면이 위아래·좌우로 흔들린다. */
.day-grid[data-filter="todo"]  > li:not([data-state="todo"]),
.day-grid[data-filter="doing"] > li:not([data-state="doing"]),
.day-grid[data-filter="done"]  > li:not([data-state="done"]) { display: none; }

/* 전환 표시는 투명도만 — 위치가 움직이는 연출은 넣지 않는다. */
.day-grid.is-refiltering > li { animation: fade-in var(--motion-base) var(--ease-out) both; }

.day-grid {
  display: grid; gap: var(--space-3);
  grid-template-columns: 1fr;
}
@media (min-width: 600px) { .day-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1024px) { .day-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

.day-card {
  display: block;
  background: var(--color-surface);
  border: 1px solid var(--color-line);
  border-radius: var(--radius-lg);
  padding: var(--space-4);
  transition: box-shadow 160ms ease-out, border-color 160ms ease-out;
}
.day-card:hover { box-shadow: var(--shadow-hover); border-color: var(--color-brand-100); }
.day-card--locked { background: var(--color-surface-soft); border-color: transparent; }
.day-card--locked:hover { box-shadow: none; border-color: transparent; }
/* 공개는 됐지만 이용권이 없어 못 여는 카드. 잠금과 달리 "열 수 있어 보이면" 안 된다. */
.day-card--blocked { background: var(--color-surface-soft); border-style: dashed; cursor: not-allowed; }
.day-card--blocked:hover { box-shadow: none; border-color: var(--color-line); }
.day-card--blocked .day-card__no,
.day-card--blocked .day-card__title { color: var(--color-muted); }
.day-card--done { border-color: var(--color-success-bg); }
.day-card__no { font-size: 14px; font-weight: 800; color: var(--color-brand-600); }
.day-card__title {
  margin-top: var(--space-1); font-size: 16px; font-weight: 700; line-height: 1.4;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.day-card__stages { margin-top: var(--space-3); display: flex; gap: var(--space-1); }
.stage-pip {
  flex: 1; height: 6px; border-radius: var(--radius-pill);
  background: var(--color-line);
}
.stage-pip[data-state="done"] { background: var(--color-success); }
.stage-pip[data-state="available"] { background: var(--color-brand-100); }

/* ── 학습 화면 ──────────────────────────────────────────── */

.learn-header { padding: var(--space-4) 0 var(--space-2); }
.learn-header__meta { display: flex; align-items: center; gap: var(--space-2); margin-bottom: var(--space-3); }

.challenge-card {
  background: var(--color-surface);
  border: 1px solid var(--color-line);
  border-radius: var(--radius-2xl);
  overflow: hidden;
  min-height: 300px;
  display: flex; flex-direction: column;
}
@media (min-width: 1024px) { .challenge-card { min-height: 380px; } }

/* 문항 1 → 2 → 3 교체. 나가는 쪽은 왼쪽으로 밀리고 들어오는 쪽은 오른쪽에서 들어온다.
   진행 방향이 보여야 "다음 문제로 넘어갔다"가 읽힌다. */
.challenge-card.is-leaving  { animation: card-out var(--motion-fast) var(--ease-in) both; }
.challenge-card.is-entering { animation: card-in var(--motion-base) var(--ease-out) both; }

@keyframes card-out {
  from { opacity: 1; transform: none; }
  to   { opacity: 0; transform: translateX(-12px); }
}
@keyframes card-in {
  from { opacity: 0; transform: translateX(16px); }
  to   { opacity: 1; transform: none; }
}

.challenge-card__body { padding: var(--space-6) var(--space-5); flex: 1; }
.challenge-card__answer { padding: var(--space-5); background: var(--color-brand-050); }
.challenge-card__answer--listening { background: var(--color-surface-soft); }
@media (min-width: 1024px) {
  .challenge-card__body { padding: var(--space-8); }
  .challenge-card__answer { padding: var(--space-6) var(--space-8); }
}

.prompt-ko { margin-bottom: var(--space-8); }

.slot-input {
  width: 100%; min-height: 48px;
  padding: var(--space-3) var(--space-4);
  background: var(--color-brand-050);
  border: 1px solid var(--color-brand-100);
  border-radius: var(--radius-md);
  font-size: 18px; line-height: 1.5;
  resize: vertical;
}
.slot-input:focus { border-color: var(--color-brand-500); background: var(--color-surface); }
.slot-input[aria-invalid="true"] { border-color: var(--color-danger); background: var(--color-danger-bg); }
.slot-input:disabled {
  opacity: 1;
  color: var(--color-ink);
  -webkit-text-fill-color: var(--color-ink);
}
.slot-input[data-result="correct"] {
  border-color: var(--color-success-line);
  background-color: var(--color-success-bg);
}
.slot-input[data-result="wrong"] {
  border-color: var(--color-danger-line);
  background-color: var(--color-danger-bg);
}

/* 오답·빈 입력을 눌렀을 때. 색만으로는 눈치채지 못하는 경우가 있다. */
.is-shaking { animation: shake 320ms var(--ease-out) both; }
@keyframes shake {
  0%, 100% { transform: none; }
  20% { transform: translateX(-6px); }
  40% { transform: translateX(5px); }
  60% { transform: translateX(-3px); }
  80% { transform: translateX(2px); }
}

/* 원어민 장면 — 클립이 짧아 탐색 막대 없이 탭해서 다시 보는 형태로 둔다. */
.scene {
  position: relative;
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: #000;
  line-height: 0;
}
.scene__video {
  display: block;
  width: 100%; height: auto;
  max-height: 46vh;
  object-fit: contain;
  background: #000;
}
.scene__overlay {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  border: 0; padding: 0; cursor: pointer;
  background: rgba(0, 0, 0, 0.28);
  color: #fff;
}
.scene__overlay::before {
  content: "";
  position: absolute;
  width: 64px; height: 64px;
  border-radius: var(--radius-pill);
  /* blur 를 걸면 배우 얼굴이 모자이크처럼 보인다. 단색 원으로 둔다. */
  background: rgba(0, 0, 0, 0.62);
}
.scene__overlay svg { position: relative; transform: translateX(2px); }
.scene__overlay[hidden] { display: none !important; }

.player {
  display: flex; align-items: center; gap: var(--space-3);
  flex-wrap: wrap;
  padding: var(--space-4);
  background: var(--color-surface-soft);
  border-radius: var(--radius-lg);
}
.player > .stack { flex: 1 1 120px; min-width: 0; gap: 2px; }
.speed-group { display: flex; gap: var(--space-1); margin-left: auto; }
/* 좁은 화면에서는 속도 버튼을 아래 줄로 내려 문구가 눌리지 않게 한다. */
@media (max-width: 479px) {
  .speed-group { margin-left: 0; width: 100%; }
  .speed-group button { flex: 1; }
}
.speed-group button {
  min-height: 36px; padding: 0 var(--space-3);
  border: 1px solid var(--color-line); background: var(--color-surface);
  border-radius: var(--radius-sm); font-size: 13px; font-weight: 700; cursor: pointer;
}
.speed-group button[aria-pressed="true"] {
  background: var(--color-brand-100); border-color: var(--color-brand-100); color: var(--color-brand-700);
}

.play-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 56px; height: 56px; flex: 0 0 56px;
  border: 0; border-radius: var(--radius-pill);
  background: var(--color-ink); color: #fff; cursor: pointer;
}

/* 마이크 */
.mic-wrap { display: flex; flex-direction: column; align-items: center; gap: var(--space-3); }
.mic-btn {
  position: relative;
  width: 88px; height: 88px;
  border: 0; border-radius: var(--radius-pill);
  background: var(--color-surface); color: var(--color-ink);
  box-shadow: var(--shadow-float);
  cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
}
@media (min-width: 1024px) { .mic-btn { width: 96px; height: 96px; } }
.mic-btn[data-state="recording"] { background: var(--color-brand-500); color: #fff; }
.mic-btn[data-state="recording"]::before,
.mic-btn[data-state="recording"]::after {
  content: ""; position: absolute; inset: 0;
  border-radius: var(--radius-pill);
  border: 2px solid var(--color-brand-500);
  animation: mic-ring 1.6s ease-out infinite;
}
.mic-btn[data-state="recording"]::after { animation-delay: 0.8s; }
@keyframes mic-ring {
  from { transform: scale(1); opacity: 0.6; }
  to   { transform: scale(1.45); opacity: 0; }
}
/* 분석·응답 대기 — 문구만 바뀌면 멈춘 것처럼 보인다. 도는 링으로 진행 중임을 보인다. */
.mic-btn[data-state="processing"] { background: var(--color-surface-soft); color: var(--color-muted); }
.mic-btn[data-state="processing"]::before {
  content: ""; position: absolute; inset: -4px;
  border-radius: var(--radius-pill);
  border: 3px solid var(--color-brand-100);
  border-top-color: var(--color-brand-500);
  animation: spin 900ms linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* 결과를 기다리는 자리 — 문구만 두면 멈춘 화면과 구분이 안 된다.
   종료 피드백은 AI 가 대화를 다시 읽고 만들기 때문에 몇 초가 걸린다. */
.wait-panel {
  display: flex; align-items: center; gap: var(--space-4);
  padding: var(--space-10) var(--space-2);
}
.spinner {
  flex: 0 0 auto; width: 26px; height: 26px; border-radius: var(--radius-pill);
  border: 3px solid var(--color-brand-100);
  border-top-color: var(--color-brand-500);
  animation: spin 800ms linear infinite;
}
/* 버튼 안에서 글자 옆에 서는 작은 것.
   비활성 버튼은 배경이 밝게 바뀌므로 흰색으로 고정하면 묻힌다 → 글자색을 따라간다. */
.spinner--sm {
  width: 16px; height: 16px; border-width: 2px;
  border-color: currentColor; border-top-color: transparent;
  opacity: 0.75;
}

.mic-btn:disabled { background: var(--color-line); color: var(--color-muted); box-shadow: none; }
/* 위 disabled 규칙이 처리 중 배경까지 덮어써서 링이 묻히지 않게 한다. */
.mic-btn:disabled[data-state="processing"] { background: var(--color-surface-soft); }

/* 점 세 개 로더 — 마이크 라벨 옆, AI 응답 대기 말풍선 안에서 함께 쓴다. */
.dot-loader { display: inline-flex; align-items: center; gap: 5px; }
.dot-loader span {
  width: 7px; height: 7px; border-radius: var(--radius-pill);
  background: var(--color-brand-500);
  animation: dot-bounce 1.1s var(--ease-out) infinite;
}
.dot-loader span:nth-child(2) { animation-delay: 0.15s; }
.dot-loader span:nth-child(3) { animation-delay: 0.3s; }
@keyframes dot-bounce {
  0%, 60%, 100% { transform: translateY(0); opacity: 0.45; }
  30%           { transform: translateY(-5px); opacity: 1; }
}

/* 버튼이 요청을 기다리는 동안 */
.btn.is-busy { position: relative; color: transparent !important; }
.btn.is-busy::after {
  content: ""; position: absolute;
  width: 18px; height: 18px; border-radius: var(--radius-pill);
  border: 2px solid rgb(255 255 255 / 45%); border-top-color: #fff;
  animation: spin 700ms linear infinite;
}

/* 결과 패널 */
.result-panel {
  border-radius: var(--radius-2xl);
  padding: var(--space-5);
  border: 1px solid transparent;
}
@media (min-width: 1024px) { .result-panel { padding: var(--space-6); } }
.result-panel--correct { background-color: var(--color-success-bg); border-color: var(--color-success-line); }
.result-panel--wrong   { background-color: var(--color-danger-bg); border-color: var(--color-danger-line); }
.result-panel--neutral { background: var(--color-surface-soft); }
.result-panel--correct .result-panel__verdict { color: var(--color-success); }
.result-panel--wrong .result-panel__verdict { color: var(--color-danger); }
/* 채점 결과가 툭 나타나지 않도록. 결과는 화면에서 가장 중요한 순간이다. */
.result-panel.is-revealing { animation: rise-in var(--motion-slow) var(--ease-out) both; }

.answer-line { font-size: 20px; font-weight: 700; line-height: 1.5; }
.ipa { color: var(--color-ink-soft); font-size: 15px; }

/* 음성인식이 받아쓴 내 발화 — 무엇이 어떻게 들렸는지 보여준다. */
.heard {
  display: flex; flex-direction: column; gap: var(--space-1);
  padding: var(--space-3) var(--space-4);
  background: var(--color-surface); border: 1px dashed var(--color-line);
  border-radius: var(--radius-md);
}
.heard__text { font-size: 16px; font-weight: 600; }

/* 하단 고정 행동 */
.bottom-action {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 20;
  padding: var(--space-3) var(--space-4) calc(var(--space-3) + env(safe-area-inset-bottom));
  background: rgb(255 255 255 / 94%);
  backdrop-filter: blur(8px);
  border-top: 1px solid var(--color-line);
}
.bottom-action__inner { max-width: var(--challenge-max); margin: 0 auto; display: flex; gap: var(--space-3); }

/* TALKING */
.sentence-strip { display: flex; flex-direction: column; gap: var(--space-2); }
.sentence-chip {
  display: flex; align-items: flex-start; gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--color-line);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  text-align: left; width: 100%;
}
.sentence-chip[data-used="1"] { background: var(--color-success-bg); border-color: #cceadb; }
.sentence-chip { transition: background-color var(--motion-base) var(--ease-out),
                             border-color var(--motion-base) var(--ease-out); }

/**
 * 종료 피드백 목록.
 * 좁은 화면에서 "사용함/미사용" 칩을 문장 왼쪽에 두면 남는 폭이 좁아 문장이 잘게 접힌다.
 * 480px 이하에서는 칩을 윗줄로 올리고 문장이 한 줄 전체를 쓰게 한다.
 */
@media (max-width: 479px) {
  .sentence-strip--feedback .sentence-chip {
    flex-wrap: wrap;
    row-gap: var(--space-2);
  }
  .sentence-strip--feedback .sentence-chip > .badge { order: 1; }
  .sentence-strip--feedback .sentence-chip > .chip-play { order: 2; margin-left: auto; }
  /* 칩·재생 버튼이 첫 줄을 차지하고, 문장은 다음 줄에서 폭을 다 쓴다. */
  .sentence-strip--feedback .sentence-chip__main { order: 3; flex: 1 0 100%; }
}
/* 카드 안에 뜻 토글과 음성 재생 두 동작이 있다. 본문 쪽만 버튼으로 만든다. */
.sentence-chip__main {
  flex: 1; min-width: 0;
  border: 0; background: transparent; padding: 0;
  text-align: left; cursor: pointer; font: inherit; color: inherit;
}
.sentence-chip__en { display: block; font-size: 16px; font-weight: 700; }
.sentence-chip__ko { display: block; font-size: 14px; color: var(--color-ink-soft); margin-top: var(--space-1); }
.sentence-chip__ko[hidden] { display: none !important; }

/* 강세 — 시트 D~F 열에서 붉은 볼드로 표시된 구간(문장에서 힘이 들어가는 자리).
   원본은 빨강이지만 화면의 빨강은 오답·오류 자리라, 브랜드색으로 옮겨 오해를 막는다.
   색을 못 보는 사람도 알아볼 수 있게 굵기와 밑줄을 함께 준다(색만으로 뜻을 나르지 않는다). */
.stress {
  font-weight: 800;
  color: var(--color-brand-700);
  text-decoration: underline;
  text-decoration-color: var(--color-brand-100);
  text-decoration-thickness: 2px;
  text-underline-offset: 3px;
}

.chip-play {
  flex: 0 0 36px;
  display: inline-flex; align-items: center; justify-content: center;
  width: 36px; height: 36px;
  border: 1px solid var(--color-line); border-radius: var(--radius-pill);
  background: var(--color-surface); color: var(--color-ink); cursor: pointer;
}
.chip-play:hover { background: var(--color-surface-soft); }
.chip-play svg { transform: translateX(1px); }

.chat-log { display: flex; flex-direction: column; gap: var(--space-3); min-height: 220px; }
.bubble {
  max-width: 82%; padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-lg); font-size: 16px; line-height: 1.55;
}
.bubble--ai   { align-self: flex-start; background: var(--color-surface-soft); border-bottom-left-radius: var(--space-1); }
.bubble--me   { align-self: flex-end; background: var(--color-brand-100); border-bottom-right-radius: var(--space-1); }
.bubble--sys  { align-self: center; background: transparent; color: var(--color-muted); font-size: 13px; }
/* AI 응답은 읽어 주지 않고 학습자가 읽는다 — 영어 아래에 한국어 해석을 흐리고 작게 붙인다.
   같은 크기·색이면 눈이 한국어부터 읽어 영어를 건너뛴다. */
.bubble__en { display: block; }
.bubble__ko {
  display: block; margin-top: var(--space-2);
  font-size: 14px; line-height: 1.5; color: var(--color-muted);
}
.bubble.is-entering { animation: bubble-in var(--motion-base) var(--ease-out) both; }
@keyframes bubble-in {
  from { opacity: 0; transform: translateY(8px) scale(0.98); }
  to   { opacity: 1; transform: none; }
}
/* AI가 응답을 만드는 동안 자리를 잡아 두는 말풍선 */
.bubble--thinking { padding: var(--space-3) var(--space-4); }

/* 안내 · 빈 상태 */
.notice {
  padding: var(--space-4);
  border-radius: var(--radius-lg);
  background: var(--color-brand-050);
  font-size: 14px; line-height: 1.6; color: var(--color-ink-soft);
}
.notice--warning { background: var(--color-warning-bg); color: var(--color-warning); }

/* ── 오늘의 미션 종료까지 (2026-09-10, 홈 히어로 카드 안) ──────────────────
   히어로 카드가 brand-050 → 흰색 그라데이션이라, 그 위에서 한 덩어리로 읽히도록
   흰 배경 + brand 테두리로 띄운다. 남은 시간이 1시간 이하면 is-urgent 로 warning
   색이 되는데, **배경만 바꾸고 자리·크기는 그대로 둔다** — 색이 바뀌면서 높이까지
   변하면 그 순간 아래 CTA 버튼이 밀려서 누르려던 손가락이 빗나간다. */
.countdown {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  border: 1px solid var(--color-brand-100);
}
.countdown__label { font-size: 13px; font-weight: 700; line-height: 1.4; color: var(--color-ink-soft); }
.countdown__value { font-size: 20px; font-weight: 750; line-height: 1.35; color: var(--color-brand-700); letter-spacing: -0.01em; white-space: nowrap; }
.countdown.is-urgent { background: var(--color-warning-bg); border-color: transparent; }
.countdown.is-urgent .countdown__label,
.countdown.is-urgent .countdown__value { color: var(--color-warning); }
/* '내 시간 …' 한 줄. 한국 시간대에서는 JS 가 hidden 을 풀지 않는다(중복). */
.countdown__local { text-align: right; }

.notice--danger  { background: var(--color-danger-bg); color: var(--color-danger); }
/* 잠긴 카드를 눌렀을 때 "여기를 보라"고 알리는 짧은 강조 */
.notice.is-attention { animation: attention 600ms var(--ease-out) both; }
@keyframes attention {
  0%   { transform: none; box-shadow: 0 0 0 0 rgb(181 106 0 / 45%); }
  30%  { transform: translateY(-3px); box-shadow: 0 0 0 6px rgb(181 106 0 / 0%); }
  100% { transform: none; box-shadow: 0 0 0 0 rgb(181 106 0 / 0%); }
}

.empty { text-align: center; padding: var(--space-16) var(--space-4); color: var(--color-muted); }

/* 폼 */
.field { display: flex; flex-direction: column; gap: var(--space-2); }
.field label { font-size: 14px; font-weight: 700; }
.field input {
  min-height: 52px; padding: 0 var(--space-4);
  border: 1px solid var(--color-line); border-radius: var(--radius-md);
  background: var(--color-surface);
}
.field input:focus { border-color: var(--color-brand-500); }
/* Task 17 말하기 화면의 연습 문장 textarea — .field input 과 같은 톤(테두리·배경·
   포커스색)을 쓰되 여러 줄 입력에 맞게 세로 패딩·resize 만 다르게 준다. */
.field textarea {
  min-height: 76px; padding: var(--space-3) var(--space-4);
  border: 1px solid var(--color-line); border-radius: var(--radius-md);
  background: var(--color-surface); resize: vertical;
}
.field textarea:focus { border-color: var(--color-brand-500); }

/* 데스크톱 Rail */
.layout-rail { display: block; }
@media (min-width: 1024px) {
  .layout-rail {
    display: grid;
    grid-template-columns: 208px minmax(0, 1fr);
    gap: var(--space-10);
    align-items: start;
  }
  .rail { position: sticky; top: calc(var(--header-h) + var(--space-6)); }
}
.rail { display: none; }
@media (min-width: 1024px) { .rail { display: block; } }
.rail a {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  font-weight: 700; color: var(--color-ink-soft);
}
.rail a[aria-current="page"] { background: var(--color-brand-100); color: var(--color-brand-700); }
.rail a:hover { background: var(--color-surface-soft); }

/* 모바일 하단 내비 */
.bottom-nav {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 20;
  display: flex;
  background: rgb(255 255 255 / 96%);
  backdrop-filter: blur(8px);
  border-top: 1px solid var(--color-line);
  padding-bottom: env(safe-area-inset-bottom);
}
.bottom-nav a {
  flex: 1; min-height: 56px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  font-size: 12px; font-weight: 700; color: var(--color-muted);
}
.bottom-nav a[aria-current="page"] { color: var(--color-brand-600); }
@media (min-width: 1024px) { .bottom-nav { display: none; } }

/* ── 온보딩 3장 ─────────────────────────────────────────── */

/* 오른쪽으로 미는 동작을 브라우저가 "뒤로 가기"로 채가지 않게 한다(앞 장으로 돌아가야 한다). */
body.onboarding { overscroll-behavior-x: contain; }

.onboard { padding-top: var(--space-8); }
.onboard__top { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); }
.onboard__dots { display: flex; gap: var(--space-2); }
.onboard__dots span {
  width: 8px; height: 5px; border-radius: var(--radius-pill);
  background: var(--color-line);
  transition: width var(--motion-slow) var(--ease-soft),
              background-color var(--motion-base) var(--ease-out);
}
.onboard__dots span[data-on="1"] { background: var(--color-brand-500); }
/* 지나온 장은 색만 채우고, 지금 보고 있는 장만 길게 늘어난다. */
.onboard__dots span[data-current="1"] { width: 28px; }

/* 세 장을 같은 격자 칸에 겹쳐 둔다. 흐름에서 빼지 않으므로 장을 넘겨도
   덱 높이(=가장 긴 장)가 그대로다 — 아래 내용이 밀렸다 사라지지 않는다.
   clip 은 옆에서 들어오는 장이 화면 밖으로 삐져나가 가로 스크롤을 만드는 걸 막는다. */
.onboard__deck { display: grid; overflow-x: clip; --onboard-shift: 24px; }
.onboard__deck[data-dir="back"] { --onboard-shift: -24px; }

.onboard__card {
  grid-area: 1 / 1;
  min-height: 380px;
  opacity: 0;
  visibility: hidden;      /* 보조기술·탭 이동에서도 빠진다 */
  pointer-events: none;
  will-change: opacity, transform;
}
@media (min-width: 1024px) { .onboard__card { min-height: 420px; } }

.onboard__card.is-active {
  opacity: 1; visibility: visible; pointer-events: auto;
  animation: onboard-in var(--motion-slow) var(--ease-soft) both;
}
/* 나가는 장은 자리를 차지한 채로 사라지기만 한다(레이아웃 영향 없음).
   들어오는 장보다 빨리 비켜야 두 장이 겹쳐 보이는 구간이 짧다. */
.onboard__card.is-leaving {
  visibility: visible;
  animation: onboard-out var(--motion-fast) var(--ease-in) both;
}

@keyframes onboard-in {
  from { opacity: 0; transform: translate3d(var(--onboard-shift), 0, 0) scale(0.985); }
  to   { opacity: 1; transform: none; }
}
@keyframes onboard-out {
  from { opacity: 1; transform: none; }
  to   { opacity: 0; transform: translate3d(calc(var(--onboard-shift) * -0.5), 0, 0) scale(0.99); }
}

/* 카드가 통째로 미끄러지기만 하면 밋밋하다. 안쪽 줄이 살짝 늦게 따라 올라온다. */
.onboard__card.is-active > * { animation: onboard-el var(--motion-slow) var(--ease-soft) both; }
.onboard__card.is-active > *:nth-child(1) { animation-delay: 40ms; }
.onboard__card.is-active > *:nth-child(2) { animation-delay: 90ms; }
.onboard__card.is-active > *:nth-child(3) { animation-delay: 140ms; }
.onboard__card.is-active > *:nth-child(n + 4) { animation-delay: 190ms; }

@keyframes onboard-el {
  from { opacity: 0; transform: translate3d(0, 10px, 0); }
  to   { opacity: 1; transform: none; }
}

.onboard__flow { display: flex; flex-direction: column; gap: var(--space-4); }
.onboard__flow li { display: flex; align-items: flex-start; gap: var(--space-3); }
.onboard__flow-no {
  flex: 0 0 28px;
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; border-radius: var(--radius-pill);
  background: var(--color-brand-100); color: var(--color-brand-700);
  font-size: 13px; font-weight: 800;
}
.onboard__flow-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; }

.onboard__notes { display: flex; flex-direction: column; gap: var(--space-4); }
.onboard__notes li { display: flex; flex-direction: column; gap: var(--space-1); }

.onboard__actions { display: flex; gap: var(--space-3); align-items: stretch; }
.onboard__actions > form { flex: 1; }
.onboard__actions .btn--ghost { flex: 0 0 auto; }

/* ── 완주 인증서 ────────────────────────────────────────── */

.cert-page { background: var(--color-surface-soft); }

.cert-bar {
  position: sticky; top: 0; z-index: 30;
  background: rgb(255 255 255 / 94%);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--color-line);
}
.cert-bar__inner {
  max-width: var(--content-max); margin: 0 auto;
  padding: var(--space-3) var(--space-4);
  display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap;
}
.cert-bar__inner .t-caption { flex: 1 1 200px; }

.cert-stage { padding: var(--space-8) var(--space-4) var(--space-16); }

/* 완주 배지 — canvas 로 그린 뒤 투명 PNG 로 내려받는다 */
.badge-stage { width: min(100%, 420px); margin: 0 auto; }
.badge-stage canvas {
  display: block; width: 100%; height: auto;
  animation: rise-in var(--motion-slow) var(--ease-out) both;
}

/* A4 세로 비율. 화면에서는 폭에 맞춰 줄어들고, 인쇄하면 한 장에 딱 들어간다. */
.cert {
  position: relative;
  width: min(100%, 794px);
  aspect-ratio: 210 / 297;
  margin: 0 auto;
  padding: clamp(24px, 6%, 64px);
  background: var(--color-surface);
  border: 1px solid var(--color-line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-float);
  display: flex; flex-direction: column; align-items: center;
  text-align: center;
  /* 기울인 워터마크가 증서 밖으로 삐져나와 가로 스크롤을 만들지 않게 한다. */
  overflow: hidden;
  animation: rise-in var(--motion-slow) var(--ease-out) both;
}
.cert::after {
  content: ""; position: absolute; inset: clamp(12px, 2.4%, 24px);
  border: 2px solid var(--color-brand-100);
  border-radius: var(--radius-md);
  pointer-events: none;
}

.cert__head { display: flex; flex-direction: column; gap: var(--space-2); align-items: center; }
.cert__brand { font-size: clamp(15px, 2.4vw, 19px); font-weight: 800; letter-spacing: -0.02em; }
.cert__brand b { color: var(--color-brand-500); }
.cert__kicker {
  font-size: clamp(10px, 1.5vw, 12px); font-weight: 700; letter-spacing: 0.22em;
  color: var(--color-muted);
}

.cert__title { margin-top: clamp(10px, 5%, 44px); font-size: clamp(26px, 5.4vw, 40px); font-weight: 800; letter-spacing: -0.02em; }
.cert__lead { margin-top: clamp(10px, 5%, 40px); font-size: clamp(13px, 1.9vw, 15px); color: var(--color-ink-soft); }
.cert__name {
  margin-top: var(--space-3);
  font-size: clamp(28px, 6vw, 46px); font-weight: 800; letter-spacing: -0.02em;
  border-bottom: 2px solid var(--color-brand-500);
  padding: 0 clamp(16px, 4vw, 40px) var(--space-2);
}
.cert__course { margin-top: clamp(10px, 5%, 40px); font-size: clamp(15px, 2.4vw, 20px); font-weight: 700; }
.cert__body { margin-top: var(--space-3); font-size: clamp(13px, 2vw, 16px); line-height: 1.9; color: var(--color-ink-soft); }

.cert__meta {
  margin: auto 0 0; padding-top: clamp(10px, 5%, 40px);
  display: flex; gap: clamp(16px, 4vw, 48px); flex-wrap: wrap; justify-content: center;
}
.cert__meta div { display: flex; flex-direction: column; gap: var(--space-1); }
.cert__meta dt { font-size: clamp(10px, 1.5vw, 12px); font-weight: 700; color: var(--color-muted); }
.cert__meta dd { margin: 0; font-size: clamp(12px, 1.8vw, 15px); font-weight: 700; }

.cert__foot {
  margin-top: clamp(10px, 5%, 40px);
  display: flex; flex-direction: column; align-items: center; gap: var(--space-2);
}
.cert__seal {
  display: inline-flex; align-items: center; justify-content: center;
  width: clamp(52px, 9vw, 72px); height: clamp(52px, 9vw, 72px);
  border: 2px solid var(--color-brand-500); border-radius: var(--radius-pill);
  color: var(--color-brand-600); font-weight: 800; font-size: clamp(12px, 1.8vw, 15px);
}
.cert__issuer { font-size: clamp(12px, 1.8vw, 15px); font-weight: 700; color: var(--color-ink-soft); }

/**
 * 인쇄 — 반드시 한 장에 들어가야 한다.
 *
 * ⚠️ 크롬 인쇄 대화상자의 **여백 설정이 `@page { margin }` 을 덮어쓴다.** 그래서 인쇄 영역 높이를
 *    미리 알 수 없다. `height: 100vh` 처럼 페이지를 꽉 채우게 만들면 여백이 "기본값" 인 순간
 *    1~2mm 넘쳐서 두 장으로 잘린다.
 *    → 높이를 고정하지 않고, 어떤 여백 설정에서도 남는 245mm 안에 들어가게 둔다.
 */
/* 완주 전 안내 — 화면에는 안 보이고 인쇄에만 나온다(아래 @media print) */
.cert-printblock { display: none; }

@media print {
  @page { size: A4 portrait; margin: 10mm; }

  html, body { height: auto; background: #fff; }
  .cert-bar, .bottom-nav, .app-header { display: none !important; }
  .cert-page { background: #fff; }
  .cert-stage { padding: 0; }

  /**
   * 완주 전에는 인쇄로도 받을 수 없다.
   * 버튼만 막으면 Ctrl+P 로 그대로 빠져나간다 — 증서 자체를 인쇄 대상에서 뺀다.
   */
  .cert-page--preview .cert-stage { display: none !important; }
  .cert-page--preview .cert-printblock {
    display: block;
    padding: 40mm 20mm;
    text-align: center;
    font-size: 12pt; line-height: 1.9;
  }

  .cert {
    width: 100%;
    height: auto;
    /* 여백을 가장 넓게 잡아도(20mm) 인쇄 영역은 257mm 다. 252mm 면 어느 설정에서도 남는다. */
    min-height: 252mm;
    aspect-ratio: auto;
    padding: 14mm 16mm;
    border: 0; border-radius: 0; box-shadow: none;
    overflow: visible;
    animation: none;
    break-inside: avoid;
    page-break-inside: avoid;
  }
  /* 뒤에 빈 블록이 하나라도 남으면 그것만으로 둘째 장이 생긴다. */
  .cert-stage, .cert { break-after: avoid; page-break-after: avoid; }

  .cert::after { inset: 0; }

  /* vw 기반 clamp 는 인쇄 폭에서 예측이 어렵다. 인쇄에서는 pt 로 고정한다. */
  .cert__brand    { font-size: 15pt; }
  .cert__kicker   { font-size: 9pt; }
  .cert__title    { font-size: 30pt; margin-top: 14mm; }
  .cert__lead     { font-size: 11pt; margin-top: 14mm; }
  .cert__name     { font-size: 34pt; margin-top: 4mm; padding: 0 12mm 3mm; }
  .cert__course   { font-size: 15pt; margin-top: 14mm; }
  .cert__body     { font-size: 12pt; margin-top: 5mm; }
  .cert__meta     { padding-top: 14mm; gap: 20mm; }
  .cert__meta dt  { font-size: 9pt; }
  .cert__meta dd  { font-size: 11pt; }
  .cert__foot     { margin-top: 12mm; }
  .cert__seal     { width: 20mm; height: 20mm; font-size: 10pt; }
  .cert__issuer   { font-size: 11pt; }

  /* 배경색·테두리가 인쇄에서 빠지면 증서로 보이지 않는다. */
  .cert, .cert::after, .cert__name, .cert__seal {
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  /* 위 규칙은 지속시간만 없앤다. 이동·확대는 여기서 따로 지운다(design-system.md §모션). */
  .reveal, .stagger > *, .cert,
  .challenge-card.is-leaving, .challenge-card.is-entering,
  .onboard__card.is-active, .onboard__card.is-active > *,
  .bubble.is-entering, .result-panel.is-revealing, .modal__panel,
  .count-bubble,
  .main, .is-shaking, .notice.is-attention {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
  }
  /* 보이지 않아야 할 장까지 opacity 를 되살리면 세 장이 겹쳐 보인다 — 여기서는 지우기만 한다. */
  .onboard__card.is-leaving { animation: none !important; transform: none !important; }
  .progress__fill { animation: none !important; transform: none !important; }
  /* 🔴 밑줄은 정보다 — 애니메이션만 없애고 밑줄 자체는 그어진 채로 둔다.
     위의 공통 규칙(animation-duration: 0.01ms)만 걸면 background-size 가 0 인
     시작 프레임에서 멈춰 **밑줄이 아예 안 보인다**. */
  .mark-draw { animation: none !important; background-size: 100% 4px !important; }
  /* 스피너는 "돌고 있다"가 곧 정보라 멈추면 안 된다. 지우는 대신 느리게 돌린다. */
  .spinner { animation: spin 2.4s linear infinite !important; }
  @view-transition { navigation: none; }
}

/* ============================================================================
   인트로 온보딩 (첫 진입 1회) — 옛 시스템 index.html 의 `.io*` 이식.
   ⚠️ 이 앱의 디자인 시스템은 밝은 테마인데 인트로는 **어두운 전체화면 오버레이**다.
      원본의 그라데이션 글자·글로우가 이 연출의 핵심이라 그대로 살렸고,
      전체화면을 덮으므로 본문과 섞이지 않는다. 색은 이 블록 안에서 자급자족한다
      (앱 토큰에 의존하지 않는다 — 앱 테마가 바뀌어도 인트로는 그대로여야 한다).
   ============================================================================ */
.io {
  --io-bg: #0d0d12; --io-line: rgba(255,255,255,.12); --io-sub: #c9cad1;
  --io-muted: #8b8c96; --io-accent: #ffc48a;
  --io-grad: linear-gradient(96deg, #fe6400, #ff9436);
  position: fixed; inset: 0; z-index: 9000; background: var(--io-bg);
  display: none; flex-direction: column; overflow: hidden; color: #f4f5f7;
}
.io.show { display: flex; }
.io-bg { position: absolute; inset: 0; pointer-events: none;
  background:
    radial-gradient(70% 44% at 50% -4%, rgba(254,100,0,.26), transparent 70%),
    radial-gradient(56% 38% at 92% 8%, rgba(255,148,54,.18), transparent 72%),
    radial-gradient(60% 40% at 6% 100%, rgba(254,100,0,.12), transparent 70%); }
.io-skip { position: absolute; top: calc(env(safe-area-inset-top,0px) + 14px); right: 14px; z-index: 3;
  background: rgba(255,255,255,.07); border: 1px solid var(--io-line); color: var(--io-sub);
  font-family: inherit; font-size: 12.5px; font-weight: 700; padding: 8px 14px; border-radius: 999px; cursor: pointer; }
.io-stage { position: relative; z-index: 2; flex: 1; min-height: 0; }
.io-slide { position: absolute; inset: 0; display: none; flex-direction: column; align-items: center;
  justify-content: center; text-align: center; padding: 58px 24px 8px; gap: 14px; }
.io-slide.act, .io-slide.leaving { display: flex; }
.io-slide.leaving { animation: ioOut .3s ease forwards; pointer-events: none; }
.io-el { opacity: 0; transform: translateY(16px); }
.io-slide.act .io-el { animation: ioUp .56s cubic-bezier(.22,.85,.3,1) forwards; animation-delay: var(--d, 0s); }
@keyframes ioUp { to { opacity: 1; transform: none; } }
@keyframes ioOut { to { opacity: 0; transform: translateY(-12px); } }
.io-h { font-size: 29px; font-weight: 900; letter-spacing: -1.2px; line-height: 1.38; word-break: keep-all; margin: 0; }
.io-h .g { background: var(--io-grad); -webkit-background-clip: text; background-clip: text; color: transparent; }
.io-sub { font-size: 15.5px; color: var(--io-sub); line-height: 1.75; word-break: keep-all; margin: 0; max-width: 340px; }
.io-sub b { color: var(--io-accent); font-weight: 800; }
.io-chip { display: inline-flex; align-items: center; gap: 7px; font-size: 12.5px; font-weight: 800; color: var(--io-accent);
  background: rgba(254,100,0,.12); border: 1px solid rgba(254,100,0,.3); border-radius: 999px; padding: 7px 15px; letter-spacing: -.2px; }
.io-pop { font-size: 44px; font-weight: 900; letter-spacing: -2px; line-height: 1;
  background: var(--io-grad); -webkit-background-clip: text; background-clip: text; color: transparent; }
.io-slide.act .io-pop { animation: ioPop .62s cubic-bezier(.2,1.5,.4,1) forwards; animation-delay: var(--d, 0s); }
@keyframes ioPop { 0% { opacity: 0; transform: scale(.6) translateY(10px); } 100% { opacity: 1; transform: none; } }
.io-blocks { display: flex; flex-direction: column; gap: 6px; align-items: center; }
.io-blk { border-radius: 11px; padding: 9px 18px; font-size: 14.5px; font-weight: 800; color: #17171d;
  letter-spacing: -.2px; box-shadow: 0 10px 26px rgba(0,0,0,.4); position: relative; }
.io-blk::before { content: ""; position: absolute; top: -6px; left: 16px; right: 16px; height: 8px;
  border-radius: 5px 5px 0 0; background: inherit; }
.io-blk.y { background: #f7f56a; }
.io-blk.g { background: #3af29a; }
.io-words { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px; max-width: 320px; }
.io-word { background: rgba(255,255,255,.06); border: 1px solid var(--io-line); color: var(--io-sub);
  border-radius: 9px; padding: 6px 10px; font-size: 12.5px; font-weight: 700; }
/* 투명 PNG(검은 글씨)라 밝은 카드 위에 얹는다 */
.io-figure { width: 100%; max-width: 360px; background: #fff; border-radius: 20px; padding: 16px 14px;
  box-shadow: 0 22px 54px rgba(0,0,0,.5); }
.io-figure img { display: block; width: 100%; max-height: 30vh; object-fit: contain; }
.io-cta { width: 100%; max-width: 340px; display: flex; flex-direction: column; gap: 10px; margin-top: 4px; }
.io-foot { position: relative; z-index: 2; display: flex; flex-direction: column; align-items: center; gap: 14px;
  padding: 16px 24px calc(env(safe-area-inset-bottom,0px) + 22px); }
.io-dots { display: flex; gap: 7px; align-items: center; }
.io-dot { width: 7px; height: 7px; border-radius: 999px; background: rgba(255,255,255,.2); position: relative;
  overflow: hidden; transition: width .34s cubic-bezier(.22,.85,.3,1), background .3s; }
.io-dot.on { width: 28px; background: rgba(255,255,255,.16); }
.io-dot .fill { position: absolute; inset: 0; width: 0; border-radius: 999px; background: var(--io-grad); }
.io-dot.on .fill { animation: ioFill var(--dur, 4s) linear forwards; }
@keyframes ioFill { to { width: 100%; } }
/* 사용자가 조작하면 자동 전환 중지 → 채워진 상태로 고정 */
.io.manual .io-dot.on .fill { animation: none; width: 100%; }
.io-hint { font-size: 12px; color: var(--io-muted); letter-spacing: -.2px; min-height: 16px; }
@media (prefers-reduced-motion: reduce) {
  .io-slide.act .io-el, .io-slide.act .io-pop { animation-duration: .01s; animation-delay: 0s; }
  .io-slide.leaving { animation-duration: .01s; }
  .io-dot.on .fill { animation: none; width: 100%; }
}
@media (max-height: 660px) {
  .io-h { font-size: 25px; } .io-sub { font-size: 14.5px; }
  .io-figure img { max-height: 24vh; } .io-slide { gap: 11px; padding-top: 52px; }
}
/* 영상 모달 */
.io-modal { position: fixed; inset: 0; z-index: 9500; background: rgba(5,5,9,.9); display: none;
  align-items: center; justify-content: center; padding: 20px; backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px); }
.io-modal.show { display: flex; }
.io-modal-in { width: 100%; max-width: 520px; animation: ioUp .32s ease forwards; color: #f4f5f7; }
.io-modal-bar { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 10px; }
.io-modal-ti { font-size: 14.5px; font-weight: 800; letter-spacing: -.3px; }
.io-x { background: rgba(255,255,255,.09); border: 1px solid rgba(255,255,255,.12); color: #f4f5f7;
  font-family: inherit; font-size: 15px; font-weight: 800; width: 34px; height: 34px; border-radius: 50%; cursor: pointer; line-height: 1; }
/* OT 영상 실측 16:9 (비메오 oEmbed 426×240). 임베드 코드의 padding 75% 는 실제 비율과 다르다 */
.io-frame { position: relative; width: 100%; aspect-ratio: 16/9; border-radius: 16px; overflow: hidden; background: #000;
  border: 1px solid rgba(255,255,255,.12); box-shadow: 0 22px 56px rgba(0,0,0,.6); }
.io-frame iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.io-soon { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 9px; background: #13131a; text-align: center; padding: 20px; }
.io-soon .t { font-size: 16px; font-weight: 800; letter-spacing: -.4px; }
.io-soon .d { font-size: 13px; color: var(--io-sub); line-height: 1.7; word-break: keep-all; }
.io-mnote { margin: 10px 2px 0; font-size: 11.5px; color: var(--io-muted); line-height: 1.6; word-break: keep-all; }
/* 인트로는 어두운 오버레이라 앱의 밝은 보조 버튼(.btn--ghost)이 하얗게 떠서
   주 CTA(주황)와 시선을 다툰다 → 이 안에서만 어두운 톤으로 낮춘다. */
.io-cta .btn--ghost {
  background: rgba(255,255,255,.08); color: #f4f5f7; border: 1px solid rgba(255,255,255,.18);
}
.io-cta .btn--ghost:hover:not(:disabled) { background: rgba(255,255,255,.14); }

/* 🧪 DEV 검수 콘솔 — 가상 시각 띠(views/_layout.njk). 검수 계정에 가상 시각이 걸렸을 때만 그려진다. */
.qa-clock-bar {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px;
  padding: 6px 16px; font-size: 13px; line-height: 1.4;
  background: var(--color-warning-bg); color: var(--color-warning);
  border-bottom: 1px solid var(--color-line);
}
.qa-clock-bar__btn {
  font: inherit; font-size: 12px; padding: 2px 8px; border-radius: 6px; cursor: pointer;
  background: var(--color-surface); color: var(--color-ink-soft);
  border: 1px solid var(--color-line); text-decoration: none;
}

/* ═══ Day5 진단 3기 개편 (2026-10-08) ═══════════════════════════════════════
   시트 '3기_진단_화면명세' + 데모 HTML. 색은 기존 토큰만 쓴다(데모의 #eb682b 대신
   --color-brand-500) — 이 앱 전체와 같은 주황이어야 한다. */

/* 작은 오렌지 머리글("DAY 5 완료" · "질문 1") */
.final-done__eyebrow { font-size: 13px; font-weight: 800; letter-spacing: 0.04em; color: var(--color-brand-600); }

/* 완료 화면 — 하단 고정 CTA 에 마지막 요소가 가리지 않게 아래를 비운다(CTA 높이 + 안전영역). */
.final-done { padding-bottom: calc(96px + env(safe-area-inset-bottom)); }

/* 진단 안내 배너 — 완료 화면 맨 위. 광고 배너가 아니라 "다음에 할 일" 예고라 차분하게. */
.diag-banner {
  padding: var(--space-4) var(--space-5);
  border-radius: var(--radius-lg);
  background: var(--color-ink); color: #fff;
}
.diag-banner__title { font-size: 16px; font-weight: 800; }
.diag-banner__title::before { content: '🧭 '; }
.diag-banner__body { margin-top: var(--space-1); font-size: 14px; line-height: 1.5; color: rgb(255 255 255 / 80%); }

/* 화면 안 수료증(완주자만). /finish 의 A4 .cert 는 너무 길어 이 화면엔 압축판을 둔다. */
.cert-mini {
  position: relative;
  padding: var(--space-6) var(--space-5);
  border-radius: var(--radius-xl);
  background: linear-gradient(180deg, var(--color-brand-050) 0%, var(--color-surface) 100%);
  border: 1px solid var(--color-brand-100);
  text-align: center;
}
.cert-mini::after {
  content: ''; position: absolute; inset: 8px;
  border: 1.5px solid var(--color-brand-100); border-radius: var(--radius-lg);
  pointer-events: none;
}
.cert-mini__top { display: flex; justify-content: space-between; font-size: 12px; font-weight: 800; color: var(--color-brand-700); }
.cert-mini__lead { margin-top: var(--space-4); font-size: 13px; color: var(--color-ink-soft); }
.cert-mini__title { margin-top: var(--space-2); font-family: Georgia, 'Times New Roman', serif; font-size: 24px; font-weight: 700; }
.cert-mini__name { margin-top: var(--space-3); font-size: 17px; font-weight: 800; }

/* 2칸 요약(완료한 미션 · 수강 리워드) */
.stat-pair {
  display: grid; grid-template-columns: 1fr 1fr;
  border: 1px solid var(--color-line); border-radius: var(--radius-xl);
  background: var(--color-surface);
}
.stat-pair__cell { display: flex; flex-direction: column; align-items: center; gap: var(--space-1); padding: var(--space-4); }
.stat-pair__cell + .stat-pair__cell { border-left: 1px solid var(--color-line); }

/* 하단 고정 CTA — .bottom-action(안전영역 포함) 위에 얹는다. 위쪽은 흰 페이드로 본문과 잇는다. */
.float-cta { border-top: 0; background: linear-gradient(180deg, rgb(255 255 255 / 0%) 0%, rgb(255 255 255 / 96%) 28%); backdrop-filter: none; padding-top: var(--space-6); }
.float-cta__btn { position: relative; gap: var(--space-2); box-shadow: 0 8px 20px rgb(254 100 0 / 28%); }
/* '약 1분 소요' 말풍선 — 버튼 위 가운데에 걸치고 천천히 둥실(2026-10-15 와니 2번: 진단 버튼 클릭률).
   🔑 위치(translateX -50%)와 움직임을 한 transform 에 같이 둔다 — 키프레임이 transform 을 덮어쓰면
      가운데 정렬이 풀린다. 자리는 .float-cta 의 padding-top(space-6)이 이미 비워 둔다. */
.float-cta__tag {
  position: absolute; left: 50%; top: -13px;
  transform: translateX(-50%);
  padding: 3px var(--space-3); border-radius: var(--radius-pill);
  border: 1.5px solid var(--color-brand-500);
  background: #fff; color: var(--color-brand-700);
  font-size: 12px; font-weight: 800; line-height: 1.4; white-space: nowrap;
  box-shadow: 0 2px 6px rgb(254 100 0 / 18%);
  animation: float-cta-bob 2.4s ease-in-out infinite;
}
/* 꼬리 — 테두리색 삼각형 위에 흰 삼각형을 겹쳐 테두리 있는 꼬리로. */
.float-cta__tag::before,
.float-cta__tag::after {
  content: ''; position: absolute; left: 50%; transform: translateX(-50%);
  border-style: solid; border-color: transparent;
}
.float-cta__tag::before { top: 100%; border-width: 6px 6px 0; border-top-color: var(--color-brand-500); }
.float-cta__tag::after { top: calc(100% - 2px); border-width: 5px 5px 0; border-top-color: #fff; }
@keyframes float-cta-bob {
  0%, 100% { transform: translate(-50%, 0); }
  50% { transform: translate(-50%, -4px); }
}
@media (prefers-reduced-motion: reduce) {
  .float-cta__tag { animation: none; }
}

/* 결과 머리 — 어두운 카드(데모). 유형명만 주황으로. */
.diag-hero { background: var(--color-ink); border-color: var(--color-ink); color: #fff; }
.diag-hero__title { display: flex; flex-direction: column; gap: var(--space-1); color: #fff; }
.diag-hero__who { font-size: 18px; font-weight: 700; line-height: 1.4; color: rgb(255 255 255 / 86%); }
.diag-hero__type { font-size: 30px; font-weight: 800; line-height: 1.25; letter-spacing: -0.02em; }
.diag-hero__title em { font-style: normal; color: #ff874f; }
.diag-hero .t-body-l { color: rgb(255 255 255 / 86%); }
.diag-hero__img { display: block; width: 100%; height: auto; border-radius: var(--radius-md); }

/* 추천 훈련 카드(유형별 1개) — 어두운 카드 위 주황 라벨 + 훈련명 + 알아보기 버튼. */
.product-card {
  padding: var(--space-6) var(--space-5) var(--space-5);
  border-radius: var(--radius-xl);
  background: #1d1d21; color: #fff;
}
.product-card__name { font-size: 13px; font-weight: 800; color: #ff8b54; }
.product-card__title { color: #fff; }
.product-card__sub { font-size: 16px; font-weight: 700; color: #c9c9c9; }
.product-card__reason { color: #c9c9c9; }

/* ── Day5 결과 보강(2026-10-15 '서베이 결과_디벨롭') ─────────────────────── */
/* 하단 고정 CTA 가 마지막 문단(고지)을 덮지 않게 — .final-done 과 같은 여백. */
.diag-root { padding-bottom: calc(96px + env(safe-area-inset-bottom)); }
.diag-sticky[hidden] { display: none; }
.diag-hero__headline { font-weight: 700; line-height: 1.5; }
/* 구역 첫 문장(인용·리드) — 본문(t-soft)보다 진하고 굵게만. 세로선은 두지 않는다
   (10-15 사용자: 구역 제목의 액센트 바와 겹쳐 보여 뺐다). */
.diag-quote { font-size: 16px; font-weight: 700; line-height: 1.5; color: var(--color-ink); }
/* 추천 구성 카드 — 기본(흰) · 업그레이드(연한 브랜드). 구성만 칩으로, 가격·기간 없음. */
.plan-card {
  display: flex; flex-direction: column; gap: var(--space-2);
  padding: var(--space-4) var(--space-5);
  border: 1px solid var(--color-line); border-radius: var(--radius-xl);
  background: var(--color-surface);
}
.plan-card--up { background: var(--color-brand-100); border-color: var(--color-brand-100); }
.plan-card__tag { font-size: 12px; font-weight: 800; letter-spacing: 0.04em; color: var(--color-brand-700); }
.plan-card__items { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-1) var(--space-2); font-size: 16px; font-weight: 700; line-height: 1.45; }
.plan-card__plus { color: var(--color-brand-500); font-weight: 800; }
.plan-card__note { font-size: 14px; }
