@charset "utf-8";

/* =========================================================
   main 페이지 전용 토큰
   --color_bg_alt는 공통 tokens.css에 없고 shop.css의 :root에만
   있던 값입니다. main은 shop.css를 불러오지 않으므로 같은 값을
   여기에 정의합니다.
   ========================================================= */

:root {
  --color_bg_alt: #f7f7f7;

  /* ★★ 화면 끝까지 채우는(full-bleed) 요소는 100vw 대신 반드시 이 변수를 쓰세요.

     1850~1990px에서 common/css/common.css가 `html { zoom: 0.75 }`를 겁니다.
     이때 100vw는 **축소되기 전 화면 폭**(1920px)으로 계산된 뒤 그려질 때 0.75가
     곱해져 1440px이 됩니다. 그래서 좌우에 233px씩 배경이 드러나 띠가 벽에 막힌
     것처럼 보였습니다(shop 마퀴 · collection 3D 스테이지에서 실제로 발생).

     축소 비율로 미리 나눠 두면 그려질 때 정확히 화면 폭이 됩니다.
     --site_view_scale은 그 구간에만 선언돼 있어 다른 폭에서는 폴백 1이 쓰입니다.

     100vw에는 스크롤바가 포함돼 실제 화면보다 약 15px 넓지만,
     common.css의 `body { overflow-x: hidden }`이 그만큼을 잘라내 가로 스크롤은
     생기지 않습니다. */
  --full_bleed_width: calc(100vw / var(--site_view_scale, 1));

  /* ★ 세로(100vh)에는 같은 보정을 하지 마세요.
     고정 구간의 높이는 이 파일 아래쪽 `.pin-spacer:has(...)` 역보정이 이미
     처리합니다. ScrollTrigger가 **역보정이 걸리기 전에** 잰 높이를 인라인으로
     박는데, 그 값이 역보정 안에서 정확히 1/0.75배가 되어 서로 상쇄됩니다.
     여기서 100vh를 미리 나눠 두면 이중 보정이 되어 섹션이 화면보다 커집니다
     (실제로 1440px이 나와 아래가 잘렸습니다). */
}

/* =========================================================
   hero — bespoke / shop 2분할
   ========================================================= */

.hero {
  display: flex;
  flex-direction: column;
}

.hero_panel {
  --hero_copy_shade: 0.48;
  position: relative;
  overflow: hidden;
  width: 100%;
  min-height: 520px;
  height: 80vh;
  transition: box-shadow var(--duration_base) var(--easing_base);
}

/* 사진의 밝은 영역 위에서도 흰 카피가 안정적으로 읽히도록 텍스트가 놓이는
   하단만 어둡힙니다. 사진 전체를 덮지 않아 원본 색감과 인물은 유지됩니다. */
.hero_panel::before {
  position: absolute;
  inset: 34% 0 0;
  z-index: 1;
  background: linear-gradient(
    to bottom,
    rgba(10, 10, 10, 0) 0%,
    rgba(10, 10, 10, 0.08) 30%,
    rgba(10, 10, 10, var(--hero_copy_shade)) 100%
  );
  content: "";
  pointer-events: none;
}

/* hover 중 반대편 패널만 은은하게 어둡게 해 선택한 히어로에 시선을 모읍니다. */
.hero_panel::after {
  position: absolute;
  inset: 0;
  z-index: 1;
  background-color: rgba(10, 10, 10, 0.42);
  content: "";
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--duration_base) var(--easing_base);
}

.hero_panel.is_dimmed::after {
  opacity: 1;
}

.hero_panel.is_active {
  z-index: 1;
  box-shadow: 0 0 42px rgba(10, 10, 10, 0.24);
}

/* 사진이 잘리는 기준 위치를 직접 조정하려면 이 두 값만 바꾸면 됩니다.
   "가로 세로" 순서로 적습니다 — 가로는 left(0%) ~ right(100%)/center(가운데),
   세로는 top(0%) ~ bottom(100%)/center(가운데)이고 %값으로도 조정할 수 있습니다.
   (예: "center 30%"로 하면 지금보다 사진이 조금 더 아래쪽을 기준으로 잘립니다) */
.hero_panel_bespoke {
  --hero_img_position: center top;
  --hero_copy_shade: 0.58;
  background-color: #f3f1ed;
}

.hero_panel_img {
  position: absolute;
  inset: 0;
  width: 100%;
  max-width: none;
  height: 100%;
  object-fit: cover;
  object-position: var(--hero_img_position, top);
  opacity: 0.9;
  pointer-events: none;
}

/* 오른쪽 히어로 (지금 작업한 확대+이동) */
.hero_panel_shop {
  --hero_copy_shade: 0.42;
  position: relative;
  overflow: hidden;
}

.hero_panel_shop .hero_panel_img {
  object-position: 100% 70%;
  transform: scale(1.15) translate(8%, 5%);
  transform-origin: center;
}

/* 왼쪽 히어로: transform 확대 없이 패널 가로폭을 채우고 위쪽을 기준으로 잘라
   얼굴과 상체가 먼저 보이게 합니다. */
.hero_panel_bespoke .hero_panel_img {
  object-position: center top;
  transform: none;
}

.hero_panel_video {
  position: absolute;
  inset: 0;
  width: 100%;
  max-width: none;
  height: 100%;
  object-fit: cover;
  object-position: top;
  opacity: 0;
  pointer-events: none;
}

.hero_panel_body {
  position: absolute;
  right: var(--layout_gutter);
  bottom: 48px;
  left: var(--layout_gutter);
  z-index: 2;
}

.hero_panel_title {
  color: var(--color_text_on_dark);
  font-family: var(--font_display);
  font-size: var(--fs_display_48);
  font-weight: 600;
  line-height: var(--lh_display_48);
  letter-spacing: var(--ls_tight);
  text-shadow: 0 1px 8px rgba(10, 10, 10, 0.24);
}

.hero_panel_desc {
  max-width: 395px;
  margin-top: 3px;
  color: var(--color_text_on_dark);
  font-family: var(--font_body);
  font-size: var(--fs_body_20);
  font-weight: 400;
  line-height: var(--lh_body_20);
  text-shadow: 0 1px 7px rgba(10, 10, 10, 0.28);
}

.hero_panel_button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-top: 36px;
  padding: 10px 20px;
  border: 1px solid var(--color_line_on_dark);
  border-radius: var(--radius_button);
  color: var(--color_text_on_dark);
  font-family: var(--font_body);
  font-size: var(--fs_body_20);
  font-weight: 500;
  line-height: 1.5;
  transition: background-color var(--duration_fast) var(--easing_base),
              border-color var(--duration_fast) var(--easing_base);
}

.hero_panel_button:hover,
.hero_panel_button:focus-visible {
  border-color: var(--color_text_on_dark);
  background-color: rgba(255, 255, 255, 0.14);
}

@media (min-width: 768px) {
  .hero {
    flex-direction: row;
  }

  .hero_panel {
    width: 50%;
    height: 100vh;
    min-height: 600px;
  }

  .hero_panel_body {
    bottom: 120px;
  }
}

@media (min-width: 1280px) {
  .hero_panel {
    height: 986px;
  }

  .hero_panel_body {
    right: auto;
    left: 80px;
  }
}

/* =========================================================
   brand_story — 브랜드 한 줄 소개 + 배너 (Figma node 1794:7100)
   ========================================================= */

/* 글과 배너가 두 조각으로 읽히지 않게 묶되, **배너는 시안(1794:7100)대로 화면 끝까지
   닿습니다**(full-bleed). 한 덩어리로 보이게 하는 것은 여백을 두른 액자가 아니라
   글과 배너 사이 간격입니다 — 섹션에는 좌우·아래 padding을 두지 않고, 글상자만
   자기 여백을 갖고 아래쪽만 좁혀 배너를 바짝 붙입니다.
   ★ 섹션에 좌우 padding을 주면 배너가 안으로 들어와 꽉 차 보이지 않습니다. */
.brand_story {
  display: flex;
  flex-direction: column;
  background-color: #0a0a0a;
}

.brand_story_textbox {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 16px;
  padding: 48px var(--layout_gutter) 28px;
}

.brand_story_title {
  color: var(--color_text_inverse);
  font-family: var(--font_display);
  font-size: var(--fs_display_48);
  font-weight: 600;
  line-height: var(--lh_display_48);
  letter-spacing: var(--ls_tight);
}

.brand_story_desc {
  color: var(--color_text_inverse);
  font-family: var(--font_body);
  font-size: var(--fs_body_20);
  font-weight: 400;
  line-height: var(--lh_body_20);
}

.brand_story_link {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding-bottom: 3px;
  border-bottom: 1px solid var(--color_text_inverse);
  color: var(--color_text_inverse);
  font-family: var(--font_body);
  font-size: 11px;
  font-weight: 600;
  line-height: 1.55;
  letter-spacing: 2.42px;
  text-transform: uppercase;
}

.brand_story_link_icon {
  width: 15px;
  height: 15px;
}

.brand_story_banner {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 1024 / 384;
  object-fit: cover;
}

@media (min-width: 1280px) {
  .brand_story_textbox {
    gap: 10px;
    padding: 100px 120px 48px;
  }
}

/* =========================================================
   model — 스크롤에 따라 영상이 재생되는 고정 장면
   ========================================================= */

.model {
  position: relative;
  min-height: 100dvh;
  padding: 0;
  overflow: clip;
  background-color: var(--color_bg);
}

.model_container {
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: clamp(24px, 4dvh, 48px);
}

.model_figure {
  width: min(544px, 48dvh, 88vw);
  aspect-ratio: 544 / 720;
  flex: none;
}

/* 스크롤 연출이 실제로 초기화된 경우에만 GPU 레이어를 준비합니다.
   GSAP 또는 영상이 동작하지 않으면 기존 정적 배치 그대로 유지됩니다. */
.model.is_scroll_ready .model_figure {
  will-change: transform;
}

/* 데스크탑 model flow — 화면을 pin하지 않고 실제로 긴 섹션을 내려갑니다.
   ★ 전체 길이는 --model_flow_height, 첫 위치는 figure/text의 top에서 조절합니다. */
@media (min-width: 1280px) {
  .model.is_model_flow {
    /* ★ 데스크탑 진행 길이 조절 위치입니다.
       값을 줄이면 모델 섹션의 빈 여백과 도착까지 필요한 스크롤이 함께 짧아집니다.
       현재 170dvh는 도착까지 필요한 스크롤을 더 줄여 움직임을 빠르게 보여줍니다. */
    --model_flow_height: 170dvh;
    min-height: var(--model_flow_height);
    /* 마지막 모델이 다음 detail_head 영역까지 이어져 보이도록 세로 클리핑만 해제합니다. */
    overflow: visible;
  }

  .model.is_model_flow .model_container {
    position: relative;
    display: block;
    min-height: var(--model_flow_height);
  }

  .model.is_model_flow .model_figure {
    position: absolute;
    top: 3dvh;
    left: 50%;
    z-index: 1;
    translate: -50% 0;
    pointer-events: none;
  }

  .model.is_model_flow .model_text {
    position: absolute;
    z-index: 2;
    /* 원래 순서인 모델 → 텍스트로 복구합니다.
       모델 높이(최대 720px / 화면 높이 기준 63.53dvh)와 기존 간격을 합친 위치입니다. */
    top: calc(3dvh + min(720px, 63.53dvh) + clamp(24px, 4dvh, 48px));
    left: 50%;
    width: min(760px, calc(100% - (var(--layout_gutter) * 2)));
    translate: -50% 0;
  }
}

.model_video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.model_text {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  text-align: center;
}

.model_title {
  color: var(--color_text);
  font-family: var(--font_display);
  font-size: clamp(28px, 4.5vw, 52px);
  font-weight: 400;
  line-height: 1.2;
  letter-spacing: var(--ls_tight);
}

.model_desc {
  color: var(--color_text);
  font-family: var(--font_body);
  font-size: var(--fs_ui_16);
  line-height: 1.63;
}

@media (max-width: 767px) {
  .model_container {
    gap: 24px;
  }

  .model_figure {
    width: min(440px, 46dvh, 88vw);
  }

  /* 360px 화면에서는 88vw 모델이 좌우로 움직일 공간이 거의 없습니다.
     스크롤 연출이 켜졌을 때만 폭을 줄여 양쪽 모두 화면 안에 남게 합니다. */
  .model.is_scroll_ready .model_figure {
    width: min(440px, 46dvh, 72vw);
  }
}

@media (prefers-reduced-motion: reduce) {
  .model_figure {
    transform: none;
  }
}

/* =========================================================
   brand_word — brand_01~04, 화면을 채우는 초대형 워드마크
   (Figma node 1712:4331~4337)
   기본은 4개가 세로로 쌓인 레이아웃(JS 미동작·모션 감소 시 그대로 사용).
   js/main.js가 .is_pinned를 붙이면 한 화면에 고정된 채 글자만 바뀝니다.
   ========================================================= */

.brand_word_pin {
  /* Figma 2068:7415 — detail 다음 장면을 따뜻하게 구분하고, 아래로 갈수록
     페이지 기본 크림색으로 자연스럽게 이어지는 수직 그라디언트입니다. */
  background-image: linear-gradient(
    to bottom,
    var(--color_surface_subtle, #f5efe4) 0%,
    var(--color_bg, #fffdf9) 100%
  );
}

.brand_word_pin.is_pinned {
  position: relative;
  height: 100vh;
  min-height: 600px;
  overflow: hidden;
  /* 그라디언트 아래의 기본색도 명시해 로딩 중 배경이 비치지 않게 합니다. */
  background-color: var(--color_bg);
}

.brand_word_pin.is_pinned .brand_word,
.brand_word_pin.is_pinned .brand_collage {
  position: absolute;
  inset: 0;
  min-height: 0;
  opacity: 0;
}

.brand_word_pin.is_pinned .brand_word.is_active,
.brand_word_pin.is_pinned .brand_collage.is_active {
  opacity: 1;
}

.brand_word {
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  min-height: 60vh;
  padding: 60px var(--layout_gutter);
}

.brand_word_text {
  color: var(--color_text);
  font-family: var(--font_display);
  font-size: clamp(40px, 12vw, 174px);
  font-weight: 600;
  line-height: 1.13;
  letter-spacing: -0.02em;
  text-align: center;
  white-space: nowrap;
}

.brand_word_split {
  flex-wrap: wrap;
  justify-content: center;
  gap: clamp(20px, 6vw, 240px);
}

.brand_word_split .brand_word_text {
  font-size: clamp(32px, 9vw, 174px);
}

@media (min-width: 1280px) {
  .brand_word {
    min-height: 1080px;
  }
}

/* =========================================================
   brand_collage — brand_05/06, 겹친 이미지 카드 + 워드마크
   (Figma node 1712:4341, 1712:4362)
   ========================================================= */

.brand_collage {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  min-height: 80vh;
  padding: 60px var(--layout_gutter);
}

.brand_collage_cards {
  position: relative;
  z-index: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 40px;
  width: 100%;
  max-width: 1603px;
}

.brand_collage_row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 20px;
  width: 100%;
}

.brand_collage_group_title {
  display: none;
}

.brand_collage_card {
  flex: 0 0 auto;
  position: relative;
  width: 20%;
  max-width: 287px;
  aspect-ratio: 180 / 242.61;
  overflow: hidden;
  backface-visibility: hidden;
  transform-origin: 50% 50%;
  will-change: transform, opacity;
}

.brand_collage_card.is_size_sm {
  width: 20%;
  max-width: 287px;
}

.brand_collage_card.is_dim {
  opacity: 1;
}

.brand_collage_card img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  backface-visibility: hidden;
}

.brand_collage_name {
  position: absolute;
  z-index: 1;
  top: 50%;
  left: 50%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 24px;
  width: 100%;
  max-width: 1920px;
  transform: translate(-50%, -50%);
  color: var(--color_text);
  font-family: var(--font_display);
  font-size: clamp(28px, 6vw, 96px);
  font-weight: 600;
  line-height: 1.13;
  letter-spacing: -0.02em;
  text-align: center;
  white-space: nowrap;
  pointer-events: none;
}

/* JS 향상 상태에서는 이름과 사진의 시작값을 숨겨 두고, 스크롤 진행률에 따라
   js/main.js가 opacity와 transform을 직접 갱신합니다. */
.brand_collage.is_enhanced .brand_collage_cards {
  opacity: 0;
  transform: scale(0.92);
}

.brand_collage.is_enhanced .brand_collage_name_left,
.brand_collage.is_enhanced .brand_collage_name_right {
  /* transform은 js/main.js의 GSAP 타임라인이 매 스크롤 프레임마다 직접 씁니다.
     여기서 CSS transition을 같이 걸면 GSAP 값과 서로 쫓아가며 밀리는 문제가 생겨 뺐습니다. */
  display: inline-block;
}

/* ★ will-change에 filter를 넣지 마세요. 예전에는 글자 17개가 각각
   filter: blur()를 스크롤에 맞춰 애니메이션했는데, blur는 합성만으로 처리되지 않아
   **글자마다 매 프레임 다시 그려졌습니다.** 이 섹션부터 스크롤이 버벅인 주된
   원인이었습니다. 등장 연출은 transform(scale·skew·이동)과 opacity로만 만듭니다 —
   둘 다 GPU 합성으로 끝나 페인트가 0입니다. */
.brand_collage_letter {
  display: inline-block;
  will-change: transform, opacity;
}

/* 중앙 카드 덱 카피 — 레퍼런스의 6개 텍스트 위계를 카드 주변에 배치합니다. */
.brand_stack_copy {
  position: absolute;
  z-index: 21;
  inset: 0;
  color: var(--color_text);
  font-family: var(--font_body);
  pointer-events: none;
}

.brand_stack_copy [data-copy-slot]:empty {
  display: none;
}

.brand_stack_text_item {
  display: block;
  opacity: 0;
}

.brand_stack_text_item:not(.is_active) {
  position: absolute;
  inset: 0;
}

.brand_stack_text_item.is_active {
  opacity: 1;
}

.brand_stack_intro,
.brand_stack_statement {
  position: absolute;
  top: 15%;
  width: 32%;
  font-size: clamp(14px, 1.25vw, 24px);
  line-height: 1.25;
}

.brand_stack_intro {
  left: 2%;
}

.brand_stack_statement {
  top: 36%;
  right: 2%;
  text-align: right;
}

.brand_stack_title {
  position: absolute;
  z-index: 1;
  top: 43%;
  left: 27%;
  width: 46%;
  padding: 0 16px 8px;
  border-bottom: 1px solid rgba(10, 10, 10, 0.18);
  font-family: var(--font_display);
  font-size: clamp(24px, 2.5vw, 48px);
  line-height: 1;
}

.brand_stack_title_item {
  position: absolute;
  left: 16px;
  bottom: 8px;
  opacity: 0;
  white-space: nowrap;
}

.brand_stack_title_item.is_active {
  position: relative;
  left: auto;
  bottom: auto;
  opacity: 1;
}

.brand_stack_title_item:empty {
  display: none;
}

.brand_stack_description {
  position: absolute;
  bottom: 18%;
  left: 10%;
  width: 20%;
  font-size: clamp(13px, 1vw, 20px);
  line-height: 1.25;
}

.brand_stack_count {
  --ring_progress: 25%;
  position: absolute;
  top: 52%;
  left: 67%;
  display: flex;
  align-items: center;
  justify-content: center;
  width: clamp(76px, 6vw, 116px);
  aspect-ratio: 1;
  font-family: var(--font_display);
  font-size: clamp(24px, 2.2vw, 42px);
  line-height: 1;
}

.brand_stack_count::before,
.brand_stack_count::after {
  position: absolute;
  content: "";
  border-radius: 50%;
}

.brand_stack_count::before {
  inset: 0;
  border: 1px solid rgba(10, 10, 10, 0.12);
}

.brand_stack_count::after {
  inset: 10%;
  background: conic-gradient(
    from 210deg,
    rgba(10, 10, 10, 0.48) 0 var(--ring_progress),
    rgba(10, 10, 10, 0.08) var(--ring_progress) 100%
  );
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 1px), #000 0);
  mask: radial-gradient(farthest-side, transparent calc(100% - 1px), #000 0);
}

.brand_stack_count_current {
  position: relative;
  width: 0.58em;
  height: 1em;
  overflow: hidden;
}

.brand_stack_count_item {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  opacity: 0;
}

.brand_stack_count_item.is_active {
  opacity: 1;
}

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

/* ★ 기본을 딥그린으로 채웁니다. 예전에는 흰 바탕이라 배경(크림·사진) 위에서
   그냥 흰 카드로 보여 "누를 수 있다"는 신호가 없었습니다.

   버튼임을 알리는 장치를 겹쳐 두었습니다 — 실무에서 1차 CTA에 쓰는 조합입니다.
     1. 채워진 브랜드 색 + 굵은 글씨   (주변 어떤 요소와도 다른 생김새)
     2. 그림자                          (페이지 위에 떠 있는 물체로 읽힘)
     3. 가만히 있을 때의 미세한 상하 움직임과 빛 스침 (시선을 끄는 신호)
     4. 호버에서 살짝 뜨고 그림자가 커짐 (마우스에 반응한다)
     5. 누르는 순간 내려앉음            (실제로 눌린다)
   ★ 하나만 남기면 신호가 약해집니다. 특히 2·4·5는 세트입니다. */
.brand_stack_action {
  --brand_stack_action_bottom: 12%; /* 숫자가 클수록 버튼이 위로 올라갑니다 */
  /* 호버에서 차오르는 더 짙은 초록. 기본색과 같으면 차오르는 게 안 보입니다 */
  --brand_stack_action_deep: #16332f;

  position: absolute;
  right: 18%;
  bottom: var(--brand_stack_action_bottom);
  width: min(248px, 18vw);
  min-height: 64px;
  padding: 16px;
  border-radius: 8px;
  background-color: var(--color_point);
  /* 표면을 천천히 스치는 빛. 배경색 위에 얹는 그라디언트라 가짜 요소를 하나 더
     만들 필요가 없습니다(::before·::after는 이미 쓰고 있습니다). */
  background-image: linear-gradient(
    100deg,
    rgba(255, 255, 255, 0) 38%,
    rgba(255, 255, 255, 0.18) 50%,
    rgba(255, 255, 255, 0) 62%
  );
  background-repeat: no-repeat;
  background-size: 250% 100%;
  background-position: 200% 0;
  box-shadow: 0 10px 24px rgba(31, 67, 63, 0.28);
  color: var(--color_text_inverse);
  font-size: 14px;
  font-weight: 600;
  line-height: 1.2;
  text-decoration: none;
  overflow: hidden;
  isolation: isolate;
  pointer-events: auto;
  cursor: pointer;
  /* ★ 떠 있는 움직임은 translate, 호버 반응은 transform으로 나눠 씁니다.
     둘은 서로 다른 CSS 속성이라 함께 적용돼도 덮어쓰지 않습니다. */
  animation:
    brand_stack_action_float 3.4s ease-in-out infinite,
    brand_stack_action_sheen 4.6s ease-in-out infinite;
  transition:
    transform 0.4s var(--easing_base),
    /* ★ background-color가 필요합니다. 카피가 김영진 ↔ 차이킴으로 바뀔 때 바탕색도
       핑크 ↔ 그린으로 함께 바뀌는데, 이게 없으면 글자는 0.3초에 걸쳐 크로스페이드
       되는데 바탕만 한 프레임에 툭 갈립니다. box-shadow와 같은 0.4초라 그림자와
       바탕이 한 몸으로 움직입니다. 호버에는 영향이 없습니다 — 호버는 바탕색이 아니라
       ::before가 차오르는 방식입니다. */
    background-color 0.4s var(--easing_base),
    box-shadow 0.4s var(--easing_base),
    color 0.9s cubic-bezier(0.35, 0.35, 0, 1);
}

.brand_stack_action::before,
.brand_stack_action::after {
  position: absolute;
  content: "";
}

/* 호버에서 아래에서 차올라 버튼을 채우는 층. 기본 딥그린보다 더 짙은 색이라
   차오르는 것이 보입니다(둘이 같으면 아무 변화가 없습니다). */
.brand_stack_action::before {
  z-index: -1;
  inset: 0;
  border-radius: 50% 50% 0 0;
  background-color: var(--brand_stack_action_deep);
  translate: 0 101%;
  transition:
    border-radius 0.9s cubic-bezier(0.35, 0.35, 0, 1),
    translate 0.9s cubic-bezier(0.35, 0.35, 0, 1);
}

/* 오른쪽 아래에서 좌우로 오가는 점 — 초록 위에 놓이므로 밝은 색입니다 */
.brand_stack_action::after {
  z-index: 2;
  right: 12px;
  bottom: 10px;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background-color: var(--color_text_inverse);
  animation: brand_stack_action_dot_slide 1.6s ease-in-out infinite;
  transition:
    background-color 0.9s cubic-bezier(0.35, 0.35, 0, 1),
    scale 0.9s cubic-bezier(0.35, 0.35, 0, 1);
}

/* 마우스를 올리면 살짝 떠오르고 그림자가 커집니다 — "반응한다"는 신호 */
.brand_stack_action:hover,
.brand_stack_action:focus-visible {
  transform: translateY(-3px);
  box-shadow: 0 18px 34px rgba(31, 67, 63, 0.38);
  color: var(--color_text_inverse);
  animation-play-state: paused;
}

/* 누르는 순간 내려앉습니다 — 실제로 눌린다는 신호 */
.brand_stack_action:active {
  transform: translateY(0);
  box-shadow: 0 6px 14px rgba(31, 67, 63, 0.3);
  transition-duration: 0.08s;
}

.brand_stack_action:hover::before,
.brand_stack_action:focus-visible::before {
  border-radius: 0;
  translate: 0 0;
}

.brand_stack_action:hover::after,
.brand_stack_action:focus-visible::after {
  scale: 0.85;
  animation-play-state: paused;
}

/* 김영진 카피일 때의 핑크. 위 그린 버튼과 **구조는 완전히 같고 색만 바꿉니다** —
   떠 있는 움직임, 빛 스침, 차오르는 층, 점, 누름 반응을 하나도 건드리지 않습니다.

   ★★ 선택자가 class가 아니라 [data-brand="youngjin"]입니다.
     이 버튼은 카드 덱 3/4 지점에서 카피가 "DISCOVER TCHAI KIM"으로 바뀝니다.
     브랜드 색이 **김영진 = 핑크 / 차이킴 = 그린**이라 색도 함께 돌아가야 하는데,
     그 전환은 js/main.js의 GSAP 스크럽 타임라인이 tl.set(attr)로 처리합니다.
     href·aria-label과 **한 속성 묶음**에 넣어 두면 셋이 절대 어긋나지 않고,
     되감을 때 GSAP이 "youngjin"으로 알아서 되돌립니다.
     ★ 여기를 .is_pink로 되돌리면 차이킴 카피에서도 핑크가 남습니다.

   바꿔야 하는 것이 넷입니다. 하나라도 빼면 티가 납니다.
     1. background-color            — 버튼 바탕
     2. --brand_stack_action_deep   — 호버에서 아래에서 차오르는 층
     3. box-shadow 3개              — 초록빛 그림자가 남으면 핑크 버튼에 초록 테가 집니다
     4. ::after 점                  — 크림 그대로입니다(핑크 위 4.76:1로 보입니다)

   ★ 그림자 색은 버튼 색과 같은 계열이어야 합니다. rgba(31, 67, 63, …)를 그대로 두면
     핑크 버튼 아래에 초록 그림자가 깔립니다. 아래 세 줄은 --color_point_pink의
     rgb(150, 102, 88)에 원래와 같은 투명도(0.28 / 0.38 / 0.3)를 씌운 값입니다. */
.brand_stack_action[data-brand="youngjin"] {
  --brand_stack_action_deep: var(--color_point_pink_deep);

  background-color: var(--color_point_pink);
  box-shadow: 0 10px 24px rgba(150, 102, 88, 0.28);
}

.brand_stack_action[data-brand="youngjin"]:hover,
.brand_stack_action[data-brand="youngjin"]:focus-visible {
  box-shadow: 0 18px 34px rgba(150, 102, 88, 0.38);
}

.brand_stack_action[data-brand="youngjin"]:active {
  box-shadow: 0 6px 14px rgba(150, 102, 88, 0.3);
}

@keyframes brand_stack_action_float {
  0%,
  100% {
    translate: 0 0;
  }
  50% {
    translate: 0 -6px;
  }
}

/* 빛이 왼쪽으로 한 번 스치고, 화면 밖에 머물다가 다시 시작합니다.
   양 끝 모두 버튼 밖이라 되돌아가는 순간은 보이지 않습니다. */
@keyframes brand_stack_action_sheen {
  0% {
    background-position: 200% 0;
  }
  55%,
  100% {
    background-position: -60% 0;
  }
}

@keyframes brand_stack_action_dot_slide {
  0%,
  100% {
    translate: 0 0;
  }
  50% {
    translate: -5px 0;
  }
}

.brand_stack_action:focus-visible {
  outline: 2px solid var(--color_text);
  outline-offset: 4px;
}

.brand_stack_action .brand_stack_text_item {
  position: relative;
  z-index: 1;
}

.brand_stack_action .brand_stack_text_item:not(.is_active) {
  position: absolute;
  inset: 16px;
}

@media (prefers-reduced-motion: reduce) {
  .brand_stack_action,
  .brand_stack_action::before,
  .brand_stack_action::after {
    animation: none;
    transition-duration: 0.01ms;
  }
}

.brand_collage_lg .brand_collage_card {
  max-width: 337px;
}

.brand_collage_lg .brand_collage_card.is_size_sm {
  max-width: 292px;
}

@media (min-width: 1280px) {
  .brand_collage {
    min-height: 1080px;
  }

  .brand_collage_name {
    flex-direction: row;
    justify-content: center;
    gap: clamp(60px, 6vw, 120px);
    white-space: nowrap;
  }

  .brand_collage_card,
  .brand_collage_card.is_size_sm {
    width: min(14.0625vw, 287px);
  }
}

/* =========================================================
   detail — 저고리 한 장을 부위별로 확대해 보여줍니다
   (Figma node 1712:4259, 4277, 4295, 4313의 확대컷·설명을 한 섹션에 모음)

   두 가지 방식이 겹쳐 있습니다.

   1) 기본 — 사진 + 버튼 4개(.detail_part_tab) + 설명 하나. 어느 부위를 보여줄지는
      .detail_stage의 data-active-part가 정합니다. 스크립트가 없어도, GSAP이 막혀도,
      모션을 줄이는 설정이어도, 좁은 화면이어도 이 방식이 그대로 남습니다.

   2) 스크롤 연출 — js/main.js가 .detail에 .is_scroll_ready를 붙였을 때만.
      섹션이 화면에 고정된 채 스크롤에 따라 돋보기(.detail_lens)가 네 부위를 차례로
      훑고, 그 자리에 설명(.detail_text)이 하나씩 나타납니다.

   ★ 두 방식의 규칙은 서로 다른 부모 선택자(:not(.is_scroll_ready) / .is_scroll_ready)
     로 갈라 두었습니다. 한쪽을 고칠 때 다른 쪽에 새지 않게 하기 위한 것이니,
     새 규칙도 반드시 둘 중 한 곳에 넣으세요.

   ★ 마우스 호버는 쓰지 않습니다. 예전에는 커서를 따라다니는 돋보기였는데, 올려보기
     전에는 인터랙션이 있는지 알 수 없고 손가락으로는 "지나간다"가 없어 터치 기기에서
     아예 성립하지 않았습니다. 스크롤은 두 환경에서 똑같이 동작합니다.
   ========================================================= */

.detail {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 60px;
  padding: 80px 0 60px;
  /* 위의 model 섹션과 같은 배경 토큰을 사용해 두 구간의 경계가 드러나지 않게 합니다. */
  background-color: var(--color_bg);
}

/* 시안: header는 items-start(왼쪽 정렬), 페이지 폭 그대로(px-120), 가운데 정렬이 아닙니다 */
.detail_head {
  position: relative;
  /* 모델 영상이 이 영역까지 내려와도 제목과 설명은 항상 영상 위에 보입니다. */
  z-index: 3;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 17px;
  text-align: left;
}

/* 데스크탑에서 brand_story_textbox와 제목 시작선을 맞춥니다.
   common_container의 max-width가 1920px 화면에서 Detail만 안쪽으로 밀기 때문에
   이 헤더에 한해서 폭 제한을 풀고 Brand와 동일한 120px 패딩을 사용합니다. */
@media (min-width: 1280px) {
  .detail_head.common_container {
    max-width: none;
    margin-inline: 0;
    padding-inline: 120px;
  }
}

.detail_title {
  color: var(--color_text);
  font-family: var(--font_display);
  font-size: var(--fs_display_64);
  font-weight: 600;
  line-height: var(--lh_display_64);
  letter-spacing: var(--ls_tight);
}

.detail_subtitle {
  color: var(--color_text_sub);
  font-family: var(--font_body);
  font-size: var(--fs_body_20);
  font-weight: 400;
  line-height: var(--lh_body_20);
}

.detail_stage {
  position: relative;
}

.detail_img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4380 / 1905;
}

.detail_part_title {
  margin-bottom: 11px;
  color: var(--color_point);
  font-family: var(--font_display);
  font-size: clamp(28px, 3.3vw, 48px);
  font-weight: 600;
  line-height: var(--lh_display_48);
  letter-spacing: var(--ls_tight);
}

.detail_part_lead {
  color: var(--color_text);
  font-family: var(--font_body);
  font-size: clamp(16px, 1.7vw, 24px);
  font-weight: 400;
  line-height: 1.58;
}

.detail_part_desc {
  color: var(--color_text);
  font-family: var(--font_body);
  font-size: var(--fs_ui_16);
  font-weight: 400;
  line-height: 1.63;
}

.detail_parts {
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 24px;
}

/* 스크롤 연출 전용 현재 부위 인디케이터. 기본 버튼 방식에서는 표시하지 않습니다. */
.detail_keywords {
  display: none;
}

.detail_part_tab {
  /* 손가락으로 누르는 버튼이라 높이를 44px 이상으로 잡습니다 */
  padding: 12px 18px;
  border: 1px solid var(--color_border);
  border-radius: 999px;
  background-color: transparent;
  color: var(--color_text_secondary);
  font-family: var(--font_ui);
  font-size: var(--fs_ui_14);
  font-weight: 500;
  letter-spacing: var(--ls_tight_sm);
  cursor: pointer;
  transition:
    background-color var(--duration_fast) ease,
    border-color var(--duration_fast) ease,
    color var(--duration_fast) ease;
}

/* 선택 상태를 색으로만 알리지 않습니다 — 글자 굵기와 테두리도 함께 바뀌고,
   읽기 도구에는 aria-pressed로 전달됩니다(js/main.js가 갱신). */
.detail_part_tab[aria-pressed="true"] {
  border-color: var(--color_point);
  background-color: var(--color_point);
  color: var(--color_text_inverse);
  font-weight: 600;
}

.detail_text {
  flex-direction: column;
  gap: 7px;
}

/* ---------------------------------------------------------
   방식 1 — 버튼으로 고르기 (기본)
   --------------------------------------------------------- */

.detail:not(.is_scroll_ready) .detail_stage {
  width: 90%;
  max-width: 1460px;
  margin-inline: auto;
}

/* 돋보기와 부위 표식은 스크롤 연출 전용입니다 */
.detail:not(.is_scroll_ready) .detail_marker,
.detail:not(.is_scroll_ready) .detail_lens {
  display: none;
}

.detail:not(.is_scroll_ready) .detail_parts {
  display: flex;
}

/* 고른 하나만 사진 아래에 보여줍니다 */
.detail:not(.is_scroll_ready) .detail_text {
  display: none;
  margin-top: 28px;
}

.detail:not(.is_scroll_ready) .detail_stage[data-active-part="collar"] .detail_text[data-part="collar"],
.detail:not(.is_scroll_ready) .detail_stage[data-active-part="sleeve"] .detail_text[data-part="sleeve"],
.detail:not(.is_scroll_ready) .detail_stage[data-active-part="body"] .detail_text[data-part="body"],
.detail:not(.is_scroll_ready) .detail_stage[data-active-part="skirt"] .detail_text[data-part="skirt"] {
  display: flex;
  /* display 전환에는 transition이 걸리지 않습니다. 감춰져 있던 요소가 보이는
     순간 keyframe이 새로 시작하므로 버튼을 누를 때마다 다시 재생됩니다. */
  animation: detail_part_reveal var(--duration_base) var(--easing_base) both;
}

@keyframes detail_part_reveal {
  from {
    opacity: 0;
    transform: translateY(8px);
  }

  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* 위 규칙과 선택자를 똑같이 반복합니다 — 우선순위가 같아야 덮을 수 있고,
   !important를 쓰지 않기 위한 것입니다. */
@media (prefers-reduced-motion: reduce) {
  .detail:not(.is_scroll_ready) .detail_stage[data-active-part="collar"] .detail_text[data-part="collar"],
  .detail:not(.is_scroll_ready) .detail_stage[data-active-part="sleeve"] .detail_text[data-part="sleeve"],
  .detail:not(.is_scroll_ready) .detail_stage[data-active-part="body"] .detail_text[data-part="body"],
  .detail:not(.is_scroll_ready) .detail_stage[data-active-part="skirt"] .detail_text[data-part="skirt"] {
    animation: none;
  }
}

/* ---------------------------------------------------------
   방식 2 — 스크롤 연출 (.is_scroll_ready)
   --------------------------------------------------------- */

/* ★★ 고정할 요소의 부모가 flex면 ScrollTrigger가 pinSpacing을 꺼버립니다.
   그러면 스크롤 길이(부위 4개분)만큼의 자리가 확보되지 않아, 돋보기만 화면에
   붙어 있고 그 아래로 다음 섹션이 올라와 함께 보입니다. 실제로 이 버그를 겪었고
   (pin-spacer 높이가 2720px이 아니라 800px이었습니다) 그래서 이 모드에서는
   섹션을 block으로 바꿉니다. 아래 .detail_pin의 margin-top이 flex의 gap 역할을
   대신합니다. **여기를 flex로 되돌리면 같은 버그가 그대로 재발합니다.** */
.detail.is_scroll_ready {
  display: block;
}

/* 화면에 고정되는 부분. 헤더는 이 밖에 있어 평소처럼 먼저 지나갑니다.

   ★ 진행 표시(.detail_keywords)와 사진(.detail_stage)을 한 덩어리로 묶어
     가로 가운데에 둡니다. 예전에는 두 요소가 각자 왼쪽 기준값을 갖고 있어서
     (키워드 left: 40~80px, 사진 margin-left: 10.99%) 오른쪽 여백만 커졌습니다 —
     1920에서 왼쪽 80px / 오른쪽 247px이라 전체가 왼쪽으로 치우쳐 보였습니다.
     지금은 둘 다 이 flex의 자식으로 흐르므로 브라우저가 키워드 폭을 직접 재서
     묶음을 가운데에 놓습니다. **폭 값을 CSS에 적어 둘 필요가 없습니다.** */
.detail.is_scroll_ready .detail_pin {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(28px, 3.6vw, 72px);
  min-height: 100vh;
  margin-top: 60px; /* block으로 바뀌면서 사라진 .detail의 gap을 대신합니다 */
}

/* 이미지 왼쪽의 세로 진행 표시입니다. --detail_progress는 JS가 0~1로 갱신하며,
   point color 선이 현재 스크롤 위치까지 위에서 아래로 내려옵니다. */
.detail.is_scroll_ready .detail_keywords {
  --detail_progress: 0;
  /* ★ absolute가 아니라 flex 자식입니다 — .detail_pin이 사진과 함께 묶어서
     가운데 정렬하려면 이 요소도 흐름 안에 있어야 폭이 계산에 들어갑니다.
     다만 relative는 남겨야 합니다: 아래 ::before/::after(진행 막대)가 이 요소를
     기준으로 absolute 배치되고, z-index도 위치 지정 요소에서만 동작합니다. */
  position: relative;
  /* 세로 위치는 그대로입니다. 부모의 align-items: center를 이 요소만 풀고
     예전 top 값과 같은 거리를 margin으로 줍니다. */
  align-self: flex-start;
  margin-top: clamp(96px, 13vh, 128px);
  z-index: 2;
  display: flex;
  flex: 0 0 auto;
  flex-direction: column;
  justify-content: space-between;
  width: max-content;
  height: min(52vh, 480px);
  list-style: none;
  color: var(--color_text_muted);
  font-family: var(--font_ui);
  font-size: var(--fs_ui_16);
  font-weight: 400;
  line-height: 1.5;
  letter-spacing: var(--ls_tight_sm);
  pointer-events: none;
}

.detail.is_scroll_ready .detail_keywords::before,
.detail.is_scroll_ready .detail_keywords::after {
  position: absolute;
  top: 7px;
  bottom: 7px;
  left: 6px;
  width: 1px;
  content: "";
}

.detail.is_scroll_ready .detail_keywords::before {
  background-color: var(--color_border_disabled);
}

.detail.is_scroll_ready .detail_keywords::after {
  background-color: var(--color_point);
  transform: scaleY(var(--detail_progress));
  transform-origin: center top;
  transition: transform 0.12s linear;
}

.detail.is_scroll_ready .detail_keywords > li {
  position: relative;
  z-index: 1;
}

.detail.is_scroll_ready .detail_keyword {
  display: flex;
  align-items: center;
  gap: 14px;
  color: var(--color_text_muted);
  white-space: nowrap;
  transition: color var(--duration_base) var(--easing_base);
}

.detail.is_scroll_ready .detail_keyword::before {
  flex: 0 0 auto;
  width: 13px;
  height: 13px;
  border: 1px solid var(--color_border_disabled);
  border-radius: 50%;
  background-color: var(--color_bg);
  content: "";
  transition: border-color var(--duration_fast) var(--easing_base),
              background-color var(--duration_fast) var(--easing_base),
              box-shadow var(--duration_fast) var(--easing_base);
}

.detail.is_scroll_ready .detail_keyword.is_reached::before {
  border-color: var(--color_point);
  background-color: var(--color_point);
}

.detail.is_scroll_ready .detail_keyword.is_active {
  color: var(--color_point);
}

.detail.is_scroll_ready .detail_keyword.is_active::before {
  box-shadow: 0 0 0 4px rgba(31, 67, 63, 0.14);
}

/* 폭은 시안값(76.04%)을 그대로 씁니다. 왼쪽 기준값(10.99%)은 더 쓰지 않습니다 —
   가로 위치는 .detail_pin이 진행 표시와 함께 묶어서 가운데에 놓습니다.

   ★ 두 번째 값은 화면 높이에 맞춘 상한입니다. 사진 위아래로 설명이 걸칠 자리
     120px씩을 남겨야 하므로 사진 높이 ≤ 화면높이 − 240px이고, 사진 높이는
     폭 × 0.435(4380:1905)이므로 폭 ≤ (화면높이 − 240px) ÷ 0.435 입니다.
     세로 980px 이상에서는 이 값이 1700px을 넘어 시안 폭 1460px이 그대로 살고,
     세로가 짧은 화면에서만 사진이 작아집니다. */
.detail.is_scroll_ready .detail_stage {
  /* ★ flex-shrink를 막습니다. 폭은 아래 width가 정하고, 줄어들면 사진 비율에
     맞춰 높이까지 따라 줄어 돋보기 좌표(js가 offsetWidth로 잽니다)와 어긋납니다. */
  flex: 0 0 auto;
  width: min(76.04%, calc((100vh - 240px) / 0.435));
  max-width: 1460px;
  /* ★ 왼쪽 기준값(10.99%)을 뺐습니다. 가운데 정렬은 .detail_pin의
     justify-content: center가 진행 표시까지 묶어서 처리합니다. */
  margin-left: 0;
}

.detail.is_scroll_ready .detail_marker,
.detail.is_scroll_ready .detail_lens {
  display: block;
}

.detail.is_scroll_ready .detail_parts {
  display: none;
}

/* 설명은 사진 위에 겹쳐 걸립니다. 자리(left/top)는 js/main.js가 돋보기 바로 옆에
   오도록 매번 계산해 인라인으로 씁니다. 켜고 끄는 것도 스크롤 진행도에 따라
   .is_active로 합니다.

   ★ 시안(Figma 1712:4266 외)은 부위마다 고정 좌표였습니다 — 사진 기준으로
     collar (8.36%, -21.89%) / sleeve (63.90%, -25.83%) / body (0.68%, 58.27%) /
     skirt (28.36%, 106.61%). 그 좌표는 섹션이 세로로 길고 위아래 여백이 넉넉할 때의
     값이라, 화면 하나에 고정하는 지금 구조에서는 Skirt 설명이 화면 아래로 잘렸습니다
     (1280 × 720에서 25px). 그래서 "돋보기 옆"으로 바꿨습니다. 좌우는 돋보기가 사진
     오른쪽에 있으면 왼쪽에, 왼쪽에 있으면 오른쪽에 붙습니다. */
.detail.is_scroll_ready .detail_text {
  position: absolute;
  top: 0;
  left: 0;
  display: flex;
  width: 36.58%;
  min-width: 200px;
  /* 사진 위에 글자만 떠 있으면 허전하고, 밝은 원단 위에서는 읽기도 어렵습니다.
     반투명 흰 판을 깔아 글이 한 덩어리로 읽히게 합니다. 완전 불투명이 아니라
     0.86이라 뒤의 사진이 은은하게 비칩니다.
     ★ 전역 box-sizing이 border-box라 padding을 넣어도 폭 36.58%는 그대로입니다. */
  padding: 28px 32px;
  border-radius: 6px;
  background-color: rgba(255, 255, 255, 0.86);
  box-shadow: 0 10px 30px rgba(10, 10, 10, 0.08);
  opacity: 0;
  transform: scale(0.96);
  transition: opacity 0.35s ease, transform 0.35s ease;
  pointer-events: none;
}

.detail.is_scroll_ready .detail_text.is_active {
  opacity: 1;
  transform: scale(1);
}

/* 돋보기가 들를 네 지점을 사진 위에 표시합니다. 시안에 없는 요소이며, 스크롤
   연출에서 "지금 어디를 보고 있고 앞으로 어디를 더 볼지"를 알려 줍니다.

   좌표는 사진 속 실제 부위 위치입니다(스테이지 기준 %). js/main.js가 이 요소들의
   좌표를 그대로 읽어 돋보기 경로를 만들기 때문에, 여기를 옮기면 돋보기도 같이
   옮겨집니다 — 좌표를 두 곳에 두지 않기 위한 구조입니다. */
.detail_marker {
  position: absolute;
  width: 20px;
  height: 20px;
  margin: -10px 0 0 -10px; /* 위 좌표가 점의 중심이 되도록 절반씩 당깁니다 */
  border-radius: 50%;
  background-color: var(--color_bg);
  box-shadow:
    0 0 0 1px rgba(10, 10, 10, 0.3),
    0 2px 12px rgba(10, 10, 10, 0.3);
  opacity: 0.75;
  transition:
    opacity var(--duration_base) ease,
    background-color var(--duration_base) ease,
    transform var(--duration_base) var(--easing_base);
  pointer-events: none;
}

/* 지금 돋보기가 머무는 지점 — js/main.js가 붙입니다.
   크기만이 아니라 색도 바꿉니다(딥그린) — 크기 변화만으로는 어느 점이 켜졌는지
   한눈에 들어오지 않았습니다. */
.detail_marker.is_active {
  background-color: var(--color_point);
  box-shadow:
    0 0 0 3px var(--color_bg),
    0 2px 14px rgba(10, 10, 10, 0.35);
  opacity: 1;
  transform: scale(1.7);
}

.detail_marker::after {
  content: "";
  position: absolute;
  inset: -8px;
  border: 2px solid var(--color_bg);
  border-radius: 50%;
  animation: detail_marker_pulse 2.4s ease-out infinite;
}

/* 켜진 점의 파장은 딥그린으로, 더 크고 또렷하게 번집니다 */
.detail_marker.is_active::after {
  border-color: var(--color_point);
  animation-name: detail_marker_pulse_active;
}

/* 넷이 동시에 깜빡이면 시선이 분산됩니다. 조금씩 어긋나게 두어 하나씩 번지도록 합니다 */
.detail_marker[data-part="sleeve"]::after {
  animation-delay: 0.4s;
}

.detail_marker[data-part="body"]::after {
  animation-delay: 0.8s;
}

.detail_marker[data-part="skirt"]::after {
  animation-delay: 1.2s;
}

@keyframes detail_marker_pulse {
  0% {
    opacity: 0.85;
    transform: scale(0.6);
  }

  70% {
    opacity: 0;
    transform: scale(3.2);
  }

  100% {
    opacity: 0;
    transform: scale(3.2);
  }
}

/* 켜진 점 — 쉬는 구간 없이 더 크게, 더 자주 번집니다 */
@keyframes detail_marker_pulse_active {
  0% {
    opacity: 0.9;
    transform: scale(0.55);
  }

  80% {
    opacity: 0;
    transform: scale(4.2);
  }

  100% {
    opacity: 0;
    transform: scale(4.2);
  }
}

.detail_marker[data-part="collar"] {
  top: 12%;
  left: 49%;
}

.detail_marker[data-part="sleeve"] {
  top: 27%;
  left: 78%;
}

.detail_marker[data-part="body"] {
  top: 33%;
  left: 46%;
}

.detail_marker[data-part="skirt"] {
  top: 66%;
  left: 52%;
}

/* 파장만 멈추고 점은 남깁니다 — 점이 사라지면 어디를 보는지 알 수 없습니다.
   .is_active::after까지 함께 꺼야 합니다(선택자가 더 강해 따로 적지 않으면 남습니다). */
@media (prefers-reduced-motion: reduce) {
  .detail_marker::after,
  .detail_marker.is_active::after {
    opacity: 0.5;
    transform: scale(1);
    animation: none;
  }
}

/* 시안 주석: 호버 시 돋보기 확대.
   부위마다 미리 잘라 둔 확대컷 4장(.detail_zoom)을 각자 자리에 띄우던 방식에서,
   원본 사진을 실시간으로 확대하는 돋보기 하나로 바꿨습니다.
   원본 img.png가 4380 × 1905인데 화면에는 1460px로 그려지므로 3배까지는
   원본 픽셀 그대로입니다 — 기본 배율 2.5는 그 안쪽이라 흐려지지 않습니다.
   (배율은 js/main.js의 DETAIL_LENS_ZOOM에서 바꿉니다)
   크기 20.55%는 이전 .detail_zoom의 지름을 그대로 이어받은 값입니다.

   ★ left/top에 transition을 걸면 안 됩니다. 스크롤 진행도에 맞춰 js/main.js가
     매 프레임 위치를 직접 쓰기 때문에, 여기서 또 부드럽게 만들면 스크롤보다
     늦게 따라오는 것처럼 보입니다. */
.detail_lens {
  position: absolute;
  top: 0;
  left: 0;
  width: 20.55%;
  min-width: 120px;
  aspect-ratio: 1 / 1;
  border-radius: 50%;
  overflow: hidden;
  box-shadow: 0 4px 24px rgba(0, 0, 0, 0.12);
  background-color: var(--color_bg, #fffdf9);
  opacity: 0;
  transform: translate(-50%, -50%) scale(0.9);
  transition: opacity 0.25s ease, transform 0.25s ease;
  pointer-events: none;
  will-change: transform;
}

/* ★ 확대된 사진을 transform으로 밀어 보여줍니다.
   예전에는 이 원의 background-position을 매 프레임 바꿨는데, background-position은
   합성만으로 처리되지 않아 **4380 × 1905 사진을 2.5배로 확대한 면적 전체를 매 프레임
   다시 칠했습니다.** transform은 GPU 합성만으로 끝나 페인트가 0이 됩니다.
   크기와 위치는 js/main.js가 인라인으로 씁니다(부모 원 기준 px). */
.detail_lens_img {
  position: absolute;
  top: 0;
  left: 0;
  max-width: none;
}

/* ★ will-change를 기본 규칙에 두면 안 됩니다.
   이 이미지는 원본을 2.5배로 늘린 3260 × 1417(약 4.6백만 픽셀)이라, 상시
   will-change면 페이지를 여는 순간부터 끝까지 그만한 GPU 레이어(약 18MB)를
   붙잡습니다. 실제로 쓰이는 것은 돋보기가 켜져 있는 detail 고정 구간뿐입니다.
   `.is_active`는 js/main.js가 그 구간에 들어올 때 붙입니다 — 스크럽이 시작되기
   전이라 레이어를 만들 시간이 충분합니다.
   (common/css/shop_transition.css의 전환 조각 8개도 같은 이유로 고쳤습니다) */
.detail_lens.is_active .detail_lens_img {
  will-change: transform;
}

/* 선명화 확대컷은 큰 원본 위에 미리 겹쳐 두고 디코딩이 끝난 이미지끼리 opacity로
   전환합니다. src 교체가 없어 흰 화면이 끼지 않으며, 투명 영역의 흰 바탕까지
   이미지와 함께 자연스럽게 페이드됩니다. */
.detail_lens_crop_matte {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background-color: var(--color_bg, #fffdf9);
  opacity: 0;
  transition: opacity 0.28s ease;
}

.detail_lens_crop {
  position: absolute;
  top: 3.125%;
  left: 3.125%;
  width: 93.75%;
  height: 93.75%;
  max-width: none;
  object-fit: contain;
  border-radius: 50%;
  background-color: var(--color_bg, #fffdf9);
  opacity: 0;
  transition: opacity 0.28s ease;
  pointer-events: none;
  will-change: auto;
}

/* 첫 번째 Collar 에셋은 640px 캔버스 안에 지름 600px 원이 들어 있어 이미 3.125%
   여백이 있습니다. 나머지 세 장만 위에서 93.75%로 줄여 실제 원 크기를 맞춥니다. */
.detail_lens_crop[data-part="collar"] {
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

.detail_lens_crop.is_ready.is_active {
  opacity: 1;
}

.detail_lens.has_active_crop .detail_lens_crop_matte {
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  .detail_lens_crop_matte,
  .detail_lens_crop {
    transition: none;
  }
}

/* 섹션이 화면에 들어와 연출이 시작될 때 js/main.js가 켭니다.
   transform의 translate(-50%, -50%)는 돋보기 중심을 지점에 맞추는 것이라
   scale만 바뀝니다. */
.detail_lens.is_active {
  opacity: 1;
  transform: translate(-50%, -50%) scale(1);
}

@media (min-width: 1024px) {
  .detail {
    padding-top: 145px;
  }
}

/* =========================================================
   아래 섹션들은 시안 1920px 기준 데스크톱 레이아웃만 작성했습니다.
   태블릿·모바일 대응은 반응형 일괄 작업에서 추가합니다.
   ========================================================= */

/* =========================================================
   promo — bespoke / shop 공통 소개 블록
   ========================================================= */

.promo {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 40px;
}

.promo_text {
  display: flex;
  flex: 1 1 320px;
  flex-direction: column;
  align-items: flex-start;
  min-width: 0;
}

.promo_figure {
  flex: 1 1 320px;
  min-width: 0;
  max-width: 727px;
}

.promo_title {
  margin-bottom: 40px;
  color: var(--color_text);
  font-family: var(--font_display);
  font-size: var(--fs_display_48);
  font-weight: 600;
  line-height: var(--lh_display_48);
  letter-spacing: var(--ls_tight_sm);
  text-transform: uppercase;
}

.promo_lead_group {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 60px;
}

.promo_lead {
  color: #1e1e1e;
  font-family: var(--font_body);
  font-size: var(--fs_body_24);
  font-weight: 500;
  line-height: var(--lh_body_24);
}

.promo_desc {
  color: var(--color_text_sub);
  font-family: var(--font_body);
  font-size: var(--fs_body_20);
  font-weight: 400;
  line-height: var(--lh_body_20);
}

.promo_img {
  width: 100%;
  height: auto;
}

/* --- bespoke: 글 왼쪽 / 사진 오른쪽 --- */

/* bespoke_banner 무드 영상 (Figma node 1712:4394) */
.promo_bespoke_wrap {
  /* 고정된 카드 덱의 pin-spacer 계산에 영향을 주지 않도록 다음 섹션에서 간격을 만듭니다. */
  margin-top: clamp(160px, 42vw, 600px);
}

.promo_media {
  width: 100%;
  aspect-ratio: 1923 / 1043;
  overflow: hidden;
}

.promo_media_video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.promo_bespoke {
  padding: 82px 0 146px;
}

.promo_bespoke .promo_text {
  max-width: 746px;
  margin-top: 85px;
}

/* =========================================================
   shop
   ========================================================= */

.shop {
  margin-top: clamp(120px, 12vw, 280px);
  padding-bottom: 155px;
}

.promo_shop {
  padding: 145px 0 0;
}

.promo_shop .promo_text {
  max-width: 606px;
  margin-top: 98px;
}

/* product 마퀴 — 같은 5장 묶음을 두 벌 이어 끊김 없이 흘립니다. */
/* 화면 끝까지 채웁니다 — 100vw를 직접 쓰면 1920 줌 구간에서 1440px로 줄어
   좌우에 벽이 생깁니다. 이유는 파일 상단 --full_bleed_width 주석 참고. */
.shop_products_viewport {
  overflow: hidden;
  width: var(--full_bleed_width);
  margin-top: clamp(80px, 8vw, 200px);
  margin-left: calc(50% - var(--full_bleed_width) / 2);
  cursor: grab;
  touch-action: pan-y;
  user-select: none;
  -webkit-user-select: none;
}

.shop_products_viewport.is_dragging {
  cursor: grabbing;
}

.shop_products_track {
  /* ★ 마퀴 속도 조절값입니다. 한 묶음이 지나가는 시간이라 숫자가 작을수록
     빠릅니다. 현재 48s → 더 빠르게 하려면 36s 또는 32s 정도로 낮추세요. */
  --shop_products_duration: 20s;
  /* 1280px 이상 간격입니다. 아래 반응형 구간에서 48px → 36px → 24px로
     다시 덮어쓰므로, 작은 미리보기 화면에서는 이 200px이 적용되지 않습니다. */
  --shop_products_gap: 150px;
  display: flex;
  align-items: center;
  gap: var(--shop_products_gap);
  width: max-content;
  animation: shop_products_scroll var(--shop_products_duration) linear infinite;
  will-change: transform;
}

.shop_products {
  display: flex;
  align-items: center;
  gap: var(--shop_products_gap);
  flex: 0 0 auto;
  margin: 0;
}

.shop_product {
  flex: 0 0 clamp(170px, 12vw, 220px);
  min-width: 0;
}

.shop_product.is_dim {
  opacity: 0.2;
}

/* =========================================================
   공통 1920px zoom 보정

   일반 콘텐츠는 common/css/common.css의 0.75 zoom을 그대로 사용합니다.
   전체 화면 Hero와 ScrollTrigger pin 구간만 바깥 좌표계까지 복원해야
   화면 잘림, 섹션 겹침, pin 순간 좌측 이동이 생기지 않습니다.
   ========================================================= */
@media (min-width: 1850px) and (max-width: 1990px) {
  .hero {
    width: 100%;
    zoom: calc(1 / var(--site_view_scale));
  }

  /* model flow는 더 이상 pin-spacer 안에 있지 않으므로 직접 zoom을 복원합니다.
     이 보정이 없으면 1920px에서 긴 스크롤 구간이 0.75배로 짧아집니다. */
  .model.is_model_flow {
    width: 100%;
    zoom: calc(1 / var(--site_view_scale));
  }

  .pin-spacer:has(> .model),
  .pin-spacer:has(> .detail_pin),
  .pin-spacer:has(> .brand_word_pin) {
    max-width: 100%;
    zoom: calc(1 / var(--site_view_scale));
  }

  /* collection은 pin-spacer 대신 native sticky 래퍼가 전체 길이를 가집니다. */
  .collection_scroll.is_scroll_ready {
    width: 100%;
    zoom: calc(1 / var(--site_view_scale));
  }

  /* 컬렉션 무대의 역줌은 유지하되, 공통 버튼은 일반 promo 버튼과 같은
     실제 화면 크기로 다시 축소합니다. 글자·간격·밑줄이 함께 동일해집니다. */
  .collection_scroll.is_scroll_ready .main_button {
    zoom: var(--site_view_scale);
  }

  .pin-spacer > .model,
  .pin-spacer > .detail_pin,
  .pin-spacer > .brand_word_pin {
    /* ScrollTrigger가 공통 zoom 기준의 인라인 폭을 넣으므로 이 두 속성만
       실제 1920px 화면 폭으로 덮어씁니다. 인라인보다 우선해야 해 !important가 필요합니다. */
    width: 100% !important;
    max-width: 100% !important;
  }

  .pin-spacer > .detail_pin {
    top: 0 !important;
  }

  /* ★ collection은 안에 full-bleed 요소(.collection_row)를 갖고 있습니다.
     위 역보정으로 이 안쪽은 화면과 1:1 좌표계가 되므로 두 변수가 0.75로 나누면
     안 됩니다(무대가 1.33배로 넘칩니다). 여기서 원래 뷰포트 단위로 되돌립니다.

     ★ `--site_view_scale: 1`만 다시 선언하는 것으로는 안 됩니다.
       커스텀 속성 안의 var()는 **선언된 곳(:root) 기준으로 먼저 계산되어**
       그 결과가 상속되기 때문에, 아래에서 축소 비율만 바꿔도 이미 계산이
       끝난 --full_bleed_* 값은 바뀌지 않습니다. 변수 자체를 덮어써야 합니다.

     선택자에 .is_scroll_ready까지 붙인 것은 우선순위 때문입니다 —
     `.collection.is_scroll_ready` 규칙이 이 블록보다 아래에 있어서
     같은 우선순위면 그쪽이 이깁니다. */
  .pin-spacer > .collection.is_scroll_ready {
    --full_bleed_width: 100vw;
  }
}

.shop_product_link {
  display: block;
  width: 100%;
}

.shop_product img {
  display: block;
  width: 100%;
  height: auto;
  object-fit: cover;
}

@keyframes shop_products_scroll {
  from { transform: translateX(0); }
  to { transform: translateX(calc(-50% - var(--shop_products_gap) / 2)); }
}

.shop_products_viewport.is_dragging .shop_products_track,
.shop_products_viewport:focus-within .shop_products_track {
  animation-play-state: paused;
}

.shop_products_viewport.is_dragging .shop_product_link {
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  .shop_products_track {
    animation: none;
  }
}

/* =========================================================
   collection — Two lines. One extraordinary aesthetic.
   (Figma node 1712:4444, celeb 섹션을 대체)
   ========================================================= */

.collection_scroll {
  position: relative;
  background-color: var(--color_bg_alt);
}

/* GSAP의 fixed pin 대신 브라우저 기본 sticky를 사용합니다.
   섹션이 원래 속도로 들어오다가 top에 닿는 순간 자연스럽게 머물러 위치 전환이 없습니다. */
.collection_scroll.is_scroll_ready {
  min-height: calc(100dvh + var(--collection_sticky_scroll, 160dvh));
}

.collection_scroll.is_scroll_ready .collection {
  position: sticky;
  top: 0;
}

.collection {
  overflow: hidden;
  padding: 120px 0;
  text-align: center;
  background-color: var(--color_bg_alt);
}

/* ---------------------------------------------------------
   스크롤 연동 + native sticky — js/main.js가 .is_scroll_ready를 붙였을 때만.
   섹션은 자연스럽게 화면에 머물고 카드 흐름은 스크롤 진행률에 맞춰 재생됩니다.
   붙지 않아도(모션 감소·GSAP 없음·1024px 미만) 기본 가로 배치를 유지합니다.

   ★ collection_scroll이 고정 구간의 실제 높이를 만들고 collection이 sticky로 머뭅니다.
     이 래퍼에 overflow를 추가하면 sticky가 동작하지 않으므로 그대로 유지하세요.
   --------------------------------------------------------- */
.collection.is_scroll_ready {
  /* 제목·링크·아래 문구·여백이 쓰는 높이입니다. 무대 상한을 여기서 뺍니다.
     값을 바꾸면 무대가 그만큼 커지거나 작아집니다. */
  --collection_chrome: 460px;

  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: 100vh;
  /* ★ max-height가 안전장치입니다. 위 --collection_chrome이 실제와 조금 어긋나도
     섹션이 화면보다 커지지 않습니다(넘치면 overflow: hidden이 위아래를 고르게
     잘라냅니다). 이게 없으면 아래 문구가 화면 밖으로 밀립니다. */
  max-height: 100vh;
  /* 원래 120px인데, 화면 하나에 다 들어가야 하므로 줄입니다 */
  padding: 48px 0;
}

/* 무대 높이를 화면 높이로도 한 번 더 제한합니다. 넓고 세로가 넉넉한 화면에서는
   상한이 원래 값보다 커서 시안 크기가 그대로 남고, 세로가 짧은 화면에서만
   무대가 낮아집니다. */
.collection.is_scroll_ready .collection_row.is_perspective_ready {
  height: min(clamp(440px, 47vw, 760px), calc(100vh - var(--collection_chrome)));
}

.collection_container {
  /* 컬렉션 세로 간격 — 필요한 값만 각각 수정하면 됩니다 */
  --collection_gap_title_links: 60px;
  --collection_gap_links_stage: 0;
  --collection_gap_stage_bottom: 60px;

  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0;
}

.collection_title {
  margin-bottom: var(--collection_gap_title_links);
  color: #1e1e1e;
  font-family: var(--font_display);
  font-size: var(--fs_display_48);
  font-weight: 600;
  line-height: var(--lh_display_48);
  letter-spacing: var(--ls_tight);
}

.collection_row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(10px, 3vw, 40px);
  width: 100%;
  min-width: 0;
  margin-bottom: var(--collection_gap_stage_bottom);
}

.collection_item {
  /* 시안 실제 폭 비율(344 / 320.5 / 360 / 320.5 / 344)을 flex-grow로 유지합니다 */
  flex: 344 1 0;
  min-width: 0;
  overflow: hidden;
}

.collection_item.is_size_md {
  flex: 320.5 1 0;
}

.collection_item.is_size_bts {
  flex: 360 1 0;
}

.collection_item img {
  display: block;
  width: 100%;
  height: auto;
}

/* ---------------------------------------------------------
   collection perspective loop — 중앙 뒤에서 좌우 앞으로
   --------------------------------------------------------- */

.collection_row.is_perspective_ready {
  --collection_card_width: clamp(150px, 16vw, 300px);
  --collection_card_height: calc(var(--collection_card_width) * 4 / 3);
  /* 숫자가 작을수록 검정 프레임과 사진 전체가 링크 쪽으로 올라갑니다 */
  --collection_stage_center_y: 42%;

  position: relative;
  display: block;
  /* 카드가 좌우로 날아가는 무대라 화면 끝까지 닿아야 합니다 — 100vw를 직접 쓰면
     1920 줌 구간에서 1440px로 줄어 233px 지점에서 사진이 잘립니다.
     이유는 파일 상단 --full_bleed_width 주석 참고. */
  width: var(--full_bleed_width);
  height: clamp(440px, 47vw, 760px);
  margin-inline: calc(50% - var(--full_bleed_width) / 2);
  padding: 0;
  overflow: hidden;
  perspective: 900px;
  perspective-origin: 50% var(--collection_stage_center_y);
  transform-style: preserve-3d;
}

/* 중앙 검정 프레임(::before)은 제거했습니다 — 사용자 요청.
   그 프레임을 켜던 .is_loop_active class도 함께 쓰이지 않게 되어
   js/main.js에서 붙이지 않습니다. 되살리려면 두 곳을 같이 되돌려야 합니다. */

.collection_row.is_perspective_ready .collection_item {
  position: absolute;
  top: var(--collection_stage_center_y);
  left: 50%;
  width: var(--collection_card_width);
  height: var(--collection_card_height);
  margin: 0;
  overflow: hidden;
  border-radius: 2px;
  backface-visibility: hidden;
  transform-style: preserve-3d;
  transform-origin: 50% 50%;
  will-change: transform, opacity;
}

.collection_row.is_perspective_ready .collection_item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.collection_row.is_perspective_ready .collection_item.is_loop_clone {
  pointer-events: none;
}

.collection_scroll_hint {
  display: none;
}

.collection.is_scroll_ready .collection_scroll_hint {
  display: flex;
  align-items: center;
  gap: 14px;
  width: 100%;
  color: rgba(10, 10, 10, 0.62);
  font-family: var(--font_body);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  transition: color 240ms ease;
}

.collection_scroll_hint_track {
  position: relative;
  flex: 1;
  height: 1px;
  overflow: hidden;
  background: rgba(10, 10, 10, 0.18);
}

.collection_scroll_hint_progress {
  position: absolute;
  inset: 0;
  background: currentColor;
  transform: scaleX(var(--collection_reveal_progress, 0));
  transform-origin: left center;
}

.collection.is_reveal_complete .collection_scroll_hint {
  color: rgba(10, 10, 10, 0.82);
}

.collection_bottom {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 20px;
  width: 100%;
}

.collection.is_scroll_ready .collection_bottom {
  /* 짧은 데스크톱에서는 무대와 겹치지 않게 덜 올리고, 1080px 높이에서는
     설명과 진행선을 함께 충분히 올려 화면 하단 여백을 확보합니다. */
  transform: translateY(clamp(-80px, calc(43px - 11.4vh), -48px));
}

.collection.is_scroll_ready .collection_desc {
  transform: translateY(-10px);
}

.collection_desc {
  color: var(--color_text);
  font-family: var(--font_body);
  font-size: var(--fs_body_24);
  font-weight: 500;
  line-height: 1.42;
  letter-spacing: 0.01em;
}

.collection_links {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 40px 150px;
  margin-bottom: var(--collection_gap_links_stage);
}

/* 이 안의 링크 2개는 공통 버튼 `.main_button`을 씁니다.
   기본 스타일은 common/css/common.css에서 다른 페이지와 공유합니다. */


/* =========================================================
   클로징 (Figma 1920 × 620 절대좌표 → common_container 기반 흐름 배치로 전환)
   시안은 글과 아이콘이 겹쳐 있지만, .common_container 도입에 맞춰
   아래로 쌓는 배치로 단순화했습니다.
   ========================================================= */

.closing {
  overflow: hidden;
  padding: 150px 0;
}

.closing_inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 60px;
}

.closing_head {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 20px;
  max-width: 894px;
  text-align: center;
}

.closing_title {
  color: var(--color_text);
  font-family: var(--font_display);
  font-size: 56px;
  font-weight: 700;
  /* Trirong 기본 행간 — 시안 텍스트 높이 97 / 56 */
  line-height: 1.73;
}

.closing_desc {
  color: #262626;
  font-family: var(--font_body);
  font-size: var(--fs_body_20);
  font-weight: 400;
  line-height: 1.2;
}

.closing_icons {
  display: flex;
  align-items: flex-end;
  justify-content: flex-end;
  gap: 10px;
  width: 100%;
}

.closing_icon_people {
  width: 200px;
  height: auto;
}

.closing_icon_dog {
  width: 120px;
  height: auto;
}

/* =========================================================
   responsive — 1920px 데스크톱 규칙은 유지하고 작은 화면에서만 재배치
   ========================================================= */

@media (max-width: 1279px) {
  .brand_stack_intro,
  .brand_stack_statement {
    width: 30%;
    font-size: clamp(13px, 1.5vw, 18px);
  }

  .brand_stack_title {
    left: 22%;
    width: 56%;
    font-size: clamp(26px, 3.2vw, 40px);
  }

  .brand_stack_description {
    bottom: 14%;
    left: 5%;
    width: 26%;
  }

  .brand_stack_count {
    left: 72%;
  }

  .brand_stack_action {
    right: 5%;
    width: min(220px, 22vw);
  }

  .detail_stage {
    width: 86%;
    margin-left: 7%;
  }

  .promo {
    gap: 32px;
  }

  .promo_bespoke_wrap {
    margin-top: clamp(160px, 32vw, 420px);
  }

  .shop_products_track {
    /* 1024~1279px에서 최종 적용 — 위의 데스크톱 간격을 덮어씁니다. */
    --shop_products_gap: 48px;
  }

  .collection_row {
    gap: 20px;
  }
}

@media (max-width: 1023px) {
  .brand_word_pin {
    padding: 32px 0;
  }

  .brand_collage {
    flex-direction: column;
    min-height: auto;
    padding: 72px var(--layout_gutter);
  }

  .brand_collage_cards {
    order: 2;
    max-width: 680px;
  }

  .brand_collage_row {
    flex-wrap: wrap;
    gap: 16px;
  }

  .brand_collage_group_title {
    display: block;
    flex: 0 0 100%;
    padding-bottom: 12px;
    border-bottom: 1px solid rgba(10, 10, 10, 0.2);
    font-family: var(--font_display);
    font-size: clamp(30px, 5vw, 46px);
    line-height: 1.15;
    text-align: left;
  }

  .brand_collage_group_title.is_bespoke {
    order: 1;
  }

  .brand_collage_card.is_bespoke {
    order: 2;
  }

  .brand_collage_group_title.is_ready {
    order: 3;
    margin-top: 40px;
  }

  .brand_collage_card.is_ready {
    order: 4;
  }

  .brand_collage_card,
  .brand_collage_card.is_size_sm {
    width: calc(50% - 8px);
    max-width: 260px;
  }

  .brand_collage_name {
    display: none;
  }

  .brand_stack_copy {
    display: none;
  }

  /* 이 폭에서는 스크롤 연출을 걸지 않습니다(js/main.js가 1024px 이상에서만
     .is_scroll_ready를 붙입니다). 버튼 방식 레이아웃은 기본 규칙에 있고,
     여기서는 섹션 여백만 좁힙니다. */
  .detail {
    gap: 36px;
    padding: 80px 0;
  }

  .promo {
    flex-direction: column;
    flex-wrap: nowrap;
  }

  .promo_text,
  .promo_figure {
    flex: none;
    width: 100%;
    max-width: none;
  }

  .promo_bespoke,
  .promo_shop {
    padding: 80px 0;
  }

  .promo_bespoke .promo_text,
  .promo_shop .promo_text {
    margin-top: 0;
  }

  .promo_shop .promo_text {
    order: -1;
  }

  .promo_media {
    aspect-ratio: 16 / 10;
  }

  .shop {
    margin-top: clamp(96px, 14vw, 160px);
    padding-bottom: 96px;
  }

  .shop_products_track {
    /* 1023px 이하에서 적용 — 1279px 규칙보다 아래라 이 값이 최종 승리합니다. */
    --shop_products_gap: 36px;
  }

  .shop_product {
    flex-basis: clamp(150px, 24vw, 200px);
  }

  .collection {
    padding: 96px 0;
  }

  .collection_row {
    justify-content: flex-start;
    gap: 24px;
    overflow-x: auto;
    padding: 0 var(--layout_gutter) 16px;
    scroll-padding-inline: var(--layout_gutter);
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
  }

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

  .collection_item,
  .collection_item.is_size_md,
  .collection_item.is_size_bts {
    flex: 0 0 min(38vw, 320px);
    scroll-snap-align: center;
  }

  .collection_links {
    gap: 24px 64px;
  }

  .closing {
    padding: 100px 0;
  }
}

@media (max-width: 767px) {
  .hero_panel {
    min-height: 560px;
    height: 80svh;
  }

  .hero_panel_body {
    bottom: 120px;
  }

  .hero_panel_title {
    font-size: clamp(32px, 10vw, 44px);
  }

  .hero_panel_desc {
    font-size: 16px;
  }

  .hero_panel_button {
    margin-top: 24px;
    font-size: 16px;
  }

  .model_container {
    padding-inline: var(--layout_gutter);
  }

  .model_title {
    font-size: clamp(30px, 10vw, 42px);
    text-align: center;
  }

  .brand_story_textbox {
    padding: 56px var(--layout_gutter) 24px;
  }

  .brand_story_title,
  .detail_title,
  .promo_title,
  .collection_title {
    font-size: clamp(32px, 10vw, 44px);
  }

  .brand_story_banner {
    min-height: 240px;
  }

  .brand_collage {
    padding: 56px var(--layout_gutter);
  }

  .brand_collage_row {
    gap: 10px;
  }

  .brand_collage_group_title {
    padding-bottom: 10px;
    font-size: clamp(28px, 9vw, 38px);
  }

  .brand_collage_group_title.is_ready {
    margin-top: 32px;
  }

  .brand_collage_card,
  .brand_collage_card.is_size_sm {
    width: calc(50% - 5px);
  }

  .detail {
    padding: 64px 0;
  }

  .detail_head {
    gap: 12px;
  }

  .detail_subtitle,
  .promo_desc,
  .collection_desc {
    font-size: 16px;
  }

  /* 기본 규칙이 .detail:not(.is_scroll_ready) .detail_stage로 걸려 있어
     선택자를 맞춰야 덮을 수 있습니다(우선순위 문제 — !important 대신). */
  .detail:not(.is_scroll_ready) .detail_stage {
    width: 100%;
    margin-top: 20px;
  }

  .promo_bespoke_wrap {
    margin-top: 120px;
  }

  .promo_media {
    aspect-ratio: 4 / 5;
  }

  .promo_bespoke,
  .promo_shop {
    padding: 64px 0;
  }

  .promo_title {
    margin-bottom: 24px;
  }

  .promo_lead_group {
    margin-bottom: 36px;
  }

  /* .promo_link는 공통 버튼(.main_button)이 되면서 이 목록에서 빠졌습니다 —
     collection 쪽 버튼과 같은 크기를 유지해야 하기 때문입니다. */
  .promo_lead {
    font-size: 18px;
  }

  .shop {
    margin-top: 96px;
    padding-bottom: 72px;
  }

  .shop_products_viewport {
    margin-top: 64px;
  }

  .shop_products_track {
    /* 모바일에서 적용되는 최종 간격입니다. */
    --shop_products_gap: 24px;
  }

  .shop_product {
    flex-basis: 140px;
  }

  .collection {
    padding: 72px 0;
  }

  .collection_container {
    --collection_gap_title_links: 40px;
    --collection_gap_links_stage: 40px;
    --collection_gap_stage_bottom: 40px;
  }

  /* 이 폭에는 줌이 걸리지 않지만, full-bleed 계산을 한 가지로 통일해 둡니다 */
  .collection_row {
    width: var(--full_bleed_width);
    margin-inline: calc(50% - var(--full_bleed_width) / 2);
  }

  .collection_item,
  .collection_item.is_size_md,
  .collection_item.is_size_bts {
    flex-basis: 72vw;
  }

  .collection_desc br {
    display: none;
  }

  .collection_links {
    flex-direction: column;
    gap: 20px;
  }

  .closing {
    padding: 72px 0;
  }

  .closing_inner {
    gap: 40px;
  }

  .closing_title {
    font-size: clamp(36px, 12vw, 48px);
    line-height: 1.25;
  }

  .closing_icons {
    justify-content: center;
  }

  .closing_icon_people {
    width: 140px;
  }

  .closing_icon_dog {
    width: 84px;
  }
}
