/* ==========================================================================
 * layout.css — 섹션 / 그리드 / 컴포넌트
 * ==========================================================================
 * 규칙
 *  · 의미 기반 클래스만 쓴다. Tailwind 유틸리티 이름 금지.
 *  · 색·간격·타이포는 tokens.css 의 커스텀 프로퍼티만 쓴다.
 *  · 미디어 쿼리는 768px 하나. 파일 맨 아래 @media 블록 한 곳에 모아 뒀다.
 *  · CONTRACT 가 data-* 훅을 정해 둔 구조 요소는 클래스와 훅을 함께 선택자에
 *    적어 뒀다. HTML 이 둘 중 하나만 달아도 레이아웃이 무너지지 않는다.
 *  · 리빌/상태 애니메이션은 motion.css 담당. 여기엔 배치만 있다.
 * ========================================================================== */

/* ======================================================================== *
 * 1. 레이아웃 프리미티브
 * ======================================================================== */

/* 좌우 거터를 가진 콘텐츠 폭. 거의 모든 섹션이 이걸 쓴다. */
.wrap {
  width: 100%;
  max-width: var(--content-max);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* 섹션 세로 리듬 */
.section {
  position: relative;
  padding-top: var(--section-pad-top);
  padding-bottom: var(--section-pad-bottom);
}

/* 아래 여백 없이 다음 섹션과 붙는 변형 */
.section--flush {
  padding-bottom: 0;
}

/* 위 여백을 크게 여는 변형 (원본 인트로 실측 11.25rem) */
.section--offset {
  padding-top: var(--space-45);
}

.section__head {
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
}

/* 섹션 대제목 */
.section__title {
  font-family: var(--font-display);
  font-size: var(--text-display);
  font-weight: var(--weight-regular);
  line-height: var(--leading-none);
  letter-spacing: var(--tracking-display);
}

/* 더 조인 변형 (원본 실측: 여러 줄짜리 대제목은 행간 0.85) */
.section__title--tight {
  line-height: var(--leading-tight);
}

/* 도입부 큰 문단 */
.section__lead {
  font-size: var(--text-lead);
  line-height: var(--leading-none);
  letter-spacing: var(--tracking-snug);
}

/* 일반 본문 문단 */
.section__body {
  font-size: var(--text-md);
  line-height: var(--leading-body);
  letter-spacing: var(--tracking-body);
}

.section__note {
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  line-height: var(--leading-caption);
  opacity: var(--opacity-quiet);
}

/* 12칸 콘텐츠 그리드.
   직계 자식은 인라인 스타일로 --span (모바일) / --span-md (데스크톱) 만 정한다.
   예) <div style="--span:12; --span-md:7"> … </div>
   아무것도 안 주면 한 줄 전체를 차지한다. */
.grid,
.layout-grid {
  display: grid;
  grid-template-columns: repeat(var(--grid-columns), minmax(0, 1fr));
  gap: var(--grid-gap);
}

.grid > *,
.layout-grid > * {
  grid-column: span var(--span, var(--grid-columns));
  min-width: 0;
}

/* 세로로 쌓이는 블록 묶음 */
.stack-y {
  display: flex;
  flex-direction: column;
  gap: var(--section-gap);
}

/* 이미지가 프레임을 꽉 채우게 하는 공용 규칙 */
.media-fill,
.media-fill img,
.media-fill video,
.media-fill picture {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* ======================================================================== *
 * 2. 고정 헤더 (work.html)
 * ======================================================================== */

.site-header,
[data-site-header] {
  position: fixed;
  inset-inline: 0;
  top: 0;
  z-index: var(--z-header);
  display: flex;
  align-items: center;
  min-height: var(--header-height);
  padding-inline: var(--gutter);
  color: var(--color-ink);
  transition:
    transform var(--dur-fast) var(--ease-ui),
    color var(--dur-fast) var(--ease-ui);
}

/* mod-header.js 가 붙이는 두 속성에만 반응한다 */
.site-header[data-dark="true"],
[data-site-header][data-dark="true"] {
  color: var(--color-accent);
}

.site-header[data-hide="true"],
[data-site-header][data-hide="true"] {
  transform: translateY(-100%);
}

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  gap: var(--space-4);
  font-size: var(--text-base);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-ui);
}

/* ======================================================================== *
 * 3. 히어로 (index.html) — [data-hero]
 * ======================================================================== *
 * 섹션은 250lvh. 그 안의 스티키 무대가 100lvh 로 화면에 붙어 있고,
 * 캔버스가 스크롤 진행도에 따라 슬라이스를 흩뜨린다(mod-hero.js).
 */

.hero,
[data-hero] {
  position: relative;
  height: var(--hero-height);
}

/* 인트로 애니메이션이 준비될 때까지 감춘다. JS 가 인라인 visibility 로 연다.
   JS 가 아예 없으면(html.no-js) 이 규칙이 안 걸려서 그냥 보인다.
   GSAP 로드 실패(html.no-gsap)일 때도 강제로 연다. */
html.js .hero,
html.js [data-hero] {
  visibility: hidden;
}

html.no-gsap .hero,
html.no-gsap [data-hero] {
  visibility: visible;
}

.hero__sticky,
[data-hero-sticky] {
  position: sticky;
  top: 0;
  height: var(--hero-stage-height);
  overflow: clip;
}

/* clip-path 로 가운데 작은 사각형에서 전체로 열리는 래퍼 */
.hero__scene,
[data-scene-wrapper] {
  position: absolute;
  inset: 0;
  z-index: var(--z-scene);
}

/* scale 1.4 → 1 로 안착하는 안쪽 래퍼 */
.hero__scene-inner,
[data-scene-inner] {
  position: absolute;
  inset: 0;
  will-change: transform;
}

.hero__canvas,
[data-scene-canvas] {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

/* ── 영상 히어로 (mod-hero-video.js) ─────────────────────────────────────
 * 캔버스 대신 <video> 를 무대에 꽉 채운다. object-fit:cover 라 비율이
 * 안 맞아도 잘려 나갈 뿐 찌그러지지 않는다.
 * 포스터가 먼저 뜨고, 영상이 준비되면 그 위에 그려진다. */
.hero__video,
[data-hero-video] {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  display: block;
  background: var(--bg);
}

/* ── 유튜브 임베드 배경 ──────────────────────────────────────────────────
 * iframe 은 16:9 로 고정이라 object-fit:cover 가 안 먹는다.
 * 그래서 "화면보다 항상 큰" 크기로 잡아 가운데 정렬해 잘라낸다.
 *   가로가 넓으면 → 폭 100vw, 높이는 그 16:9 (=56.25vw)
 *   세로가 길면   → 높이 100vh, 폭은 그 16:9 (=177.78vh)
 * pointer-events 를 꺼야 유튜브 제목·관련영상 오버레이가 호버로 뜨지 않고
 * 스크롤도 iframe 에 먹히지 않는다. */
.hero__yt {
  position: absolute;
  inset: 0;
  overflow: hidden;
  background: var(--bg);
  pointer-events: none;
}
.hero__yt-frame {
  position: absolute;
  top: 50%;
  left: 50%;
  /* --hero-yt-zoom 만큼 더 키워서 유튜브가 얹는 UI(왼쪽 위 제목, 오른쪽 아래
     "동영상 더보기")를 화면 밖으로 밀어낸다. 1.0 이면 UI 가 그대로 보인다.
     너무 키우면 영상이 많이 잘리니 1.25~1.5 사이에서 조절. */
  transform: translate(-50%, -50%) scale(var(--hero-yt-zoom, 1.35));
  width: max(100vw, 177.7778vh);
  height: max(100vh, 56.25vw);
  border: 0;
  pointer-events: none;
  /* JS 가 재생을 확인하기 전까지 0 으로 둔다. 유튜브가 무엇을 그리든
     화면에 나올 수 없게 하는 마지막 방어선. */
  opacity: 0;
  transition: opacity 0.35s ease;
}
/* 유튜브 UI 가리개.
   재생 중이 아닐 때(버퍼링·일시정지·종료) iframe 위를 스틸컷으로 덮어
   유튜브가 띄우는 큰 재생/정지 버튼과 관련영상 오버레이를 안 보이게 한다.
   JS 가 data-on 을 토글한다. */
.hero__yt-cover {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 0.45s ease;
  pointer-events: none;
}
.hero__yt-cover[data-on="true"] { opacity: 1; }

/* 모션 최소화일 때 iframe 대신 뜨는 썸네일 */
.hero__yt-thumb {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* 영상 위에 까는 어두운 막. 흰 글자(내비·버튼) 가독성용.
   영상 자체가 이미 어두우면 --hero-video-scrim 을 0 으로 낮춰라. */
.hero__scrim {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: rgb(0 0 0 / var(--hero-video-scrim, 0.6));
}

/* ── 히어로 로고 ─────────────────────────────────────────────────────── */
.hero__logo {
  position: absolute;
  top: calc(var(--gutter) * 1.6);
  left: 50%;
  transform: translateX(-50%);
  z-index: 3;
  display: block;
  line-height: 0;
}
.hero__logo img {
  display: block;
  /* 크기는 css/tokens.css 의 --hero-logo-width 에서 조절한다 */
  width: var(--hero-logo-width, 150px);
  height: auto;
}

/* ── 히어로 타이틀 ────────────────────────────────────────────────────
 * 화면 정중앙. 두 줄이 각자 마스크 안에서 아래→위로 올라온다.
 * 마스크는 overflow:hidden 이라 글자 위아래가 잘릴 수 있어서,
 * 안쪽 여백을 주고 같은 만큼 음수 마진으로 되돌린다. */
.hero__title {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 2;
  width: min(100%, 22em);
  margin: 0;
  padding: 0 var(--gutter);
  text-align: center;
  /* 크기·굵기·자간은 css/tokens.css 에서 조절한다 (--text-hero-title 등) */
  font-size: var(--text-hero-title);
  font-weight: var(--hero-title-weight, 700);
  line-height: var(--hero-title-leading, 1.28);
  letter-spacing: var(--hero-title-tracking, -0.035em);
  color: var(--off-white);
  text-wrap: balance;
  /* 글자 뒤 그림자는 껐다. 밝은 영상 위에서 가독성이 부족하면
     css/tokens.css 의 --hero-title-shadow 에 값을 넣어라.
     예: 0 2px 24px rgb(0 0 0 / 0.35) */
  text-shadow: var(--hero-title-shadow, none);
}
.hero__title-mask {
  display: block;
  overflow: hidden;
  padding: 0.14em 0;
  margin: -0.14em 0;
}
.hero__title-line {
  display: block;
  will-change: transform;
}

@media (max-width: 767px) {
  .hero__title { width: 100%; }   /* 크기는 tokens.css 의 --text-hero-title */
  .hero__logo { top: calc(var(--gutter) * 1.8); }   /* 2026-09-04 채린 "윗 마진 타이트" — 1배(15px) → 1.8배(27px, PC 28px 와 비슷) */
  .hero__logo img { width: var(--hero-logo-width-mobile, 120px); }
}

/* 소리 토글 버튼 — 무대 오른쪽 아래 */
.hero__sound {
  position: absolute;
  right: var(--gutter);
  bottom: calc(var(--gutter) * 1.5);
  z-index: 3;
  display: inline-flex;
  align-items: center;
  gap: 0.55em;
  padding: 0.5em 0.9em;
  border: 1px solid rgb(255 255 255 / 0.35);
  border-radius: 999px;
  background: rgb(0 0 0 / 0.25);
  color: var(--off-white);
  font-size: var(--text-sm);
  line-height: 1;
  cursor: pointer;
  backdrop-filter: blur(6px);
  transition: background-color 0.3s ease, border-color 0.3s ease;
}
.hero__sound:hover {
  background: rgb(0 0 0 / 0.45);
  border-color: rgb(255 255 255 / 0.7);
}

/* 스피커 아이콘 — 소리 꺼짐일 땐 사선이 그어진다 */
.hero__sound-icon {
  position: relative;
  display: block;
  width: 0.55em;
  height: 0.62em;
  background: currentColor;
  clip-path: polygon(0 30%, 40% 30%, 100% 0, 100% 100%, 40% 70%, 0 70%);
}
.hero__sound[data-sound="off"] .hero__sound-icon::after {
  content: "";
  position: absolute;
  left: -20%;
  top: 45%;
  width: 150%;
  height: 1.5px;
  background: currentColor;
  transform: rotate(-38deg);
  transform-origin: center;
}

@media (max-width: 767px) {
  .hero__sound {
    bottom: calc(var(--gutter) * 1.2);
    font-size: var(--text-xs, 0.8rem);
  }
}

/* 캔버스에 그릴 원본 슬라이스들. 화면에는 절대 나오지 않는다.
   display:none 이면 디코딩이 늦어지므로 시각적으로만 숨긴다. */
.hero__sources,
[data-scene-sources] {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  opacity: 0;
  pointer-events: none;
}

/* 캔버스 위에 얹히는 타이포/내비 층.
 *
 * 이 요소는 [data-hero-sticky] 의 "형제"다(CONTRACT §5.2). 그래서 자기도
 * 스티키가 되어야 무대 위에 겹쳐 붙는다. 음수 margin 으로 앞선 스티키 위로
 * 끌어올린 뒤 같은 조건으로 고정한다.
 *
 * 여기 높이를 100lvh 로 못 박는 게 핵심이다. 안 그러면 안쪽 % 좌표가
 * 250lvh 짜리 섹션 기준으로 계산돼 글자가 화면 밖으로 나간다.
 */
.hero__overlay,
[data-hero-overlay] {
  position: sticky;
  top: 0;
  height: var(--hero-stage-height);
  margin-top: calc(-1 * var(--hero-stage-height));
  z-index: var(--z-hero-overlay);
  color: var(--color-ink-quiet);
  pointer-events: none;
  /* 36vw 짜리 글자가 화면 밖으로 나가도 가로 스크롤이 생기면 안 된다.
     clip 은 (hidden 과 달리) 스크롤 컨테이너를 만들지 않아 sticky 가 살아 있다. */
  overflow-x: clip;
}

/* 오버레이 자체는 클릭을 통과시키고, 실제로 눌러야 하는 것만 되살린다 */
.hero__overlay a,
.hero__overlay button,
[data-hero-overlay] a,
[data-hero-overlay] button {
  pointer-events: auto;
}

/* 디바이더 + 내비. 화면 세로 정중앙 (원본 실측) */
.hero__navwrap,
[data-hero-navwrap] {
  position: absolute;
  inset-inline: var(--gutter);
  top: 50%;
  transform: translateY(-50%);
}

/* 모바일에서는 내비 대신 메뉴 버튼을 쓴다 (원본 실측: 데스크톱에서만 표시) */
.hero__nav,
[data-hero-nav] {
  display: none;
  justify-content: space-between;
  gap: var(--space-4);
  margin-top: var(--space-1);
  font-size: var(--text-base);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-ui);
}

/* 스크롤 스파이가 현재 섹션 링크에 aria-current 를 넣는다 */
.hero__nav [aria-current],
[data-hero-nav] [aria-current] {
  opacity: 1;
}

.hero__nav [aria-current]::before,
[data-hero-nav] [aria-current]::before {
  content: "";
  display: inline-block;
  width: 0.4em;
  height: 0.4em;
  margin-right: 0.45em;
  border-radius: 50%;
  background: currentColor;
  vertical-align: middle;
}

/* 초대형 타이포 두 줄. 스크롤하면 좌/우로 빠진다(mod-hero.js 가 transform 담당).
   그래서 여기서는 transform 을 쓰지 않고 top 계산으로만 자리를 잡는다. */
.hero__line,
[data-line] {
  --hero-line-leading: 1.5; /* 원본 실측 */
  position: absolute;
  font-family: var(--font-display);
  font-size: var(--text-hero);
  font-weight: var(--weight-regular);
  line-height: var(--hero-line-leading);
  letter-spacing: var(--tracking-hero);
  white-space: nowrap;
  /* 화면을 크게 덮지만 클릭을 가로채면 안 된다 */
  pointer-events: none;
  /* 글자 중심을 --hero-line-N-y 위치에 놓기 위해 행상자 절반만큼 끌어올린다 */
  top: calc(var(--hero-line-y, 50%) - (var(--hero-line-leading) * 0.5em));
}

.hero__line[data-line="1"],
[data-line="1"] {
  --hero-line-y: var(--hero-line-1-y);
  left: var(--gutter);
}

.hero__line[data-line="2"],
[data-line="2"] {
  --hero-line-y: var(--hero-line-2-y);
  right: var(--gutter);
  text-align: right;
}

/* 연도 표기도 데스크톱에서만 (원본 실측) */
.hero__year,
[data-year] {
  display: none;
  position: absolute;
  left: var(--gutter);
  bottom: var(--space-8);
  font-size: var(--text-xs);
  line-height: var(--leading-caption);
}

/* ======================================================================== *
 * 4. 인트로 / 바이오 / 커리어 섹션 (index.html)
 * ======================================================================== */

/* 원본 실측: 대부분의 섹션은 아래 여백이 0 이고 내부 블록 간격으로 리듬을 만든다.
   딱 한 섹션(바이오)만 아래로 크게 벌어진다.
   마크업이 .wrap 을 따로 쓰지 않으므로 좌우 거터도 섹션 자신이 갖는다. */
.section-intro,
.section-career {
  position: relative;
  padding: var(--section-pad-top) var(--gutter) 0;
}

.section-bio {
  position: relative;
  padding: var(--section-pad-top) var(--gutter) var(--section-pad-bottom);
}

/* 3열 이미지 묶음 */
.figure-row {
  display: grid;
  grid-template-columns: repeat(var(--grid-columns), minmax(0, 1fr));
  gap: var(--grid-gap);
  margin-top: var(--grid-gap);
}

.figure {
  grid-column: span var(--span, 4);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  min-width: 0;
}

/* .reveal-image 의 배경/오버플로는 motion.css 계약이 정한다. 여기선 비율만. */
.figure__media {
  position: relative;
  aspect-ratio: var(--figure-aspect, 3 / 4);
}

.figure__media img,
.figure__media video {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.figure__caption {
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  line-height: var(--leading-caption);
  /* 원본 실측: 본문색의 80%. color-mix 로 currentColor 를 섞으면
     자기 참조라 브라우저가 무시하므로 opacity 로 처리한다. */
  opacity: var(--opacity-quiet);
}

/* 인용문 블록 */
.quote {
  font-size: var(--text-lead);
  line-height: var(--leading-none);
  letter-spacing: var(--tracking-snug);
}

.quote__source {
  display: block;
  margin-top: var(--space-6);
  font-size: var(--text-base);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-ui);
  opacity: var(--opacity-quiet);
}

/* --- 비디오 블록 ------------------------------------------------------- */

.video,
[data-video] {
  position: relative;
  aspect-ratio: var(--video-aspect);
  overflow: clip;
  background: var(--surface-2);
  cursor: pointer;
}

.video video,
.video img,
[data-video] video,
[data-video] img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.video__poster,
[data-video-poster] {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: opacity var(--dur-fast) var(--ease-ui);
}

.video__play,
[data-video-play] {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-3) var(--space-6);
  border: 1px solid currentColor;
  border-radius: 100vmax;
  font-size: var(--text-base);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-ui);
  color: var(--color-ink);
  background: transparent;
  transition: transform var(--dur-fast) var(--ease-magic);
}

@media (hover: hover) {
  .video:hover .video__play,
  [data-video]:hover [data-video-play] {
    transform: scale(1.06);
  }
}

/* --- 전폭 패럴랙스 이미지 ---------------------------------------------- */

.section-fullbleed {
  padding: var(--section-pad-top) var(--gutter) 0;
  overflow: clip;
}

.section-fullbleed__frame,
.section-fullbleed__inner {
  position: relative;
  overflow: clip;
  margin: 0;
}

/* 이미지를 프레임보다 크게 잡아 둬야 패럴랙스로 움직여도 빈틈이 안 생긴다.
   mod-reveal.js 는 transform 을 쓰고, 여기 확대는 독립 속성 scale 이라 안 부딪힌다. */
.section-fullbleed__frame img,
.section-fullbleed__frame video,
.section-fullbleed__img {
  width: 100%;
  max-width: none;
  scale: var(--parallax-overscan);
  will-change: transform;
}

/* ======================================================================== *
 * 5. 연표 (index.html) — [data-timeline-root]
 * ======================================================================== */

.timeline,
[data-timeline-root] {
  position: relative;
  padding: var(--section-pad-top) var(--gutter) var(--section-pad-bottom);
}

.timeline__heading {
  font-family: var(--font-display);
  font-size: var(--text-display);
  line-height: var(--leading-none);
  letter-spacing: var(--tracking-display);
  margin-bottom: var(--space-16);
}

/* 가운데 세로 배경선 */
.timeline__track,
[data-timeline-track] {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  z-index: var(--z-timeline-track);
  width: var(--timeline-line-width);
  background: var(--surface-3);
  pointer-events: none;
}

/* 스크롤에 맞춰 자라나는 흰 선. height 는 JS 가 인라인으로 준다. */
.timeline__progress,
[data-timeline-progress] {
  position: absolute;
  top: 0;
  left: 50%;
  z-index: var(--z-timeline-progress);
  width: var(--timeline-line-width);
  background: var(--color-line-strong);
  pointer-events: none;
}

/* 선 끝의 마름모.
   진행선은 위에서 아래로 자라므로 마름모는 **아래 끝**에 붙어야 따라 내려간다.
   (top 에 붙이면 선만 자라고 마름모는 연표 맨 위에 남는다)
   음수 bottom 은 마름모 중심을 선의 끝점에 정확히 맞추기 위한 절반값이다. */
.timeline__tip,
[data-timeline-tip] {
  position: absolute;
  left: 50%;
  bottom: calc(var(--timeline-tip-size) / -2);
  width: var(--timeline-tip-size);
  height: var(--timeline-tip-size);
  background: var(--color-line-strong);
  transform: translateX(-50%) rotate(45deg);
}

/* 16칸 그리드. 셀 배치는 마크업의 인라인 grid-row/grid-column 이 정한다.
   모바일에서는 mod-timeline.js 가 전부 span 16 으로 덮어쓴다. */
.timeline__grid,
[data-timeline-grid] {
  display: grid;
  grid-template-columns: repeat(var(--timeline-columns), minmax(0, 1fr));
  gap: var(--timeline-gap);
}

/* 셀의 가로 배치는 마크업의 인라인 grid-column 이 정한다(데스크톱).
   모바일 전용 무효화는 파일 맨 아래 @media (max-width:767px) 참고. */
.timeline__cell,
[data-timeline-cell] {
  position: relative;
  min-width: 0;
}

/* 모바일: 이미지 절반 폭 가운데 정렬 + 제목이 그 아래.
   데스크톱에서는 아래 @media 가 일반 블록으로 되돌린다. */
.timeline__item,
[data-timeline-item] {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
}

/* 이미지 박스. aspect-ratio 는 항목마다 다르므로 인라인 style 로 준다.
   clip-path 는 mod-timeline.js 가 스크럽으로 움직인다. */
.timeline__media,
[data-timeline-item-child] {
  position: relative;
  width: 50%;
  overflow: hidden;
  background: var(--surface-2);
  aspect-ratio: var(--media-aspect, 4 / 3);
  transition: clip-path var(--dur-medium) var(--ease-magic);
}

/* 블러 플레이스홀더가 background-image 로 들어가는 층 */
.timeline__reveal,
[data-timeline-item-reveal] {
  position: absolute;
  inset: 0;
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
  will-change: clip-path;
}

.timeline__reveal img,
[data-timeline-item-reveal] img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* 항목 사진 */
.timeline__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* 제목 상자.
   데스크톱: 이미지 옆에 절대 배치. 최대 폭은 mod-timeline.js 가
   --timeline-title-safe-w 로 심어 준다(가운데 진행선을 넘지 않게).
   모바일: 그냥 이미지 아래 흐름 배치. */
/* 모바일 기본: 사진 아래 가운데.
   margin-top 은 활성 항목이 1.3배로 커질 때 사진이 제목을 덮지 않을 만큼 띄운 값이다. */
.timeline__title,
[data-timeline-title] {
  position: relative;
  margin-top: var(--timeline-title-gap-mobile);
  text-align: center;
}

.timeline__title h3,
[data-timeline-title] h3 {
  font-size: var(--text-lg);
  font-weight: var(--weight-medium);
  line-height: var(--leading-snug);
  letter-spacing: var(--tracking-snug);
}

.timeline__title-inner {
  display: block;
}

.timeline__title-sub {
  display: block;
  font-size: var(--text-sub);
  opacity: var(--opacity-muted);
}

/* 설명 문단 — 원본 연표에는 없던 층이다.
   연도·제목만 있던 항목에 글을 붙이려고 더했고, .timeline--annotated 판에서만 쓴다.
   모바일에서는 제목 아래 흐름 배치(제목은 가운데 정렬이지만 긴 글은 왼쪽 정렬이 읽기 낫다). */
.timeline__desc,
[data-timeline-desc] {
  margin-top: var(--space-3);
  font-size: var(--text-base);
  line-height: var(--leading-normal);
  letter-spacing: var(--tracking-body);
  text-align: start;
  word-break: keep-all;
  overflow-wrap: break-word;
  opacity: var(--opacity-quiet);
}

/* ── 설명이 붙는 연표 (.timeline--annotated) ────────────────────────────
   항목이 화면 절반짜리 [사진 | 글] 블록이 되므로 위아래 여백으로 리듬을 만든다.
   (원본 연표는 사진 비율과 들쭉날쭉한 그리드 좌표가 그 리듬을 대신했다) */
.timeline--annotated [data-timeline-cell] {
  padding-block: var(--timeline-anno-row-pad);
}

/* 글 칸이 좁아 한글이 낱말 한가운데서 끊긴다("선구적"이 "선/구적"으로).
   keep-all 이 그걸 막는다. 긴 영문·URL 은 넘칠 수 있어 break-word 를 같이 준다. */
.timeline--annotated [data-timeline-title] h3 {
  word-break: keep-all;
  overflow-wrap: break-word;
}

/* 모바일에서는 글이 사진 아래에 흐른다. 사진이 화면 절반 폭인데 글만
   끝에서 끝까지 가면 균형이 깨지므로 폭을 맞춰 준다. 가운데 진행선이 글을
   가로지르기 때문에 글을 선 위로 올려 읽히게 한다.
   ⚠ 반드시 미디어쿼리 안에 둬야 한다 — 밖에 두면 데스크톱의 절대 배치를 덮어써
     (선택자가 더 세다) 제목이 사진 옆이 아니라 아래로 내려간다. */
@media (max-width: 767px) {
  .timeline--annotated [data-timeline-title] {
    position: relative;
    z-index: var(--z-timeline-progress);
    width: var(--timeline-anno-text-w-mobile);
    margin-inline: auto;
  }
}

/* 가운데 연도 셀은 데스크톱 전용. 모바일에서는 항목 왼쪽의
   [data-timeline-item-year-mobile] 가 그 역할을 대신한다. */
.timeline__yearcell,
[data-timeline-yearcell] {
  display: none;
  align-items: center;
  justify-content: center;
  grid-column: 1 / -1;
  position: relative;
  pointer-events: none;
}

.timeline__year,
[data-timeline-year] {
  font-family: var(--font-numeric);
  font-size: var(--text-year);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-label);
  opacity: var(--opacity-idle); /* 진행선이 지나가면 JS 가 1 로 올린다 */
}

/* 모바일 전용 연도 — 항목 왼쪽에 붙는다 (데스크톱에서는 숨김).
   top 은 확대된 사진과 겹치지 않도록 원본에서 잰 값이다. */
.timeline__year-mobile,
[data-timeline-item-year-mobile] {
  position: absolute;
  top: var(--timeline-year-mobile-top);
  left: 0;
  font-size: var(--text-base);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-label);
  opacity: var(--opacity-idle);
}

/* ======================================================================== *
 * 6. 히어로 Flip (work.html) — [data-flip-root]
 * ======================================================================== */

.flip-hero,
.work-hero,
[data-flip-root] {
  position: relative;
  overflow-x: clip;
}

/* 목적지 1 — 전체 화면 칸.
   CONTRACT §5.5 는 목적지를 [data-zone] 으로만 정의한다(클래스는 선택). 그래서
   훅만 달린 마크업도 같은 배치가 나오도록 훅 선택자를 함께 적어 둔다.
   루트의 직계 [data-zone] = 첫 목적지, 제목 안의 [data-zone] = 두 번째 목적지. */
.flip-hero__stage,
.work-hero__stage,
[data-flip-root] > [data-zone] {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100lvh;
}

/* 날아다니는 요소. Flip.fit 이 transform/width 를 직접 만진다. */
.flip-hero__target,
.work-hero__target,
[data-target] {
  position: relative;
  z-index: var(--z-scene);
  width: 100%;
  height: 100%;
}

.flip-hero__target img,
.flip-hero__target picture,
.work-hero__target img,
.work-hero__target picture,
[data-target] img,
[data-target] picture {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.flip-hero__credits,
.work-hero__credits,
[data-hero-credits] {
  position: absolute;
  left: var(--gutter);
  right: var(--gutter);
  bottom: var(--gutter);
  z-index: var(--z-hero-overlay);
  border-radius: var(--radius-sm);
  font-size: var(--text-base);
  font-weight: var(--weight-medium);
  text-align: left;
  opacity: var(--opacity-quiet);
  transition: opacity var(--dur-fast) var(--ease-ui);
}

.flip-hero__title,
.work-hero__title {
  padding-inline: var(--gutter);
  margin-top: var(--section-gap);
  font-family: var(--font-display);
  font-size: var(--text-title);
  font-weight: var(--weight-medium);
  line-height: var(--leading-none);
  letter-spacing: var(--tracking-display);
}

/* 목적지 2 — 제목 문장 안에 비워 둔 칸.
   폭은 Flip 타임라인이 0 → 원래 폭으로 키운다. */
.flip-hero__slot,
.work-hero__slot,
[data-flip-root] :where(h1, h2) [data-zone] {
  display: inline-block;
  aspect-ratio: var(--flip-slot-aspect);
  height: 0.73em; /* 원본 실측: 제목 글자 크기 대비 */
  vertical-align: baseline;
}

/* ======================================================================== *
 * 7. 카드 스택 (work.html) — [data-stack-root]
 * ======================================================================== */

.stack,
[data-stack-root] {
  position: relative;
  height: var(--stack-height);
}

.stack__viewport,
[data-stack-viewport] {
  position: sticky;
  top: 0;
  height: 100svh;
  overflow: clip;
}

/* 카드 1장 = 뷰포트의 직계 div. DOM 역순으로 쌓인다(mod-stack.js).
   모바일은 미디어 위 / 캡션 아래로 나뉘고, 데스크톱은 캡션이 미디어 위에 얹힌다. */
.stack__card,
.stack__viewport > div,
[data-stack-viewport] > div {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  justify-content: flex-start;
  overflow: hidden;
  will-change: clip-path;
}

.stack__media,
[data-stack-media] {
  position: relative;
  height: var(--stack-media-height);
  overflow: hidden;
}

.stack__media-inner,
[data-stack-media-inner] {
  position: absolute;
  inset: 0;
  will-change: transform;
}

.stack__media img,
.stack__media video,
[data-stack-media] img,
[data-stack-media] video {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.stack__caption,
[data-stack-caption] {
  position: static;
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--gutter);
  font-size: var(--text-base);
  font-weight: var(--weight-medium);
  line-height: var(--leading-label);
  letter-spacing: var(--tracking-label);
  background: var(--color-ink-quiet);
  color: var(--color-accent);
}

/* 위 카드가 걷히기 전까지 아래 카드를 어둡게 덮는 층 (2번째 카드부터) */
.stack__layer,
[data-stack-layer] {
  position: absolute;
  inset: 0;
  background: var(--color-bg);
  opacity: var(--opacity-veil);
  pointer-events: none;
}

/* ======================================================================== *
 * 8. 가로 스크롤러 — [blossom-carousel]
 * ======================================================================== *
 * mod-carousel.js 가 하는 일은 세 가지뿐이다.
 *   · --snap-type 을 "x mandatory" 로 세팅
 *   · 넘칠 때 has-overflow="true" / has-snap="true" 부여
 *   · fine 포인터에서 드래그 스크롤
 * 나머지 그림은 전부 아래 CSS.
 */

[blossom-carousel] {
  display: flex;
  gap: var(--grid-gap);
  width: 100%;
  padding-inline: var(--gutter);
  /* padding 과 짝을 맞춰야 한다. 없으면 scroll-snap 이 첫 카드를 컨테이너
     맨 왼쪽에 붙이려고 스스로 거터만큼 스크롤해 버려서 왼쪽 여백이 사라진다. */
  scroll-padding-inline: var(--gutter);
  overflow-x: auto;
  overflow-y: hidden;
  overscroll-behavior-x: contain;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  -ms-overflow-style: none;
}

[blossom-carousel]::-webkit-scrollbar {
  display: none;
}

[blossom-carousel] > * {
  flex: 0 0 var(--carousel-item-width);
  min-width: 0;
}

/* 넘칠 때만 잡아끌 수 있다는 신호 */
[blossom-carousel][has-overflow="true"] {
  cursor: grab;
}

[blossom-carousel][has-overflow="true"]:active {
  cursor: grabbing;
}

/* 스냅은 넘칠 때만 켠다. 안 넘치는데 켜면 첫 칸에 붙어 버린다. */
[blossom-carousel][has-snap="true"] {
  scroll-snap-type: var(--snap-type);
}

[blossom-carousel][has-snap="true"] > * {
  scroll-snap-align: start;
}

.carousel__item {
  position: relative;
  overflow: hidden;
  background: var(--surface-2);
  aspect-ratio: var(--carousel-item-aspect);
}

.carousel__item img,
.carousel__item video {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* ======================================================================== *
 * 9. 다음 작품 링크 (work.html)
 * ======================================================================== */

.next-work {
  display: block;
  position: relative;
  padding: var(--section-gap) var(--gutter);
}

.next-work__label,
.next-work__heading {
  font-size: var(--text-base);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-ui);
  opacity: var(--opacity-quiet);
}

.next-work__title {
  font-size: var(--text-display);
  line-height: var(--leading-none);
  letter-spacing: var(--tracking-display);
}

/* ======================================================================== *
 * 10. 모바일 메뉴 — [data-menu-panel]
 * ======================================================================== */

.menu-toggle,
.hero__nav-toggle,
.site-nav__toggle,
[data-menu-open] {
  font-size: var(--text-base);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-ui);
  color: inherit;
}

.menu,
.menu-panel,
[data-menu-panel] {
  position: fixed;
  inset: 0;
  z-index: var(--z-menu);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: var(--space-16);
  padding: var(--gutter);
  background: var(--color-bg);
  color: var(--color-ink-quiet);
  /* 시작 상태. mod-shell.js 가 GSAP autoAlpha 로 연다. */
  visibility: hidden;
  opacity: 0;
}

.menu__close,
.menu-panel__close,
[data-menu-close] {
  align-self: flex-end;
  font-size: var(--text-base);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-ui);
}

.menu__items,
.menu-panel__list,
[data-menu-items] {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: var(--text-lead);
  line-height: var(--leading-none);
  letter-spacing: var(--tracking-snug);
}

.menu__footer,
.menu-panel__footer,
[data-menu-footer] {
  display: flex;
  justify-content: space-between;
  gap: var(--space-4);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  opacity: var(--opacity-quiet);
}

/* ======================================================================== *
 * 11. 푸터 — [data-footer]
 * ======================================================================== */

.site-footer,
[data-footer] {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: var(--space-16);
  min-height: var(--footer-height);
  padding: var(--space-6) var(--gutter);
}

.site-footer__quote {
  font-size: var(--text-quote);
  line-height: var(--leading-none);
  letter-spacing: var(--tracking-label);
}

/* 푸터 아래쪽 묶음(크레딧 + 디바이더 + 타이틀 마스크)은 세로로 쌓인다.
   가로로 나뉘는 건 그 안의 .site-footer__credits 다. */
.site-footer__meta {
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
  font-size: var(--text-base);
  letter-spacing: var(--tracking-ui);
}

/* 마스크 SVG 는 비율로 높이가 정해진다. flex 가 눌러 버리면 글자가 잘리므로 고정. */
.site-footer__meta > * {
  flex: none;
}

/* 큰 타이틀 글자를 마스크로 뚫고 사진을 채우는 SVG 를 감싸는 상자.
   높이는 안쪽 <svg> 의 viewBox 비율이 정한다. 여기서 aspect-ratio 를 또 주면
   상자와 svg 의 비율이 어긋나 글자가 잘린다.
   (JS 훅 [data-title-mask] 는 svg 안쪽 <image> 라서 여기서 건드리지 않는다) */
.site-footer__mask {
  display: block;
  width: 100%;
}

/* ======================================================================== *
 * 12. 페이지 전환 오버레이
 * ======================================================================== */

.transition-dim,
[data-transition-dim] {
  position: fixed;
  inset: 0;
  z-index: var(--z-transition-dim);
  background: var(--color-bg);
  opacity: 0;
  pointer-events: none;
}

.transition-panel,
[data-transition-panel] {
  position: fixed;
  inset-inline: 0;
  top: 0;
  z-index: var(--z-transition-panel);
  height: 100lvh;
  background: var(--color-bg);
  clip-path: inset(0 0 100% 0);
  pointer-events: none;
}

.transition-panel img,
.transition-panel__img,
[data-transition-img] {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
}



/* ======================================================================== *
 * 12b. 문서 골격 · 유틸
 * ======================================================================== */

.page-main {
  display: block;
}

/* 스크린리더 전용 텍스트 (.sr-only 와 같은 역할, 마크업이 쓰는 이름) */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* 본문 바로가기 — 평소엔 화면 밖, 탭으로 포커스되면 나타난다 */
.skip-link {
  position: absolute;
  left: var(--gutter);
  top: 0;
  z-index: var(--z-menu);
  padding: var(--space-2) var(--space-4);
  background: var(--color-ink);
  color: var(--color-bg);
  transform: translateY(-200%);
}

.skip-link:focus-visible {
  transform: translateY(0);
}

/* 사진 아래 붙는 작은 설명. 원본 실측: 본문색의 80%, 500 굵기 */
.caption {
  display: block;
  margin-top: var(--space-3);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  line-height: var(--leading-caption);
  opacity: var(--opacity-quiet);
}

/* ======================================================================== *
 * 12c. 섹션별 그리드 배치 (원본 12칸 실측값)
 * ======================================================================== *
 * 마크업은 .layout-grid 로 12칸만 깔아 두고, 각 블록이 어느 칸에 앉는지는
 * 여기서 정한다. 숫자는 전부 원본 사이트를 계측해 옮긴 것이다.
 * 모바일에서는 전부 한 줄 전체(기본값)라 아래 값은 데스크톱 블록에만 있다.
 */

/* 인트로 */
.section-intro__lead {
  font-size: var(--text-lead);
  line-height: var(--leading-none);
  letter-spacing: var(--tracking-snug);
  margin-top: var(--space-8);
}

.section-intro__body {
  font-size: var(--text-md);
  line-height: var(--leading-body);
  letter-spacing: var(--tracking-body);
  margin-top: var(--space-8);
}

/* 소개 */
.section-bio__heading {
  font-family: var(--font-display);
  font-size: var(--text-display);
  line-height: var(--leading-none);
  letter-spacing: var(--tracking-display);
  margin-block: var(--space-8) var(--section-gap);
}

.section-bio__label,
.section-career__label {
  font-size: var(--text-base);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-ui);
  opacity: var(--opacity-quiet);
}

.section-bio__lead {
  font-size: var(--text-lead);
  line-height: var(--leading-none);
  letter-spacing: var(--tracking-snug);
}

.section-bio__body,
.section-career__note {
  font-size: var(--text-md);
  line-height: var(--leading-body);
  letter-spacing: var(--tracking-body);
}

.section-bio__figure {
  position: relative;
  margin: 0;
  aspect-ratio: var(--figure-aspect, 3 / 2);
}

.section-bio__figure img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* .caption 이 figure 안에 있으면 사진 밖으로 흘러나가면 안 된다 */
.section-bio__figure .caption {
  position: absolute;
  left: 0;
  top: 100%;
}

/* 활동 */
.section-career__heading {
  font-family: var(--font-display);
  font-size: var(--text-display);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-display);
  margin-block: var(--space-8) var(--section-gap);
}

.section-career__lead {
  font-size: var(--text-lead);
  line-height: var(--leading-none);
  letter-spacing: var(--tracking-snug);
}

.section-career__quote {
  margin: var(--section-gap) 0;
  font-size: var(--text-lead);
  line-height: var(--leading-none);
  letter-spacing: var(--tracking-snug);
}

.section-career__quote-cite {
  display: block;
  margin-top: var(--space-6);
  font-size: var(--text-base);
  font-style: normal;
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-ui);
  opacity: var(--opacity-quiet);
}

/* 상세 페이지 본문 */
.work-intro {
  position: relative;
  padding: var(--section-gap) var(--gutter);
}

.work-intro__heading {
  font-size: var(--text-lead);
  line-height: var(--leading-none);
  letter-spacing: var(--tracking-snug);
}

.work-intro__body,
.work-intro__meta {
  font-size: var(--text-md);
  line-height: var(--leading-body);
  letter-spacing: var(--tracking-body);
}

/* ======================================================================== *
 * 12d. 갤러리 (3열 그리드 ↔ 모바일 가로 스크롤러)
 * ======================================================================== *
 * 같은 사진 묶음을 두 벌 넣어 두고, 화면 폭에 따라 한쪽만 보여 준다.
 * 모바일: .gallery__scroller 안의 [blossom-carousel]
 * 데스크톱: .gallery__grid (12칸 중 4칸씩)
 */

.gallery {
  position: relative;
  margin-block: var(--section-gap);
}

/* 갤러리가 그 자체로 섹션일 때(work.html)만 좌우 거터를 갖는다.
   index.html 처럼 다른 섹션 안에 들어가면 부모가 이미 거터를 주고 있어서
   여기서 또 주면 두 배가 된다. */
section.gallery {
  padding-inline: var(--gutter);
}

/* 모바일 전용 스크롤러.
   스크롤러는 거터를 자기가 갖고 있으므로(=[blossom-carousel] 의 padding-inline)
   부모가 준 거터는 음수 margin 으로 되돌린다. */
.gallery__scroller {
  display: block;
  margin-inline: calc(-1 * var(--gutter));
}

/* 데스크톱 전용 3열 */
.gallery__grid {
  display: none;
}

.gallery__figure {
  position: relative;
  margin: 0;
  aspect-ratio: var(--figure-aspect, 3 / 4);
}

/* .reveal-image 가 overflow:hidden 이라 캡션이 잘린다.
   캡션만 상자 밖 아래로 빼 준다. */
.gallery__figure .caption {
  position: absolute;
  left: 0;
  top: 100%;
}

.gallery__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* ======================================================================== *
 * 12e. 상세 페이지 부속
 * ======================================================================== */

.site-nav {
  display: flex;
  align-items: center;
  gap: var(--space-6);
}

.site-nav__link {
  font-size: var(--text-base);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-ui);
}

/* 데스크톱 내비 링크는 모바일에서 감춘다 (메뉴 버튼이 대신한다) */
.site-nav__link,
.hero__nav-link {
  display: none;
}

.hero__nav-link {
  font-size: var(--text-base);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-ui);
}

/* 히어로 큰 타이포를 감싸는 h1. 자식 두 줄은 절대 배치라 자신은 껍데기다. */
.hero__type {
  margin: 0;
  font-size: inherit;
  font-weight: inherit;
  line-height: inherit;
  letter-spacing: inherit;
}

/* Flip 히어로 제목 묶음 */
.work-hero__titlebox {
  padding-inline: var(--gutter);
  margin-top: var(--section-gap);
}

.work-hero__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.work-hero__index {
  font-size: var(--text-lead);
  line-height: var(--leading-none);
  letter-spacing: var(--tracking-snug);
  margin-top: var(--space-8);
}

/* 카드 스택 캡션 속 구조 */
.stack__caption-inner {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.stack__caption-index {
  font-size: var(--text-base);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-ui);
  opacity: var(--opacity-quiet);
}

.stack__caption-text {
  font-size: var(--text-base);
  font-weight: var(--weight-medium);
  line-height: var(--leading-label);
  letter-spacing: var(--tracking-label);
}

.stack__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* 다음 작업 (.next-work 본체 규칙은 위 9번 항목에 있다) */
.next-work__text {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.next-work__figure {
  position: relative;
  margin: 0;
  aspect-ratio: var(--figure-aspect, 4 / 3);
}

.next-work__figure img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* ======================================================================== *
 * 12f. 비디오 블록 속 구조
 * ======================================================================== */

/* 비율만 잡아 주는 투명 이미지 */
.video__sizer {
  display: block;
  width: 100%;
  height: auto;
  visibility: hidden;
}

.video__poster-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* 재생 버튼이 잘 보이도록 사진을 살짝 눌러 주는 막 */
.video__scrim {
  position: absolute;
  inset: 0;
  background: var(--color-bg);
  opacity: 0.25;
  pointer-events: none;
}

.video__play {
  position: relative;
  z-index: 1;
}

/* ======================================================================== *
 * 12g. 메뉴 패널 속 구조
 * ======================================================================== */

.menu-panel__inner {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: var(--space-16);
  height: 100%;
}

.menu-panel__rule {
  display: block;
  width: 100%;
  height: var(--divider-height);
  background: var(--color-line);
}

.menu-panel__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  font-size: var(--text-base);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-ui);
}

.menu-panel__nav {
  flex: 1;
  display: flex;
  align-items: center;
}

.menu-panel__item {
  list-style: none;
}

.menu-panel__link {
  display: block;
}

.menu-panel__footer-row {
  display: flex;
  gap: var(--space-4);
}

/* ======================================================================== *
 * 12h. 푸터 속 구조
 * ======================================================================== */

.site-footer__inner {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: var(--space-16);
  min-height: calc(var(--footer-height) - var(--space-6) * 2);
}

.site-footer__credits {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--space-4);
  font-size: var(--text-base);
  letter-spacing: var(--tracking-ui);
}

.site-footer__credits p {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.site-footer__links {
  display: flex;
  gap: var(--space-4);
}

/* 글자 모양 안쪽을 사진으로 채우는 마스크.
   데스크톱은 한 줄, 모바일은 두 줄짜리 SVG 를 각각 따로 두고 하나만 보여 준다. */
.site-footer__mask svg {
  display: block;
  width: 100%;
  height: auto;
}

.site-footer__mask-text {
  font-family: var(--font-display);
  font-size: 200px; /* viewBox 좌표계 안의 값이라 뷰포트와 무관하다 */
  font-weight: var(--weight-regular);
  letter-spacing: var(--tracking-display);
}

.site-footer__mask--desktop {
  display: none;
}

.site-footer__mask--mobile {
  display: block;
}

/* ======================================================================== *
 * 13. 데스크톱 (≥768px)
 * ======================================================================== *
 * 이 파일의 유일한 미디어 쿼리다. 위쪽은 전부 모바일 기준이고,
 * 여기서 "구조가 바뀌는 것"만 되돌린다.
 * 크기·간격 값이 달라지는 것은 tokens.css 의 같은 조건 블록이 담당한다.
 */
@media (min-width: 768px) {
  /* 12칸 그리드 자식은 데스크톱 전용 span 을 쓸 수 있다 */
  .grid > *,
  .layout-grid > * {
    grid-column: span var(--span-md, var(--span, var(--grid-columns)));
  }

  /* --- 히어로 ----------------------------------------------------------- */

  /* 데스크톱에서만 내비와 연도가 보인다 */
  .hero__nav,
  [data-hero-nav] {
    display: flex;
  }

  .hero__year,
  [data-year] {
    display: block;
  }

  /* 모바일 메뉴와 그 버튼은 데스크톱에서 존재하지 않는다 */
  .menu-toggle,
  .hero__nav-toggle,
  [data-menu-open],
  .menu,
  .menu-panel,
  [data-menu-panel] {
    display: none;
  }

  /* --- 연표 ------------------------------------------------------------- */

  /* 가운데 연도 셀이 살아난다 */
  .timeline__yearcell,
  [data-timeline-yearcell] {
    display: flex;
  }

  /* 항목은 다시 평범한 블록. 이미지가 셀을 꽉 채운다 */
  .timeline__item,
  [data-timeline-item] {
    display: block;
  }

  .timeline__media,
  [data-timeline-item-child] {
    width: 100%;
  }

  /* 모바일 전용 연도는 감춘다 */
  .timeline__year-mobile,
  [data-timeline-item-year-mobile] {
    display: none;
  }

  /* 제목이 이미지 옆으로 빠져나간다 */
  .timeline__title,
  [data-timeline-title] {
    position: absolute;
    top: 50%;
    margin-top: 0;
    text-align: start;
  }

  /* 오른쪽 배치: 상자의 오른쪽 끝을 이미지 밖에 고정하고 왼쪽으로 자란다.
     최대 폭은 mod-timeline.js 가 --timeline-title-safe-w 로 준다.
     그 값은 "화면 세로 중앙선까지의 거리 - 3rem" 이라, 제목이 진행선을 넘지 않는다.
     JS 가 값을 못 정하면 아래 폴백(45ch / 43ch — 원본과 같은 수치)이 쓰인다. */
  .timeline__title[data-title-side="right"],
  [data-timeline-title][data-title-side="right"] {
    left: auto;
    right: calc(-1 * var(--timeline-title-offset));
    max-width: var(--timeline-title-safe-w, var(--timeline-title-max-right));
  }

  /* 왼쪽 배치: 왼쪽 끝을 고정하고 오른쪽으로 자란다 */
  .timeline__title[data-title-side="left"],
  [data-timeline-title][data-title-side="left"] {
    right: auto;
    left: calc(-1 * var(--timeline-title-offset));
    max-width: var(--timeline-title-safe-w, var(--timeline-title-max-left));
  }

  /* ── 설명이 붙는 연표 (.timeline--annotated) ──────────────────────────
     원본과 같다 — 사진은 셀을 꽉 채우고, 제목은 그 옆 빈자리에 떠 있다.
     다른 점은 그 제목 상자 안에 설명 문단이 함께 들어간다는 것뿐이다.

     원본은 상자의 바깥쪽 끝을 사진 밖에 못 박고 사진 위로 글을 겹쳐 놓는다
     (제목 한 줄이 전제라 그래도 읽혔다). 설명이 붙으면 글 덩어리가 커져
     사진을 덮어 버리므로, 여기서는 반대로 **사진 바깥 모서리에 상자를 붙이고**
     바깥쪽으로 자라게 한다. 그래서 사진이 클수록 글은 화면 가장자리 쪽에 선다.
     폭은 셀의 인라인 --timeline-anno-text-w 로 항목마다 준다.
     ⚠ 이 블록은 위의 절대 배치 규칙보다 **뒤에** 있어야 이긴다. */
  .timeline--annotated [data-timeline-title] {
    /* 사진의 세로 한가운데에 글 덩어리의 한가운데를 맞춘다.
       (원본은 top:50% 만 줘서 긴 글이 아래로만 흘렀다) */
    transform: translateY(-50%);
  }

  /* 사진이 가운데 선을 넘어오는 항목이 있어서, 연도가 사진 뒤로 숨는 일이 생긴다.
     원본처럼 연도는 항상 사진 위에 얹힌다. */
  .timeline--annotated [data-timeline-yearcell] {
    z-index: var(--z-timeline-progress);
  }

  /* ⚠ 폭은 max-width 가 아니라 width 로 못 박아야 한다.
     상자를 사진 바깥(left/right: 100% + 여백)에 두면 남는 자리가 0 이 되어,
     max-width 만 주면 글이 낱말 하나 폭으로 쪼그라든다.

     ⚠ 그 폭을 rem 하나로만 주면 좁은 화면에서 화면 밖으로 밀린다.
       루트 글꼴(--font-size-root)은 vw 를 따라 줄지만 15px 에서 멈추는데,
       사진 옆에 남는 자리는 화면 폭에 정비례해 계속 줄기 때문이다.
       (실측: 768px 에서 가로로 62px 넘쳤다)
       그래서 "쓰고 싶은 폭"과 "남은 자리" 중 작은 쪽을 쓴다.
         --timeline-anno-text-w     쓰고 싶은 폭 (넓은 화면에서 쓰인다)
         --timeline-anno-text-room  사진 바깥에 남는 자리. **셀 폭 대비 %** 다.
                                    = (16 - 사진이 끝나는 열) ÷ 사진이 차지한 열수
                                    예) 1 / span 9  →  7 ÷ 9 = 77%
       여기서 사진과의 간격과 화면 가장자리 여백을 뺀 값이 실제 상한이다. */
  /* 오른쪽에 서는 글은 화면 오른쪽에 목차 자리(--timeline-anno-edge-right)까지 비워야 한다.
     왼쪽에 서는 글은 화면 가장자리 여백(--gutter)만 비우면 된다. */
  .timeline--annotated [data-timeline-title][data-title-side="right"] {
    left: calc(100% + var(--timeline-anno-gap));
    right: auto;
    width: min(
      var(--timeline-anno-text-w),
      calc(
        var(--timeline-anno-text-room, 80%) - var(--timeline-anno-gap) -
          var(--timeline-anno-edge-right)
      )
    );
    max-width: none;
  }

  .timeline--annotated [data-timeline-title][data-title-side="left"] {
    right: calc(100% + var(--timeline-anno-gap));
    left: auto;
    width: min(
      var(--timeline-anno-text-w),
      calc(var(--timeline-anno-text-room, 80%) - var(--timeline-anno-gap) - var(--gutter))
    );
    max-width: none;
  }

  .timeline--annotated [data-timeline-title] h3 {
    font-size: var(--timeline-anno-title-size);
    line-height: var(--leading-snug);
  }

  .timeline--annotated [data-timeline-desc] {
    margin-top: var(--space-5);
    font-size: var(--text-base);
  }


  /* --- 카드 스택: 미디어가 카드를 꽉 채우고 캡션이 그 위에 얹힌다 --------- */
  .stack__card,
  .stack__viewport > div,
  [data-stack-viewport] > div {
    flex-direction: row;
    align-items: center;
    justify-content: center;
  }

  .stack__media,
  [data-stack-media] {
    position: absolute;
    inset: 0;
    height: auto;
  }

  .stack__caption,
  [data-stack-caption] {
    position: absolute;
    left: 0;
    bottom: 0;
    flex: none;
    max-width: var(--stack-caption-max);
    background: transparent;
    color: var(--color-ink-invert);
  }

  /* --- 상세 히어로 크레딧: 오른쪽 아래로 --------------------------------- */
  .flip-hero__credits,
  .work-hero__credits,
  [data-hero-credits] {
    left: auto;
    text-align: right;
  }

  /* --- 내비 링크가 보인다 ------------------------------------------------ */
  .site-nav__link,
  .hero__nav-link {
    display: inline-block;
  }

  /* --- 갤러리: 스크롤러 대신 3열 그리드 ---------------------------------- */
  .gallery__scroller {
    display: none;
  }

  .gallery__grid {
    display: grid;
  }

  .gallery__figure {
    grid-column: span 4;
  }

  /* --- 섹션별 12칸 배치 (원본 실측) -------------------------------------- */

  /* 인트로: 큰 문단은 전폭, 작은 문단은 오른쪽 끝 4칸 */
  .section-intro__lead {
    grid-column: 1 / span 12;
  }

  .section-intro__body {
    grid-column: 9 / span 4;
  }

  /* 소개: 라벨 1~5칸, 큰 문단 전폭, 사진 7~12칸, 작은 본문 1~4칸 */
  .section-bio__label {
    grid-column: 1 / span 5;
  }

  .section-bio__lead {
    grid-column: 1 / span 12;
  }

  .section-bio__figure {
    grid-column: 7 / span 6;
  }

  .section-bio__body {
    grid-column: 1 / span 4;
  }

  /* 활동: 주석 10~12칸, 큰 문단 전폭, 라벨 1~5칸, 비디오 6~12칸 */
  .section-career__note {
    grid-column: 10 / span 3;
  }

  .section-career__lead {
    grid-column: 1 / span 12;
  }

  .section-career__label {
    grid-column: 1 / span 5;
  }

  .section-career__quote {
    max-width: 60%;
  }

  .video,
  [data-video] {
    grid-column: 6 / span 7;
  }

  /* 상세 본문: 제목 전폭, 본문 1~6칸, 메타 9~12칸 */
  .work-intro__heading {
    grid-column: 1 / span 12;
  }

  .work-intro__body {
    grid-column: 1 / span 6;
  }

  .work-intro__meta {
    grid-column: 9 / span 4;
  }

  /* 상세 히어로 제목: 전폭, 번호는 오른쪽 끝 */
  .work-hero__title {
    grid-column: 1 / span 12;
  }

  .work-hero__index {
    grid-column: 9 / span 4;
  }

  /* 다음 작업: 글 1~5칸, 사진 7~12칸 */
  .next-work__text {
    grid-column: 1 / span 5;
  }

  .next-work__link {
    grid-column: 7 / span 6;
  }

  /* --- 푸터 마스크: 한 줄짜리로 교체 ------------------------------------- */
  .site-footer__mask--desktop {
    display: block;
  }

  .site-footer__mask--mobile {
    display: none;
  }
}

/* ======================================================================== *
 * 14. 모바일에서 인라인 스타일을 무효화하는 예외 (같은 768px 경계)
 * ======================================================================== *
 * 위쪽은 전부 모바일 우선이라 이 블록은 필요 없어야 정상이다.
 * 딱 하나 예외가 인라인 style 이다. 연표 셀의 배치는 CONTRACT §5.3 대로
 * 마크업에 style="grid-column:2 / span 3" 로 박혀 있는데, 인라인 선언은
 * 일반 규칙으로는 못 이긴다. 데스크톱 배치를 살리면서 모바일에서만
 * 무효화하려면 이 좁은 블록 + !important 조합밖에 없다.
 *
 * mod-timeline.js 도 같은 일을 하지만(모바일에서 span 16 으로 덮어씀),
 * JS 가 늦게 뜨거나 죽어도 모바일 연표가 깨지지 않도록 여기서도 못 박는다.
 */
@media (max-width: 767px) {
  .timeline__cell,
  [data-timeline-cell] {
    grid-column: 1 / -1 !important;
  }
}

/* ==========================================================================
 * 설명이 붙는 연표 — 사진 아래로 글이 내려가는 구간 (768 ~ 1279px)
 * ==========================================================================
 * 768px 부터 연표는 데스크톱 배치(사진이 셀을 꽉 채우고 글은 그 옆에 뜬다)로
 * 넘어간다. 그런데 이 폭에서는 사진 옆에 남는 자리가 300px 안팎이라,
 * 설명 문단이 사진보다 두 배 가까이 길어진다. 글 상자는 사진 세로 한가운데를
 * 기준으로 서 있으므로, 길어진 만큼 위아래로 삐져나와 섹션 제목과 이웃 항목을
 * 덮는다(실측: 768px 에서 "6년의 기록" 제목 위로 올라탔다).
 *
 * 그래서 이 구간은 글을 사진 아래로 내린다 — 모바일과 같은 흐름 배치다.
 * 나란히 세우는 배치는 **1280px 부터**다. 1024~1279 도 옆에 세울 수는 있지만,
 * 화면 오른쪽 목차(right:32px + 130px)를 피하고 나면 글 폭이 230px 안팎까지 줄어
 * 사진보다 글이 두 배로 길어진다. 그 폭에서는 내려놓는 편이 낫다.
 * ⚠ 위의 @media (min-width: 768px) 블록보다 **뒤에** 있어야 이긴다.
 * ========================================================================== */
@media (min-width: 768px) and (max-width: 1279px) {
  /* 셀을 한 줄 전체로 편다. 항목마다 다른 열 좌표를 그대로 두면 오른쪽에 붙은
     항목의 글이 화면 오른쪽 목차 자리로 들어가 라벨과 겹친다.
     ⚠ 마크업의 인라인 grid-column 을 이겨야 해서 !important 가 필요하다
       (아래 모바일 블록이 같은 이유로 쓰는 것과 같다). */
  .timeline--annotated [data-timeline-cell] {
    grid-column: 1 / -1 !important;
  }

  /* 사진 크기는 항목마다 다르게 유지한다. 셀의 인라인 --timeline-anno-media-w-stack. */
  .timeline--annotated [data-timeline-item-child] {
    width: var(--timeline-anno-media-w-stack, 70%);
  }

  .timeline--annotated [data-timeline-title],
  .timeline--annotated [data-timeline-title][data-title-side="right"],
  .timeline--annotated [data-timeline-title][data-title-side="left"] {
    /* static 이 아니라 relative — 흐름으로 되돌리면서 z-index 를 쓸 수 있어야 한다.
       사진이 가운데 선을 넘는 항목이 있어 글도 선을 가로지르는데, 선이 글자 위로
       지나가면 읽기 힘들다. 모바일과 같은 처리로 글을 선 위에 얹는다. */
    position: relative;
    z-index: var(--z-timeline-progress);
    /* ⚠ 오프셋도 반드시 함께 푼다. relative 는 left/top 을 "밀어내는 양"으로 읽어서,
       데스크톱 값(left:100%+여백, top:50%)이 남아 있으면 글이 사진 옆으로 밀려
       화면 밖까지 나간다. */
    inset: auto;
    width: auto;
    /* 글은 가운데 진행선 앞에서 멈춘다. 그래야 가운데 연도 라벨과도,
       화면 오른쪽 목차와도 부딪히지 않는다(사진은 원본처럼 선을 넘어도 된다). */
    max-width: calc(50% - var(--timeline-anno-gap));
    margin-top: var(--space-6);
    transform: none;
    text-align: start;
  }
}

/* ── (안 씀) 모바일 히어로 타이틀 네 줄 ── (2026-08-31 되돌림)
 * 한때 모바일에서 '기업의 / 오늘을 보는 / 대한민국 / 최초의 금융' 네 줄로 끊었다가
 * 채린이 **두 줄로 되돌리라**고 해서 뺐다. 지금은 데스크톱과 같은 두 줄이다:
 *     기업의 오늘을 보는 / 대한민국 최초의 금융
 * 다시 네 줄로 할 일이 생기면 아래 규칙을 살리면 된다:
 *     @media (max-width: 767px) { .hero__title-line .hero__word:first-child { display: block } }
 * ⚠ **<br> 로는 안 된다.** 이 타이틀은 GSAP SplitText 가 공백 단위로 마크업을 다시 짓기 때문에
 *   <br> 이 지워지고 앞뒤 낱말이 붙어 버린다("기업의오늘을 보는"). 실제로 그렇게 한 번 깨뜨렸다. */
