/* ─────────────────────────────────────────────────────────────
   LAPIS — Week 3 실습
   색·간격·타이포·이징은 전부 저장소 루트 tokens.css 에서만 온다.
   여기서 hex 색이나 px 글자크기를 새로 만들지 않는다. (CLAUDE.md 하드룰 1)
   ───────────────────────────────────────────────────────────── */
@import url("../tokens.css");

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

body {
  margin: 0;
  background: var(--bg-primary);
  color: var(--text-primary);
  font-family: var(--font-sans-kr);
  font-size: var(--text-body);
  line-height: 1.8;
  -webkit-font-smoothing: antialiased;
}

img, video { display: block; max-width: 100%; }
h1, h2, h3, p, figure { margin: 0; }
ul { margin: 0; padding: 0; list-style: none; }
a { color: inherit; text-decoration: none; }

:focus-visible { outline: 2px solid var(--state-focus-ring); outline-offset: 3px; }

.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}
.skip {
  position: absolute; left: var(--space-4); top: calc(var(--space-4) * -4);
  z-index: 100; padding: var(--space-3) var(--space-5);
  background: var(--bg-inverse); color: var(--text-inverse);
  transition: top var(--duration-fast) var(--ease-out);
}
.skip:focus { top: var(--space-4); }

/* ── 공통 타이포 ───────────────────────────────────────── */
.eyebrow {
  font-family: var(--font-serif-kr);
  font-size: var(--text-eyebrow);
  letter-spacing: var(--tracking-wide);
  color: var(--text-accent);
  margin-bottom: var(--space-4);
}
.h1 {
  font-family: var(--font-serif-kr);
  font-size: var(--text-h1);
  font-weight: 400;
  line-height: 1.35;
  letter-spacing: var(--tracking-tight);
}
.h2 {
  font-family: var(--font-serif-en);
  font-size: var(--text-h2);
  font-weight: 400;
  letter-spacing: var(--tracking-base);
}
.body { color: var(--text-secondary); max-width: 46ch; }
.body + .body { margin-top: var(--space-4); }

/* 아웃라인 CTA — 호버 시 반전. 처음부터 채워진 버튼은 쓰지 않는다. (하드룰 5) */
.btn {
  display: inline-block;
  margin-top: var(--space-6);
  padding: var(--space-4) var(--space-7);
  border: 1px solid var(--border-active);
  color: var(--text-accent);
  font-size: var(--text-button);
  letter-spacing: var(--tracking-button);
  background: transparent;
  cursor: pointer;
  transition: background var(--duration-base) var(--ease-out),
              color var(--duration-base) var(--ease-out);
}
.btn:hover, .btn:focus-visible {
  background: var(--bg-inverse);
  color: var(--text-inverse);
}

/* ── Nav ──────────────────────────────────────────────── */
.nav {
  position: fixed; inset: 0 0 auto 0; z-index: 50;
  display: flex; align-items: center; justify-content: space-between;
  padding: var(--space-5) var(--margin-desktop);
  transition: background var(--duration-base) var(--ease-out),
              padding var(--duration-base) var(--ease-out);
}
.nav.is-solid {
  background: var(--bg-secondary);
  padding-block: var(--space-3);
  border-bottom: 1px solid var(--border-hairline);
}
.nav__mark {
  font-family: var(--font-serif-en);
  font-size: var(--text-h2);
  letter-spacing: var(--tracking-wide);
}
.nav__links { display: flex; gap: var(--space-7); }
.nav__links a {
  font-size: var(--text-caption);
  letter-spacing: var(--tracking-wide);
  color: var(--text-secondary);
  transition: color var(--duration-fast) var(--ease-out);
}
.nav__links a:hover { color: var(--text-accent); }

.nav__toggle {
  display: none;
  flex-direction: column; gap: var(--space-1);
  padding: var(--space-2);
  background: none; border: 0; cursor: pointer;
}
.nav__bar { width: var(--icon-md); height: var(--icon-stroke); background: var(--text-primary); }

/* ── Hero ─────────────────────────────────────────────────
   .hero 의 높이가 곧 모션 길이다. --progress 는 motion.js 가 매 프레임 넣는다.
   --p 를 --motion-scroll 로 곱해두면 reduced-motion 에서 0으로 얼어붙는다. */
.hero {
  position: relative;
  height: 250vh;

  --p:  calc(var(--progress, 0) * var(--motion-scroll, 1));
  /* 구간을 셋으로 쪼개 서로 다른 박자를 준다 */
  --pA: clamp(0, calc(var(--p) / 0.45), 1);              /* 0.00 → 0.45  자간 확장 */
  --pB: clamp(0, calc((var(--p) - 0.35) / 0.35), 1);     /* 0.35 → 0.70  타이틀 퇴장 */
  --pC: clamp(0, calc((var(--p) - 0.68) / 0.32), 1);     /* 0.68 → 1.00  두 번째 카피 */
}
.hero__stage {
  position: sticky; top: 0;
  height: 100vh; overflow: hidden;
  display: grid; place-items: center;
}
.hero__video {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover;
  transform: scale(calc(1.04 + var(--p) * 0.1));
}
.hero__veil {
  position: absolute; inset: 0;
  background: var(--bg-primary);
  opacity: calc(0.34 + var(--pA) * 0.42);
}
.hero__grad {
  position: absolute; inset: 0;
  background: linear-gradient(to bottom, transparent 45%, var(--bg-primary));
}

.hero__copy {
  position: relative; text-align: center;
  padding-inline: var(--margin-mobile);
  opacity: calc(1 - var(--pB));
  transform: scale(calc(1 + var(--pB) * 0.16));
}
.hero__eyebrow {
  font-family: var(--font-serif-kr);
  font-size: var(--text-eyebrow);
  color: var(--text-accent);
  margin-bottom: var(--space-5);
  letter-spacing: calc(var(--tracking-wide) + var(--pA) * 0.10em);
}
.hero__title {
  font-family: var(--font-serif-en);
  font-size: var(--text-display);
  font-weight: 400; line-height: 1.02;
  letter-spacing: calc(var(--tracking-tight) + var(--pA) * 0.12em);
}

/* 단어별 등장·퇴장 — 좌/우를 번갈아 출발점으로 잡고, 스크롤하면
   들어온 쪽의 **반대편으로 빠져나간다**. 1784 의 c/d 키프레임이
   -100% 에서 들어와 +100% 로 나가는 걸 그대로 옮긴 것.
   들어오기만 하는 것과 통과하는 것은 체감이 꽤 다르다. */

/* 바깥 층 — 스크롤이 만드는 퇴장. --w 가 클수록 조금 더 멀리 나가
   단어들이 한 줄로 붙어 움직이지 않는다. */
.hero__title .word {
  display: inline-block;
  transform: translateX(calc(
    var(--dir, 1) * -40vw * var(--pB) * (1 + var(--w, 0) * 0.12)
  ));
}

/* 안쪽 층 — 로드 직후의 진입 */
.hero__title .word__in {
  display: inline-block;
  opacity: 0;
  transform: translateX(calc(var(--dir, 1) * 28vw));
  animation: word-in var(--duration-cinematic) var(--ease-out) forwards;
  animation-delay: calc(var(--w, 0) * 130ms);
}
@keyframes word-in {
  to { opacity: 1; transform: translateX(0); }
}

.hero__second {
  position: absolute; left: 0; right: 0;
  text-align: center;
  padding-inline: var(--margin-mobile);
  opacity: var(--pC);
  transform: translateY(calc((1 - var(--pC)) * var(--space-6)));
}
.hero__second-line {
  font-family: var(--font-serif-kr);
  font-size: var(--text-h1);
  line-height: 1.6;
  letter-spacing: var(--tracking-base);
}

.hero__hint {
  position: absolute; bottom: var(--space-7);
  font-size: var(--text-caption);
  letter-spacing: var(--tracking-wide);
  color: var(--text-secondary);
  opacity: calc(1 - var(--pA));
}

/* ── Divider — 라인이 좌우로 그려진다 ──────────────────── */
.divider {
  display: flex; align-items: center; gap: var(--space-5);
  padding: var(--space-9) var(--margin-desktop);
}
.divider::before, .divider::after {
  content: ""; flex: 1; height: 1px;
  background: linear-gradient(to right, transparent, var(--border-active), transparent);
  transform: scaleX(0);
  transition: transform var(--duration-cinematic) var(--ease-out);
}
.divider.is-visible::before, .divider.is-visible::after { transform: scaleX(1); }
.divider__mark { color: var(--gold); font-size: var(--text-caption); }

/* ── 앰비언트 루프 ────────────────────────────────────────
   코드잇과 우리 사이의 진짜 차이는 리빌 종류가 아니라 이것이었다.
   등장하고 멈추면 화면이 죽는다. 아주 느리게 계속 움직이는 층을 깔아둔다.
   LAPIS 는 조용한 럭셔리라 진폭을 작게 잡는 것이 핵심.
   (전부 transform/opacity 라 레이아웃을 다시 계산하지 않는다) */

.hero__grad    { animation: breathe 14s var(--ease-in-out) infinite alternate; }
.divider__mark { animation: pulse 6s var(--ease-in-out) infinite alternate; }

@keyframes breathe { to { opacity: 0.8; } }
@keyframes pulse   { to { opacity: 0.4; } }

/* 롤링 텍스트 — 트랙에 같은 세트를 두 벌 넣고 -50% 까지 밀면
   이음새 없이 무한히 흐른다. */
.marquee {
  overflow: hidden;
  padding: var(--space-6) 0;
  border-block: 1px solid var(--border-hairline);
}
.marquee__track {
  display: flex; width: max-content;
  animation: roll 38s linear infinite;
}
.marquee__set {
  display: inline-flex; align-items: center; gap: var(--space-5);
  padding-right: var(--space-5);
  font-family: var(--font-serif-en);
  font-size: var(--text-h2);
  letter-spacing: var(--tracking-wide);
  color: var(--text-secondary);
  white-space: nowrap;
}
.marquee__set i { color: var(--gold); font-style: normal; }

@keyframes roll { to { transform: translateX(-50%); } }

/* ── 공통 리빌 (IntersectionObserver 가 .is-visible 을 붙인다) ── */
[data-reveal] {
  opacity: 0;
  transform: translateY(var(--space-6));
  transition: opacity var(--duration-slow) var(--ease-out),
              transform var(--duration-slow) var(--ease-out);
  transition-delay: calc(var(--i, 0) * var(--duration-fast) * 0.6);
}
[data-reveal].is-visible { opacity: 1; transform: none; }

/* 리빌 변형 — 전부 같은 페이드업이면 아래로 갈수록 지루해진다.
   섹션 성격에 맞는 걸 골라 쓴다. (코드잇) */
[data-reveal="scale"]        { transform: scale(0.93); }         /* 카드류 */
[data-reveal="grow"]         { transform: scaleY(0.3);           /* 아래에서 자라남 */
                               transform-origin: bottom; }
[data-reveal="slide"]        { transform: translateX(calc(var(--dir, 1) * var(--space-9))); }
[data-reveal].is-visible     { transform: none; }

.section-head { padding: 0 var(--margin-desktop) var(--space-8); }

/* ── Brand Story — 좌우 역방향 패럴랙스 ────────────────── */
.story {
  --p: calc(var(--progress, 0) * var(--motion-scroll, 1));
  display: grid; gap: var(--space-8);
  grid-template-columns: 1fr 1fr;
  align-items: center;
  padding: var(--space-9) var(--margin-desktop);
}
/* 이미지는 느리게 올라오고, 텍스트는 반대로 내려간다 */
.story__media { transform: translateY(calc((0.5 - var(--p)) * var(--space-10))); }
.story__text  { transform: translateY(calc((var(--p) - 0.5) * var(--space-8))); }

/* ── Notes — 3카드 스태거 ─────────────────────────────── */
.notes { padding-bottom: var(--space-9); }

/* ── Notes — 대면 펼쳐지고, 나머지는 물러난다 ──────────────
   폭을 애니메이션하려면 grid 가 아니라 flex 여야 한다.
   grid-template-columns 는 브라우저에 따라 전환이 걸리지 않지만
   flex-grow 는 어디서나 애니메이션되는 숫자 속성이다.
   min-width:0 이 없으면 이미지가 카드를 밀어 줄어들지 않는다. */
.notes__grid {
  display: flex; gap: var(--space-6);
  padding-inline: var(--margin-desktop);
  align-items: flex-start;
}
.note {
  flex: 1 1 0; min-width: 0;
  transition: flex-grow var(--duration-slow) var(--ease-out),
              opacity var(--duration-base) var(--ease-out),
              filter var(--duration-base) var(--ease-out);
}

/* 1단계 — 격자 위에 마우스가 올라오면 전원 물러선다 */
.notes__grid:hover .note {
  flex-grow: 0.5;
  opacity: 0.28;
  filter: saturate(0.4);
}
/* 2단계 — 그중 대고 있는 하나만 앞으로 나온다.
   앞 규칙과 명시도가 같으므로 반드시 뒤에 와야 이긴다. */
.notes__grid .note:hover {
  flex-grow: 3.4;
  opacity: 1;
  filter: none;
}

.note img {
  width: 100%; height: 420px; object-fit: cover;
  margin-bottom: var(--space-5);
  transition: height var(--duration-slow) var(--ease-out);
}
/* 카드가 넓어지면 object-fit:cover 가 가로를 더 보여주고,
   높이까지 자라면서 완전히 다른 사진처럼 열린다. */
.notes__grid .note:hover img { height: 560px; }

/* 펼쳐진 카드에서만 설명이 길게 열린다 */
.note .body {
  max-height: 3.6em; overflow: hidden;
  transition: max-height var(--duration-slow) var(--ease-out);
}
.notes__grid .note:hover .body { max-height: 12em; }
.note__names {
  color: var(--text-accent);
  font-size: var(--text-caption);
  letter-spacing: var(--tracking-base);
  margin: var(--space-2) 0 var(--space-3);
}

/* ── Collection — 가로 핀 스크롤 ───────────────────────── */
.collection {
  --p: calc(var(--progress, 0) * var(--motion-scroll, 1));
  height: 300vh;
}
.collection__stage {
  position: sticky; top: 0;
  height: 100vh; overflow: hidden;
  display: flex; align-items: center;
}
.collection__track {
  display: flex; width: 200vw;
  transform: translateX(calc(var(--p) * -100vw));
}
.line {
  width: 100vw; flex-shrink: 0;
  display: grid; grid-template-columns: 1fr 1fr;
  gap: var(--space-8); align-items: center;
  padding-inline: var(--margin-desktop);
}
.line__media img { width: 100%; aspect-ratio: 1 / 1; object-fit: cover; }

/* ── Philosophy — 마스크 리빌 ──────────────────────────── */
.phil { padding-bottom: var(--space-9); }
.phil__grid {
  display: grid; gap: var(--space-7);
  grid-template-columns: repeat(3, 1fr);
  padding-inline: var(--margin-desktop);
}
.phil__item[data-reveal] {
  clip-path: inset(0 0 100% 0);
  transform: none;
  transition: clip-path var(--duration-cinematic) var(--ease-out),
              opacity var(--duration-slow) var(--ease-out);
  transition-delay: calc(var(--i, 0) * var(--duration-fast) * 0.8);
}
.phil__item[data-reveal].is-visible { clip-path: inset(0 0 0 0); }
.phil__num {
  font-family: var(--font-script-en);
  font-size: var(--text-h1);
  color: var(--text-accent);
  margin-bottom: var(--space-3);
}
.phil__item .h2 { margin-bottom: var(--space-3); }

/* ── Newsletter ───────────────────────────────────────── */
.news {
  text-align: center;
  padding: var(--space-9) var(--margin-desktop) var(--space-10);
}
.news__lead { margin: var(--space-4) auto 0; }
.news__form {
  display: flex; gap: var(--space-5);
  justify-content: center; align-items: flex-end;
  flex-wrap: wrap;
  margin-top: var(--space-7);
}
.field { position: relative; }
.field input {
  width: 22rem; max-width: 100%;
  padding: var(--space-3) 0;
  background: transparent; border: 0;
  border-bottom: 1px solid var(--border-hairline);
  color: var(--text-primary);
  font-family: inherit; font-size: var(--text-body);
}
.field input::placeholder { color: var(--text-secondary); }
.field input:focus { outline: none; }
.field__line {
  position: absolute; left: 0; right: 0; bottom: 0;
  height: 1px; background: var(--border-active);
  transform: scaleX(0); transform-origin: left;
  transition: transform var(--duration-base) var(--ease-out);
}
.field input:focus ~ .field__line { transform: scaleX(1); }
.news__form .btn { margin-top: 0; }

/* ── Footer ───────────────────────────────────────────── */
.foot {
  text-align: center;
  padding: var(--space-8) var(--margin-desktop);
  border-top: 1px solid var(--border-hairline);
}
.foot__mark {
  font-family: var(--font-serif-en);
  font-size: var(--text-h2);
  letter-spacing: var(--tracking-wide);
}
.foot__note {
  font-family: var(--font-script-en);
  color: var(--text-accent);
  margin: var(--space-2) 0 var(--space-5);
}
.foot__copy { font-size: var(--text-caption); color: var(--text-secondary); }

/* ── 반응형 ───────────────────────────────────────────── */
@media (max-width: 820px) {
  .nav { padding-inline: var(--margin-mobile); }
  .nav__links {
    position: absolute; inset: 100% 0 auto 0;
    flex-direction: column; gap: var(--space-5);
    padding: var(--space-6) var(--margin-mobile);
    background: var(--bg-secondary);
    display: none;
  }
  .nav__links.is-open { display: flex; }
  .nav__toggle { display: flex; }

  .story, .phil__grid, .line { grid-template-columns: 1fr; }

  /* 손가락에는 호버가 없다. 좁은 화면에서는 펼침을 끄고 세로로 쌓는다. */
  .notes__grid { flex-direction: column; }
  .notes__grid:hover .note,
  .notes__grid .note:hover {
    flex-grow: 1; opacity: 1; filter: none;
  }
  .notes__grid .note:hover img { height: 420px; }
  .note .body, .notes__grid .note:hover .body { max-height: none; }
  .story { padding-inline: var(--margin-mobile); }
  .notes__grid, .phil__grid, .line, .section-head { padding-inline: var(--margin-mobile); }
  .divider { padding-inline: var(--margin-mobile); }
  .story__media, .story__text { transform: none; }

  /* 좁은 화면에서 가로 핀은 답답하다 — 세로로 편다 */
  .collection { height: auto; }
  .collection__stage { position: static; height: auto; display: block; }
  .collection__track { width: 100%; flex-direction: column; transform: none; }
  .line { width: 100%; padding-block: var(--space-8); }
}

/* ── prefers-reduced-motion ──────────────────────────────
   --motion-scroll 이 0이 되어 변형은 멈추지만, 높이/sticky 는 CSS 가 직접 걷어내야
   빈 스크롤 구간이 남지 않는다. (tokens.css 주석 참고) */
/* 아래 규칙은 전부 :root:not([data-motion="force"]) 로 잠가둔다.
   기본값은 언제나 OS 설정을 따르고, 사람이 명시적으로 켤 때만 풀린다.
   (실습·발표 중에 정작 모션을 못 보여주는 상황을 막기 위한 장치) */
@media (prefers-reduced-motion: reduce) {
  /* stage 가 static 이 되면 절대배치된 .hero__video 의 기준이 stage(overflow:hidden)
     에서 .hero 로 옮겨간다. 그대로 두면 scale(1.04) 가 잘리지 않고 가로로 넘친다. */
  :root:not([data-motion="force"]) .hero { height: auto; overflow: hidden; }
  :root:not([data-motion="force"]) .hero__stage {
    position: static;
    height: 100vh;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
  }
  :root:not([data-motion="force"]) .hero__video { transform: none; }
  :root:not([data-motion="force"]) .hero__second {
    position: static; opacity: 1; transform: none; margin-top: var(--space-6);
  }
  :root:not([data-motion="force"]) .hero__copy { opacity: 1; transform: none; }

  :root:not([data-motion="force"]) .collection { height: auto; }
  :root:not([data-motion="force"]) .collection__stage {
    position: static; height: auto; display: block;
  }
  :root:not([data-motion="force"]) .collection__track {
    width: 100%; flex-direction: column; transform: none;
  }
  :root:not([data-motion="force"]) .line { width: 100%; padding-block: var(--space-8); }

  :root:not([data-motion="force"]) .story__media,
  :root:not([data-motion="force"]) .story__text { transform: none; }

  :root:not([data-motion="force"]) [data-reveal],
  :root:not([data-motion="force"]) .phil__item[data-reveal] {
    opacity: 1; transform: none; clip-path: none; transition: none;
  }
  :root:not([data-motion="force"]) .divider::before,
  :root:not([data-motion="force"]) .divider::after {
    transform: scaleX(1); transition: none;
  }
  /* 펼침 자체를 없애지는 않는다 — 정보가 사라지면 안 되니 전부 같은 크기로 둔다 */
  :root:not([data-motion="force"]) .notes__grid:hover .note,
  :root:not([data-motion="force"]) .notes__grid .note:hover {
    flex-grow: 1; opacity: 1; filter: none; transition: none;
  }
  :root:not([data-motion="force"]) .notes__grid .note:hover img { height: 420px; }
  :root:not([data-motion="force"]) .note .body,
  :root:not([data-motion="force"]) .notes__grid .note:hover .body {
    max-height: none; transition: none;
  }

  /* 앰비언트 루프는 --duration-* 토큰을 쓰지 않고 초를 직접 적었으므로
     토큰을 1ms 로 낮추는 것으로는 꺼지지 않는다. 여기서 직접 끈다.
     끄기만 하면 시작 프레임에 멈추므로 최종 상태도 같이 지정해야 한다. */
  :root:not([data-motion="force"]) .hero__grad,
  :root:not([data-motion="force"]) .divider__mark,
  :root:not([data-motion="force"]) .marquee__track { animation: none; }
  :root:not([data-motion="force"]) .hero__title .word,
  :root:not([data-motion="force"]) .hero__title .word__in {
    animation: none; opacity: 1; transform: none;
  }
  /* 흐르지 않는 마퀴는 잘린 문장일 뿐이다 */
  :root:not([data-motion="force"]) .marquee { display: none; }
}

/* 모션이 꺼져 있다는 사실과 켜는 법을 알려주는 띠 */
.motion-bar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
  display: none;
  align-items: center; justify-content: center; gap: var(--space-4);
  padding: var(--space-3) var(--space-5);
  background: var(--bg-secondary);
  border-top: 1px solid var(--border-hairline);
  font-size: var(--text-caption);
  letter-spacing: var(--tracking-base);
  color: var(--text-secondary);
}
:root[data-motion-off="true"] .motion-bar { display: flex; }
.motion-bar button {
  padding: var(--space-2) var(--space-5);
  background: transparent;
  border: 1px solid var(--border-active);
  color: var(--text-accent);
  font: inherit; letter-spacing: var(--tracking-button);
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease-out),
              color var(--duration-fast) var(--ease-out);
}
.motion-bar button:hover, .motion-bar button:focus-visible {
  background: var(--bg-inverse); color: var(--text-inverse);
}
