/* monday9.com — NOIR v2.0 스타일시트.
   값은 css/noir.css(@designer tokens-v2) 토큰만 사용.
   느와르 3규칙: ① 광원 하나 ② 골드는 선·라벨·소면적(밴드 1개 예외) ③ 움직임은 빛의 변화로.
   스크롤 모션 3종만: 배경 패럴랙스 / 순차 페이드업 / 룰 드로잉. 하이재킹·핀고정·스케일 금지. */

* { box-sizing: border-box; margin: 0; padding: 0; }

body {
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
}

ul, ol { list-style: none; }
img { display: block; max-width: 100%; }

a { color: inherit; text-decoration: none; }

/* ---------- 상단 바 ---------- */
.topbar {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 40;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-block: var(--sp-2);   /* 좌우는 공통 컨테이너 규칙 */
  background: linear-gradient(180deg, rgba(7, 8, 11, 0.9) 0%, transparent 100%);
}

.wordmark {
  font-size: var(--fs-label);
  letter-spacing: var(--track-label);
  font-weight: 600;
  white-space: nowrap;   /* 390px에서 2행으로 접히는 것 방지 */
}

.topnav { display: flex; gap: var(--sp-4); }

.topnav a {
  font-size: var(--fs-label);
  letter-spacing: var(--track-label);
  color: var(--fg-mute);
  transition: color var(--dur-fast) var(--ease);
}

.topnav a:hover { color: var(--gold); }

/* ---------- 공통 ---------- */
/* 컨테이너 정렬: 좌우 패딩을 "여백 vs 컨테이너 밖 잔여폭" 중 큰 쪽으로 잡는다.
   면(背)은 화면 끝까지 두고 콘텐츠만 중앙으로 모으므로, 풀블리드 띠(FIGURES)와
   중앙 정렬 섹션이 같은 규칙 하나로 공존한다(v2.1 --container: 1280px).
   모바일은 컨테이너가 화면보다 넓어 max()가 --margin을 택하므로 자동 무효. */
.topbar, .sec, .path, .hero, .band {
  padding-inline: max(var(--margin), calc((100% - var(--container)) / 2));
}

.sec { padding-block: var(--sp-8); }

/* §S — 첫 섹션 상단 235px → 72px. §L-3에서 1.4배를 넣은 이유는 "100svh 풀블리드 히어로 바로 아래에
   작은 라벨이 놓여 시각 무게에 눌린다"였는데, §P·§R로 히어로가 92%에서 끝나고 다음 섹션이 이미
   화면에 보인다. 전환이 시각적으로 예고된 상태라 낙차를 여백으로 만들 필요가 없어졌다 —
   판단이 바뀐 게 아니라 전제가 사라진 것이다. */
.hero + .sec { padding-top: var(--sp-7); }   /* §S 확정 112px — 72px이면 히어로 경계→라벨이 96px로 내려간다 */

.label {
  font-size: var(--fs-label);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--fg-mute);
}

.label.gold { color: var(--gold); }

/* 라벨 앞 짧은 골드 룰 — 레퍼런스 시그니처, 등장 시 좌→우 드로잉 */
.rule-gold {
  display: block;
  width: 56px;
  height: var(--rule-mark);
  background: var(--gold);
  margin-bottom: var(--sp-2);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--dur) var(--ease);
}

.reveal.in .rule-gold { transform: scaleX(1); }

.h2 {
  font-family: var(--font-display);
  font-size: var(--fs-section);
  font-weight: var(--fw-display);
  line-height: var(--lh-tight);
  letter-spacing: var(--track-display);
  margin-top: var(--sp-2);
}

.h3 {
  font-family: var(--font-display);
  font-size: var(--fs-card);
  font-weight: var(--fw-display);
  line-height: var(--lh-tight);
}

.body { font-size: var(--fs-body); line-height: var(--lh-body); max-width: 64ch; }
.body + .body { margin-top: var(--sp-3); }
.caption { font-size: var(--fs-label); letter-spacing: var(--track-label); text-transform: uppercase; color: var(--fg-dim); margin-top: var(--sp-3); }

/* ---------- 순차 페이드업 (24px / 450ms / stagger 80ms) ---------- */
.reveal {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity var(--dur) var(--ease) var(--d, 0ms), transform var(--dur) var(--ease) var(--d, 0ms);
}

.reveal.in { opacity: 1; transform: none; }

/* ---------- 히어로 ---------- */
.hero {
  position: relative;
  /* §R — 히어로 높이를 인물 렌더 높이에서 "파생"시킨다.
     이전에는 92svh 고정이었는데, 히어로는 뷰포트에 비례하고 인물은 44vw 상한에 걸려 있어
     세로로 긴 창일수록 인물이 히어로를 못 채웠다(1240×1920에서 인물 하단 51.7% vs 히어로 92% = 빈 어둠 40%p).
     두 값이 서로 다른 축을 참조하던 구조 문제이므로, 값이 아니라 관계로 고친다.
     · 가로형: 인물 하단이 92svh보다 아래라 92svh가 선택된다(인물은 화면 밖으로 흘러나간다 — 종전과 동일)
     · 세로형: 인물 하단이 위로 올라오므로 그 값이 선택되어 히어로가 인물과 함께 짧아진다
     하한은 따로 쓰지 않는다 — min-height는 콘텐츠 높이보다 작아질 수 없어 그것이 자동으로 바닥이 된다. */
  --portrait-w: min(max(34.9vw, 64vh), 44vw);              /* §H-1·§H-6① 원식 그대로, 정의 위치만 올림 */
  --portrait-top: calc(11.1vh - 0.0700 * var(--portrait-w));
  --portrait-h: calc(1.4995 * var(--portrait-w));          /* 원본 1067×1600 */
  /* §R — 히어로 하단을 인물에서 파생시킨다. 기준점은 "요소 하단"이고, 페이드 소멸점(요소 89%)이 아니다.
     소멸점을 쓰면 히어로가 4.7%p 더 짧아지는 대신, 콘텐츠 높이가 바닥을 만드는 창(좁고 긴 형태)에서
     페이드가 히어로 하단보다 위에서 끝나 빈 띠가 남는다(실측 1024×1536 2.5%p · 900×1600 5.6%p).
     요소 하단을 쓰고 마스크 소멸점을 히어로 하단에 맞춰 파생시키면 그 초과분을 페이드가 흡수한다.
     1920에서는 인물 하단 102.6vh > 92svh라 92svh가 선택되어 가로형 회귀가 없다. */
  --portrait-bottom: calc(var(--portrait-top) + var(--portrait-h));
  min-height: min(92svh, var(--portrait-bottom));
  display: flex;
  flex-direction: column;
  justify-content: flex-start;              /* v2.5 — 텍스트를 인물 얼굴 높이로 올린다 */
  /* 18.5vh → 16vh. 1366×768처럼 세로가 짧은 화면에서 콘텐츠가 92svh를 넘겨 히어로가 94.1%가 되고
     다음 섹션 노출이 5.9vh로 줄던 것을 8vh로 되돌린다. 데스크톱은 헤드라인(잉크 우단 53.0%)과
     인물(실루엣 좌단 66.4%)이 가로로 13.4%p 떨어져 겹침이 0이라, 밴드가 위로 올라가도 얼굴에 닿지 않는다
     — 얼굴 비침범은 겹침이 있는 모바일 구간의 판정 항목이다(§H-6-5와 같은 구분). 모바일은 28vh 유지. */
  /* §S — 하단 48px → 32px. 이 자리는 배경과 인물이 채우므로 "보이는 간격"이 아니고,
     히어로 높이는 대개 §R 파생식이 정해 이 값과 무관하다. 다만 콘텐츠가 바닥을 만드는 창에서는
     이 값이 곧 히어로 높이라, 줄인 만큼 §R-5의 잔여 빈 영역이 함께 줄어든다.
     전역 --sp-5를 낮추지 않고 히어로 선언에서만 한 단계 내린다(다른 섹션 여백 불변). */
  padding-block: 16vh 24px;
  overflow: hidden;
  isolation: isolate;
}

.hero-media { position: absolute; inset: 0; z-index: -1; }

/* §N-4 — 층 분리. 스크롤 패럴랙스는 이 스택 컨테이너가, 켄번즈 줌은 각 슬라이드가 맡는다.
   둘을 한 요소에 걸면 같은 transform 속성을 다투어 나중에 쓴 쪽이 앞의 것을 지운다.
   스크림(.scrim)과 하단 페이드(::after)는 스택 밖 형제라 패럴랙스에 딸려 움직이지 않는다 —
   같이 움직이면 스택이 아래로 밀릴 때 상단에 스크림 없는 띠가 드러난다. */
.hero-stack { position: absolute; inset: 0; will-change: transform; }

.hero-slide {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  /* 128% → 100% (§Q). 128%는 스카이라인 원본 하단 21.9%가 "평균 밝기 9.5의 검은 띠"여서
     잘라낸 값이다. 실사 공간 컷의 같은 구간은 앞줄 좌석과 바닥이라 잘라내면 근경을 버리는 것이 되고,
     계단식 강의실이 "내려다보는 공간"으로 읽히지 않는다. 원본을 덜 자르므로 줌 여유도 커진다.
     이 값이 100%이므로 생성 종횡비 = 히어로 종횡비 그대로다(크롭 비율에 1.28을 곱하지 않는다). */
  object-fit: cover;
  object-position: 50% 0;
  filter: var(--img-noir);
  /* §N-3 줌은 애니메이션이 아니라 "상태"다 — 목표 스케일을 클래스로 주고 뗀다.
     전환 순서가 꼬여도 상태가 어긋나지 않는다.
     §N-8 때문에 "보인다(is-visible)"와 "확대 중이다(is-zooming)"를 분리한다 —
     나가는 컷은 가시성만 빠지고 확대는 페이드 내내 계속되어야 한다. */
  opacity: 0;
  transform: scale(1);
  transform-origin: 50% 50%;     /* 좌측 원점은 텍스트 뒤 배경을 크게 바꿔 가독이 흔들린다 */
  /* transform 전이 0s — is-zooming이 빠지는 순간(이미 투명해진 뒤) 되감김 없이 즉시 리셋된다 */
  transition: opacity var(--hero-fade) linear, transform 0s linear;
}

.hero-slide.is-zooming {
  transform: scale(var(--hero-zoom));
  transition: opacity var(--hero-fade) linear, transform var(--hero-zoom-dur) linear;
}

.hero-slide.is-visible { opacity: 1; }

/* 움직이는 장에만 — 동시에 최대 2장(페이드 중 나가는 컷 + 들어오는 컷)이고 그 외에는 1장이다.
   is-visible에만 걸면 페이드 중인 나가는 컷이 아직 보이는 상태에서 레이어를 잃는다. */
.hero-slide.is-visible,
.hero-slide.is-zooming { will-change: transform, opacity; }

/* 광원 하나 — 좌측 스크림 + 하단 페이드(느와르 문법, v1 그라디언트 금지 폐기) */
.hero-media .scrim { position: absolute; inset: 0; background: var(--scrim-hero); }
/* 히어로 한정 완화: 공용 --scrim-bottom(0.95/60%)은 하단을 완전히 검게 마감해
   방금 살린 도시 야경을 다시 지운다. 캐러셀 캡션용 원값은 토큰에 그대로 둔다. */
.hero-media::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(0deg, rgba(7, 8, 11, 0.75) 0%, transparent 45%);
}

.hero-body {
  position: relative;
  z-index: 1;          /* v2.2 §F-3 — 헤드라인 블록이 인물보다 앞 */
  max-width: 80%;      /* 2행 유지에 필요한 폭 */
}

/* v2.2b §F-4 — 국소 스크림. 글자가 어깨 위로 올라가도 4.5:1을 확보한다.
   블록 폭 기준으로 깔고 우측으로 감쇠시켜 인물 실루엣과의 경계를 만들지 않는다. */
.hero-body::before {
  content: '';
  position: absolute;
  /* §G-8 — 사각형 폐기, 모서리 없는 타원 방사형.
     사각 그라디언트는 히어로 밖으로 늘려 잘라도 "잘리지 않은 변"이 남아 직선으로 드러난다.
     타원 반경을 박스의 78%/62%로 두면 네 변 어디서도 알파가 0에 도달해 모서리가 존재하지 않고,
     크기가 텍스트 블록에 종속되므로 창이 세로로 길어져도 스크림이 따라 커지지 않는다. */
  /* §G-8 개정 — 모서리 없는 형태를 두 축 분리로 만든다.
     타원 단독은 기준 ①(실루엣 상단 +6%p에서 알파 ≤0.03)과 텍스트 덮기가 양립하지 않는다
     (타원은 밴드 좌우 끝에서 알파가 0으로 떨어져 헤드라인 양끝이 비보호).
     세로는 포락선(양끝 0), 가로는 마스크 페이드 — 네 변 모두 0에 도달하고 모서리가 없다. */
  inset: -4vh calc(var(--sp-6) * -1) -4vh calc(var(--margin) * -1);
  z-index: -1;
  background: linear-gradient(180deg,
    rgba(7, 8, 11, 0) 0%,
    rgba(7, 8, 11, 0) 6%,          /* 실루엣 상단(11.1%)+6%p 아래에서 시작 */
    rgba(7, 8, 11, 0.35) 17%,      /* 헤드라인 상단 직전 최대 도달 */
    rgba(7, 8, 11, 0.35) 84%,
    rgba(7, 8, 11, 0) 100%);
  /* §H-6-5 — 데스크톱은 헤드라인(잉크 우단 53.0%)과 인물(실루엣 좌단 58.5%)이 겹치지 않으므로
     인물 위 스크림은 가독 기여가 0이다. 실루엣 좌단 전에 알파 0에 도달시켜 아예 닿지 않게 한다.
     퍼센트 스톱은 박스 폭이 뷰포트마다 달라 흔들리므로 vw로 고정한다. */
  -webkit-mask-image: linear-gradient(90deg, #000 0, #000 40vw, transparent 56vw);
  mask-image: linear-gradient(90deg, #000 0, #000 40vw, transparent 56vw);
  pointer-events: none;
}

.hero-title {
  /* 정장 하이라이트(최악 1.9:1) 위를 획이 스칠 때의 보험. 느와르에서 그림자는 문법이고,
     3대 금지 대상인 "UI 장식용 소프트 섀도"와는 용도가 다르다. */
  text-shadow: 0 2px 12px rgba(7, 8, 11, 0.35);
  font-family: var(--font-display);
  font-size: var(--fs-hero);
  font-weight: var(--fw-display);
  line-height: var(--lh-hero);
  letter-spacing: var(--track-display);
  margin: var(--sp-3) 0 var(--sp-3);
}

/* §J — 서브는 본문이 아니라 데크(deck). 헤드라인 대비 1:4.7~4.8 위계를 유지한다.
   헤드라인 상한이 해제돼 있으므로(§H-4) 서브에도 상한을 두지 않는다 — 한쪽만 걸리면
   2560에서 위계가 1:6.1로 되돌아간다. 폭은 우단이 56vw에서 멈추도록 52vw(좌단 4vw + 52 = 56).
   그 선은 국소 스크림이 0에 도달하는 선이자 실루엣 좌단(58.5%)보다 2.5%p 왼쪽이다. */
.hero-sub {
  /* §J-8 — 색상은 히어로 서브 전용(전역 --fg-mute 불변: PROFILE·카드 본문까지 밝아진다).
     섀도는 보조가 아니라 필수 — 색상 단독은 미달 4.0%, 섀도 단독 6.4%, 조합에서만 0%. */
  color: #D5D9DD;
  /* §J-12 발동 — 히어로 90svh로 서브 밴드가 45.4~70.4%까지 넓어지며 인물의 밝은 구간이 더 들어와
     모바일 최악이 4.52:1(기준 4.5, 여유 0.02)이 됐다. 0.45면 원본 상한이 266이라
     인물 밝기와 무관하게 안전해진다. 헤드라인은 0.35 유지 — 미달 여유가 이미 크다. */
  text-shadow: 0 2px 12px rgba(7, 8, 11, 0.45);
  font-size: max(1.1875rem, 1.6vw);   /* §J 확정 — 모바일 하한 19px(현행 15.2px 대비 +25%) */
  max-width: 52vw;
}

/* ---------- THE PATH 캐러셀 (클릭 + 화살표 + 키보드 / 크로스페이드) ---------- */
.path { padding-block: var(--sp-8); }

.stage { margin-top: var(--sp-5); }

/* 캡션·화살표의 위치 기준. 데스크톱에선 둘 다 absolute라 프레임 높이 = 이미지 높이. */
.stage-frame { position: relative; }

.stage-media {
  position: relative;
  aspect-ratio: 16 / 9;   /* 원본 자산 비율(1280×720) — 아래 프레임 규칙과 단일 출처 */
  background: var(--bg-raise);
  overflow: hidden;
}

.slide {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity var(--dur) var(--ease-veil); /* 크로스페이드 450ms — 이동·스케일 금지 */
}

.slide.active { opacity: 1; }

.slide img { width: 100%; height: 100%; object-fit: cover; filter: var(--img-noir); }

.slide-placeholder {
  width: 100%; height: 100%;
  background: linear-gradient(135deg, #14171D 0%, #0C0E12 60%, #07080B 100%);
}

.stage-veil { position: absolute; inset: 0; background: var(--scrim-bottom); pointer-events: none; }

.stage-caption {
  position: absolute;
  left: var(--sp-5);
  bottom: var(--sp-5);
  right: var(--sp-8);
}

.slide-year {
  font-size: var(--fs-label);
  letter-spacing: var(--track-label);
  color: var(--gold);
}

.slide-title {
  font-family: var(--font-display);
  font-size: var(--fs-section);
  font-weight: var(--fw-display);
  line-height: var(--lh-tight);
  letter-spacing: var(--track-display);
  margin: var(--sp-1) 0;
}

.slide-caption { color: var(--fg-mute); max-width: 56ch; }

.stage-controls { display: contents; }   /* 데스크톱: 래퍼는 레이아웃에 관여하지 않음 */

.nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 48px; height: 48px;
  background: rgba(7, 8, 11, 0.55);
  border: var(--rule-hair) solid var(--rule);
  border-radius: var(--radius);   /* v2.1 — 직각 */
  color: var(--fg);
  font: inherit;
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}

/* v2.1 — 좌측은 아웃라인, 우측만 주홍 면 + 잉크 화살표(레퍼런스 문법) */
.nav.prev { left: var(--sp-3); }
.nav.prev:hover { background: rgba(7, 8, 11, 0.85); border-color: var(--gold); color: var(--gold); }

.nav.next {
  right: var(--sp-3);
  background: var(--gold);
  border-color: var(--gold);
  color: var(--on-gold);
}

.nav.next:hover { background: var(--gold-bright); border-color: var(--gold-bright); }

.thumbs {
  display: flex;
  gap: var(--gutter);
  margin-top: var(--sp-3);
  overflow-x: auto;
  scrollbar-width: none;
}

.thumbs::-webkit-scrollbar { display: none; }

.thumb {
  flex: 1 1 0;      /* v2.1 QA — 컨테이너 폭을 슬라이드 수만큼 등분해 8개가 모두 들어온다 */
  min-width: 0;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  text-align: left;
  opacity: 0.5;
  transition: opacity var(--dur) var(--ease); /* 크기 변화 금지 — opacity·보더만 */
}

.thumb.active { opacity: 1; }

.thumb img, .thumb-placeholder {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  filter: var(--img-noir);
  border: var(--rule-hair) solid transparent;
  background: var(--bg-raise);
}

.thumb.active img, .thumb.active .thumb-placeholder { border-color: var(--gold); }

.thumb-year {
  display: block;
  margin-top: 6px;
  font-size: var(--fs-label);
  letter-spacing: var(--track-label);
  color: var(--fg-dim);
}

.thumb.active .thumb-year { color: var(--fg); }

/* ---------- FIGURES 밴드 (v2.1 §E-1: 주홍 풀블리드 유지 + 높이로 통제) ----------
   색을 빼는 대신 면적을 줄인다 — 주홍은 골드보다 전진감이 강해
   같은 높이(112px)면 "빛의 띠"가 아니라 덩어리가 된다. */
.band {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;   /* v2.1 QA — 5등분 셀은 잉크가 셀 좌측에 몰린다. 항목을 양끝까지 분산 */
  align-items: center;
  gap: var(--sp-2) var(--gutter);
  min-height: var(--sp-6); /* v2.1 — 112px → 72px 축소 */
  background: var(--gold);
  color: var(--on-gold); /* 주홍 면 위 텍스트는 잉크색 필수(5.42:1 / 흰색 3.21:1 미달) */
  padding-block: var(--sp-1);   /* 면은 풀블리드, 안쪽 수치만 컨테이너 정렬 */
}

.band-num {
  display: block;
  font-family: var(--font-display);
  font-size: var(--fs-card);   /* v2.1 — 밴드 72px 축소에 맞춰 한 단 하향 */
  font-weight: var(--fw-display);
  line-height: 1;
}

.band-label {
  display: block;
  margin-top: var(--sp-1);
  font-size: var(--fs-label);
  letter-spacing: var(--track-label);
  opacity: 0.75;
}

/* ---------- START HERE 4카드 ---------- */
.cards {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--gutter);
  margin-top: var(--sp-6);
}

.card {
  background: var(--bg-raise);
  border-top: var(--rule-mark) solid var(--gold);
  padding: var(--sp-4);
  min-height: 220px;
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}

.card-idx { font-size: var(--fs-label); letter-spacing: var(--track-label); color: var(--gold); }
.card-note { margin-top: auto; font-size: var(--fs-label); letter-spacing: var(--track-label); color: var(--fg-dim); }

/* ---------- 2컬럼 소개 ---------- */
.intro {
  display: grid;
  grid-template-columns: 4fr 8fr;
  gap: var(--gutter);
  background: var(--bg-deep);
}

.titles { margin-top: var(--sp-5); border-top: var(--rule-hair) solid var(--rule); }

.titles li {
  padding: var(--sp-2) 0;
  border-bottom: var(--rule-hair) solid var(--rule);
  font-size: var(--fs-small);
  color: var(--fg-mute);
}

.titles li:first-child { color: var(--fg); }

/* ---------- 저서 (원색 유지 — 느와르 예외, 골드 밴드와 같은 화면 금지) ---------- */
.books { margin-top: var(--sp-5); display: grid; gap: var(--sp-4); max-width: 780px; }

.books li { display: grid; grid-template-columns: 92px 1fr; gap: var(--sp-4); align-items: center; }

.books img { width: 100%; box-shadow: var(--noir-shadow); }

.book-title {
  display: block;
  font-family: var(--font-display);
  font-size: var(--fs-card);
  font-weight: var(--fw-display);
  letter-spacing: 0.02em;
}

.book-sub { display: block; margin-top: 4px; font-size: var(--fs-small); color: var(--fg-mute); }

/* ---------- 연락 ---------- */
.contact { background: var(--bg-deep); }

.email {
  display: inline-block;
  margin: var(--sp-3) 0 var(--sp-5);
  font-family: var(--font-display);
  font-size: var(--fs-section);
  font-weight: var(--fw-display);
  letter-spacing: var(--track-display);
  transition: color var(--dur-fast) var(--ease);
}

.email:hover { color: var(--gold-bright); }

.links { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: var(--sp-4); border-top: var(--rule-hair) solid var(--rule); padding-top: var(--sp-4); }
.links li .label { display: block; margin-bottom: 4px; }
.links a:hover { color: var(--gold); }
.links .arrow { display: inline-block; transition: transform var(--dur-fast) var(--ease); }
.links a:hover .arrow { transform: translateX(4px); }

.colophon { margin-top: var(--sp-6); font-size: var(--fs-label); letter-spacing: var(--track-label); color: var(--fg-dim); }


/* ---------- 히어로 인물 누끼 (§5.0 층 구조: 배경 → 스크림 → 인물 → 타이포) ---------- */
/* v2.2 §F-2 — 전신 100vh 풀블리드 폐기, 1:1 상반신으로 축소.
   1:1 크롭이라 높이가 곧 폭이므로 32vw 상한이 "인물 폭 ≤ 화면 34%" 기준을 보장한다. */
/* v2.5 §F-8 — bust(1:1) 폐기, 전신(2:3) 복귀 + 상단 정렬.
   bust로는 높이를 키우면 폭이 같이 커져(1:1) 인물이 화면을 지배한다.
   전신은 같은 높이에서 폭이 2/3라 "세로를 채우되 폭은 40% 이하"가 성립한다.
   머리 상단이 이미지의 3.2% 지점이므로 top 6vh면 머리가 화면 8%대에서 시작한다. */
.hero-portrait {
  /* §H-1 — 기준축은 vw(목표값이 전부 폭 기준). 머리 위치만 vh라 그 차이를 보정한다.
     §H-2 하한 64vh — vw 단독이면 16:10 창에서 인물이 짧아져 허벅지 단면이 화면 안에 노출된다.
     right 식은 우측 여백이 아니라 실루엣 "좌단"을 58.5%에 고정한다(헤드라인과의 간극 불변). */
  /* §H-6① — 64vh 하한이 세로형에서 폭주한다(981×1114에서 64vh = 72.7vw → 실루엣 우단 105%).
     44vw 상한을 겹쳐 어떤 비율에서도 화면 밖으로 잘리지 않게 한다.
     §R — --portrait-w·--portrait-top은 .hero에서 정의해 상속받는다. 히어로 높이가 이 값들에서
     파생되므로 정의가 두 곳에 갈리면 두 값이 어긋난다(같은 식을 두 번 쓰지 않는다). */
  position: absolute;
  width: var(--portrait-w);
  height: auto;
  /* §M(@designer·@main 확정) — 우측 여백 과다로 인물을 8vw 오른쪽 평행이동(실루엣 우단 81.8% → 89.8%).
     7vw(우단 88.8%/간극 10.4%p) 안이 나왔다가 "간극은 빈 공간이 아니라 배경이 보이는 구간"이라는
     판단으로 8vw·간극 13.5%p 현행 유지로 확정됐다. 1%p 차이로 다시 만지지 않는다.
     41.5%(좌단 앵커)나 --portrait-w는 건드리지 않는다 — 그 값을 만지면 인물 크기가 함께 변한다. */
  right: calc(41.5% - 0.809 * var(--portrait-w) - 8vw);
  top: var(--portrait-top);
  bottom: auto;
  z-index: 0;                                     /* 배경(-1)보다 앞, 헤드라인(1)보다 뒤 */
  display: flex;
  align-items: flex-start;
  /* §H-6② — 하단 크롭 단면 상시 마스크. 조건 분기가 필요 없다:
     가로형은 인물 하단이 102.6%라 페이드 구간이 화면 밖(무변화), 세로형에서만 작동한다. */
  /* §P-3·§R — 소멸 지점을 "히어로 하단"에 맞춰 파생시킨다. 고정 89%는 히어로가 92svh일 때만 맞는 값이고,
     히어로가 인물이나 콘텐츠에 따라 줄면 다리가 화면 안에서 먼저 사라져 같은 빈 띠가 다시 생긴다.
     아래 식은 요소 상단부터 히어로 하단까지의 실제 길이라 어느 경우에도 히어로 하단에서 알파가 0이 된다.
     페이드 길이 8vh 고정 — 더 길게 잡으면 다리가 더 일찍 지워진다. */
  --fade-end: calc(min(92svh, var(--portrait-bottom)) - var(--portrait-top));
  -webkit-mask-image: linear-gradient(180deg, #000 calc(var(--fade-end) - 8vh), transparent var(--fade-end));
  mask-image: linear-gradient(180deg, #000 calc(var(--fade-end) - 8vh), transparent var(--fade-end));
}

.hero-portrait img {
  width: 100%;
  height: auto;
  object-fit: contain;
  object-position: top right;
  filter: var(--img-noir-soft);
}

/* ---------- 히어로 버튼 (v2.1: 주 = 주홍 면 + 잉크 텍스트 / 보조 = 아웃라인, 직각) ---------- */
.hero-actions { display: flex; gap: var(--sp-2); margin-top: var(--sp-4); flex-wrap: wrap; }

.btn {
  display: inline-block;
  padding: 14px 28px;
  border-radius: var(--radius);   /* v2.1 — 필형 폐기, 직각 사각형 */
  font-size: var(--fs-label);
  letter-spacing: var(--track-label);
  border: var(--rule-hair) solid transparent;
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}

.btn-gold { background: var(--gold); color: var(--on-gold); }
.btn-gold:hover { background: var(--gold-bright); }

.btn-outline { border-color: var(--rule-strong); color: var(--fg); }
.btn-outline:hover { border-color: var(--gold); color: var(--gold); }

/* ---------- ⑥ 캐러셀 슬라이드 프레임 (@designer QA P1) ----------
   높이만 제한하면 폭은 컨테이너 전폭이라 프레임이 3~5:1로 늘어나고,
   object-fit: cover가 16:9 원본의 상하를 잘라 소실점 구도·광원이 사라진다.
   → 원본 비율(16:9)을 유지한 채 "높이 상한에서 역산한 폭"을 명시해 중앙 정렬한다.
   폭을 명시해야 height = width * 9/16 로 결정되어 레터박스도 크롭도 생기지 않는다. */
.stage-frame {
  width: min(100%, calc(min(62vh, 560px) * 16 / 9));
  margin-inline: auto;
}

.stage-media {
  aspect-ratio: 16 / 9;
  height: auto;
  width: 100%;
}

/* 진행 바 (@designer QA P2) — 스펙 §5 인디케이터 3종 중 누락분.
   썸네일 스트립 아래 헤어라인 위를 골드가 채워 나간다. */
.progress {
  position: relative;
  height: var(--rule-hair);
  margin-top: var(--sp-3);
  background: var(--rule);
}

.progress-bar {
  position: absolute;
  left: 0; top: 0; bottom: 0;
  background: var(--gold);
  transition: width var(--dur) var(--ease);
}

/* ============================================================
   모바일 v2.4 (@designer §G) — 원칙: 겹침 0.
   데스크톱의 "겹쳐서 만드는 깊이감" 문법을 전부 해제하고 세로 스택 + 명시적 간격으로 간다.
   좁은 폭에서 겹침은 깊이가 아니라 사고다.
   ============================================================ */
@media (max-width: 768px) {
  /* --- 히어로: 인물을 텍스트 아래로 내리고 배경 확대 해제 --- */
  /* v2.6 §G-5 — 겹침 0 원칙의 유일한 예외. 좁은 폭에선 좌우로 어긋나게 둘 수 없으므로
     텍스트는 상단, 인물은 하단으로 "세로로" 어긋나게 배치해 얼굴을 피한다. */
  /* §P — 90svh. 레터박스를 없앤 인물이 bottom:0으로 붙어 다리 끝 = 히어로 하단이 되고,
     하단 빈 어둠이 0이 된다. 상단 패딩 28vh는 그대로 — 그 값이 §G-6(텍스트를 내려 얼굴을 피함)의 기준이다. */
  .hero { min-height: 90svh; justify-content: flex-start; padding-block: 28vh var(--sp-5); }
  .hero-body { max-width: 100%; }
  /* 배경 확대 불필요 — @desginer-info 검증: 지면선 아래는 원본에 디테일이 없어(99.3%가 밝기 20 미만)
     CSS 확대든 크롭이든 검은 띠가 남는다. 진짜 원인은 인물 하단 하드컷이므로 페이드로 해결한다. */
  /* 컷별 가로 크롭 위치 — 모바일 전용. data.js의 posMobile이 인라인 --pos-mobile로 들어오고,
     값이 없는 컷은 기본값 50% 0(중앙)이 그대로 쓰인다. */
  .hero-slide { height: 100%; object-position: var(--pos-mobile, 50% 0); }
  /* 패럴랙스만 비활성 — 스택에 걸어야 한다. 슬라이드에 transform:none을 걸면 켄번즈 줌까지 죽는다. */
  .hero-stack { transform: none !important; }
  /* v2.6b — 사용자 지시: 인물을 더 작게 + 헤드라인 "뒤쪽"에 겹치게.
     헤드라인 밴드가 화면 14~25.8%라 머리가 그 안으로 들어와야 겹침이 생기고,
     그러려면 바닥 밀착을 포기해야 한다(밀착 상태에서 머리를 올리려면 인물을 오히려 키워야 함).
     대신 하단을 마스크로 페이드시켜 "잘린 단면"이 보이지 않게 한다. */
  /* v2.7b §G-6 — 배치 순서를 뒤집는다: 인물이 위, 텍스트가 아래.
     인물은 얼굴이 최상단이라 "올려서 겹치기"와 "얼굴 비침범"을 같은 방향으로 풀 수 없다.
     텍스트를 내리면 헤드라인이 어깨·상체 뒤를 지나 겹치고, 얼굴·셔츠(밝아서 위험한 구간)는
     텍스트 위에 남아 침범이 구조적으로 불가능해진다. */
  .hero-portrait {
    /* B: 인물 하단 = 히어로(배경) 하단. 데스크톱과 같은 원리로 단면이 화면 밖에서 끝난다.
       하단 정렬을 먼저 만족시킨 뒤, 헤드라인과 겹치도록 높이를 키운다(390 폭 상한 내). */
    /* 사용자 지시 — 이 해상도에서는 인물이 작은 편이 낫다. 가시 실루엣 78.3% → 64.6%로 복귀.
       레터박싱(전역 max-width:100% + contain)이 걸린 상태가 그 크기이므로 그대로 두고,
       그 대가인 하단 단면(85.2%)은 페이드 마스크로 도시 어둠에 잠기게 한다. */
    /* §P — 요소가 84vh인데 그려지는 이미지는 69.3vh뿐이라 나머지 14.7vh가 요소 안의 투명 여백이었다.
       그 여백이 "다리 끝 아래 빈 어둠"의 정체다(히어로가 커서가 아니다).
       폭 기준(width:100% + height:auto)으로 바꾸면 요소가 그려진 이미지에 딱 맞는다 —
       폭이 390px 그대로라 렌더 크기·실루엣 폭 64.6%는 불변이고, bottom:0이 다리 끝을 히어로 하단에 붙인다. */
    position: absolute;
    top: auto;
    bottom: 0;
    right: 0;
    /* 사용자 지시 — 우측으로 더 붙임. right 음수는 요소 폭을 늘려 인물까지 커지므로(64.6% → 75.6%)
       레이아웃에 영향이 없는 transform으로 평행이동만 한다. 실루엣 우단 83.7% → 화면 끝. */
    transform: translateX(16.3%);
    width: 100%;
    height: auto;
    align-items: flex-end;
    opacity: 0.9;
    /* 레터박스가 사라져 요소 = 그려진 이미지가 됐으므로 마스크 스톱을 이미지 좌표로 환산한다.
       옛 값(요소 68%→82.5%)은 이미지 기준 82.4%→100%였다 — 같은 구간을 그대로 유지한다. */
    -webkit-mask-image: linear-gradient(180deg, #000 82%, transparent 100%);
    mask-image: linear-gradient(180deg, #000 82%, transparent 100%);
  }
  /* 폭 기준으로 그린다 — height:100%였을 때 전역 max-width가 걸려 contain 레터박스가 생겼다.
     렌더 결과(390 × 585px = 실루엣 64.6%)는 이전과 동일하고, 요소 박스만 그 크기에 맞춰진다. */
  .hero-portrait img { width: 100%; height: auto; }
  /* §G-8 — 모바일도 동일 원칙. 이전 사각 띠는 상단 모서리가 화면 20.5%(이마 높이)에
     최대 불투명도로 시작해 직선이 드러났고, 같은 사각형이 세로 긴 창에서 인물 상단 2/3를 덮었다. */
  .hero-body::before {
    display: block;
    /* 값은 §G-8 합격 기준(① 상단 밴드 알파 ≤0.03 ② 실루엣 덮음 ≤35%) 아래에서
       겹침부 평균 알파를 최대화하도록 수치 탐색으로 잡았다. */
    inset: -2vh calc(var(--margin) * -1) -2vh calc(var(--margin) * -1);
    background: linear-gradient(180deg,
      rgba(7, 8, 11, 0) 0%,
      rgba(7, 8, 11, 0) 10%,       /* 실루엣 상단(19.9%)+6%p 아래에서 시작 */
      rgba(7, 8, 11, 0.35) 22%,    /* 헤드라인 상단(30.5%) 직전 최대 도달 */
      rgba(7, 8, 11, 0.35) 75%,
      rgba(7, 8, 11, 0) 100%);
    /* 가로 마스크 해제 — 모바일은 §H-6-5대로 스크림이 인물 위에 있어야 하고(겹침 12~30%p),
       좌우가 화면 가장자리까지 나가 있어 화면 안에 모서리가 없다.
       선언을 빼면 베이스(데스크톱)의 56vw 마스크가 상속되므로 반드시 none으로 명시한다. */
    -webkit-mask-image: none;
    mask-image: none;
  }
  .hero-actions .btn { padding: 12px 20px; }
  .hero-sub { max-width: 100%; }   /* §J — 모바일은 실루엣 좌단이 1.9%라 인물을 피할 공간이 없다. 전폭 사용 */
  /* §J-9 — 모바일은 데이터 개행을 무시하고 자동 랩(헤드라인과 동일 원칙).
     37자로 쪼개 명시 개행하면 조각 낭비가 누적돼 9행이 되고, 자동 랩이면 7행에서 끝난다. */
  .hero-sub br { display: none; }

  /* --- 캐러셀: 오버레이 전면 해제, 세로 스택 --- */
  .stage-frame { width: 100%; }
  .stage-media {
    width: 100%;
    height: auto;                                /* vh 금지 — 주소창 변화로 비율이 깨진다 */
    aspect-ratio: 16 / 9;
  }
  .stage-veil { display: none; }                 /* 캡션이 이미지 밖으로 나가므로 베일 불필요 */
  .stage-caption {
    position: static;                            /* 오버레이 → 이미지 아래 정적 배치 */
    margin-top: var(--sp-3);
  }
  .slide-title { font-size: clamp(1.5rem, 7vw, 2rem); }
  .slide-caption { font-size: var(--fs-small); }

  .nav {                                          /* 이미지 위 absolute → 하단 컨트롤 행 */
    position: static;
    transform: none;
    width: 48px; height: 48px;                    /* 터치 타깃 44px 이상 */
  }
  .stage-controls { display: flex; gap: var(--sp-2); margin-top: var(--sp-3); }   /* display:contents 해제 → 실제 행 */

  /* 썸네일: 가로 스크롤 → 4열 × 2행 그리드(8장이 모두 보여야 인덱스가 성립) */
  .thumbs {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: var(--sp-2);
    overflow: visible;
  }
  .thumb { flex: none; width: 100%; }
  .thumb-year { font-size: 0.625rem; letter-spacing: 0.12em; }

  /* --- 나머지 섹션 --- */
  .sec { padding-block: var(--sp-6); }
  /* §S — 모바일 72px → 48px. 데스크톱과 폭을 다르게 잡는다: 모바일은 히어로가 이미 짧고
     라벨까지의 실거리가 데스크톱보다 짧아 같은 비율로 줄이면 붙어 보인다. */
  .hero + .sec { padding-top: var(--sp-5); }
  .path { padding-block: var(--sp-6); }
  .band {                                         /* 2열 × 3행, 높이 auto */
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    min-height: 0;
    padding-block: var(--sp-4);
    row-gap: var(--sp-3);
  }
  .cards { grid-template-columns: 1fr; }
  .intro { grid-template-columns: 1fr; }
  /* §G-2 — 표지 3권은 가로 1행 유지(작아도 나란해야 "3권"으로 읽힌다) */
  .books { grid-template-columns: repeat(3, 1fr); gap: var(--sp-3); }
  .books li { grid-template-columns: 1fr; gap: var(--sp-2); align-items: start; }
  .book-title { font-size: var(--fs-small); }
  .book-sub { display: none; }
  .email { font-size: clamp(1.125rem, 5.6vw, 1.75rem); word-break: break-all; }  /* 거대 타이포 금지 */
  .links { grid-template-columns: 1fr; }
  .topnav { gap: 10px; }
  .topnav a { font-size: 0.625rem; letter-spacing: 0.1em; }
  /* 터치 타깃 44px — 작은 라벨 링크는 글자 크기 대신 패딩으로 확보한다 */
  .topnav a, .links a, .email { display: inline-block; min-height: 44px; line-height: 44px; }
  .links li .label { margin-bottom: 0; }
  .topbar { padding-block: 0; }
}

/* 태블릿(600~768) — 인물이 화면 우측 끝에 밀착해 가운데가 비어 보인다는 사용자 지적 반영.
   좌측으로 당기면 390·430과 같은 구조(얼굴은 텍스트 위, 정장만 헤드라인 뒤)가 이 폭에서도 성립한다.
   ※ 모바일 블록 뒤에 두어야 우선순위가 유지된다. */
@media (min-width: 600px) and (max-width: 768px) {
  /* §G-7 — 20%. 16%는 겹침 1.4%p라 폰트 폴백(Times New Roman에서 잉크 우단 51.4%)에서
     겹침이 음수로 뒤집힌다. 20%면 폴백 하한에서도 3.8%p가 남는다. */
  .hero-portrait { right: 20%; }
  /* §P는 폰(≤600) 조건에서 세운 값이다. 이 구간에 그대로 적용하면 폭 기준 크기가 폭발한다 —
     768폭에서 인물 높이가 112vh가 되어 머리가 화면 위로 잘리고 실루엣이 48.3% → 64.7%로 커진다.
     이 구간만 이전 기하(84vh 고정 + 레터박싱)를 유지한다. 높이 축소는 @designer 판단 대기. */
  .hero { min-height: 100svh; }
  .hero-portrait { width: auto; height: 84vh; }
  .hero-portrait img { width: auto; height: 100%; }
}

/* v3.0 데스크톱 구도 고정 — 히어로 텍스트만 컨테이너 중앙 정렬에서 좌측 마진 기준으로 바꾼다.
   중앙 정렬이면 넓은 화면에서 잉크 우단이 53.8% → 66.7%로 밀려 레퍼런스 구도가 깨진다.
   폰트 상한(9.3rem)도 해제해야 2560px에서 잉크 우단이 40.3%로 무너지지 않는다. */
@media (min-width: 769px) {
  /* §H-3 최종 — 전역 컨테이너 92vw, 히어로 예외 폐기.
     헤더·히어로·캐러셀·PRACTICE 네 기준선이 계산이 아니라 구조적으로 0px 일치한다.
     (1280 안은 검토·폐기: 2560에서 콘텐츠 2355px·카드 589px 우려가 있었으나 §H-5 카드 상한으로 해소,
      대신 1280 안에서는 섹션−히어로 좌단이 2560에서 568px 튄다.) */
  .hero-title { font-size: max(2.75rem, 7.6vw); }
}

/* §H-5 현재 유효 — 92vw에서는 카드 그리드만 무한히 늘어나므로 고유 상한을 준다.
   캐러셀 996px · PROFILE 64ch · 저서 780px과 같은 패턴. 중앙 정렬 금지(좌단은 컨테이너에 붙임).
   실측: 2560에서 그리드 1800px · 카드 432px(1920의 424px과 사실상 동일). */
.cards { max-width: 1800px; }
