/* KONECT 메인 — Figma 424:2497 / 424:2576 구현.
   수치는 전부 tokens.css 의 var() 를 쓴다. */

/* ==================== reset / base ==================== */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--c-white);
  color: var(--c-text);
  font: var(--t-link);
  /* 한국어는 어절 단위로만 줄바꿈. 카드 제목의 zero-width space 가
     "여기서 나눠도 된다" 는 유일한 예외가 된다. */
  word-break: keep-all;
  overflow-wrap: break-word;
  -webkit-font-smoothing: antialiased;
}
h1, h2, h3, p, ul, figure { margin: 0; }
ul { padding: 0; list-style: none; }
img { display: block; max-width: 100%; height: auto; }
a { color: inherit; text-decoration: none; }
/* padding 을 반드시 0 으로 되돌린다. 브라우저 기본 버튼 padding(1px 6px)이 남으면
   flex 항목의 min-width:auto 하한이 12px 이 되어, width:6px 를 줘도 안 줄어든다
   (배너 dot 이 전부 12px 로 나왔던 원인). */
button {
  margin: 0; padding: 0; border: 0;
  background: none; color: inherit; font: inherit; cursor: pointer;
}
address { font-style: normal; }

:where(a, button, [tabindex]):focus-visible {
  outline: 2px solid var(--c-primary);
  outline-offset: 2px;
  border-radius: 4px;
}

.skip-link {
  position: fixed;
  top: 8px; left: 8px;
  z-index: 100;
  padding: 8px 16px;
  border-radius: var(--r-sm);
  background: var(--c-primary);
  color: var(--c-white);
  font: var(--t-small-bold);
  transform: translateY(-200%);
}
.skip-link:focus { transform: none; }

/* 1440 콘텐츠 폭을 중앙에 두는 공통 규칙 */
.header__inner,
.services__body,
.institutions__inner,
.footer__inner {
  width: min(var(--container), 100% - var(--gutter) * 2);
  margin-inline: auto;
}

/* ==================== HERO ==================== */
.hero { position: relative; }

/* 배경은 시안(Figma v2_bg)대로 3겹이다:
     (1) 맨 아래 앵귤러 그라디언트 + blur 60
     (2) 그 위에 떠다니는 원 2개  (Ellipse 10 / 11, 각각 blur 12.8)
     (3) 맨 위 흰색 그라디언트 오버레이 — 아래로 갈수록 흰색으로 사라진다

   (1)을 PNG 로 받아 쓰지 않는 이유: blur 60 의 알파 감쇠가 180px 넘게 이어져서
   export 한 PNG 의 가장자리가 반투명하다. 흰 배경 위에 깔면 위쪽에 흰 띠가 생긴다.
   그래서 conic-gradient 로 다시 만들고, 보이는 영역보다 200px 크게 그린 뒤
   .hero__bg 의 overflow:hidden 으로 잘라낸다 — 감쇠 구간이 화면 밖으로 나간다.
   conic-gradient 는 중심점만 있으면 되므로 크게 그려도 형태가 왜곡되지 않는다. */
.hero__bg {
  position: absolute;
  inset: 0 0 auto;
  height: var(--hero-bg-h);
  overflow: hidden;
  pointer-events: none;
  /* 원의 color-burn 이 페이지 흰 배경까지 태우지 않도록 여기서 합성을 가둔다.
     Figma 의 v2_bg 프레임 안에서만 블렌드되는 것과 같은 상태가 된다. */
  isolation: isolate;
}

/* (1) 베이스 — Figma GRADIENT_ANGULAR 5스톱.
   중심 (0.483, 0.219) 을 200px 확장한 박스 기준으로 환산 = 48.6% / 33.1%.
   시작각은 핸들 벡터 atan2(0.384*600, 0.270*1920) 를 CSS 기준(12시 시계방향)으로 변환. */
.hero__bg::before {
  content: "";
  position: absolute;
  inset: -200px;
  background: conic-gradient(from 118deg at 48.6% 33.1%,
    #dad8f2   0%,
    #ffc5ec  26.4%,
    #a197ff  50%,
    #7b8dea  74.5%,
    #a2aaff 100%);
  filter: blur(60px);
}

/* (2) 떠다니는 원 — Figma: blendMode COLOR_BURN, opacity 0.6, LAYER_BLUR 12.8 */
.hero__orb {
  position: absolute;
  border-radius: 50%;
  filter: blur(12.8px);
  mix-blend-mode: color-burn;
  opacity: var(--orb-opacity);
  will-change: transform, opacity;
}
.hero__orb--1 {
  width: var(--orb-1-size); height: var(--orb-1-size);
  left: var(--orb-1-x); top: var(--orb-1-y);
  background: radial-gradient(circle at 50% 50%, #dad8f2 0%, #958cee 100%);
  /* linear — 가로로 등속 이동이라야 흐르는 느낌이 난다. ease-in-out 을 쓰면
     양 끝(화면 밖)에서 느려지고 가운데서만 빨라져 어색하다.
     음수 delay 로 이미 화면 안에 들어와 있는 상태에서 시작한다. 두 원의 주기를
     다르게(14s / 17s) 둬서 매번 다른 조합으로 겹친다.
     이동 거리 1371px / 1490px -> 약 90~100px/s. */
  animation: orb-drift-1 14s linear -4s infinite;
}
.hero__orb--2 {
  width: var(--orb-2-size); height: var(--orb-2-size);
  left: var(--orb-2-x); top: var(--orb-2-y);
  background: radial-gradient(circle at 50% 50%, #dad8f2 0%, #ffc5ec 100%);
  animation: orb-drift-2 17s linear -11s infinite;
}

/* (3) 흰색 오버레이 — 원보다 위에 와야 하므로 ::after (자식 다음에 그려진다) */
.hero__bg::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg,
    rgb(255 255 255 / 0.10) 0%,
    rgb(255 255 255 / 0.52) 30%,
    rgb(255 255 255 / 1) 100%);
}

/* 두 원은 가운데 위에서 나타나 서로 반대쪽으로 갈라져 빠진다.
   1번(보라)은 오른쪽으로, 2번(분홍)은 왼쪽으로 — 방향을 바꾸려면 두 keyframes 의
   100% x 값을 서로 맞바꾸면 된다.

   좌표 근거 (.hero__bg 1920 폭, overflow:hidden):
     1번 원 x 1513~1949 (중심 1731) → 화면 중앙(960) 에 두려면 -771,
                                      오른쪽 완전히 밖 = +600
     2번 원 x  -101~542 (중심 220)  → 중앙 = +740,  왼쪽 완전히 밖 = -750

   한 주기: 가운데에서 서서히 나타남(0~12%) → 바깥으로 흘러감 → 화면 밖에서 사라짐.
   100% 는 화면 밖 + opacity 0 이라, 다시 가운데로 되돌아가는 순간이 보이지 않는다
   (0% 도 opacity 0 이므로 반복 지점의 보이는 프레임은 동일). */
@keyframes orb-drift-1 {
  0%   { transform: translate3d(-771px, -40px, 0) scale(0.85); opacity: 0; }
  12%  { opacity: var(--orb-opacity); }
  88%  { opacity: var(--orb-opacity); }
  100% { transform: translate3d(600px, 30px, 0) scale(1.15);   opacity: 0; }
}
@keyframes orb-drift-2 {
  0%   { transform: translate3d(740px, -40px, 0) scale(0.85);  opacity: 0; }
  12%  { opacity: var(--orb-opacity); }
  88%  { opacity: var(--orb-opacity); }
  100% { transform: translate3d(-750px, 30px, 0) scale(1.15);  opacity: 0; }
}

/* --- 헤더 ---
   Figma 노드에는 r16 + backdrop-blur(20) + drop-shadow 가 있지만 fill 이 없어
   시안 렌더에서 아무것도 보이지 않는다. 그래서 투명 헤더로 구현했다. */
.header { position: relative; z-index: 1; }   /* 패밀리사이트 목록이 아래 내용 위에 오도록 */
.header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: var(--header-h);
  padding-inline: 24px;
}
.header__logo img { width: 169px; height: 60px; object-fit: contain; }

.header__nav { display: flex; align-items: center; gap: 16px; }
.header__pill {
  display: flex;
  align-items: center;
  height: 40px;
  padding-inline: 16px;
  font: var(--t-nav);
  white-space: nowrap;
}
.header__menu { display: flex; width: 40px; height: 40px; }

/* --- 패밀리사이트 (시안 466:2510 닫힘 / 466:2511 펼침) ---
   히어로 그라디언트 위에 얹히는 유리판: 흰색 50% + 배경 blur 14, 흰 1px 테두리.
   펼치면 시안대로 버튼과 목록이 둘 다 불투명 흰색이 된다. */
.family { position: relative; }
.family__toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  width: 178px;
  height: 41px;
  padding: 0 9px 0 16px;         /* 오른쪽 9 = 화살표(24) 와 테두리 사이 여백 */
  border-radius: var(--r-sm);
  /* 테두리를 border 로 주면 41 안에 들어가지 않는다 (시안 stroke 는 INSIDE) */
  box-shadow: inset 0 0 0 1px var(--c-white);
  background: rgb(255 255 255 / 0.5);
  backdrop-filter: blur(14px);
  color: var(--c-text);
  font: var(--t-family);
}
.family__toggle[aria-expanded="true"] { background: var(--c-white); }
.family__toggle img { flex: none; }

/* 목록은 버튼 아래 4px (시안: 버튼 41 + 4 → 목록 y 128) */
.family__list {
  position: absolute;
  top: calc(100% + 4px);
  right: 0;                      /* 우측 정렬 — 좁은 화면에서 버튼이 좁아도 화면을 안 넘는다 */
  z-index: 1;
  width: 178px;
  overflow: hidden;              /* 항목 hover 배경이 둥근 모서리를 넘지 않게 */
  border-radius: var(--r-sm);
  box-shadow: inset 0 0 0 1px var(--c-white);
  background: var(--c-white);
}
.family__item {
  display: flex;
  align-items: center;
  min-height: 35px;              /* 시안 행 높이 (8 + 19 + 8) */
  padding: 8px 10px;
  color: var(--c-text);
  font: var(--t-family);
}
/* 시안에 hover 변형이 없다 — 누를 수 있는 항목이라 최소한의 반응만 직접 넣었다 */
.family__item:hover { background: var(--c-surface); }

/* ==================== 서비스 영역 ==================== */
/* 세로 리듬은 Figma 실측 y좌표에 맞춘 값이다 (헤더 80 기준):
   카드 368 · 배너 792 · 앵커 999 · 다음 섹션 1080.
   문구 위 여백(시안 88)은 고정값으로 두지 않는다 — 아래 규칙에서 문구 칸이
   남는 화면 높이를 먹고 그 안에서 가운데 정렬되므로 화면마다 달라진다. */
.services {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
}

/* --- 첫 화면을 뷰포트에 꽉 채운다 ---
   시안 Frame 37 은 정확히 1080px 이다 (1920x1080 화면 한 장). 남거나 모자란
   높이는 히어로 문구 칸(.services__title)이 흡수한다 — 늘어나고, 그 안에서
   메인 카피가 가운데에 선다. 낮은 화면은 파일 아래쪽 max-height 규칙이 글자·카드까지
   줄여 맞추고, 그래도 안 들어가면 min-height 라 잘리지 않고 그냥 스크롤된다. */
@media (min-width: 1024px) {
  .hero {
    display: flex;
    flex-direction: column;
    min-height: 100dvh;
  }
  .services { flex: 1 0 auto; }
}
/* 롤링 문구.
   슬라이드마다 높이가 다르다 (한국어 120/106/60, 영어 120/166/120).
   그리드 한 칸에 전부 겹쳐 쌓으면 컨테이너가 "가장 높은 것" 만큼 자리를 잡아서,
   문구가 바뀌어도 아래 카드들이 밀리지 않는다. 언어별로 필요한 만큼만 쓴다. */
.services__title {
  display: grid;
  align-content: center;         /* 늘어난 칸 안에서 카피가 가운데 */
  flex: 1 1 auto;                /* 남는 화면 높이는 이 칸이 가져간다 */
  width: min(var(--container), 100% - var(--gutter) * 2);
  text-align: center;
}
.services__slide {
  grid-area: 1 / 1;             /* 전부 같은 칸에 겹친다 */
  align-self: center;
  display: flex;
  flex-direction: column;
  gap: 16px;                    /* 시안 HeroTextWrap gap */
  /* 대기 상태 = 아래에 투명하게. 들어올 때 아래에서 위로 올라온다. */
  opacity: 0;
  transform: translateY(24px);
  transition: opacity 0.6s var(--ease), transform 0.6s var(--ease);
}
.services__slide.is-on  { opacity: 1; transform: none; }
.services__slide.is-out { opacity: 0; transform: translateY(-24px); }  /* 나갈 때는 위로 */

.services__line {
  font: var(--t-hero);
  white-space: pre-line;         /* 사전의 \n = 시안의 의도된 줄바꿈 */
  text-wrap: balance;
}
.services__sub {
  color: var(--c-text-sub);
  font: var(--t-hero-sub);
}
.services__body { display: flex; flex-direction: column; gap: 24px; }

/* --- 서비스 카드 5장 --- */
.cards { display: flex; gap: 24px; }

.card {
  display: flex;
  min-width: 0;
  /* 기본은 5장 균등(268.8px). hover 규칙에서 이 비율만 바꾼다. */
  flex: 1 1 0;
  transition: flex-grow var(--dur) var(--ease),
              opacity var(--dur) var(--ease),
              transform var(--reveal-dur) var(--ease);
}
.card__link {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 14px;
  width: 100%;
  height: var(--card-h);
  padding: 20px 20px 28px;
  border-radius: var(--r-card);
  background: var(--card);
  color: var(--c-white);
  transition: background var(--dur) var(--ease);
}
.card__title { font: var(--t-card-title); }

/* 제목의 괄호 부분 — 시안에서 굵기·크기가 다르고 항상 새 줄에서 시작한다 */
.card__paren {
  display: block;
  font: var(--t-card-paren);
}

/* 접혔을 때만 나타나는 줄바꿈.
   기본값은 "없음" 이다 — 모바일/태블릿처럼 카드가 넓을 때는 한 줄이어야 한다.
   데스크톱에서 269px 로 접혀 있을 때만 살리고, 펼쳐지면 다시 숨긴다.
   숨겨도 바로 뒤 zero-width space 가 남아 폭이 모자라면 같은 자리에서 접힌다. */
.card__br { display: none; }
.card__desc {
  font: var(--t-card-desc);
  letter-spacing: var(--ls-card-desc);
  color: rgb(255 255 255 / 0.5);
}
/* 아이콘은 카드 좌하단, 노치는 우하단 — Figma 에서도 둘 다 absolute */
.card__icon {
  position: absolute;
  bottom: 0; left: 0;
  width: var(--card-icon);
  height: var(--card-icon);
  object-fit: contain;
  transition: width var(--dur) var(--ease), height var(--dur) var(--ease),
              left var(--dur) var(--ease);
}
.card__notch {
  position: absolute;
  right: 0; bottom: 0;
  width: var(--notch);
  height: var(--notch);
}

/* hover 확장: 400 / 236·4 / gap 24·4 = 1440 (Figma 실측 그대로).
   flex-basis 0 + flex-grow 비율이 이 수치를 그대로 만든다.
   :hover 와 :focus-within 을 항상 짝으로 걸어야 한다 — 한쪽만 걸면 키보드로
   포커스했을 때 형제 카드가 flex-grow:1 로 남아 3px 로 짜부라진다. */
@media (hover: hover) and (min-width: 1024px) {
  .cards:hover .card,
  .cards:focus-within .card {
    flex-grow: var(--grow-shrunk);
    opacity: var(--card-dim);            /* 시안: 선택 안 된 카드 opacity 0.5 */
  }
  .cards .card:hover,
  .cards .card:focus-within {
    flex-grow: var(--grow-hover);
    opacity: 1;
  }

  .card__br { display: inline; }                 /* 접힘(269px) = 두 줄 */
  .cards .card:hover .card__br,
  .cards .card:focus-within .card__br { display: none; }   /* 펼침(400px) = 한 줄 */

  .card:hover .card__link,
  .card:focus-within .card__link {
    background: linear-gradient(180deg, var(--card-top) 0%, var(--card) 100%);
  }

  .card:hover .card__icon,
  .card:focus-within .card__icon {
    width: var(--card-icon-hover);
    height: var(--card-icon-hover);
    left: var(--card-icon-hover-x);
  }
}

/* --- 배너 캐러셀 --- */
.banner {
  position: relative;
  /* flex 항목의 min-width 기본값(auto)은 "내용만큼" 이라, Swiper 가 컨테이너 폭을 재서
     슬라이드 폭을 정하는 순간 컨테이너 -> 슬라이드 -> 컨테이너 로 폭이 무한히 커진다
     (실제로 33,554,432px 까지 부풀었다). 0 으로 눌러 부모 폭을 따르게 한다. */
  width: 100%;
  min-width: 0;
  overflow: hidden;
  border-radius: var(--r-md);
  /* 1px 흰 테두리를 border 로 주면 높이가 200→202 로 늘어난다. inset 링으로 대체. */
  box-shadow: inset 0 0 0 1px var(--c-white), var(--shadow-banner);
}
/* 트랙과 슬라이드의 배치·이동은 Swiper 가 맡는다 (.swiper-wrapper / .swiper-slide).
   여기서 display:flex 나 transition 을 다시 걸면 Swiper 의 인라인 transform 과 싸운다. */
.banner__slide img { width: 100%; height: auto; }

/* 배너가 1장이면 Swiper 를 아예 띄우지 않아서 dot 이 하나도 안 생긴다.
   그때 알약 배경만 남아 검은 얼룩처럼 보이므로 비어 있으면 감춘다. */
.banner__dots:empty { display: none; }

.banner__dots {
  position: absolute;
  right: 20px; bottom: 20px;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 8px;
  border-radius: var(--r-pill);
  background: rgb(23 23 23 / 0.3);
}

/* Swiper 가 pagination el 에 swiper-pagination-bullets / -horizontal 클래스를 붙이는데,
   그 CSS 가 left:0; width:100%; bottom:8px 를 덮어써서 알약이 배너 폭 전체로 늘어난다.
   게다가 .swiper-wrapper 가 z-index:1 이라 기본값(auto)인 dot 은 이미지 뒤로 깔린다.
   둘 다 여기서 되돌린다 (선택자 3개로 Swiper 의 2개짜리보다 우선하게). */
.banner.swiper .banner__dots {
  left: auto;
  width: auto;
  right: 20px;
  bottom: 20px;
  z-index: 2;
}
/* 시안: 비활성 6x6, 활성 12x6 (Figma Frame 9 — 컨테이너 56x18, pad 6/8, gap 8)
   Swiper 가 bulletClass 로 이 클래스를 붙인 <span> 을 만든다 — button 이 아니므로
   cursor 를 직접 준다 (button 리셋에서 오던 것이 없어졌다). */
.banner__dot {
  flex: none;                    /* 줄어들지도 늘어나지도 않게 */
  cursor: pointer;
  width: 6px; height: 6px;
  border-radius: 3px;
  background: rgb(255 255 255 / 0.3);
  transition: width var(--dur) var(--ease), background var(--dur) var(--ease);
}
.banner__dot.is-active { width: 12px; background: var(--c-dot-active); }

/* --- 유관기관 앵커 --- */
.jump {
  margin-top: 7px;               /* Figma: 배너 992 → 앵커 999 */
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding-block: 20px;
  color: var(--c-text-anchor);
  font: var(--t-small-bold);
}

/* 화살표는 "아래로 내려가라" 는 신호라, 위에서 아래로 흘러내리며 나타났다 사라진다.
   0% 와 100% 가 둘 다 opacity 0 이라 반복 지점에서 튀지 않는다 (위치는 달라도 안 보인다).
   위아래로 흔들리면 자리를 차지하므로 padding 안에서만 움직이게 진폭을 작게 뒀다. */
.jump img {
  animation: jump-arrow 1.8s ease-in-out infinite;
}
@keyframes jump-arrow {
  0%   { transform: translateY(-6px); opacity: 0; }
  30%  { opacity: 1; }
  65%  { opacity: 1; }
  100% { transform: translateY(8px);  opacity: 0; }
}

/* ==================== 유관기관 ==================== */
/* 유관기관 + 푸터가 화면 한 장을 채운다. 즉 유관기관은 "뷰포트 - 푸터" 만큼 늘어난다.
   min-height 라서 목록이 화면보다 길면 늘어나기만 하고 평범하게 스크롤된다. */
.screen { display: flex; flex-direction: column; min-height: 100dvh; }

.institutions { padding-block: 120px; flex: 1 1 auto; display: flex; flex-direction: column; }
.institutions__inner { display: flex; flex-direction: column; gap: 40px; flex: 1 1 auto; }
.institutions__title { font: var(--t-h2); }

.partners { display: flex; gap: 24px; align-items: stretch; flex: 1 1 auto; }
.partners__divider { flex: 0 0 1px; background: var(--c-border); }
.partners__content { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }

/* --- 좌측 탭 --- */
.partners__tabs {
  display: flex;
  flex-direction: column;
  gap: 8px;
  flex: 0 0 var(--tab-w);
}
/* 시안은 세로가 HUG(내용에 맞춤) + padding 11 이라, 라벨이 두 줄이 되면 탭이 늘어난다.
   height 를 44 로 못박으면 영문 "Analytical CRO/Central LAB" 처럼 두 줄짜리 라벨이
   위아래 여백을 다 먹고 테두리에 붙는다. padding + min-height 로 시안과 같게 맞춘다.
   gap 은 시안이 0 이지만 8 로 뒀다 — space-between 이라 평소엔 아무 차이가 없고,
   라벨이 길어져 배지와 닿을 때만 최소 간격으로 동작한다. */
.tab {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  min-height: var(--tab-h);
  padding: 11px 16px;
  border-radius: var(--r-sm);
  background: var(--c-white);
  /* 시안 stroke 가 INSIDE 라 44 안에 테두리가 포함된다. border 를 쓰면 11+22+11 에 2 가
     더해져 46 이 되므로 inset 링으로 그린다 (배지·제목줄과 같은 처리). */
  box-shadow: inset 0 0 0 1px var(--c-border);
  color: var(--c-text-sub);
  font: var(--t-tab);
  text-align: left;
  transition: background 0.15s var(--ease), color 0.15s var(--ease),
              box-shadow 0.15s var(--ease);
}
/* 시안에는 hover 변형이 없다 — 누를 수 있는 요소라 최소한의 반응만 직접 넣었다 */
.tab:hover { box-shadow: inset 0 0 0 1px var(--c-primary); color: var(--c-primary); }
.tab.is-active {
  background: var(--c-primary);
  box-shadow: inset 0 0 0 1px var(--c-primary);
  color: var(--c-white);
}
/* 시안 배지는 30x22 이고 stroke 가 INSIDE 다. border 를 쓰면 가로·세로가 2px 씩 커지므로
   inset 그림자로 그린다 (활성 상태는 시안에 stroke 가 아예 없다). */
.tab__count {
  flex: none;
  display: flex;
  align-items: center;
  height: var(--badge-h);
  padding-inline: 8px;
  border-radius: 20px;
  background: var(--c-surface);
  box-shadow: inset 0 0 0 1px var(--c-border);
  color: var(--c-text-icon);
  font: var(--t-badge);
}
.tab.is-active .tab__count {
  background: var(--c-white);
  box-shadow: none;
  color: var(--c-primary);
}

/* --- 우측 콘텐츠 --- */
.partners__head {
  display: flex;
  align-items: center;
  padding: 16px;
  /* 시안은 아래쪽 한 변에만 선이 있다 (individualStrokeWeights 0/0/1/0, INSIDE).
     border-bottom 을 쓰면 높이가 56 -> 57 로 늘어나므로 inset 그림자로 그린다.
     시안 노드에 radius [8,8,0,0] 이 있지만 배경도 위쪽 선도 없어 아무것도 그려지지
     않으므로 넣지 않았다. */
  box-shadow: inset 0 -1px 0 var(--c-border-strong);
}
.partners__head h3 { font: var(--t-panel-head); color: var(--c-heading-accent); }

.partners__panels {
  display: flex;
  min-height: calc(var(--panel-h) - 56px);   /* 시안: 460 - 헤더 56 = 404 — 여기가 하한 */
  flex: 1 1 auto;                            /* 남는 화면 높이는 목록 판이 가져간다 */
}
.partners__col { flex: 1 1 0; min-width: 0; }
.partners__col:nth-child(even) { background: var(--c-surface); }

.partners__empty {
  padding: 24px 16px;
  color: var(--c-text-sub);
  font: var(--t-link);
}

.ext {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: var(--row-h);
  padding: 8px 16px;
  font: var(--t-ext);
  transition: background 0.15s var(--ease), color 0.15s var(--ease);
}
.ext > span { flex: 1 1 auto; min-width: 0; }
.ext img { flex: none; width: 16px; height: 16px; }
.ext:hover { background: var(--c-link-hover-bg); color: var(--c-link-hover-text); }
/* SVG 안 fill 을 직접 못 바꾸므로 hover 색은 필터로 근사 (#58585a → #5793d9) */
.ext:hover img { filter: invert(45%) sepia(51%) saturate(626%) hue-rotate(178deg) brightness(94%); }

/* ==================== FOOTER ==================== */
.footer { padding: 48px 0 40px; background: var(--c-surface); }
.footer__inner { display: flex; flex-direction: column; gap: 24px; }
.footer__links { display: flex; flex-wrap: wrap; gap: 24px; }
.footer__links a { color: var(--c-text-sub); font: var(--t-small); }
.footer__links a.is-strong { font: var(--t-small-bold); }
.footer__divider { height: 1px; background: var(--c-border); }
.footer__info { display: flex; flex-direction: column; gap: 8px; }
.footer__info p { color: var(--c-text-sub); font: var(--t-small); }
.footer__phones { display: flex; flex-wrap: wrap; gap: 4px 12px; }
.footer__phones span { white-space: nowrap; }
.footer__copyright { color: var(--c-text-sub); font: var(--t-copyright); }

/* ==================== 반응형 ====================
   시안은 1920 데스크톱 한 벌뿐이라 아래 구간은 직접 설계했다. */

/* --- 화면 높이별: 첫 화면을 한 눈에 담기 위한 압축 ---
   시안 1080 을 그대로 두면 노트북(뷰포트 약 950)에서 넘친다.
   여백 -> 문구 크기 -> 카드 순으로 줄인다. 이 규칙들은 .services__body 정의보다
   뒤에 와야 margin-top 을 덮어쓸 수 있다. */

/* 1080 미만: 여백과 문구만 줄여 964px 에 담는다 */
@media (min-width: 1024px) and (max-height: 1079px) {
  :root { --t-hero: 600 32px/46px var(--font); }
  .services__body { margin-top: 40px; }
}

/* 980 미만: 카드까지 줄여 888px 에 담는다.
   아이콘도 같이 줄여야 한다 — 카드가 낮아지면 설명문 끝과 아이콘 윗변이 부딪힌다
   (카드 2 기준 여유 13px). */
@media (min-width: 1024px) and (max-height: 979px) {
  :root {
    --card-h: 340px;
    --card-icon: 120px;
    --card-icon-hover: 170px;
  }
  .services__body { margin-top: 32px; }
}

/* 1024–1439: 유동 축소 */
@media (max-width: 1439px) {
  :root {
    --t-hero: 600 32px/46px var(--font);
    --t-hero-sub: 400 18px/28px var(--font);
  }
  .hero__bg { height: clamp(360px, 32vw, var(--hero-bg-h)); }
  .services { gap: 56px; }
}

/* 768–1023: 카드 3+2 랩, hover 확장 해제, 리스트 2열 */
@media (max-width: 1023px) {
  :root {
    --t-hero: 600 28px/40px var(--font);
    --t-hero-sub: 400 16px/24px var(--font);
    --t-h2: 600 24px/30px var(--font);
    --card-h: 340px;
    --card-icon: 128px;
  }
  .cards { flex-wrap: wrap; }
  .card { flex: 1 1 calc((100% - 48px) / 3); min-width: 200px; }

  .institutions { padding-block: 72px; }
  .partners { flex-wrap: wrap; }
  .partners__tabs {
    flex: 1 1 100%;
    flex-direction: row;
    overflow-x: auto;
    padding-bottom: 4px;
    scrollbar-width: thin;
  }
  .tab { flex: 0 0 auto; }
  .partners__divider { display: none; }
  .partners__content { flex: 1 1 100%; }
  /* flex 4열을 2개씩 랩하면 좌측 열이 1~5 다음 11~15 로 튄다.
     CSS 다단으로 바꾸면 DOM 순서대로 1~17 이 이어진다. */
  .partners__panels { display: block; column-count: 2; column-gap: 24px; min-height: 0; }
  .partners__col { break-inside: auto; }
  /* 2열/1열에서는 열 배경 교대가 체스판처럼 보여 끈다 */
  .partners__col:nth-child(even) { background: none; }
  .ext { border-bottom: 1px solid var(--c-border); }
}

/* <768: 단일 열 */
@media (max-width: 767px) {
  :root {
    --gutter: var(--gutter-mobile);
    --t-hero: 600 24px/34px var(--font);
    --t-hero-sub: 400 15px/22px var(--font);
    --header-h: 72px;
    /* 모바일 카드는 낮고 넓은 가로형이다 — 아이콘이 좌상단에서 위로 삐져나오고
       제목은 그만큼 들여쓴다 */
    --card-h: 170px;
    --card-icon: 80px;
    --notch: 60px;
  }
  .header__inner { padding-inline: 0; }
  .header__logo img { width: 100px; height: 36px; }
  .header__pill { padding-inline: 8px; font-size: 15px; }
  .header__menu { width: 24px; height: 24px; }
  .header__nav { gap: 8px; }
  .family__toggle { width: 132px; padding-inline: 10px 5px; font-size: 14px; }

  .services { gap: 40px; padding-block: 32px; }
  .services__body { margin-top: 0; }
  .card { flex: 1 1 100%; }

  /* 아이콘을 좌하단 -> 좌상단으로. bottom 을 풀어줘야 top 이 먹는다. */
  .card__icon {
    top: -20px;
    bottom: auto;
    left: 10px;
    width: var(--card-icon);
    height: var(--card-icon);
  }
  .card__title { padding-left: 80px; }   /* 아이콘(10 + 80 = 90) 을 피해서 */
  .banner.swiper .banner__dots { right: 12px; bottom: 12px; }

  .institutions { padding-block: 48px; }
  .institutions__inner { gap: 24px; }
  .partners__panels { column-count: 1; }
}

/* ==================== 등장 애니메이션 ====================
   .has-reveal 은 <head> 인라인 스크립트가 붙인다. JS 가 없으면 클래스가 안 붙어서
   숨김 상태가 아예 적용되지 않는다 (내용이 사라지지 않게). */
/* :where() 로 우선순위를 0 으로 낮춘다. 그냥 `.has-reveal [data-reveal].is-in`
   으로 쓰면 opacity:1 이 카드 hover 시의 opacity:0.5(--card-dim) 를 눌러버린다. */
.has-reveal :where([data-reveal]) {
  opacity: 0;
  transform: translateY(24px);
}
.has-reveal :where([data-reveal].is-in) {
  opacity: 1;
  transform: none;
}
.has-reveal [data-reveal]:not(.card) {
  transition: opacity var(--reveal-dur) var(--ease),
              transform var(--reveal-dur) var(--ease);
}
/* 카드 순차 등장은 CSS transition-delay 가 아니라 js/reveal.js 에서 .is-in 을
   시차를 두고 붙여서 처리한다. transition-delay 를 쓰면 등장이 끝난 뒤에도
   hover 확장/축소가 최대 320ms 늦게 반응한다. */

/* 앵커 이동·섹션 이동을 부드럽게 (js/scroll.js 도 이 설정을 따른다) */
@media (min-width: 1024px) {
  html { scroll-behavior: smooth; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    transition-duration: 0.01ms !important;
    animation: none !important;
  }
  .banner__track { transition: none; }
  /* 움직임을 끈 상태에서도 내용은 보여야 한다 */
  .has-reveal [data-reveal] { opacity: 1; transform: none; }
}
