/* ============================================================
   COMPONENTS — 버튼 / 헤더 / 언어토글 / 드로어 / 모바일바 / 카드 / 푸터 / 폼
   ============================================================ */

/* ============================================================
   1. BUTTON
   각진 형태(radius 4px). pill 금지. hover 시 transform 금지.
   ============================================================ */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-1);
  min-height: 48px;
  padding: 12px var(--space-3);
  border: var(--border-w) solid transparent;
  border-radius: var(--radius);
  font-family: inherit;
  font-size: var(--fs-body);
  font-weight: var(--fw-semibold);
  line-height: 1.2;
  letter-spacing: inherit;
  text-align: center;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: var(--transition);
}

.btn svg {
  width: 18px;
  height: 18px;
  transition: transform var(--dur) var(--ease);
}

/* hover 시 화살표만 3px 민다.

   디자인 시스템의 "hover 시 transform 금지"와 어긋나 보이지만 취지는 지킨다.
   그 규칙은 요소가 마우스에 반응해 튀어올라 가벼워 보이는 것을 막으려는
   것이고, 여기서 움직이는 것은 버튼이 아니라 그 안의 화살표다.
   버튼의 면·크기·위치는 그대로이고, 방향을 가리키는 기호만 그 방향으로
   조금 간다. 레이아웃도 흔들리지 않는다.

   :last-child 로 좁힌 이유
     버튼에 들어가는 아이콘이 화살표만은 아니다. mail·phone·pin 도 쓰이는데
     이들은 전부 글자 앞에 온다(아이콘 → 글자). 화살표만 글자 뒤에 온다.
     전화 아이콘이 오른쪽으로 미끄러지면 아무 의미가 없으므로 뒤에 붙는
     것만 고른다. */
.btn:hover svg:last-child {
  transform: translateX(3px);
}

@media (prefers-reduced-motion: reduce) {
  .btn:hover svg:last-child {
    transform: none;
  }
}

/* 주 CTA — 브랜드 청록 */
.btn--primary {
  background-color: var(--teal-500);
  border-color: var(--teal-500);
  color: var(--white);
}
.btn--primary:hover {
  background-color: var(--navy-700);
  border-color: var(--navy-700);
  color: var(--white);
}

/* 다크 CTA — 밝은 배경 위 강한 대비가 필요할 때 */
.btn--dark {
  background-color: var(--navy-900);
  border-color: var(--navy-900);
  color: var(--white);
}
.btn--dark:hover {
  background-color: var(--teal-500);
  border-color: var(--teal-500);
  color: var(--white);
}

/* 보조 — 보더만 */
.btn--outline {
  background-color: transparent;
  border-color: var(--gray-300);
  color: var(--navy-700);
}
.btn--outline:hover {
  background-color: var(--teal-050);
  border-color: var(--navy-700);
  color: var(--navy-700);
}

/* 다크 섹션 위 보조 버튼 */
.btn--on-dark {
  background-color: transparent;
  border-color: rgba(255, 255, 255, 0.4);
  color: var(--white);
}
.btn--on-dark:hover {
  background-color: var(--white);
  border-color: var(--white);
  color: var(--navy-900);
}

/* 크기 변형 */
.btn--sm {
  min-height: 40px;
  padding: 8px var(--space-2);
  font-size: var(--fs-caption);
}
.btn--lg {
  min-height: 56px;
  padding: var(--space-2) var(--space-4);
  font-size: var(--fs-body-lg);
}
.btn--full {
  width: 100%;
}

/* ---------- 텍스트 링크형 액션 ---------- */
/* 밑줄이 hover 에서 통째로 켜지면 딸깍 하고 붙는다.
   background-size 로 왼쪽에서 그어지게 하면 같은 200ms 라도 손이
   닿아서 그어진 것처럼 읽힌다. transform 이 아니라 background 라
   "hover 에 transform 금지" 규칙과 충돌하지 않는다. */
.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  font-weight: var(--fw-semibold);
  color: var(--teal-500);
  padding-bottom: 3px;
  background-image: linear-gradient(currentColor, currentColor);
  background-repeat: no-repeat;
  background-position: left bottom;
  background-size: 0% 1px;
  transition: var(--transition), background-size var(--dur) var(--ease);
}
.link-arrow:hover {
  color: var(--navy-700);
  background-size: 100% 1px;
}
.link-arrow svg {
  width: 16px;
  height: 16px;
}

/* ============================================================
   2. BADGE
   --accent 는 텍스트/배경 조합으로 쓰지 않는다 (흰 글자 대비 3.97:1 로 AA 미달).
   좌측 3px 마커로만 사용해 접근성과 팔레트 규칙을 동시에 지킨다.
   ============================================================ */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  padding: 6px var(--space-2) 6px 13px;
  background-color: var(--white);
  border: var(--border);
  border-left: 3px solid var(--teal-500);
  border-radius: var(--radius-sm);
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  color: var(--navy-700);
  white-space: nowrap;
}

.badge svg {
  width: 16px;
  height: 16px;
  color: var(--teal-500);
}

/* 긴급 대응 등 최상위 강조 — accent 사용은 페이지당 1회 이내 */
.badge--urgent {
  border-left-color: var(--accent);
}

.badge--on-dark {
  background-color: transparent;
  border-color: var(--color-border-dark);
  border-left-color: var(--teal-300);
  color: var(--white);
}

/* ============================================================
   3. HEADER
   상단 유틸리티 스트립(다크) + 메인 헤더(화이트) 2단 구성.
   ============================================================ */
/* 두 가지 상태를 오간다.

     최상단 : 투명. 뒤의 히어로가 그대로 비친다. 글자·로고는 흰색
     스크롤 후 : 반투명 흰 배경 + 블러 + 1px 선 + 얕은 그림자. 글자는 네이비

   전환은 nav.js 가 붙이는 .is-scrolled 하나로 갈린다.
   색·그림자·블러만 바꾸므로 레이아웃 재계산이 없다.

   ⚠ 기본값은 '불투명 흰색'이다. 투명은 히어로가 있는 문서에서만 켠다.
     styleguide 처럼 히어로 없이 흰 본문으로 시작하는 페이지에서 투명을
     기본으로 두면 흰 바탕에 흰 메뉴가 놓여 헤더가 통째로 사라진다.
     실제로 그렇게 만들었다가 발견했다.
     :has() 를 못 쓰는 브라우저에서는 이 기본값이 그대로 남아
     연출만 없는 예전 헤더가 된다 — 읽을 수 없게 되는 쪽이 아니다. */
.site-header {
  position: sticky;
  top: 0;
  z-index: var(--z-header);
  background-color: var(--white);
  border-bottom: var(--border-w) solid transparent;
  transition: background-color var(--dur-header) var(--ease-soft),
    border-color var(--dur-header) var(--ease-soft),
    box-shadow var(--dur-header) var(--ease-soft),
    -webkit-backdrop-filter var(--dur-header) var(--ease-soft),
    backdrop-filter var(--dur-header) var(--ease-soft);
}

/* 히어로가 있는 문서에서만 최상단을 투명으로 연다.
   :where() 로 감싸 특이도를 0 으로 두었다 — 아래 규칙들의 우선순위 계산이
   이 가드 때문에 달라지지 않게 하기 위해서다. */
:where(body:has(.hero, .page-hero)) .site-header:not(.is-scrolled) {
  background-color: transparent;
}

.site-header.is-scrolled {
  /* 완전 불투명이 아니라 0.86 이다. 뒤 콘텐츠가 아주 옅게 비쳐야
     블러가 '유리'로 읽힌다. 불투명하면 그냥 흰 판이다. */
  background-color: rgba(255, 255, 255, 0.86);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
  backdrop-filter: saturate(180%) blur(14px);
  border-bottom-color: var(--gray-300);
  box-shadow: var(--shadow-header-lift);
}

/* backdrop-filter 를 못 쓰는 브라우저에서는 반투명이 그냥 흐린 흰색으로
   보여 글자 대비가 떨어진다. 그럴 때는 불투명하게 되돌린다. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .site-header.is-scrolled {
    background-color: var(--white);
  }
}

/* ---------- 3-1. 유틸리티 스트립 ---------- */
.topbar {
  display: none;
  /* 기본은 네이비. 히어로가 있는 문서의 최상단에서만 투명하게 비운다
     (헤더 배경과 같은 이유 — 히어로가 없으면 비칠 것이 없다). */
  background-color: var(--navy-900);
  color: rgba(255, 255, 255, 0.72);
  font-size: var(--fs-caption);
  transition: background-color var(--dur-header) var(--ease-soft);
}

:where(body:has(.hero, .page-hero)) .site-header:not(.is-scrolled) .topbar {
  background-color: transparent;
}

@media (min-width: 900px) {
  .topbar {
    display: block;
  }
}

.topbar__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  /* 토큰을 쓰는 이유: 이 높이는 base.css 의 scroll-padding-top 계산에도
     들어간다. 여기서만 숫자를 바꾸면 앵커가 헤더 밑으로 들어간다. */
  min-height: var(--topbar-h);
}

.topbar__tagline {
  letter-spacing: 0.01em;
}

.topbar__actions {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.topbar__link {
  display: inline-flex;
  align-items: center;
  gap: 0.45em;
  color: rgba(255, 255, 255, 0.72);
  font-variant-numeric: tabular-nums;
  transition: var(--transition);
}
.topbar__link:hover {
  color: var(--white);
}
.topbar__link svg {
  width: 14px;
  height: 14px;
  color: var(--teal-300);
}

.topbar__divider {
  width: 1px;
  height: 14px;
  background-color: rgba(255, 255, 255, 0.24);
}

/* ---------- 3-2. 메인 헤더 ---------- */
.header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  min-height: var(--header-h);
}

/* ---------- 3-3. 로고 ---------- */
.logo {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  color: var(--navy-900);
  flex-shrink: 0;
}
.logo:hover {
  color: var(--navy-900);
}

/* 로고 심볼 — 렌즈 형태 아치 안의 선박 실루엣.
   높이 기준으로 잡고 폭은 auto (파일 비율 176/110 = 1.6:1). */
.logo__mark {
  height: 30px;
  width: auto;
}

@media (min-width: 768px) {
  .logo__mark {
    height: 36px;
  }
}

.logo__text {
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.logo__name {
  font-size: 1.0625rem;
  font-weight: var(--fw-bold);
  letter-spacing: -0.01em;
  line-height: 1.1;
  color: var(--navy-900);
}

/* 영문 사명은 Inter로, 자간을 벌려 로고의 워드마크 느낌을 살린다 */
html[lang="en"] .logo__name {
  font-family: var(--font-en);
  letter-spacing: 0.02em;
}

.logo__sub {
  font-size: 0.6875rem;
  font-weight: var(--fw-medium);
  letter-spacing: 0.02em;
  line-height: 1.1;
  color: var(--gray-600);
}

@media (max-width: 419px) {
  .logo__sub {
    display: none;
  }
}

/* ---------- 3-3b. 최상단(투명) 상태 ----------
   헤더가 어두운 히어로 위에 떠 있는 동안은 전부 흰색으로 뒤집는다.
   .is-scrolled 가 붙으면 이 블록이 통째로 빠지면서 원래 네이비로 돌아간다.
   색만 바꾸므로 레이아웃 재계산이 없다. */
:where(body:has(.hero, .page-hero)) .site-header:not(.is-scrolled) .logo,
:where(body:has(.hero, .page-hero)) .site-header:not(.is-scrolled) .logo:hover,
:where(body:has(.hero, .page-hero)) .site-header:not(.is-scrolled) .logo__name,
:where(body:has(.hero, .page-hero)) .site-header:not(.is-scrolled) .nav__link,
:where(body:has(.hero, .page-hero)) .site-header:not(.is-scrolled) .nav__link[aria-current="page"],
:where(body:has(.hero, .page-hero)) .site-header:not(.is-scrolled) .menu-toggle {
  color: var(--white);
}

/* 업종 서브라벨은 한 단 낮춰 위계를 유지한다 (흰색 위 0.66 = 약 10:1) */
:where(body:has(.hero, .page-hero)) .site-header:not(.is-scrolled) .logo__sub {
  color: rgba(255, 255, 255, 0.66);
}

:where(body:has(.hero, .page-hero)) .site-header:not(.is-scrolled) .nav__link:hover {
  color: var(--white);
}
:where(body:has(.hero, .page-hero)) .site-header:not(.is-scrolled) .nav__link:hover::after,
:where(body:has(.hero, .page-hero)) .site-header:not(.is-scrolled) .nav__link[aria-current="page"]::after {
  background-color: var(--white);
}

:where(body:has(.hero, .page-hero)) .site-header:not(.is-scrolled) .menu-toggle:hover {
  background-color: rgba(255, 255, 255, 0.12);
}

/* 어두운 배경 위 포커스 링은 흰색으로 (base.css 의 .on-dark 와 같은 처리) */
:where(body:has(.hero, .page-hero)) .site-header:not(.is-scrolled) :focus-visible {
  outline-color: var(--white);
}

/* CTA — 채운 teal 대신 흰 아웃라인. 히어로 위에서 면이 하나 줄어 가벼워진다.
   hover 에서는 흰 면으로 반전. transform 은 쓰지 않는다. */
:where(body:has(.hero, .page-hero)) .site-header:not(.is-scrolled) .header__cta {
  background-color: transparent;
  border-color: rgba(255, 255, 255, 0.55);
  color: var(--white);
}
:where(body:has(.hero, .page-hero)) .site-header:not(.is-scrolled) .header__cta:hover {
  background-color: var(--white);
  border-color: var(--white);
  color: var(--navy-900);
}

/* ---------- 로고 심볼 두 벌 교차 ----------
   심볼은 어떤 상태에서도 사라지지 않는다. 배경에 따라 그림만 바뀐다.

     최상단(어두움) : ipickkorea-symbol-light.png  흰 단색
     그 외(밝음)     : ipickkorea-symbol-alpha.png 원색, 배경 제거

   세 파일 모두 tools/build-logo-variants.mjs 가 마스터에서 생성한다
   (마스터 352×221 은 assets-src/ 에 있고 배포되지 않는다).
   ipickkorea-symbol.png 도 함께 남겨 둔다 — HTML 의 <img src> 가
   그것을 가리키고 있어서, CSS 가 통째로 실패하면 그 그림이 그대로 보인다.
   연출을 잃을 뿐 로고가 사라지지는 않는 쪽이 안전한 실패다.
   세 장 합계 16KB 라 이 안전망의 값이 싸다 (이전에는 191KB 였다).

   왜 <img> 가 아니라 pseudo 로 그리는가
     src 는 HTML 이 정하는데 이 작업에서는 HTML 을 건드리지 않기로 했다.
     background-image 는 전환되지 않아 두 벌을 겹쳐 opacity 로 교차해야 하고,
     그러려면 레이어가 둘 필요하다. <img> 는 자리만 지키고(opacity:0)
     그림은 ::before/::after 가 그린다.

   심볼 크기는 .logo__mark 의 height(30/36px) × 원본비율(352/221 ≈ 1.593). */
.logo {
  position: relative;
  --mark-h: 30px;
  --mark-w: 48px;
}

@media (min-width: 768px) {
  .logo {
    --mark-h: 36px;
    --mark-w: 58px;
  }
}

.logo__mark {
  /* 자리만 차지한다. 실제 그림은 아래 pseudo 두 장이 그린다. */
  opacity: 0;
}

.logo::before,
.logo::after {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  width: var(--mark-w);
  height: var(--mark-h);
  margin-top: calc(var(--mark-h) / -2);
  background-position: center;
  background-size: contain;
  background-repeat: no-repeat;
  transition: opacity var(--dur-header) var(--ease-soft);
  pointer-events: none;
}

/* 밝은 배경용 — 기본값 */
.logo::after {
  background-image: url("/assets/logos/ipickkorea-symbol-alpha.png");
  opacity: 1;
}

/* 어두운 배경용 — 최상단에서만 켜진다 */
.logo::before {
  background-image: url("/assets/logos/ipickkorea-symbol-light.png");
  opacity: 0;
}

:where(body:has(.hero, .page-hero)) .site-header:not(.is-scrolled) .logo::before {
  opacity: 1;
}
:where(body:has(.hero, .page-hero)) .site-header:not(.is-scrolled) .logo::after {
  opacity: 0;
}

/* 푸터의 .logo--dark 는 심볼 없이 워드마크만 쓴다(매크로가 <img> 를 아예
   렌더하지 않는다). pseudo 까지 따라가면 없던 심볼이 생기므로 끈다. */
.logo--dark::before,
.logo--dark::after {
  content: none;
}

/* ---------- 3-4. 데스크톱 내비게이션 ---------- */
.nav {
  display: none;
}

@media (min-width: 900px) {
  .nav {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    margin-left: auto;
  }
}

.nav__link {
  position: relative;
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding-inline: 2px;
  color: var(--navy-900);
  font-size: 0.9375rem;
  font-weight: var(--fw-medium);
  transition: var(--transition);
}

/* 하단 밑줄은 pseudo element로 — 레이아웃 이동 없이 색만 전환 */
.nav__link::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 14px;
  height: 2px;
  background-color: transparent;
  transition: background-color var(--dur) var(--ease);
}

.nav__link:hover {
  color: var(--teal-500);
}
.nav__link:hover::after {
  background-color: var(--teal-300);
}

.nav__link[aria-current="page"] {
  color: var(--navy-900);
  font-weight: var(--fw-semibold);
}
.nav__link[aria-current="page"]::after {
  background-color: var(--teal-500);
}

/* ---------- 3-5. 헤더 우측 액션 ---------- */
.header__actions {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-left: var(--space-3);
}

.header__cta {
  display: none;
}

@media (min-width: 900px) {
  .header__cta {
    display: inline-flex;
  }
}

/* ============================================================
   4. LANGUAGE TOGGLE
   "KR | EN" — 현재 언어는 강조, 반대 언어는 링크.
   쿠키에 저장 (localStorage 미사용).
   ============================================================ */
.langtoggle {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-en);
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  letter-spacing: 0.04em;
}

.langtoggle__current {
  color: var(--white);
}

.langtoggle__sep {
  color: rgba(255, 255, 255, 0.32);
  font-weight: var(--fw-regular);
}

.langtoggle__link {
  color: rgba(255, 255, 255, 0.6);
  transition: var(--transition);
}
.langtoggle__link:hover {
  color: var(--white);
}

/* 밝은 배경 위(드로어 등)에서 쓰는 변형 */
.langtoggle--light .langtoggle__current {
  color: var(--navy-900);
}
.langtoggle--light .langtoggle__sep {
  color: var(--gray-300);
}
.langtoggle--light .langtoggle__link {
  color: var(--gray-600);
}
.langtoggle--light .langtoggle__link:hover {
  color: var(--teal-500);
}

/* 터치 타겟 44px 확보 */
.langtoggle--light .langtoggle__current,
.langtoggle--light .langtoggle__link {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding-inline: 4px;
}

/* ============================================================
   5. 모바일 메뉴 (햄버거 + 드로어)
   ============================================================ */
.menu-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  margin-right: -8px;
  color: var(--navy-900);
  border: var(--border-w) solid transparent;
  border-radius: var(--radius);
  transition: var(--transition);
}
.menu-toggle:hover {
  background-color: var(--gray-100);
}
.menu-toggle svg {
  width: 24px;
  height: 24px;
}

@media (min-width: 900px) {
  .menu-toggle {
    display: none;
  }
}

.drawer {
  position: fixed;
  inset: 0;
  z-index: var(--z-drawer);
  display: flex;
  flex-direction: column;
  background-color: var(--white);
  overflow-y: auto;
  overscroll-behavior: contain;
}

.drawer[hidden] {
  display: none;
}

.drawer__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: var(--header-h);
  border-bottom: var(--border);
}

.drawer__nav {
  border-bottom: var(--border);
}

.drawer__link {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 60px;
  padding-block: var(--space-2);
  border-bottom: var(--border);
  color: var(--navy-900);
  font-size: 1.125rem;
  font-weight: var(--fw-semibold);
  transition: var(--transition);
}
.drawer__link:last-child {
  border-bottom: 0;
}
.drawer__link:hover,
.drawer__link[aria-current="page"] {
  color: var(--teal-500);
}
.drawer__link svg {
  width: 18px;
  height: 18px;
  color: var(--gray-300);
}

.drawer__foot {
  padding-block: var(--space-3) var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.drawer__contact {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  font-size: var(--fs-caption);
  color: var(--gray-600);
}

.drawer__contact a {
  color: var(--navy-700);
  font-variant-numeric: tabular-nums;
}

/* 드로어 열림 시 배경 스크롤 잠금 */
body.is-drawer-open {
  overflow: hidden;
}

/* ============================================================
   6. 모바일 하단 고정 CTA 바
   스크롤 200px 이후 등장 (scripts/nav.js 가 .is-visible 부여)
   ============================================================ */
.mobile-bar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: var(--z-mobilebar);
  display: grid;
  grid-template-columns: 1fr 1fr;
  height: var(--mobilebar-h);
  background-color: var(--white);
  border-top: var(--border);
  box-shadow: var(--shadow-overlay);
  /* 등장 전: 화면 밖. opacity만 쓰면 숨겨진 버튼이 터치를 가로챈다 */
  transform: translateY(100%);
  transition: transform var(--dur) var(--ease);
  padding-bottom: env(safe-area-inset-bottom);
}

.mobile-bar.is-visible {
  transform: translateY(0);
}

@media (min-width: 768px) {
  .mobile-bar {
    display: none;
  }
}

.mobile-bar__btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 44px;
  font-size: 0.9375rem;
  font-weight: var(--fw-semibold);
  transition: var(--transition);
}

.mobile-bar__btn svg {
  width: 18px;
  height: 18px;
}

.mobile-bar__btn--call {
  color: var(--navy-900);
  border-right: var(--border);
}
.mobile-bar__btn--call:hover {
  background-color: var(--gray-100);
}

.mobile-bar__btn--quote {
  background-color: var(--teal-500);
  color: var(--white);
}
.mobile-bar__btn--quote:hover {
  background-color: var(--navy-700);
  color: var(--white);
}

/* ============================================================
   7. CARD
   그림자 없음. 1px 보더로 구분.
   ============================================================ */
.card {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-3);
  background-color: var(--white);
  border: var(--border);
  border-radius: var(--radius);
  transition: var(--transition);
}

a.card:hover,
.card--link:hover {
  border-color: var(--navy-700);
  background-color: var(--teal-050);
}

.card__icon {
  color: var(--teal-500);
}
.card__icon svg {
  width: 28px;
  height: 28px;
}

.card__title {
  font-size: var(--fs-h3);
  font-weight: var(--fw-semibold);
  color: var(--navy-700);
}

.card__body {
  font-size: 0.9375rem;
  color: var(--color-text-muted);
  line-height: 1.65;
}

/* 번호가 붙는 카드 (차별화 6가지 등) */
.card__num {
  font-family: var(--font-en);
  font-size: var(--fs-caption);
  font-weight: var(--fw-bold);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.08em;
  color: var(--teal-300);
}

.card--dark {
  background-color: transparent;
  border-color: var(--color-border-dark);
}
.card--dark .card__title {
  color: var(--white);
}
.card--dark .card__body {
  color: rgba(255, 255, 255, 0.68);
}

/* ============================================================
   8. FOOTER
   ============================================================ */
.site-footer {
  background-color: var(--navy-900);
  color: rgba(255, 255, 255, 0.7);
  font-size: var(--fs-caption);
  line-height: 1.7;
}

.footer__main {
  display: grid;
  gap: var(--space-4);
  padding-block: var(--space-5);
  grid-template-columns: 1fr;
}

@media (min-width: 700px) {
  .footer__main {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 1000px) {
  .footer__main {
    grid-template-columns: minmax(0, 4fr) minmax(0, 2fr) minmax(0, 3fr);
    gap: var(--space-5);
  }
}

.footer__brand .logo__name,
.footer__brand .logo {
  color: var(--white);
}
.footer__brand .logo__name {
  color: var(--white);
  font-size: 1.125rem;
}
.footer__brand .logo__sub {
  color: rgba(255, 255, 255, 0.55);
}

.footer__tagline {
  margin-top: var(--space-2);
  max-width: 34ch;
  color: rgba(255, 255, 255, 0.7);
}

.footer__heading {
  margin-bottom: var(--space-2);
  font-family: var(--font-en);
  font-size: var(--fs-eyebrow);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--teal-300);
}

.footer__nav {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.footer__nav a {
  color: rgba(255, 255, 255, 0.78);
}
.footer__nav a:hover {
  color: var(--white);
}

/* 정의형 정보 목록 (주소/전화/이메일) */
.footer__dl {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 6px var(--space-2);
  margin: 0;
}

.footer__dl dt {
  color: rgba(255, 255, 255, 0.45);
  white-space: nowrap;
}

.footer__dl dd {
  margin: 0;
  color: rgba(255, 255, 255, 0.82);
  font-variant-numeric: tabular-nums;
}

.footer__dl dd a {
  color: rgba(255, 255, 255, 0.82);
}
.footer__dl dd a:hover {
  color: var(--white);
}

/* 등록·보험 신뢰 라인 */
.footer__credentials {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-3);
  padding-block: var(--space-3);
  border-top: var(--border-dark);
  color: rgba(255, 255, 255, 0.6);
}

.footer__credentials li {
  display: flex;
  align-items: center;
  gap: 0.5em;
}

.footer__credentials svg {
  width: 15px;
  height: 15px;
  color: var(--teal-300);
}

.footer__bottom {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  padding-block: var(--space-3);
  border-top: var(--border-dark);
  color: rgba(255, 255, 255, 0.45);
  font-size: 0.8125rem;
}

/* ---------- 푸터 법적 링크 ----------
   좁은 화면에서는 이 줄이 먼저 오게 한다. 법적 고지는 찾을 수 있어야 하는데
   모바일에서 저작권·업종 뒤로 밀리면 화면 맨 끝에 묻힌다. */
.footer__legal {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-1) var(--space-3);
  margin: 0;
  padding: 0;
  list-style: none;
  order: -1;
}

.footer__legal a {
  /* inline 이면 높이가 글자 높이(17px)에 묶여 손가락으로 누르기 어렵다.
     이 프로젝트는 터치 타겟 44px 를 기준으로 잡아 두었으므로 맞춘다.
     여백은 보이지 않으므로 시각적으로는 그대로다. */
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: rgba(255, 255, 255, 0.62);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: var(--transition);
}

@media (min-width: 768px) {
  /* 데스크톱에서는 마우스로 누르므로 44px 를 유지할 이유가 없다.
     푸터 하단 줄이 불필요하게 두꺼워지는 것만 막는다. */
  .footer__legal a {
    min-height: 32px;
  }
}

.footer__legal a:hover {
  color: var(--white);
  border-bottom-color: rgba(255, 255, 255, 0.4);
}

/* 개인정보처리방침은 나머지 안내와 구분되게 표시하는 것이 일반적이다.
   .footer__legal a 가 0-1-1 이라 클래스 하나(0-1-0)로는 색을 못 덮는다.
   !important 대신 부모를 한 번 더 적어 특이도를 맞춘다. */
.footer__legal .footer__legal-strong {
  font-weight: var(--fw-semibold);
  color: rgba(255, 255, 255, 0.9);
}

@media (min-width: 768px) {
  .footer__legal {
    order: 0;
  }
}

/* ============================================================
   9. FORM
   ============================================================ */
.field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.field__label {
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  color: var(--navy-700);
}

.field__required {
  color: var(--accent);
  margin-left: 2px;
}

.field__hint {
  font-size: 0.8125rem;
  color: var(--gray-600);
}

.input,
.select,
.textarea {
  width: 100%;
  min-height: 48px;
  padding: 12px var(--space-2);
  background-color: var(--white);
  border: var(--border-w) solid var(--gray-300);
  border-radius: var(--radius);
  font-size: var(--fs-body);
  color: var(--black-900);
  transition: var(--transition);
}

.textarea {
  min-height: 120px;
  line-height: 1.6;
}

.input::placeholder,
.textarea::placeholder {
  color: #9aa4b0;
}

.input:hover,
.select:hover,
.textarea:hover {
  border-color: var(--gray-600);
}

.input:focus-visible,
.select:focus-visible,
.textarea:focus-visible {
  border-color: var(--teal-500);
  outline: var(--focus-ring);
  outline-offset: 0;
}

.field.is-invalid .input,
.field.is-invalid .select,
.field.is-invalid .textarea {
  border-color: var(--accent);
}

.field__error {
  display: flex;
  align-items: center;
  gap: 0.4em;
  font-size: 0.8125rem;
  color: var(--accent);
}

.field__error svg {
  width: 15px;
  height: 15px;
}

.field__error[hidden] {
  display: none;
}

/* ============================================================
   10. HERO
   좌측 정렬 고정. 중앙 정렬 금지(템플릿처럼 보임).

   사진은 여기서 CSS background 로 깔지 않는다.
   .hero--feature 가 .hero__bg 의 <picture> 로 따로 넣기 때문이다.
   여기에도 url() 을 두면 같은 파일을 두 번 내려받는다 — 실제로
   hero-port.webp 와 hero-port-900.webp 가 동시에 요청되어 LCP 경로에서
   225KB 를 헛되이 쓰고 있었다. 게다가 두 레이어가 겹쳐 스크림 농도까지
   의도보다 짙어진다. 그라데이션만 남긴다.
   ============================================================ */
.hero {
  position: relative;
  background-color: var(--navy-900);
  background-image: var(--overlay-hero);
  background-size: cover;
  background-position: center right;
  color: rgba(255, 255, 255, 0.82);
  --hero-pad: var(--space-5);
  /* overflow:hidden 을 두면 항구 선택 패널이 히어로 경계에서 잘린다 */
}

@media (min-width: 768px) {
  .hero {
    --hero-pad: var(--space-6);
  }
}

/* ---------- 헤더를 히어로 위로 겹친다 ----------
   투명 네비게이션이 성립하려면 헤더 뒤에 어두운 히어로가 있어야 한다.
   지금까지는 헤더가 자기 자리를 차지하고 히어로가 그 아래에서 시작했으므로,
   배경을 투명하게 만들면 흰 body 가 비쳐 흰 글자가 사라진다.

   히어로를 헤더 높이만큼 끌어올리고(margin-top 음수) 같은 값을 위쪽 여백으로
   되돌려 준다(padding-top). 박스는 그만큼 커지지만 그만큼 올라가므로
   내용의 위치도, 문서 전체 높이도 달라지지 않는다.

   히어로에만 걸어 두는 이유: 히어로가 없는 문서(styleguide)에서 헤더가
   본문 위로 올라타 글자를 덮는 사고를 막기 위해서다. 그런 페이지는
   지금처럼 헤더가 자리를 차지한 채로 남는다.

   여백을 --hero-pad 변수로 모은 것도 이 때문이다. 변형마다 값이 다른데
   (compact 40 / 기본 64 / masthead 96) 더하는 자리는 한 곳이어야 한다. */
.hero,
.page-hero {
  padding-block: var(--hero-pad);
  margin-top: calc(-1 * var(--header-total-h));
  padding-top: calc(var(--hero-pad) + var(--header-total-h));
}

.hero__inner {
  display: grid;
  gap: var(--space-5);
  align-items: center;
}

@media (min-width: 1000px) {
  .hero__inner {
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    gap: var(--space-5);
  }
}

.hero h1 {
  color: var(--white);
  /* 카피의 줄바꿈(\n)을 그대로 살린다 — 어절이 아니라 의미 단위로 끊기 위함 */
  white-space: pre-line;
}

.hero__lead {
  margin-top: var(--space-3);
  max-width: 52ch;
  font-size: var(--fs-body-lg);
  color: rgba(255, 255, 255, 0.78);
}

.hero__actions {
  margin-top: var(--space-4);
}

/* ---------- 히어로 내 간이 견적 폼 ----------
   LX판토스가 히어로에 즉시 견적 도구를 둔 구조를 참고했다.
   백엔드가 없으므로 GET으로 Contact 페이지에 값을 넘겨 프리필한다. */
.quickquote {
  padding: var(--space-3);
  background-color: var(--white);
  border-radius: var(--radius);
  border: var(--border);
}

@media (min-width: 768px) {
  .quickquote {
    padding: var(--space-4);
  }
}

.quickquote__title {
  font-size: var(--fs-h3);
  font-weight: var(--fw-bold);
  color: var(--navy-700);
  letter-spacing: var(--ls-heading);
}

.quickquote__note {
  display: inline-flex;
  align-items: center;
  gap: 0.45em;
  margin-top: var(--space-1);
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  color: var(--teal-500);
}

.quickquote__note svg {
  width: 15px;
  height: 15px;
}

.quickquote__fields {
  display: grid;
  gap: var(--space-2);
  margin-top: var(--space-3);
}

@media (min-width: 480px) {
  .quickquote__fields {
    grid-template-columns: 1fr 1fr;
  }
  .quickquote__fields .field--full {
    grid-column: 1 / -1;
  }
}

/* ============================================================
   11. STEP — 3대 특전 (가로 스텝)
   3단 카드 그리드 대신 번호가 흐르는 가로 배열.
   ============================================================ */
.steps {
  display: grid;
  gap: var(--space-3);
  counter-reset: step;
}

@media (min-width: 900px) {
  .steps {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 0;
  }
}

.step {
  position: relative;
  padding: var(--space-3) 0 0;
  border-top: 2px solid var(--teal-500);
}

@media (min-width: 900px) {
  .step {
    padding: var(--space-3) var(--space-3) 0 0;
  }
  /* 마지막 칸은 우측 여백 제거 — 그리드가 어긋나 보이는 것을 막는다 */
  .step:last-child {
    padding-right: 0;
  }
}

.step__num {
  font-family: var(--font-en);
  font-size: var(--fs-caption);
  font-weight: var(--fw-bold);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.1em;
  color: var(--teal-500);
}

.step__label {
  display: block;
  margin-top: var(--space-1);
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  color: var(--gray-600);
}

/* 헤드라인이 이 섹션의 본체다.
   "선사 영업부와 DIRECT 거래", "4주간 외부 CY 이용 서비스 (무상)" —
   회사가 파는 조건의 실체가 전부 이 문장 안에 있는데 1.375rem 이라
   설명문과 같은 음량으로 지나갔다. 수치를 따로 떼어 크게 박는 방법은
   표시용 JSON 키가 필요해서 쓰지 않기로 했으므로(승인 조건),
   문장 자체를 키운다. 핵심어가 문장 앞머리에 있어 효과는 같다. */
.step__headline {
  margin-top: 6px;
  font-size: clamp(1.5rem, 1.1rem + 1.6vw, 2rem);
  font-weight: var(--fw-bold);
  line-height: 1.3;
  letter-spacing: var(--ls-heading);
  color: var(--navy-900);
}

/* 4열 변형(영문 pillars)은 칸이 좁아 같은 크기면 두 줄 접힘이 심하다 */
.steps--4 .step__headline {
  font-size: clamp(1.25rem, 1rem + 0.9vw, 1.5rem);
}

.step__body {
  margin-top: var(--space-2);
  font-size: 0.9375rem;
  color: var(--color-text-muted);
  line-height: 1.65;
}

.step__extra {
  display: block;
  margin-top: var(--space-2);
  padding-left: var(--space-2);
  border-left: 2px solid var(--gray-300);
  font-size: 0.9375rem;
  font-weight: var(--fw-semibold);
  color: var(--navy-700);
}

/* 품목 나열 아래 붙는 보조 블록 (Clients — 가구 운송).
   별도 섹션이었을 때는 제목 하나·문장 하나로 293px 를 썼다.
   여기서는 앞 내용에 딸린 각주 성격이므로 h3 급으로 낮추고
   같은 섹션 안에 괘선으로만 구분한다. */
.cargo-note {
  display: grid;
  gap: var(--space-2);
  margin-top: var(--space-4);
  padding-top: var(--space-3);
  border-top: var(--border);
}

@media (min-width: 900px) {
  .cargo-note {
    grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
    gap: var(--space-4);
    align-items: start;
  }
}

.cargo-note__title {
  margin-top: 6px;
}

/* 섹션 끝의 문맥 CTA — 하단 CTA 밴드까지 내려가지 않아도
   그 자리에서 바로 넘어갈 수 있게 하는 작은 출구.
   버튼이 아니라 링크인 것은 의도적이다. 섹션마다 버튼이 서 있으면
   광고처럼 읽히고, 이 사이트의 절제 어법에도 맞지 않는다. */
.section-cta {
  margin-top: var(--space-4);
  padding-top: var(--space-3);
  border-top: var(--border);
}

/* ============================================================
   12. SERVICE ITEM — 2×4 그리드
   ============================================================ */
.service-grid {
  display: grid;
  gap: 0;
  border-top: var(--border);
}

@media (min-width: 600px) {
  .service-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 1000px) {
  .service-grid {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

/* hover 에서 하단선이 teal 로 굵어진다.
   border-width 를 바꾸면 칸 높이가 흔들리므로 inset box-shadow 로 겹친다.
   요소가 뜨거나 움직이지 않고 선 하나만 진해진다 — 7칸이 나란한 그리드에서
   "지금 어디에 있는지"를 알려주는 데 그 이상은 필요 없다. */
.service-item {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding: var(--space-3) var(--space-3) var(--space-4) 0;
  border-bottom: var(--border);
  box-shadow: inset 0 -2px 0 transparent;
  transition: var(--transition), box-shadow var(--dur) var(--ease);
}

.service-item:not(.service-item--action):hover {
  box-shadow: inset 0 -2px 0 var(--teal-500);
}

.service-item:not(.service-item--action):hover .service-item__title {
  color: var(--navy-900);
}

.service-item:not(.service-item--action):hover .service-item__icon {
  color: var(--navy-700);
}

@media (min-width: 600px) {
  .service-item {
    padding-right: var(--space-3);
  }
}

.service-item__icon {
  color: var(--teal-500);
  margin-bottom: var(--space-1);
  transition: color var(--dur) var(--ease);
}
.service-item__icon svg {
  width: 28px;
  height: 28px;
  /* stroke 1.5 는 이 크기에서 흐려 보인다. 아이콘 7개가 나란히 흐리면
     화면 전체가 덜 완성된 인상을 준다. */
  stroke-width: 1.75;
}

.service-item__title {
  font-size: 1.0625rem;
  font-weight: var(--fw-semibold);
  color: var(--navy-700);
  transition: color var(--dur) var(--ease);
}

.service-item__body {
  font-size: 0.875rem;
  line-height: 1.6;
  color: var(--color-text-muted);
}

/* 마지막 칸의 전체보기 액션 */
.service-item--action {
  justify-content: center;
  background-color: var(--teal-050);
  padding-left: var(--space-3);
}

/* ============================================================
   13. 차별화 리스트 — sticky-split 우측
   ============================================================ */
.diff-list {
  border-top: var(--border);
}

/* 여섯 항목이 같은 간격으로 쌓여 있어 눈이 미끄러진다.
   hover 에서 그 행만 좌측 teal 마커가 서고 배경이 아주 옅게 든다.
   읽던 자리를 잃지 않게 하는 장치이지 장식이 아니다.
   padding-left 를 미리 확보해 마커가 생겨도 글자가 밀리지 않는다. */
.diff-item {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--space-2) var(--space-3);
  padding-block: var(--space-3);
  padding-left: var(--space-2);
  border-bottom: var(--border);
  box-shadow: inset 2px 0 0 transparent;
  transition: var(--transition), box-shadow var(--dur) var(--ease);
}

.diff-item:hover {
  box-shadow: inset 2px 0 0 var(--teal-300);
  background-color: rgba(255, 255, 255, 0.04);
}

.diff-item__num {
  font-family: var(--font-en);
  font-size: var(--fs-caption);
  font-weight: var(--fw-bold);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.08em;
  color: var(--teal-300);
  padding-top: 4px;
}

.diff-item__title {
  font-size: 1.125rem;
  font-weight: var(--fw-semibold);
  color: var(--navy-700);
}

.diff-item__body {
  grid-column: 2;
  margin-top: 4px;
  font-size: 0.9375rem;
  color: var(--color-text-muted);
  line-height: 1.65;
}

/* 다크 섹션 안의 차별화 리스트 — 인라인 style 대신 여기서 처리 */
.section--dark .diff-list,
.section--dark .diff-item {
  border-color: var(--color-border-dark);
}

.section--dark .diff-item__title {
  color: var(--white);
}

.section--dark .diff-item__body {
  color: rgba(255, 255, 255, 0.68);
}

/* ============================================================
   14. 고객사 그리드 — 로고 게재 동의 전 placeholder
   ============================================================ */
/* ---------- 고객사 — 타이포 인덱스 ----------
   처음에는 회색 상자(gray-100 채움 + 72px 셀 + 13px 회색 글자)였다.
   로고가 들어올 자리처럼 보여서, 동의를 못 받아 텍스트만 넣은 상태가
   "준비 중"으로 읽혔다. GS글로벌·씰리 같은 이름이 갖는 신뢰의 무게가
   상자 안에서 0이 됐다.

   그래서 상자를 버리고 이름 자체를 조판한다. 편집물의 크레딧 목록처럼
   괘선(1px 하단선)만 쓰고 채움과 테두리 상자를 없앤다. 로고를 기다리는
   빈 틀이 아니라, 처음부터 텍스트로 설계한 목록으로 읽히게.
   마크업(.client-grid / .client-cell)은 그대로 두고 표현만 바꿨으므로
   Home·Clients·영문 Home 세 곳에 동시에 적용된다.
   로고 동의가 확정되면 그때 이미지 셀로 되돌리면 된다. */
.client-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0 var(--space-4);
  border-top: 1px solid var(--color-border);
}

@media (min-width: 600px) {
  .client-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

/* 6열 → 4열. 6열이면 한 칸이 좁아 이름이 두 줄로 접히고 목록이 두 줄로
   끝나 목록감이 없다. 3열로 했더니 이번엔 4행이 되어 Home 섹션이 기존보다
   96px 길어졌다 — 밀도를 올리려는 작업에서 역행이라, 12개가 3행으로
   떨어지는 4열로 잡는다. 이름이 한 줄로 서는 최대 밀도 지점이다. */
@media (min-width: 900px) {
  .client-grid {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

.client-cell {
  display: flex;
  align-items: center;
  min-height: 64px;
  padding: var(--space-2) 0;
  border-bottom: 1px solid var(--color-border);
  font-size: 1.0625rem;
  font-weight: var(--fw-semibold);
  color: var(--color-heading);
  letter-spacing: var(--ls-heading);
  line-height: 1.35;
  box-shadow: inset 0 -1px 0 transparent;
  transition: var(--transition), box-shadow var(--dur) var(--ease);
}

/* 12개 이름이 균질하게 늘어서면 목록 전체가 한 덩어리로 읽힌다.
   커서가 닿은 이름의 괘선만 teal 로 진해져 '개별 거래처'로 분해된다.
   로고를 못 쓰는 상태에서 이름 하나하나에 무게를 주는 방법이다. */
.client-cell:hover {
  color: var(--navy-900);
  box-shadow: inset 0 -1px 0 var(--teal-500);
}

/* ============================================================
   15. 회사 요약 팩트
   ============================================================ */
.facts {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-2);
  padding-top: var(--space-3);
  border-top: var(--border);
}

.fact__label {
  font-size: var(--fs-caption);
  color: var(--color-text-muted);
}

.fact__value {
  margin-top: 2px;
  font-size: 1.375rem;
  font-weight: var(--fw-bold);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
  color: var(--navy-700);
}

.fact__unit {
  font-size: 0.9375rem;
  font-weight: var(--fw-medium);
  color: var(--gray-600);
}

/* ---------- 대표 경력 미니 타임라인 ---------- */
.timeline__heading {
  margin-bottom: var(--space-2);
}

/* ---------- 대표 경력 ----------
   처음에는 연도+라벨이 0.9375rem 본문 5줄이었다. "선사 출신"이 이 회사의
   유일한 복제 불가능 자산인데 이력서 각주처럼 읽혔다.
   선사명이 증거의 본체이므로 라벨을 키워 이름이 지배하게 하고,
   연도는 작은 서수로 종속시킨다. 데이터와 마크업은 그대로다 —
   "TS LINE 근무" 문자열에서 조판을 키우면 어차피 이름이 화면을 갖는다.
   설립(2015) 행은 마지막이자 결론이므로 한 단계 더 크게, navy-900으로.
   괘선·좌측정렬·채움 없음 — 기존 어법 유지. */
.timeline {
  display: flex;
  flex-direction: column;
  border-top: var(--border);
}

.timeline__row {
  display: grid;
  grid-template-columns: 64px minmax(0, 1fr);
  gap: var(--space-2);
  align-items: baseline;
  padding-block: 14px;
  border-bottom: var(--border);
  transition: var(--transition);
}

/* 선사 네 곳이 이 회사의 유일한 복제 불가능 자산이다.
   커서가 닿은 행의 연도가 진해지며 그 한 줄만 살아난다.
   채움도 이동도 없다 — 이력을 읽는 화면에서 그 이상은 과하다. */
.timeline__row:hover .timeline__year {
  color: var(--navy-700);
}

.timeline__row:hover .timeline__label {
  color: var(--navy-900);
}

.timeline__year,
.timeline__label {
  transition: color var(--dur) var(--ease);
}

.timeline__year {
  font-family: var(--font-en);
  font-size: 0.8125rem;
  font-weight: var(--fw-semibold);
  font-variant-numeric: tabular-nums;
  color: var(--teal-500);
}

.timeline__label {
  /* 모바일에서 "DONGJIN SHIPPING 근무"가 접히지 않는 상한.
     처음 상한을 1.25rem 으로 잡았다가 검토에서 과하다고 해서 반 단계 내렸다.
     본문(0.9375rem)보다는 확실히 크게 — 증거라는 위계는 유지한다. */
  font-size: clamp(1rem, 0.9rem + 0.5vw, 1.125rem);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-heading);
  line-height: var(--lh-snug);
  color: var(--navy-700);
}

.timeline__row--founding .timeline__label {
  font-size: clamp(1.125rem, 1rem + 0.7vw, 1.3125rem);
  font-weight: var(--fw-bold);
  color: var(--navy-900);
}

/* ============================================================
   16. CTA BAND
   ============================================================ */
/* 마지막 전환 지점인데 281px 로 가장 낮아서, 큰 푸터 바로 위에 낀
   띠처럼 보였다. 상단 teal 괘선 한 줄로 본문과 끊어 "여기서부터는 요청"
   임을 알린다.

   ⚠ 여백을 96px 로 올렸다가 되돌렸다. 이 밴드의 콘텐츠는 145px 뿐이라
     (eyebrow + 제목 + 리드 / 버튼 2개) 여백을 키우면 채움률이 42% 까지
     떨어져 "비어 있다"로 읽힌다. 낮아 보이는 원인은 여백이 아니라
     콘텐츠가 얇은 것이므로, 존재감은 괘선과 색으로 만든다.
     실측: space-5 → 51% / space-6 → 42%. */
.cta-band {
  background-color: var(--navy-900);
  color: rgba(255, 255, 255, 0.8);
  border-top: 2px solid var(--teal-500);
}

.cta-band__inner {
  display: grid;
  gap: var(--space-3);
  padding-block: var(--space-5);
}

@media (min-width: 900px) {
  .cta-band__inner {
    grid-template-columns: minmax(0, 7fr) minmax(0, 4fr);
    gap: var(--space-5);
    align-items: center;
  }
}

.cta-band h2 {
  color: var(--white);
}

.cta-band__lead {
  margin-top: var(--space-2);
  color: rgba(255, 255, 255, 0.72);
  max-width: 56ch;
}

.cta-band__actions {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

@media (min-width: 480px) and (max-width: 899px) {
  .cta-band__actions {
    flex-direction: row;
  }
}

/* ============================================================
   17. 영문 Home 전용 보조 컴포넌트
   ============================================================ */

/* 4열 스텝 — 영문 Home의 'Why partners work with us' */
@media (min-width: 900px) {
  .steps--4 {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

/* 태그 목록 — 파트너 국가, 취급 화물 품목 */
.tag-list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
}

.tag {
  display: inline-flex;
  align-items: center;
  padding: 7px var(--space-2);
  background-color: var(--white);
  border: var(--border);
  border-radius: var(--radius);
  font-size: var(--fs-caption);
  color: var(--navy-700);
  white-space: nowrap;
}

.section--dark .tag {
  background-color: transparent;
  border-color: var(--color-border-dark);
  color: rgba(255, 255, 255, 0.86);
}

/* 자사(대한민국) 표시 */
.tag--home {
  border-color: var(--teal-500);
  font-weight: var(--fw-semibold);
}

.section--dark .tag--home {
  border-color: var(--teal-300);
  color: var(--white);
}

/* 등록·보험 카드 */
.cred-card {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: var(--space-3);
  border: var(--border);
  border-left: 3px solid var(--teal-500);
  border-radius: var(--radius);
  background-color: var(--white);
}

.cred-card__icon {
  color: var(--teal-500);
  margin-bottom: 2px;
}
.cred-card__icon svg {
  width: 22px;
  height: 22px;
}

.cred-card__title {
  font-size: 1rem;
  font-weight: var(--fw-semibold);
  color: var(--navy-700);
}

.cred-card__issuer {
  font-size: var(--fs-caption);
  color: var(--color-text-muted);
}

/* 라이선스 요건 — 번호 없는 체크 목록 */
.check-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.check-list li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 0.6em;
  align-items: start;
  font-size: 0.9375rem;
  color: var(--color-text-muted);
}

.check-list svg {
  width: 17px;
  height: 17px;
  color: var(--teal-500);
  margin-top: 3px;
}

/* 큰 수치 강조 — 80 partners */
.bignum {
  display: flex;
  align-items: baseline;
  gap: 0.35em;
}

.bignum__value {
  font-family: var(--font-en);
  font-size: clamp(3rem, 8vw, 5rem);
  font-weight: var(--fw-bold);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.03em;
  line-height: 1;
  color: var(--white);
}

.bignum__label {
  font-size: var(--fs-body-lg);
  color: rgba(255, 255, 255, 0.72);
}

/* ============================================================
   18. CONTACT — 폼 / 상태 패널 / 정보 카드 / FAQ
   ============================================================ */

/* ---------- 페이지 히어로 (Home 히어로보다 낮은 변형) ---------- */
.page-hero {
  background-color: var(--navy-900);
  background-image: var(--overlay-hero);
  color: rgba(255, 255, 255, 0.82);
  /* 실제 여백은 위쪽 `.hero, .page-hero` 규칙이 헤더 높이를 더해 확정한다 */
  --hero-pad: var(--space-5);
}

.page-hero h1 {
  color: var(--white);
}

.page-hero__lead {
  margin-top: var(--space-3);
  max-width: 60ch;
  font-size: var(--fs-body-lg);
  color: rgba(255, 255, 255, 0.78);
}

.page-hero .badge {
  margin-top: var(--space-3);
}

/* ---------- 페이지 히어로 2단 변형 ----------
   우측에 그 페이지의 사실 패널이 붙는다 (목차·수치·품목).

   비율을 Home 히어로(.hero__inner)와 똑같은 7:5 로 맞췄다.
   Home 에서 하위 페이지로 넘어올 때 좌측 텍스트 기둥의 폭이 그대로여서
   같은 사이트 안에서 움직이고 있다는 감각이 유지된다.

   1000px 미만에서는 한 단으로 접힌다. 좁은 화면에서 5fr 은
   목차 항목 하나가 두 줄로 접히는 폭이라 오히려 읽기 나빠진다. */
.page-hero--split .page-hero__lede .page-hero__lead {
  /* 2단일 때는 우측 패널이 폭을 가져가므로 60ch 상한이 의미가 없다.
     오히려 상한 때문에 좌측이 어중간하게 남는다. */
  max-width: 52ch;
}

@media (min-width: 1000px) {
  .page-hero--split .page-hero__inner {
    display: grid;
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    gap: var(--space-5);
    align-items: center;
  }

  /* "lede" 변형 — 리드를 제목 오른쪽 아래로 보낸다.
     제목이 홀로 서면서 주장이 먼저 읽히고, 설명은 뒤따라온다.
     .section-head--split 과 같은 리듬이다: 아래를 맞추고 리드를
     제목 baseline 에 얹는다. */
  .page-hero--lede .page-hero__inner {
    align-items: end;
  }

  .page-hero--lede .page-hero__aside .page-hero__lead {
    margin-top: 0;
    padding-bottom: 0.35em; /* 제목 baseline 에 맞춤 */
  }
}

/* ---------- 압축 변형 (Clients) ----------
   히어로 높이로 페이지 사이의 위계를 만든다.

     Company   96px (--space-6)  정체성 페이지. 표제면으로 가장 높게
     기본       64px (--space-5)  Services / Strength
     Clients   40px (--space-4)  가장 낮게

   Clients 를 낮추는 건 이 페이지가 덜 중요해서가 아니라, 방문자의 질문이
   "내 화물을 다뤄봤나" 하나이고 그 답(취급 품목 목록)이 바로 아래에 있기
   때문이다. 히어로가 길면 답에 닿기까지 스크롤이 한 번 더 필요해진다.
   여기서 히어로가 할 일은 버티는 게 아니라 비켜서는 것이다. */
.page-hero--compact {
  --hero-pad: var(--space-4);
}

/* ---------- 표제면 변형 (Company) ----------
   이 페이지는 히어로에 올릴 사실이 없다. 바로 아래가 설립일·대표이사·업종·
   주소·연락처가 늘어선 회사 개요 표라서, 무엇을 가져와도 두 번 말하게 된다.
   그래서 사실을 더하지 않고 지면을 다룬다.

   장치는 셋뿐이다 — 괘선 하나, 여백, 좁은 리드.
   이 시스템은 그림자 대신 1px 선을 쓰고, 화려함이 아니라 절제로 신뢰를
   만든다고 정해 두었다. 표제면도 같은 어법으로 간다.
   제목 크기는 건드리지 않았다. 한 페이지만 크게 하면 그 페이지만 뜬다. */
.page-hero--masthead {
  --hero-pad: var(--space-6);
}

.page-hero__rule {
  display: block;
  height: 1px;
  margin-block: var(--space-3);
  background-color: rgba(255, 255, 255, 0.22);
}

.page-hero--masthead .page-hero__lead {
  /* 기본 60ch 보다 좁게. 제목 아래에서 한 덩어리로 앉아야 표제면이 된다. */
  max-width: 46ch;
  margin-top: var(--space-4);
}

/* ---------- 히어로 목차 ----------
   Services 히어로 우측. 흰 카드로 만들지 않았다.
   Home 히어로의 견적 폼이 이미 흰 카드라, 여기서 같은 형태를 쓰면
   두 페이지가 같은 장치를 반복하는 것으로 읽힌다.
   여기서는 채우지 않고 괘선만으로 표를 만든다 — 편집물의 목차에 가깝게. */
.hero-index__list {
  margin: 0;
  padding: 0;
  list-style: none;
  border-top: 1px solid rgba(255, 255, 255, 0.16);
}

.hero-index__link {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-2);
  align-items: baseline;
  padding-block: var(--space-1);
  border-bottom: 1px solid rgba(255, 255, 255, 0.16);
  text-decoration: none;
  /* 다크 배경 위에서 --color-link(teal-500)는 대비가 무너진다.
     링크 색을 여기서 명시적으로 끊어 준다. */
  color: rgba(255, 255, 255, 0.82);
  transition: var(--transition);
}

.hero-index__num {
  font-family: var(--font-en);
  font-size: 0.6875rem;
  font-weight: var(--fw-semibold);
  letter-spacing: 0.14em;
  color: rgba(255, 255, 255, 0.42);
  transition: var(--transition);
}

.hero-index__label {
  font-size: var(--fs-body);
  font-weight: var(--fw-medium);
}

/* transform 은 쓰지 않는다 (금지 사항). 색과 괘선만 움직인다. */
.hero-index__link:hover {
  color: var(--white);
  border-bottom-color: var(--teal-300);
}

.hero-index__link:hover .hero-index__num {
  color: var(--teal-300);
}

/* ---------- 개인정보 수집·이용 동의 ----------
   제출 버튼 바로 위 한 줄. 폼이 이미 길어서 여기서 더 늘리지 않는다.

   체크박스를 숨기고 가짜 사각형을 그리는 방식은 쓰지 않았다.
   네이티브 체크박스를 그대로 두면 키보드 조작·스크린리더·브라우저
   자동완성이 전부 공짜로 따라온다. accent-color 만 브랜드 색으로 바꾼다. */
.field--consent {
  margin-top: var(--space-3);
}

.consent {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  cursor: pointer;
}

.consent__box {
  /* 터치 타겟을 유지하면서 시각 크기는 18px로. margin 으로 라벨 첫 줄에 맞춘다. */
  flex-shrink: 0;
  width: 18px;
  height: 18px;
  margin: 2px 0 0;
  accent-color: var(--teal-500);
  cursor: pointer;
}

.consent__label {
  font-size: var(--fs-body);
  line-height: 1.5;
  color: var(--color-text);
}

.consent__link {
  margin-left: 0.35em;
  color: var(--color-link);
  /* 본문 안의 링크는 밑줄로 구분한다 (색상만으로 구분하지 않음) */
  text-underline-offset: 3px;
}

.consent__summary {
  margin-top: 6px;
  /* 체크박스 폭 + gap 만큼 들여써 라벨과 왼쪽을 맞춘다 */
  padding-left: 28px;
  font-size: var(--fs-caption);
  line-height: 1.6;
  color: var(--color-text-muted);
}

.field--consent .field__error {
  padding-left: 28px;
}

/* 오류 상태 — 다른 필드와 같은 신호를 쓴다 */
.field--consent.is-invalid .consent__box {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ---------- 법적 문서 (개인정보처리방침) ----------
   읽으라고 만든 페이지다. 장식을 넣지 않고 읽기 흐름만 정리한다. */
.legal-date {
  margin-bottom: var(--space-4);
  padding-bottom: var(--space-2);
  border-bottom: var(--border);
  font-size: var(--fs-caption);
  color: var(--color-text-muted);
}

.legal-section + .legal-section {
  margin-top: var(--space-4);
}

.legal-section__title {
  margin-bottom: var(--space-2);
  font-size: var(--fs-h3);
  color: var(--color-heading);
}

.legal-section__body {
  max-width: 68ch;
  color: var(--color-text);
}

.legal-list {
  margin: var(--space-2) 0 0;
  padding-left: 0;
  list-style: none;
  max-width: 68ch;
}

.legal-list li {
  position: relative;
  padding-left: var(--space-2);
  color: var(--color-text-muted);
}

.legal-list li + li {
  margin-top: 6px;
}

.legal-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.7em;
  width: 4px;
  height: 1px;
  background-color: var(--color-border);
}

/* 보호책임자·문의처 — 회사 개요 표와 같은 어법 */
.legal-contact {
  display: grid;
  grid-template-columns: 96px minmax(0, 1fr);
  gap: 6px var(--space-2);
  margin: var(--space-2) 0 0;
  padding: var(--space-2) var(--space-3);
  border-left: 3px solid var(--teal-500);
  background-color: var(--color-bg-subtle);
  font-size: var(--fs-caption);
}

.legal-contact dt {
  color: var(--color-text-muted);
}

.legal-contact dd {
  margin: 0;
  color: var(--color-text);
}

.legal-back {
  margin-top: var(--space-5);
  padding-top: var(--space-3);
  border-top: var(--border);
}

.legal-back a {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-weight: var(--fw-semibold);
}

/* ---------- 폼 셸 ---------- */
.form-shell {
  padding: var(--space-3);
  background-color: var(--white);
  border: var(--border);
  border-radius: var(--radius);
}

@media (min-width: 768px) {
  .form-shell {
    padding: var(--space-4);
  }
}

/* 폼 안의 소제목 — 운송 구간 / 화물 정보 / 연락처 */
.form-section + .form-section {
  margin-top: var(--space-4);
  padding-top: var(--space-4);
  border-top: var(--border);
}

.form-section__title {
  margin-bottom: var(--space-2);
  font-family: var(--font-en);
  font-size: var(--fs-eyebrow);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--gray-600);
}

html[lang="ko"] .form-section__title {
  font-family: var(--font-body);
  letter-spacing: 0.02em;
  text-transform: none;
  font-size: var(--fs-caption);
}

.form-grid {
  display: grid;
  gap: var(--space-2);
}

@media (min-width: 600px) {
  .form-grid--2 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .form-grid .field--full {
    grid-column: 1 / -1;
  }
}

.field__optional {
  margin-left: 4px;
  font-weight: var(--fw-regular);
  color: var(--gray-600);
}

.form-foot {
  margin-top: var(--space-4);
  padding-top: var(--space-3);
  border-top: var(--border);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

@media (min-width: 600px) {
  .form-foot {
    flex-direction: row-reverse;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
  }
  .form-foot .btn {
    flex-shrink: 0;
  }
}

/* 스팸 봇용 함정 필드. 사람에게는 보이지 않는다.
   display:none 은 일부 봇이 걸러내므로 화면 밖으로 밀어낸다. */
.honeypot {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* 제출 중 버튼 */
.btn[aria-busy="true"] {
  opacity: 0.7;
  pointer-events: none;
}

/* ---------- 프리필 안내 ---------- */
.prefill-note {
  display: flex;
  align-items: flex-start;
  gap: 0.6em;
  margin-bottom: var(--space-3);
  padding: 12px var(--space-2);
  background-color: var(--teal-050);
  border-left: 3px solid var(--teal-500);
  border-radius: var(--radius-sm);
  font-size: var(--fs-caption);
  color: var(--navy-700);
}

.prefill-note svg {
  width: 16px;
  height: 16px;
  color: var(--teal-500);
  margin-top: 2px;
}

.prefill-note[hidden] {
  display: none;
}

/* ---------- 오류 요약 ---------- */
.form-alert {
  display: flex;
  align-items: flex-start;
  gap: 0.6em;
  margin-bottom: var(--space-3);
  padding: 12px var(--space-2);
  background-color: var(--white);
  border: var(--border);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-sm);
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  color: var(--navy-700);
}

.form-alert svg {
  width: 16px;
  height: 16px;
  color: var(--accent);
  margin-top: 2px;
}

.form-alert[hidden] {
  display: none;
}

/* ---------- 제출 결과 패널 ---------- */
.form-result {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  align-items: flex-start;
  padding: var(--space-4) var(--space-3);
  border: var(--border);
  border-radius: var(--radius);
  background-color: var(--white);
}

@media (min-width: 768px) {
  .form-result {
    padding: var(--space-5) var(--space-4);
  }
}

.form-result[hidden] {
  display: none;
}

.form-result--success {
  border-left: 3px solid var(--teal-500);
}

.form-result--error {
  border-left: 3px solid var(--accent);
}

.form-result__icon svg {
  width: 32px;
  height: 32px;
}

.form-result--success .form-result__icon {
  color: var(--teal-500);
}

.form-result--error .form-result__icon {
  color: var(--accent);
}

.form-result__title {
  font-size: var(--fs-h3);
  font-weight: var(--fw-bold);
  color: var(--navy-700);
  letter-spacing: var(--ls-heading);
}

.form-result__body {
  max-width: 56ch;
  color: var(--color-text-muted);
}

/* ---------- 연락처 정보 카드 ---------- */
.info-grid {
  display: grid;
  gap: var(--space-2);
  grid-template-columns: 1fr;
}

@media (min-width: 600px) {
  .info-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 1000px) {
  .info-grid {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

.info-card {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: var(--space-3);
  border: var(--border);
  border-radius: var(--radius);
  transition: var(--transition);
}

.info-card__icon {
  color: var(--teal-500);
  margin-bottom: 2px;
}
.info-card__icon svg {
  width: 22px;
  height: 22px;
}

.info-card__label {
  font-size: var(--fs-caption);
  color: var(--color-text-muted);
}

.info-card__value {
  font-size: 1.0625rem;
  font-weight: var(--fw-semibold);
  font-variant-numeric: tabular-nums;
  color: var(--navy-700);
  line-height: 1.45;
}

a.info-card:hover {
  border-color: var(--navy-700);
  background-color: var(--teal-050);
}

/* ---------- FAQ — <details> 네이티브. JS 불필요 ---------- */
.faq-list {
  border-top: var(--border);
}

.faq-item {
  border-bottom: var(--border);
}

.faq-item__q {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: var(--space-2);
  align-items: center;
  padding-block: var(--space-3);
  font-size: 1.0625rem;
  font-weight: var(--fw-semibold);
  color: var(--navy-700);
  cursor: pointer;
  list-style: none;
  transition: var(--transition);
}

/* 기본 삼각형 마커 제거 */
.faq-item__q::-webkit-details-marker {
  display: none;
}

.faq-item__q:hover {
  color: var(--teal-500);
}

.faq-item__q:focus-visible {
  outline: var(--focus-ring);
  outline-offset: -2px;
}

/* +/− 대신 회전하는 셰브런 — transform은 아이콘 회전에만 허용 */
.faq-item__mark {
  width: 20px;
  height: 20px;
  color: var(--gray-600);
  transition: transform var(--dur) var(--ease), color var(--dur) var(--ease);
}

.faq-item[open] .faq-item__mark {
  transform: rotate(90deg);
  color: var(--teal-500);
}

.faq-item__a {
  padding-bottom: var(--space-3);
  max-width: var(--measure);
  color: var(--color-text-muted);
  line-height: 1.75;
}

/* ============================================================
   19. 하위 페이지 — 서비스 상세 / 프로세스 / 개요 표 / 인용
   ============================================================ */

/* ---------- 서비스 상세 행 ----------
   Home의 4열 그리드와 달리, 상세 페이지는 한 항목씩 넓게 읽히도록 행으로 쌓는다. */
.service-rows {
  border-top: var(--border);
}

/* 행 하나가 [번호] [아이콘+제목] [설명] 3단이다.

   전에는 번호·아이콘·제목이 한 덩어리(5fr)로 묶이고 설명이 7fr 이었다.
   그러면 7개 행에서 제목의 시작 x 좌표가 번호 폭에 따라 조금씩 흔들리고,
   무엇보다 번호가 제목에 붙어 있어 '목록 항목'으로만 읽혔다.
   번호를 자기 칸으로 떼어내면 왼쪽에 서수 열이 생겨 편집물의 색인처럼
   읽힌다 — 같은 데이터로 위계를 하나 더 만드는 방법이다.

   ⚠ 12칼럼 오프셋 함정(HANDOFF 3번)을 피해 grid-template-columns 로
     3단을 직접 정의한다. span/start 를 섞지 않는다. */
.service-row {
  position: relative;
  display: grid;
  /* 모바일에서는 번호·제목·본문이 세로로 쌓이므로 8px 이면 충분하다.
     16px 이면 세 덩어리가 흩어져 한 항목으로 안 묶인다. */
  gap: var(--space-1);
  /* 40px 였을 때 행 높이 153px 에 콘텐츠가 59px — 채움률 39% 로
     한 문장짜리 항목에 여백이 두 배였다. 7행이 이어지면 그 느슨함이
     누적돼 "내용이 없는 페이지"로 읽힌다. 24px 로 조이면 55% 가 된다. */
  padding-block: var(--space-3);
  padding-left: var(--space-2);
  border-bottom: var(--border);
  box-shadow: inset 2px 0 0 transparent;
  transition: var(--transition), box-shadow var(--dur) var(--ease);
}

@media (min-width: 800px) {
  .service-row {
    grid-template-columns: 88px minmax(0, 4fr) minmax(0, 7fr);
    gap: var(--space-3);
    align-items: baseline;
  }
}

/* 커서가 닿은 행만 좌측 teal 마커가 서고 배경이 아주 옅게 든다.
   7행이 같은 간격으로 쌓여 눈이 미끄러지는 것을 잡아 준다.
   Home 의 .diff-item 과 같은 어법이다 — 페이지가 바뀌어도 같은 규칙. */
.service-row:hover {
  box-shadow: inset 2px 0 0 var(--teal-500);
  background-color: var(--teal-050);
}

.service-row:hover .service-row__num {
  color: var(--teal-500);
}

.service-row:hover .service-row__icon {
  color: var(--navy-700);
}

.service-row:hover .service-row__title {
  color: var(--navy-900);
}

/* ---------- 색인에서 건너온 행 표시 ----------
   히어로의 목차를 눌러 내려오면 스크롤만 되고 "어느 행에 왔는지"는
   알려주지 않았다. 7행이 균질해서 도착점을 눈으로 다시 찾아야 했다 —
   목차를 둔 의미가 절반 사라지는 지점이다.

   :target 은 CSS 만으로 처리된다. JS 아코디언처럼 상태를 직접 관리하면
   뒤로가기·새로고침·링크 공유에서 어긋나는데, 이건 URL 이 곧 상태다.

   hover 와 같은 마커를 쓰되 색을 navy 로 바꿔 구분한다.
   hover 는 지나가는 것이고 target 은 머무는 것이다. */
.service-row:target {
  box-shadow: inset 3px 0 0 var(--navy-700);
  background-color: var(--teal-050);
}

.service-row:target .service-row__num {
  color: var(--navy-700);
}

.service-row__head {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
}

/* 번호를 구조 요소로 키운다.
   이 페이지는 같은 무게의 행 7개가 이어져서, 스크롤하면 어디쯤인지
   감이 오지 않고 전부 한 덩어리로 읽혔다. 큰 서수가 세로 리듬을 만들어
   "7개 중 3번째"라는 위치감을 준다.
   색은 gray-300(괘선과 같은 색)이다. 구조를 표시하는 장치이지 내용이
   아니므로 읽히되 앞에 나서지 않아야 한다. */
/* 데스크톱에서는 왼쪽 서수 열을 만드는 구조 요소라 크지만,
   모바일에서는 3단이 세로로 쌓여 번호가 제목 위에 혼자 눕는다.
   그 자리에서 2.25rem 은 제목보다 커져 위계가 뒤집힌다. */
.service-row__num {
  font-family: var(--font-en);
  font-size: 1.5rem;
  font-weight: var(--fw-bold);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
  line-height: 1;
  color: var(--gray-300);
  transition: color var(--dur) var(--ease);
}

@media (min-width: 800px) {
  .service-row__num {
    font-size: 2.25rem;
  }
}

.service-row__icon {
  color: var(--teal-500);
  transition: color var(--dur) var(--ease);
}
.service-row__icon svg {
  width: 34px;
  height: 34px;
  /* 기본 stroke 1.5 는 이 크기에서 흐려 보인다. 아이콘이 흐리면
     "대충 만든 사이트" 인상을 주므로 이 크기에서는 굵기를 올린다. */
  stroke-width: 1.75;
}

.service-row__title {
  font-size: 1.375rem;
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-heading);
  color: var(--navy-700);
  transition: color var(--dur) var(--ease);
}

/* 설명은 소개서 원문 한 문장뿐이다. 문장을 늘리거나 지어내지 않는 대신
   조판으로 읽히게 한다 — 본문 크기를 유지하되 줄길이를 46ch 로 줄여
   두 줄 안에 떨어지게 했다. 7행이 전부 한 줄이면 표처럼, 넉 줄이면
   덩어리처럼 보인다. 두 줄이 목록과 문장 사이의 지점이다. */
.service-row__body {
  font-size: var(--fs-body-lg);
  color: var(--color-text-muted);
  max-width: 46ch;
  line-height: 1.65;
}

/* ---------- 프로세스 (리스크 관리 7단계) ----------
   가로로 흐르되 모바일에서는 세로로 쌓인다. 번호가 연결선 역할을 한다. */
.process {
  display: grid;
  gap: var(--space-2);
  counter-reset: process;
}

@media (min-width: 700px) {
  .process {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 1000px) {
  .process {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

.process__step {
  position: relative;
  padding: var(--space-2) var(--space-2) var(--space-3);
  border: var(--border);
  border-top: 2px solid var(--teal-500);
  border-radius: var(--radius);
}

.section--dark .process__step {
  border-color: var(--color-border-dark);
  border-top-color: var(--teal-300);
}

.process__num {
  font-family: var(--font-en);
  font-size: 0.75rem;
  font-weight: var(--fw-bold);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.1em;
  color: var(--teal-500);
}

.section--dark .process__num {
  color: var(--teal-300);
}

.process__label {
  display: block;
  margin-top: 6px;
  font-size: 1rem;
  font-weight: var(--fw-semibold);
  color: var(--navy-700);
  line-height: var(--lh-snug);
}

.section--dark .process__label {
  color: var(--white);
}

.process__sub {
  display: block;
  margin-top: 2px;
  font-family: var(--font-en);
  font-size: var(--fs-caption);
  color: var(--color-text-muted);
}

.section--dark .process__sub {
  color: rgba(255, 255, 255, 0.55);
}

/* ---------- 회사 개요 표 ---------- */
.spec-table {
  border-top: var(--border);
}

.spec-table__row {
  display: grid;
  grid-template-columns: 1fr;
  gap: 4px;
  padding-block: var(--space-2);
  border-bottom: var(--border);
}

@media (min-width: 600px) {
  .spec-table__row {
    grid-template-columns: 200px minmax(0, 1fr);
    gap: var(--space-3);
    align-items: baseline;
  }
}

.spec-table__key {
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  color: var(--gray-600);
}

.spec-table__value {
  font-variant-numeric: tabular-nums;
  color: var(--color-text);
}

/* ---------- Vision / Mission 블록 ---------- */
.statement {
  padding: var(--space-3);
  border: var(--border);
  border-left: 3px solid var(--teal-500);
  border-radius: var(--radius);
  background-color: var(--white);
}

.statement__label {
  font-family: var(--font-en);
  font-size: var(--fs-eyebrow);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--teal-500);
}

.statement__text {
  margin-top: var(--space-1);
  font-size: 1.25rem;
  font-weight: var(--fw-semibold);
  line-height: var(--lh-snug);
  letter-spacing: var(--ls-heading);
  color: var(--navy-700);
}

.statement__sub {
  margin-top: var(--space-1);
  font-size: 0.9375rem;
  color: var(--color-text-muted);
}

.statement__list {
  margin-top: var(--space-2);
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.statement__list li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 0.6em;
  align-items: start;
  color: var(--color-text-muted);
}

.statement__list svg {
  width: 17px;
  height: 17px;
  color: var(--teal-500);
  margin-top: 4px;
}

/* ---------- 인용/강조 문장 ---------- */
.pullquote {
  padding-left: var(--space-3);
  border-left: 3px solid var(--teal-500);
  font-size: var(--fs-body-lg);
  font-weight: var(--fw-medium);
  color: var(--navy-700);
  max-width: var(--measure);
}

/* ============================================================
   20. PORT PICKER — 출발지·도착지 선택 패널
   네이티브 select 를 뒤에 남겨둔 채(폼 값의 원본) 그 위에 패널을 씌운다.
   JS 가 실패하면 select 가 그대로 보이므로 폼은 어떤 경우에도 동작한다.
   ============================================================ */
.portpicker {
  position: relative;
}

/* JS 가 붙으면 원본 select 를 시각적으로만 숨긴다 (접근성 트리에서는 유지) */
.js-port-field.is-enhanced .js-port-select {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.portpicker__trigger {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  width: 100%;
  min-height: 48px;
  padding: 12px var(--space-2);
  background-color: var(--white);
  border: var(--border-w) solid var(--gray-300);
  border-radius: var(--radius);
  font-size: var(--fs-body);
  color: var(--black-900);
  text-align: left;
  transition: var(--transition);
}

.portpicker__trigger:hover {
  border-color: var(--gray-600);
}

.portpicker__trigger[aria-expanded="true"] {
  border-color: var(--teal-500);
}

/* 아직 고르지 않은 상태 */
.portpicker__trigger.is-placeholder .portpicker__value {
  color: #9aa4b0;
}

.portpicker__trigger svg {
  width: 18px;
  height: 18px;
  color: var(--gray-600);
  transition: transform var(--dur) var(--ease);
}

.portpicker__trigger[aria-expanded="true"] svg {
  transform: rotate(180deg);
}

/* ---------- 패널 ---------- */
.portpicker__panel {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  z-index: var(--z-sticky);
  width: min(560px, calc(100vw - var(--space-4)));
  background-color: var(--white);
  border: var(--border-w) solid var(--gray-300);
  border-radius: var(--radius);
  box-shadow: var(--shadow-overlay);
  overflow: hidden;
}

.portpicker__panel[hidden] {
  display: none;
}

/* 필드가 화면 오른쪽에 붙어 있으면 패널을 오른쪽 기준으로 정렬 */
.portpicker--flip-right .portpicker__panel {
  left: auto;
  right: 0;
}

.portpicker__head {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-2);
  border-bottom: var(--border);
}

.portpicker__search {
  flex: 1;
  min-height: 40px;
  padding: 8px var(--space-2);
  border: var(--border-w) solid var(--gray-300);
  border-radius: var(--radius);
  font-size: 0.9375rem;
}

.portpicker__search:focus-visible {
  border-color: var(--teal-500);
  outline: var(--focus-ring);
  outline-offset: 0;
}

.portpicker__close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  color: var(--gray-600);
  border-radius: var(--radius);
  transition: var(--transition);
}

.portpicker__close:hover {
  background-color: var(--gray-100);
  color: var(--navy-900);
}

.portpicker__close svg {
  width: 18px;
  height: 18px;
}

/* ---------- 본문: 좌 권역 / 우 도시 ---------- */
/* grid 자식이 스크롤되려면 행 높이가 확정돼야 한다.
   max-height 만 주면 행은 콘텐츠 높이(auto)로 잡혀 자식이 넘쳐 흐르고,
   결과적으로 하단 "직접 입력" 영역을 덮어버린다. */
.portpicker__body {
  display: grid;
  grid-template-columns: 116px minmax(0, 1fr);
  grid-template-rows: minmax(0, 320px);
}

.portpicker__regions {
  display: flex;
  flex-direction: column;
  border-right: var(--border);
  overflow-y: auto;
  /* grid 자식의 기본 min-height 는 auto 라 줄어들지 않는다. 0 으로 풀어야 스크롤된다. */
  min-height: 0;
  background-color: var(--gray-100);
}

.portpicker__region {
  padding: 12px var(--space-2);
  font-size: 0.875rem;
  font-weight: var(--fw-medium);
  color: var(--gray-600);
  text-align: left;
  border-left: 2px solid transparent;
  transition: var(--transition);
  white-space: nowrap;
}

.portpicker__region:hover {
  color: var(--navy-700);
  background-color: var(--white);
}

.portpicker__region.is-active {
  background-color: var(--white);
  border-left-color: var(--teal-500);
  color: var(--navy-700);
  font-weight: var(--fw-semibold);
}

.portpicker__cities {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  align-content: start;
  gap: 2px;
  padding: var(--space-1);
  overflow-y: auto;
  min-height: 0;
}

@media (min-width: 520px) {
  .portpicker__cities {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

.portpicker__city {
  padding: 10px var(--space-1);
  font-size: 0.9375rem;
  color: var(--black-900);
  text-align: left;
  border-radius: var(--radius-sm);
  transition: var(--transition);
}

.portpicker__city:hover,
.portpicker__city.is-focused {
  background-color: var(--teal-050);
  color: var(--navy-700);
}

.portpicker__city[aria-selected="true"] {
  background-color: var(--teal-500);
  color: var(--white);
  font-weight: var(--fw-semibold);
}

/* 검색 결과가 없을 때 */
.portpicker__empty {
  grid-column: 1 / -1;
  padding: var(--space-3) var(--space-2);
  font-size: var(--fs-caption);
  color: var(--gray-600);
}

/* ---------- 하단: 직접 입력 ---------- */
.portpicker__foot {
  padding: var(--space-1);
  border-top: var(--border);
  background-color: var(--gray-100);
}

.portpicker__other {
  display: flex;
  align-items: center;
  gap: 0.5em;
  width: 100%;
  min-height: 44px;
  padding: 10px var(--space-2);
  font-size: 0.9375rem;
  font-weight: var(--fw-semibold);
  color: var(--teal-500);
  border-radius: var(--radius-sm);
  transition: var(--transition);
}

.portpicker__other:hover {
  background-color: var(--white);
  color: var(--navy-700);
}

.portpicker__other svg {
  width: 16px;
  height: 16px;
}

/* ---------- 모바일 ---------- */
@media (max-width: 519px) {
  .portpicker__body {
    grid-template-columns: 96px minmax(0, 1fr);
    grid-template-rows: minmax(0, 260px);
  }
  .portpicker__region {
    padding: 10px 12px;
    font-size: 0.8125rem;
  }
}

/* ============================================================
   21. HOME 프리미엄 리파인
   기존 컴포넌트를 대체하지 않고 Home 에서만 덧입히는 변형이다.
   색·간격·형태 토큰은 그대로 쓴다.
   ============================================================ */

/* ---------- 21-1. 히어로 ----------
   여백을 사치스럽게 쓰고, 타이포가 화면을 지배하게 한다.
   이미지는 배경이 아니라 무대다. */
.hero--feature {
  position: relative;
  display: flex;
  align-items: center;
  /* vh 만 두면 세로로 긴 창에서 히어로가 끝없이 늘어난다. 상한을 둔다.
     헤더가 히어로 위로 겹치면서 실제로 쓸 수 있는 세로가 헤더 높이만큼
     줄었다. 76vh 그대로 두면 이전보다 답답해 보인다. 86vh 로 올려
     사진이 숨 쉴 자리를 주되, 견적 폼 하단이 첫 화면에서 잘리지 않도록
     상한은 780px 에서 멈춘다. */
  min-height: min(86vh, 780px);
  --hero-pad: var(--space-4);
  background-color: var(--navy-900);
  overflow: hidden;
}

@media (max-width: 767px) {
  .hero--feature {
    min-height: auto;
    --hero-pad: var(--space-5);
  }
}

/* 배경 이미지 레이어를 따로 둔다.
   background-image 로 두면 패럴랙스에서 페인트가 일어나지만,
   별도 레이어를 transform 하면 합성만으로 끝난다. */
.hero__bg {
  position: absolute;
  inset: -8% 0 -8% 0;
  /* 이미지가 없어도 오버레이만으로 성립한다 */
  background-color: var(--navy-900);
  will-change: transform;
}

/* 배경 영상.
   960×540 이 전폭 히어로에서 2.5배 정도 확대된다. 위에 덮이는
   .hero__scrim 이 좌측 0.94 · 우측 0.34 로 두꺼워서 디테일이 아니라
   "움직임"으로 읽히는 자리다. 선명도보다 용량이 중요하다 —
   첫 화면에서 받는 파일이기 때문이다.

   원본은 3840×2160 / 193MB 였고, macOS 내장 avconvert 로
   960×540 / 7초 / 3.6MB 로 줄였다. 재생성 방법은
   public/assets/video/README.md 참고. */
.hero__video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 45%;
  display: block;
}

/* 모바일에서는 아예 띄우지 않는다.

   ⚠ 다운로드를 막는 것은 이 규칙이 아니다. display:none 은 이미 시작된
   전송을 멈추지 못한다 — 예전에 autoplay + preload="none" 로 두었을 때
   375px 뷰포트에서 3.6MB 가 그대로 전송되는 것을 실측했다.
   실제로 막는 것은 reveal.js 다(HTML 에 src 를 두지 않고 조건이 맞을 때만 넣는다).
   여기 768px 을 고치면 reveal.js 의 matchMedia 값도 같이 고쳐야 한다.

   뒤의 navy 그라데이션이 그대로 보인다. */
@media (max-width: 767px) {
  .hero__video {
    display: none;
  }
}

/* 모션 최소화를 선택한 사용자에게 24초짜리 루프는 그 자체로 방해다. */
@media (prefers-reduced-motion: reduce) {
  .hero__video {
    display: none;
  }
}

/* 좌측을 무겁게 덮어 텍스트가 앉을 자리를 만든다.
   우측은 열어 두어 사진이 살아 있게 한다. */
.hero__scrim {
  position: absolute;
  inset: 0;
  background:
    /* ① 헤더 자리를 눌러 주는 상단 스크림.
       헤더가 투명하게 히어로 위에 겹치는데, 사진 상단이 하필 밝은 하늘이라
       흰 메뉴·흰 로고가 묻히고 헤더 자리에 흰 띠가 남은 것처럼 보였다.

       ⚠ 정지점은 반드시 --header-total-h 기준(px)이어야 한다.
         처음에 히어로 높이의 %(12%/30%)로 잡았다가 1280px 창에서만
         멀쩡하고 1900px 창에서 흰 띠가 그대로 남았다.
         % 는 히어로 높이를 따라가는데 덮어야 하는 것은 헤더 높이라서,
         창이 넓어질수록(=사진이 크게 잘려 밝은 하늘이 상단을 채울수록)
         오히려 덮이는 두께가 어긋났다. px 로 고정하면 창 크기와 무관하게
         헤더 밴드를 항상 같은 두께로 덮는다.

       사진을 흐리지 않고 어둡게만 하므로 선명도는 그대로다. */
    linear-gradient(
      to bottom,
      rgba(10, 30, 60, 0.9) 0,
      rgba(10, 30, 60, 0.8) calc(var(--header-total-h) * 0.55),
      rgba(10, 30, 60, 0.54) var(--header-total-h),
      rgba(10, 30, 60, 0.2) calc(var(--header-total-h) * 1.8),
      rgba(10, 30, 60, 0) calc(var(--header-total-h) * 3)
    ),
    /* ② 좌 → 우. 글자가 앉는 왼쪽은 흰 제목이 읽히도록 무겁게 덮고,
       오른쪽은 영상이 그대로 보이게 연다.
       원래 사진(정지 이미지)을 거의 가리는 값(우측 0.55/0.34)이었는데,
       영상으로 바뀌면서 "움직임이 안 보인다"는 문제가 생겼다.
       우측을 0.18까지 낮춰 영상이 살아나게 한다. 좌측은 그대로. */
      linear-gradient(
        100deg,
        rgba(10, 30, 60, 0.92) 0%,
        rgba(10, 30, 60, 0.78) 30%,
        rgba(10, 30, 60, 0.38) 60%,
        rgba(10, 30, 60, 0.14) 100%
      ),
    /* ③ 하단 — 신뢰 배지 줄과 스크롤 큐가 앉는 자리 */
      linear-gradient(to top, rgba(10, 30, 60, 0.8) 0%, rgba(10, 30, 60, 0) 42%),
    /* ④ 가장자리를 아주 옅게만 눌러 중앙에 시선을 모은다.
       영상을 가리지 않도록 사진 때보다 약하게(0.34 → 0.2) 한다. */
      radial-gradient(
        130% 90% at 68% 42%,
        rgba(18, 53, 107, 0.2) 0%,
        rgba(10, 30, 60, 0) 58%,
        rgba(4, 14, 30, 0.34) 100%
      );
}

.hero__inner--feature {
  position: relative;
  z-index: var(--z-base);
  display: grid;
  gap: var(--space-5);
  width: 100%;
}

@media (min-width: 1000px) {
  .hero__inner--feature {
    grid-template-columns: minmax(0, 6.6fr) minmax(0, 4.4fr);
    gap: var(--space-4);
    align-items: center;
  }
}

.hero__title {
  color: var(--white);
  font-size: clamp(2.05rem, 5.6vw, 4.25rem);
  line-height: 1.1;
  letter-spacing: -0.03em;
  white-space: pre-line;
  text-wrap: balance;
}

.hero__lead--feature {
  margin-top: var(--space-3);
  max-width: 46ch;
  font-size: var(--fs-body-lg);
  line-height: 1.75;
  color: rgba(255, 255, 255, 0.76);
}

.hero__actions--feature {
  margin-top: var(--space-4);
}

@media (max-width: 519px) {
  .hero__actions--feature {
    display: grid;
    gap: var(--space-2);
  }
  .hero__actions--feature .btn {
    width: 100%;
  }
}

/* 히어로 하단 — 스크롤 큐와 신뢰 지표를 한 줄에 */
.hero__foot {
  position: relative;
  z-index: var(--z-base);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  /* 헤더가 히어로 위로 겹치면서 히어로가 헤더 높이만큼 아래로 자랐다.
     그 탓에 등록·보험 한 줄이 첫 화면에서 12px 차이로 접혔다.
     이 줄은 "믿어도 되는 회사인가"에 답하는 첫 신호라 접히면 의미가 준다.
     40 → 24 로 조여 되찾는다. 위의 구분선이 이미 단락을 나누고 있어
     여백이 그만큼 넓을 이유가 없었다. */
  margin-top: var(--space-3);
  padding-top: var(--space-3);
  border-top: 1px solid rgba(255, 255, 255, 0.14);
}

.hero__creds {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-3);
  font-size: var(--fs-caption);
  color: rgba(255, 255, 255, 0.58);
}

.hero__creds li {
  display: flex;
  align-items: center;
  gap: 0.5em;
}

.hero__creds svg {
  width: 14px;
  height: 14px;
  color: var(--teal-300);
}

@media (max-width: 767px) {
  .hero__foot .scroll-cue {
    display: none;
  }
}

/* 견적 카드가 히어로 안에서 떠 있는 느낌 */
.quickquote--feature {
  border-color: transparent;
  box-shadow: 0 24px 60px rgba(4, 14, 30, 0.34);
}

/* ---------- 21-3. 섹션 리듬 ----------
   한때 여백을 1.35배로 늘렸다가 섹션 사이가 259px 이 되어
   화면이 비어 보였다. 디자인 시스템 기본값(모바일 64 / 데스크톱 96)이
   이미 충분히 넉넉하다. 클래스는 훅으로만 남긴다. */
.section--airy {
  padding-block: var(--section-y);
}

/* 큰 제목 변형 — 섹션 헤드가 화면을 끌고 가게 한다 */
.section-head__title--lg {
  font-size: clamp(1.9rem, 3.6vw, 2.9rem);
  line-height: 1.16;
  letter-spacing: -0.025em;
}

/* ============================================================
   22. WORLD MAP — 글로벌 네트워크
   ============================================================ */
/* 차별화(04)와 네트워크(05)가 둘 다 navy-900 이라 1,576px 이 이음매 없이
   이어졌다. 스크롤하는 사람에게는 끝나지 않는 한 덩어리로 읽힌다.
   배경을 밝히면 다크 구간이 잘게 쪼개지므로, 괘선 한 줄만 넣어
   "장이 넘어갔다"는 신호를 준다. 어두운 흐름은 그대로 둔 채 마디만 만든다. */
.network {
  position: relative;
  background-color: var(--navy-900);
  overflow: hidden;
  border-top: var(--border-dark);
}

.network__inner {
  position: relative;
  z-index: var(--z-base);
}

/* 좌 글·통계 / 우 지도 2단.

   처음엔 전폭 세로 나열(1,133px)이었다가 밀도가 낮아 2단으로 접었고,
   그때 지도를 "배경"으로 취급해 4:8 로 눌러 두었다. 그런데 그래픽을
   올리고 나니(허브 그라데이션·헤일로·파장) 지도가 배경이 아니라
   이 섹션의 논거가 됐다 — "80개 파트너"를 눈으로 확인하는 유일한 곳이다.

   ⚠ 칼럼비를 4:8 에서 3.5:8.5 로 넓혀 봤다가 되돌렸다.
     지도는 768 → 788px 로 20px 밖에 안 커지는데, 좌측 칼럼이 370 → 324px 로
     좁아지면서 통계의 "2015" 가 "201/5" 로 접혔다 (셀 81px, 숫자 82px).
     아래 stat-value 주석이 경고하던 바로 그 현상이다. 이득 20px 에
     숫자가 깨지는 값을 치를 이유가 없다.

     크기는 가로가 아니라 **세로 여백과 그래픽 밀도**로 만든다.
     칼럼비를 바꾸려면 stat-value 상한부터 다시 계산할 것.

   전폭으로 되돌리지도 않는다. 좌측 통계(80·4·2015)와 나란히 보여야
   숫자와 그림이 서로를 보증하는데, 세로로 쌓으면 그 관계가 끊긴다. */
@media (min-width: 1000px) {
  .network__grid {
    display: grid;
    grid-template-columns: minmax(0, 4fr) minmax(0, 8fr);
    gap: var(--space-4);
    align-items: center;
  }

  /* 지도가 커진 만큼 섹션도 숨 쉴 자리가 필요하다.
     차별화(04) 다음에 오는 두 번째 다크 섹션이라 여기서 한 번
     넓어져야 두 장이 다른 리듬으로 읽힌다.

     ⚠ 1.4 배까지 올렸다가 1.15 로 내렸다. 좌측 칼럼(글+통계)이 471px 인데
       여백만 162px 이 되어 채움률이 66% 로 페이지 최저였다. 지도는 이미
       그래픽 밀도로 커 보이므로 여백까지 키울 필요가 없다. */
  .network {
    padding-block: calc(var(--section-y) * 1.15);
  }

  /* 좌측 컬럼이 370px 로 좁아 기본 clamp(최대 2.75rem)면 "2015"가
     "201/5"로 접힌다. 세 칸(각 ~106px)에 4자리 tabular 숫자가 들어가는
     상한은 2.125rem 이다. */
  .network__grid .network__stat-value {
    font-size: clamp(1.75rem, 1.3rem + 0.9vw, 2.125rem);
  }
}

.network__map {
  position: relative;
  margin-top: var(--space-4);
}

@media (min-width: 1000px) {
  .network__map {
    margin-top: 0;
  }
}

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

/* 육지 도트 — 배경보다 아주 조금만 밝게. 지도는 무대이지 주인공이 아니다.
   circle 이 아니라 path 하나다(생성기의 round-cap 트릭 — DOM 을 도트 수만큼
   쓰지 않기 위해서). 점 지름은 r 이 아니라 stroke-width 로 조절한다. */
.wm__dots {
  fill: none;
  stroke: rgba(255, 255, 255, 0.15);
  /* 격자가 120열이라 점 간격이 8.33px. 점:간격 비율 0.52 를 유지한다.
     열 수를 바꾸면 이 값도 같이 바꿔야 한다 — 안 그러면 점이 붙거나 성글어진다. */
  stroke-width: 4.3;
  stroke-linecap: round;
}

/* 좁은 화면에서는 지도가 작아져 도트가 먼지처럼 사라진다.
   굵기와 대비를 함께 올려 형태가 남게 한다. */
@media (max-width: 700px) {
  .wm__dots {
    stroke-width: 6.4;
    stroke: rgba(255, 255, 255, 0.2);
  }
  .wm__arc {
    stroke-width: 1.8;
  }
  .wm__dot {
    r: 7;
  }
  .wm__marker--home .wm__dot {
    r: 9;
  }
  /* 작은 화면에서 헤일로까지 겹치면 점이 뭉개진다 */
  .wm__halo {
    display: none;
  }
}

/* 연결선 — 그려지는 애니메이션. stroke-dasharray 는 컴포지터를 못 타지만
   선이 11개뿐이라 부담이 없다. */
/* 그라데이션 정지점 — 색을 여기서 주는 이유는 팔레트 토큰을 쓰기 위해서다.
   SVG 의 stop-color 속성에 hex 를 박으면 tokens.css 바깥에 색이 하나 생긴다. */
.wm__grad-near {
  stop-color: var(--teal-300);
  stop-opacity: 0.95;
}
.wm__grad-mid {
  stop-color: var(--teal-300);
  stop-opacity: 0.5;
}
.wm__grad-far {
  stop-color: var(--teal-300);
  stop-opacity: 0.14;
}

.wm__glow-in {
  stop-color: var(--teal-500);
  stop-opacity: 0.3;
}
.wm__glow-out {
  stop-color: var(--teal-500);
  stop-opacity: 0;
}

/* 허브 뒤 번짐. 연결선이 어디서 나가는지를 색으로 먼저 알린다. */
.wm__glow {
  fill: url(#wm-hub-glow);
}

/* 연결선 — 한국에서 멀어질수록 옅어진다.
   전에는 균일한 teal 이라 11개가 그물처럼 읽혔다. 허브 중심 그라데이션을
   주면 "한국에서 뻗어나간다"는 방향이 생긴다. 정지 상태에서도 읽히는
   정보라 애니메이션보다 이쪽이 먼저다. */
.wm__arc {
  fill: none;
  stroke: url(#wm-arc-grad);
  stroke-width: 1.4;
  stroke-linecap: round;
}

/* ⚠ 숨김 상태는 .js-reveal 아래에만 (HANDOFF 함정 1).
   예전에는 이 두 줄이 .wm__arc 본체에 있었다. 그러면 JS 가 죽는 순간
   연결선 11개와 마커 12개가 **영구히 사라지고** 도트 대륙만 남는다.
   "80개 파트너"를 말하는 섹션에서 근거 그림이 통째로 없어지는 셈이다. */
.js-reveal .wm__arc {
  stroke-dasharray: var(--arc-len);
  stroke-dashoffset: var(--arc-len);
}

.js-reveal .is-revealed .wm__arc {
  animation: wm-draw 1500ms var(--ease-reveal) forwards;
  animation-delay: calc(360ms + var(--arc-i) * 90ms);
}

@keyframes wm-draw {
  to {
    stroke-dashoffset: 0;
  }
}

.wm__dot {
  fill: var(--teal-300);
  opacity: 0.9;
}

/* 헤일로 — 점을 도트 대륙에서 떼어내는 얇은 링.
   지도가 커지면서 5px 점이 배경 도트(굵기 4.3)와 구별되지 않았다. */
.wm__halo {
  fill: none;
  stroke: var(--teal-300);
  stroke-width: 1;
  opacity: 0.35;
}

/* 위와 같은 이유로 숨김은 .js-reveal 아래에만 둔다 */
.js-reveal .wm__dot,
.js-reveal .wm__halo {
  opacity: 0;
}

.js-reveal .is-revealed .wm__dot {
  animation: wm-pop 620ms var(--ease-reveal) forwards;
  animation-delay: calc(200ms + var(--m-i) * 70ms);
}

.js-reveal .is-revealed .wm__halo {
  animation: wm-pop-halo 760ms var(--ease-reveal) forwards;
  animation-delay: calc(260ms + var(--m-i) * 70ms);
}

@keyframes wm-pop-halo {
  from {
    opacity: 0;
  }
  to {
    opacity: 0.35;
  }
}

@keyframes wm-pop {
  from {
    opacity: 0;
  }
  to {
    opacity: 0.9;
  }
}

/* 한국 마커 — 유일하게 강조한다 */
.wm__marker--home .wm__dot {
  fill: var(--white);
  opacity: 1;
}

.wm__marker--home .wm__halo {
  stroke: var(--white);
  opacity: 0.5;
}

.js-reveal .is-revealed .wm__marker--home .wm__dot {
  animation: wm-pop-home 700ms var(--ease-reveal) forwards;
}

.js-reveal .is-revealed .wm__marker--home .wm__halo {
  animation: wm-pop-home-halo 800ms var(--ease-reveal) forwards;
}

@keyframes wm-pop-home-halo {
  from {
    opacity: 0;
  }
  to {
    opacity: 0.5;
  }
}

/* ---------- 허브 파장 ----------
   화면에서 유일하게 계속 움직이는 것이다. "실시간으로 연결된 협업 체계"라고
   쓰는 섹션이라 정지한 지도보다 맞지만, 그래서 더 조심해야 한다 —
   3.6초 주기에 최고 불투명도 0.45, 링 두 개가 1.8초 어긋나 돈다.
   시선을 끄는 것이 아니라 "살아 있다"만 전달하고 멈춘다.

   transform-box: fill-box 를 줘야 SVG 도형의 transform-origin 이
   제 도형 중심이 된다. 없으면 SVG 좌표 원점(0,0) 기준으로 커져서
   링이 지도 왼쪽 위로 날아간다.

   숨김이 .js-reveal 밖에 있어도 되는 유일한 예외다 —
   이건 정보가 아니라 순수 장식이고, 정지 상태에서 링이 그냥 떠 있으면
   오히려 버그로 보인다. JS 가 죽으면 파장이 없을 뿐 지도는 온전하다. */
.wm__pulse {
  fill: none;
  stroke: var(--teal-300);
  stroke-width: 1.5;
  opacity: 0;
  transform-box: fill-box;
  transform-origin: center;
}

.js-reveal .is-revealed .wm__pulse {
  animation: wm-pulse 3600ms var(--ease-soft) infinite;
  animation-delay: calc(1400ms + var(--p-i) * 1800ms);
}

@keyframes wm-pulse {
  0% {
    transform: scale(1);
    opacity: 0;
  }
  15% {
    opacity: 0.45;
  }
  100% {
    transform: scale(6);
    opacity: 0;
  }
}

@keyframes wm-pop-home {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

/* 지도가 취항 항로가 아님을 밝히는 한 줄 */
.network__note {
  margin-top: var(--space-2);
}

/* 네트워크 수치 */
.network__stats {
  display: grid;
  gap: var(--space-3);
  margin-top: var(--space-4);
  padding-top: var(--space-3);
  border-top: 1px solid rgba(255, 255, 255, 0.14);
}

@media (min-width: 700px) {
  .network__stats {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--space-4);
  }
}

.network__stat-value {
  font-family: var(--font-en);
  font-size: clamp(2rem, 4vw, 2.75rem);
  font-weight: var(--fw-bold);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.03em;
  line-height: 1;
  color: var(--white);
}

.network__stat-label {
  margin-top: 6px;
  font-size: var(--fs-caption);
  color: rgba(255, 255, 255, 0.6);
}

@media (prefers-reduced-motion: reduce) {
  .wm__arc {
    stroke-dashoffset: 0;
    animation: none !important;
  }
  .wm__dot {
    opacity: 0.9;
    animation: none !important;
  }
  .wm__halo {
    opacity: 0.35;
    animation: none !important;
  }
  .wm__marker--home .wm__dot {
    opacity: 1;
  }
  .wm__marker--home .wm__halo {
    opacity: 0.5;
  }
  /* 파장은 완전히 끈다 — 모션 최소화 사용자에게 반복 애니메이션은
     이 페이지에서 가장 방해되는 요소다 */
  .wm__pulse {
    animation: none !important;
    display: none;
  }
}
