/* =========================================================
   AQNET — Data·Product Tech Premium Design System (v3)
   ========================================================= */

:root {
  /* --- Base palette --- */
  --ink: #05070d;
  --ink-2: #0a1020;
  --navy: #0d1b32;
  --navy-soft: #14243f;
  /* 라이트 섹션 전용 블루. #2276ff는 흰 배경 4.11:1로 AA(4.5) 미달이라
     같은 색상각(217°)을 유지한 채 명도만 내렸다 → 텍스트 5.26 / 흰 글자 채움 5.26 모두 통과.
     다크 섹션의 시그니처는 --cyan(CI azure #0390ee, 다크 위 5.97:1)이라 영향 없음 */
  --blue: #0f63ea;
  --blue-deep: #0b4fc0; /* --blue가 내려온 만큼 함께 내려 액티브 칩 그라디언트의 깊이를 유지 */
  /* 시그니처 액센트 — CI v2.0 팔레트의 azure. 구 하늘색(#2ed3ff)에서 전환(2026-08 클라이언트 A안).
     토큰명은 사이트 전역 참조 유지를 위해 그대로 두었으나 값은 하늘색 계열이 아님 */
  --cyan: #0390ee;
  --signal: #7ab7ff;
  --ice: #e8f2ff;
  --white: #ffffff;
  --fog: #f4f7fb;

  /* --- Dark surfaces (depth) --- */
  --surface-0: #05070d;
  --surface-1: #0a111f;
  --surface-2: #0e1729;
  --surface-3: #131e34;
  --surface-glass: rgba(18, 30, 54, 0.55);

  /* --- Light surfaces --- */
  --surface-l0: #ffffff;
  --surface-l1: #f8fbff;
  --surface-l2: #f1f6fd;

  /* --- Borders --- */
  --border-1: rgba(255, 255, 255, 0.08);
  --border-2: rgba(255, 255, 255, 0.14);
  --border-3: rgba(122, 183, 255, 0.32);
  --hairline-top: rgba(255, 255, 255, 0.22);
  --border-l1: #e6edf6;
  --border-l2: #dce4ef;
  --border-l3: rgba(34, 118, 255, 0.34);

  /* --- Text --- */
  --text-d-1: #ffffff;
  --text-d-2: rgba(255, 255, 255, 0.72);
  --text-d-3: rgba(255, 255, 255, 0.5);
  /* 0.45는 블랙 4.47 / 네이비 4.42로 AA(4.5)에 근소 미달이었다.
     0.48로 올려 두 다크 면 모두 통과(4.96 / 4.85). 17곳 각주·캡션에 일괄 적용된다.
     ※ --text-d-3(0.50)과 간격이 0.02로 좁아졌다 — 두 단계를 유지할지는 별도 판단 필요 */
  --text-d-4: rgba(255, 255, 255, 0.48);
  --text-l-1: #0a1020;
  --text-l-2: #3a4861;
  /* 라이트 전환(09·11) 후 실측에서 #6b7a92는 흰 배경 4.35:1로 AA(4.5) 미달이었다.
     색조는 그대로 두고 명도만 한 단계 내려 l0 5.08 / l1 4.90 / l2 4.68로 전부 통과시킨다 */
  --text-l-3: #626f85;

  /* --- Signature gradients & glows --- */
  --grad-brand: linear-gradient(118deg, #0390ee 0%, #7ab7ff 46%, #2276ff 100%);
  --grad-action: linear-gradient(135deg, #2276ff 0%, #0390ee 150%);
  --grad-bar: linear-gradient(180deg, #0390ee 0%, #2276ff 100%);
  --grad-accent-surface: linear-gradient(180deg, rgba(3, 144, 238, 0.16) 0%, transparent 54%);
  --grad-line: linear-gradient(90deg, transparent, rgba(3, 144, 238, 0.6), transparent);
  --glow-blue: 0 18px 50px rgba(34, 118, 255, 0.28);
  --glow-cyan: 0 0 26px rgba(3, 144, 238, 0.32);
  --mesh-cyan: radial-gradient(620px 420px at 78% 16%, rgba(3, 144, 238, 0.16), transparent 70%);
  --mesh-blue: radial-gradient(700px 520px at 10% 92%, rgba(34, 118, 255, 0.14), transparent 72%);
  /* 라이트 섹션 미세 텍스처 — 다크 섹션의 mesh·그리드에 대응하는 화이트 면의 결.
     섹션 배경에만 깔리고 카드(--surface-l0/l1)는 그대로 덮으므로 카드가 한 겹 떠 보인다.
     본문 대비를 건드리지 않도록 알파는 0.05 상한 */
  --dot-light: radial-gradient(rgba(34, 118, 255, 0.05) 1.2px, transparent 1.2px);
  --dot-light-size: 24px 24px;

  /* --- Elevation --- */
  --e-1: 0 1px 2px rgba(8, 16, 32, 0.06);
  --e-2: 0 10px 30px rgba(20, 36, 63, 0.1);
  --e-3: 0 18px 42px rgba(20, 36, 63, 0.14);
  --e-dark-1: 0 1px 0 var(--hairline-top) inset, 0 12px 30px rgba(0, 0, 0, 0.45);
  --e-dark-2: 0 1px 0 var(--hairline-top) inset, 0 24px 60px rgba(0, 0, 0, 0.55);
  --e-focus: 0 0 0 4px rgba(34, 118, 255, 0.18);

  /* --- Radius --- */
  --r-xs: 6px;
  --r-sm: 10px;
  --r-md: 14px;
  --r-lg: 20px;
  --r-pill: 999px;

  /* --- Card grammar (소개서 카드 문법) ---
     콘텐츠 카드 공통 규칙: 상단 2px 블루 라인(상시 노출) + hover에서
     리프트 2px · 보더 한 단계 · 그림자 한 단계.
     리프트를 transform이 아니라 translate로 두는 이유 —
     기존 등장 리빌·스크럽 패럴랙스가 transform을 점유했던 잔재이며,
     축을 분리해 두어야 다른 transform과 서로의 값을 덮어쓰지 않는다 */
  --card-line: var(--grad-action);
  --card-lift: -2px;

  /* --- Layout --- */
  --max: 1200px;
  --max-wide: 1320px;
  --header-height: 74px;
  --section-y: clamp(80px, 10vw, 140px);
  --section-y-tight: clamp(56px, 7vw, 96px);

  /* --- Type scale — 역할 토큰(R8 감사 1-F 권고값) ---
     섹션 헤딩(h2)·eyebrow·리드는 이미 단일값이라 토큰이 필요 없었고,
     산포는 "서브블록 타이틀"에 몰려 있었다(같은 역할에 9값: 17.5/18w800/18w900/19/20/22/24/24/28).
     이걸 2단으로 접는다. 2단을 남기는 이유는 실제로 두 층이기 때문 —
       L1 = 섹션 안의 대분류 카드(03 C.O.R.E · 04 SERVICE · 07 라인업/탭 · 12 WORKS)
       L2 = 그 아래 스텝·모듈 단위(05 도착지 · 06 STAGE · 08 STEP · 10 모듈 · 14 인사이트)
     lh까지 토큰에 묶는다 — 같은 24px에 1.20과 1.25가 공존하던 것이 산포의 절반이었다 */
  --t-sub-1: clamp(20px, 2.4vw, 24px);
  --t-sub-1-lh: 1.2;
  --t-sub-2: 18px;
  --t-sub-2-lh: 1.25;
  /* 마이크로 라벨 자간 2단 — 5단(0.08/0.10/0.12/0.14/0.16em)에서 접는다.
     eyebrow(챕터 진입 라벨)와 마이크로 라벨(캡스 캡션·축 라벨)은 크기도 역할도 달라
     한 값으로 합치지 않고 2단으로 둔다. 값은 각 역할의 기존 다수결값 그대로 */
  --t-eyebrow-ls: 0.12em;
  --t-label-ls: 0.14em;

  /* --- Spacing scale — base-8 4단 + 편집 1단(R8 감사 2-C) ---
     grid/flex gap이 22값, 블록 간격이 9값으로 흩어져 있었다. 8의 배수로 접는다.
     1·2·4px(로고월 헤어라인·루프 내부 실선)는 "의미 있는 1px 라인"이라 스케일 밖에 둔다 */
  --gap-1: 8px; /* 칩·태그·인라인 마크 */
  --gap-2: 16px; /* 카드 그리드·리스트 행 — 14 vs 16 반반 갈림을 8정합으로 16에 붙임 */
  --gap-3: 24px; /* 주요 2열 분할·블록 소전환 */
  --gap-4: 48px; /* 블록 간 표준(= .section-heading이 이미 쓰던 검증값) */
  --gap-editorial: 72px; /* 챕터 안의 장(章) 전환 */

  /* --- Motion --- */
  --dur-fast: 160ms;
  --dur: 200ms;
  --dur-med: 360ms;
  --dur-slow: 600ms;
  --dur-reveal: 720ms;
  --ease-out: cubic-bezier(0.2, 0.7, 0.2, 1);
  --ease-inout: cubic-bezier(0.65, 0, 0.35, 1);
  --ease-emphasized: cubic-bezier(0.16, 1, 0.3, 1);
  --stagger-step: 70ms;

  font-family:
    "Pretendard", "Pretendard Variable", -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans KR", Arial,
    sans-serif;
  color: var(--text-l-1);
  background: var(--white);
}

* {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
  scroll-padding-top: var(--header-height);
}

body {
  margin: 0;
  min-width: 320px;
  background: var(--surface-0);
  letter-spacing: 0;
}

.nowrap {
  white-space: nowrap;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.skip-link {
  position: fixed;
  top: 8px;
  left: 8px;
  z-index: 100;
  padding: 10px 16px;
  border-radius: var(--r-sm);
  background: var(--blue);
  color: var(--white);
  font-weight: 800;
  transform: translateY(-150%);
  transition: transform var(--dur-fast) ease;
}

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

/* 상단 스크롤 진행바 */
.scroll-progress {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 60;
  width: 100%;
  height: 2px;
  transform: scaleX(var(--p, 0));
  transform-origin: left;
  background: var(--grad-action);
  pointer-events: none;
  will-change: transform;
}

body.menu-open {
  overflow: hidden;
}

a {
  color: inherit;
  text-decoration: none;
}

button,
input,
textarea {
  font: inherit;
}

.site-shell {
  min-height: 100vh;
  /* Keep desktop sticky sections pinned while preventing horizontal bleed. */
  overflow-x: clip;
  background: var(--surface-0);
}

section[id] {
  scroll-margin-top: var(--header-height);
}

/* ---------- Background motif utilities ---------- */
.bg-grid {
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.045) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.045) 1px, transparent 1px);
  background-size: 52px 52px;
}

.bg-dots {
  background-image: radial-gradient(rgba(34, 118, 255, 0.1) 1.2px, transparent 1.2px);
  background-size: 22px 22px;
}

.bg-mesh {
  background-image: var(--mesh-cyan), var(--mesh-blue);
}

/* =========================================================
   HEADER
   ========================================================= */
.site-header {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 50;
  width: 100%;
  height: var(--header-height);
  display: grid;
  grid-template-columns: auto 1fr auto auto;
  align-items: center;
  gap: var(--gap-3);
  padding: 0 clamp(20px, 5vw, 64px);
  color: var(--white);
  /* 테두리·backdrop 레이어를 항상 유지해 스크롤 전환 시 로고가 0.5px 밀리거나
     재래스터화되는 현상을 방지 (색/블러만 전환) */
  border-bottom: 1px solid transparent;
  backdrop-filter: blur(0px);
  transition:
    background var(--dur) ease,
    border-color var(--dur) ease,
    backdrop-filter var(--dur) ease;
}

.site-header::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: linear-gradient(180deg, rgba(5, 7, 13, 0.5), transparent);
  transition: opacity var(--dur) ease;
}

.site-header.scrolled::before,
body.menu-open .site-header::before {
  opacity: 0;
}

.site-header.scrolled,
body.menu-open .site-header {
  background: rgba(5, 7, 13, 0.8);
  border-bottom: 1px solid var(--border-1);
  backdrop-filter: blur(20px) saturate(1.2);
}

.brand {
  display: inline-flex;
  align-items: center;
  width: clamp(142px, 12vw, 176px);
  min-width: 142px;
  height: 46px;
  color: inherit;
}

.brand-logo {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: left center;
}

.nav-links {
  justify-self: center;
  display: inline-flex;
  align-items: center;
  gap: clamp(18px, 3vw, 34px);
  color: var(--text-d-2);
  font-size: 14px;
  font-weight: 700;
}

.nav-links a {
  position: relative;
  padding: 28px 0;
  transition: color var(--dur-fast) ease;
}

.nav-links a::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 20px;
  width: 100%;
  height: 2px;
  background: var(--cyan);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur-fast) var(--ease-out);
}

.nav-links a:hover,
.nav-links a:focus-visible,
.nav-links a.active {
  color: var(--white);
}

.nav-links a:hover::after,
.nav-links a:focus-visible::after,
.nav-links a.active::after {
  transform: scaleX(1);
}

.header-cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 40px;
  padding: 0 16px;
  border: 1px solid var(--border-2);
  border-radius: var(--r-xs);
  background: rgba(255, 255, 255, 0.06);
  color: var(--white);
  font-size: 14px;
  font-weight: 800;
  transition:
    background var(--dur-fast) ease,
    border-color var(--dur-fast) ease;
}

.header-cta:hover,
.header-cta:focus-visible {
  background: rgba(255, 255, 255, 0.12);
  border-color: var(--border-3);
}

.menu-toggle {
  display: none;
  width: 42px;
  height: 42px;
  border: 1px solid var(--border-2);
  border-radius: var(--r-xs);
  background: rgba(255, 255, 255, 0.08);
  color: var(--white);
  cursor: pointer;
}

.menu-toggle span {
  display: block;
  width: 18px;
  height: 2px;
  margin: 4px auto;
  background: currentColor;
  transition:
    transform var(--dur-fast) ease,
    opacity var(--dur-fast) ease;
}

.menu-toggle[aria-expanded="true"] span:first-child {
  transform: translateY(3px) rotate(45deg);
}

.menu-toggle[aria-expanded="true"] span:last-child {
  transform: translateY(-3px) rotate(-45deg);
}

.mobile-panel {
  position: fixed;
  inset: var(--header-height) 0 auto 0;
  z-index: 45;
  display: grid;
  padding: 12px 20px 24px;
  background: rgba(5, 7, 13, 0.97);
  backdrop-filter: blur(18px);
  color: var(--white);
  transform: translateY(-120%);
  visibility: hidden; /* inert 미지원 브라우저에서 닫힌 메뉴 포커스 차단 */
  transition:
    transform 220ms var(--ease-out),
    visibility 0s 220ms;
  border-bottom: 1px solid var(--border-1);
}

.mobile-panel.open {
  transform: translateY(0);
  visibility: visible;
  transition:
    transform 220ms var(--ease-out),
    visibility 0s;
}

.mobile-panel a {
  padding: 18px 0;
  border-bottom: 1px solid var(--border-1);
  font-size: 18px;
  font-weight: 800;
}

.mobile-panel a.mobile-cta {
  margin-top: 16px;
  border-bottom: 0;
  border-radius: var(--r-sm);
  background: var(--blue);
  color: var(--white);
  text-align: center;
  padding: 16px;
}

/* =========================================================
   TYPOGRAPHY HELPERS
   ========================================================= */
/* 섹션 라벨 — 가독성 요청으로 12px→13.5px 상향(자간은 커진 만큼 소폭 축소) */
.eyebrow {
  margin: 0 0 16px;
  color: var(--blue);
  font-size: 13.5px;
  line-height: 1.2;
  font-weight: 800;
  letter-spacing: var(--t-eyebrow-ls);
  text-transform: uppercase;
}

.eyebrow-signal {
  color: var(--cyan);
}

/* 섹션 인덱스 — 소개서의 "NN · LABEL" 문법을 본문 섹션 아이브로우로 이식.
   색은 아이브로우 관례를 그대로 상속받아 라이트 섹션 var(--blue) / 다크 섹션 var(--cyan)로 갈린다.
   숫자 폭이 흔들리지 않게 tabular-nums, 구분자는 라벨과 한 호흡 떨어지도록 반투명 처리 */
.eyebrow-no {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

.eyebrow-no::after {
  content: "·";
  margin: 0 0.5em;
  opacity: 0.5;
  font-weight: 700;
}

.grad {
  background: var(--grad-brand);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* 파란색 계열 전용 강조(시안 제외) — .grad와 동일 기법, 헤드라인 부분 강조용.
   구 값(#5b9cff→#2276ff)은 토큰 교체 전 색이라 밝은 끝이 흰 배경 2.75:1로
   대형 텍스트 3:1조차 못 넘겼다. 그라디언트 텍스트는 color가 transparent라
   대비 감사에서 걸러지지 않는 사각지대였다. 현행 토큰으로 교체해
   가장 어두운 라이트 면(l2)에서도 양끝 4.84 / 6.68로 통과시킨다 */
.accent-blue {
  background: linear-gradient(90deg, var(--blue), var(--blue-deep));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* eyebrow 밑줄 — 스크롤 등장 연출을 걷어내고 상시 표시 */
.eyebrow {
  position: relative;
}

.eyebrow::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: -10px;
  width: 30px;
  height: 2px;
  background: linear-gradient(90deg, var(--cyan), transparent);
}

/* =========================================================
   HERO
   ========================================================= */
.hero {
  position: relative;
  color: var(--white);
}

.hero-stage {
  position: relative;
  min-height: 82vh; /* svh 미지원 폴백 */
  min-height: 82svh;
  isolation: isolate;
  display: grid;
  align-items: center;
  background:
    var(--mesh-cyan),
    var(--mesh-blue),
    linear-gradient(rgba(255, 255, 255, 0.04) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.04) 1px, transparent 1px),
    linear-gradient(135deg, var(--ink) 0%, #091124 48%, #061323 100%);
  background-size:
    auto,
    auto,
    78px 78px,
    78px 78px,
    auto;
}

.hero-canvas,
.hero-noise {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: -2;
  backface-visibility: hidden;
  contain: paint;
  transform: translate3d(0, 0, 0);
}

/* CI 모션 비디오 레이어 — 데스크탑 핀 전용(미디어쿼리에서 활성화).
   모바일·태블릿은 레이어 자체가 없어 JS가 src를 승격하지 않음(대역폭 0) */
.hero-videos {
  display: none;
}

/* 핸드오프 레일 — 데스크탑 핀 스크럽 exit 전용(미디어쿼리에서 활성화) */
.hero-rail {
  display: none;
}

/* 스크럽 메시지 비트 · 챕터 도트 — 데스크탑 핀 전용(미디어쿼리에서 활성화) */
.hero-beats,
.hero-chapters {
  display: none;
}

.hero-noise {
  z-index: -1;
  opacity: 0.2;
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.03) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.03) 1px, transparent 1px);
  background-size: 44px 44px;
  mask-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.9), rgba(0, 0, 0, 0.12));
}

.hero-inner {
  width: 100%;
  padding: calc(var(--header-height) + 28px) max(24px, calc((100% - var(--max)) / 2)) 56px;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-items: center;
}

.hero-copy {
  max-width: 820px;
  /* 스크롤 스크럽 — 히어로 이탈 시 카피가 배경과 시차를 두고 침강 */
  transform: translate3d(0, calc(var(--hs, 0) * var(--hero-drift, -46px)), 0)
    scale(calc(1 - var(--hs, 0) * 0.03));
  transform-origin: left center;
  opacity: calc(1 - var(--hs, 0) * 0.85);
  will-change: transform, opacity;
}

.hero-title {
  margin: 18px 0 0;
  max-width: 880px;
  font-size: clamp(34px, 5.4vw, 72px);
  line-height: 1.05;
  font-weight: 900;
  letter-spacing: -0.015em;
  word-break: keep-all;
}

.lead-mobile {
  display: none;
}

.hero-sub {
  margin: 24px 0 0;
  max-width: 640px;
  color: var(--text-d-2);
  font-size: clamp(16px, 2vw, 19px);
  line-height: 1.75;
  word-break: keep-all;
}

.hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 36px;
}

.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  padding: 0 22px;
  border-radius: var(--r-sm);
  border: 1px solid transparent;
  font-weight: 800;
  cursor: pointer;
  transition:
    transform var(--dur) var(--ease-out),
    filter var(--dur) ease,
    background var(--dur) ease,
    border-color var(--dur) ease,
    box-shadow var(--dur) ease;
}

.button-primary {
  background: var(--grad-action);
  color: var(--white);
  box-shadow: var(--glow-blue);
}

.button-primary:hover,
.button-primary:focus-visible {
  transform: translateY(-1px);
  filter: brightness(1.06);
  box-shadow: 0 22px 60px rgba(34, 118, 255, 0.36);
}

.button-ghost {
  border-color: var(--border-2);
  background: rgba(255, 255, 255, 0.06);
  color: var(--white);
}

.button-ghost:hover,
.button-ghost:focus-visible {
  transform: translateY(-1px);
  background: rgba(255, 255, 255, 0.12);
  border-color: var(--border-3);
}

.button:focus-visible {
  box-shadow: var(--e-focus);
}

.button:active {
  transform: translateY(0) scale(0.98);
  transition-duration: var(--dur-fast);
}

.hero-scrollcue {
  position: absolute;
  left: 50%;
  bottom: 22px;
  transform: translateX(-50%);
  opacity: calc(1 - var(--hs, 0) * 3.5);
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--text-d-4);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

.hero-scrollcue span {
  width: 1px;
  height: 26px;
  background: linear-gradient(var(--cyan), transparent);
  animation: scrollCue 1.8s ease-in-out infinite;
}

/* 인트로 스킵 — 데스크탑 핀 트랙 전용(모바일은 트랙이 없어 불필요) */
.hero-skip {
  display: none;
}

/* Solution 브리지 — 통과 서사의 결론 선언+CTA (모바일: 정적, 데스크탑: 레일 위 스크럽) */
.hero-bridge {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 6px 14px;
  margin: 0;
  padding: 0 24px 36px;
  font-size: clamp(15px, 1.8vw, 20px);
  font-weight: 700;
  color: var(--text-d-1);
  word-break: keep-all;
  text-align: center;
}

.hero-bridge-core {
  position: relative;
  display: inline-block;
  color: var(--cyan);
  font-weight: 900;
  letter-spacing: 0;
  text-shadow: 0 0 16px rgba(3, 144, 238, 0.34);
  white-space: nowrap;
}

.hero-bridge-core::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -4px;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(3, 144, 238, 0.9), transparent);
  opacity: 0.86;
}

.hero-bridge a {
  color: var(--cyan);
  font-weight: 800;
  white-space: nowrap;
}

.hero-bridge a:hover,
.hero-bridge a:focus-visible {
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* 로드 인트로 — 요소 단위 캐스케이드 (backwards: 종료 후 스크럽 스타일로 복귀) */
@keyframes heroIn {
  from {
    opacity: 0;
    transform: translateY(24px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.hero-copy .eyebrow {
  animation: heroIn 640ms var(--ease-emphasized) 60ms backwards;
}

.hero-title {
  animation: heroIn 700ms var(--ease-emphasized) 160ms backwards;
}

.hero-sub {
  animation: heroIn 640ms var(--ease-emphasized) 340ms backwards;
}

.hero-actions {
  animation: heroIn 640ms var(--ease-emphasized) 480ms backwards;
}

/* 데스크탑 핀 스크럽 — 히어로 240svh 트랙 + sticky 무대 (CTO 리뷰: 330→240 축소)
   (막1 카피 침강 → 막2 정렬+비트1 → 막3 통과 줌+비트2 → 막4 브리지·레일 → exit 오버랩)
   휠 하이재킹 없음 — 네이티브 스크롤 + 시각 진행도 lerp(애플 방식).
   막 배분은 script.js warpHeroPhase()가 재배분 — 막1(첫 CTA)은 절대 스크롤 기준으로 길게 유지 */
@media (min-width: 1025px) {
  .hero {
    height: 240vh;
    height: 240svh;
    --hero-drift: -56px;
  }

  .hero-stage {
    position: sticky;
    top: 0;
    height: 100vh;
    height: 100svh;
    min-height: 0;
    overflow: hidden;
    /* exit — 상향 이탈(스크롤 관성 방향)만. scale은 줌 연출과 모순이라 미사용 */
    transform: translate3d(0, calc(var(--hx, 0) * -2vh), 0);
    backface-visibility: hidden;
    contain: paint;
    will-change: transform;
  }

  /* exit 스크림 — filter 대신 opacity(컴포지터 전용)로 어둡게 */
  .hero-stage::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 3;
    background: var(--surface-0);
    opacity: calc(var(--hx, 0) * 0.5);
    pointer-events: none;
  }

  /* CI 모션 비디오(단일층) — screen 블렌드로 어두운 배경은 소거되고 광원만 무대에 합성.
     AQ 엠블럼 드로잉을 스크롤 진행도에 프레임 단위 스크럽(JS currentTime) — 브리지 직전 심볼 완성.
     오퍼시티는 JS가 .hero에 주입하는 --hve(0~1, exit에서만 소등)의 순수 함수 */
  .hero-videos {
    display: block;
    position: absolute;
    inset: 0;
    pointer-events: none;
    /* ★래퍼를 스태킹 컨텍스트로 만들지 말 것: z-index뿐 아니라 opacity<1, transform, filter,
       backdrop-filter, will-change, contain(paint/layout/content), isolation, perspective, mask
       중 무엇이 생겨도 래퍼가 블렌드 격리 그룹이 되어 자식의 screen 블렌드가 .hero-stage 배경과
       합성되지 못하고 어두운 사각형으로 덮임(조용한 시각적 실패). 레이어 순서는 아래
       .hero-video의 z-index가 .hero-stage 컨텍스트에서 직접 결정 */
  }

  .hero-video {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    /* .hero-canvas(-2)·.hero-noise(-1)보다 한 칸 아래, .hero-stage 배경 위.
       기존 레이어(캔버스·노이즈·레일·카피·비트·챕터·스킵)의 z-index는 그대로 두어 렌더 불변 */
    z-index: -3;
    object-fit: cover;
    mix-blend-mode: screen;
    opacity: 0;
    will-change: opacity;
  }

  /* 첫 화면 카피와 공존해야 하므로 배율은 0.7로 억제("영상이 과함" 반영).
     --hvr은 첫 프레임 확보 시 JS가 0→1로 램프하는 준비 페이드 — 지연 로드된 심볼이
     툭 튀어나오지 않게 한다. 미로드/로드 실패 시 0이라 레이어가 조용히 비활성 */
  .hero-video-emblem {
    opacity: calc(var(--hve, 0) * var(--hvr, 0) * 0.7);
  }

  /* 핸드오프 레일 — 코어(70%W)를 고속 통과할 때의 모션 스트릭이 수평 광선으로 확장.
     top 62%→56%: 브리지 문장만 56%로 올라가고 레일이 아래 남아 "수평선은 그대로"라는
     피드백(2026-08-26) — 문장과 함께 올려 "문장 하단 30px 아래 레일" 정박 구도를 새 높이에
     복원한다(간격이 %가 아닌 상수 30px이 되어 뷰포트 높이와 무관해진다).
     ★대가: p=1 시점 레일(56% − 무대 이탈 2vh = 54svh)이 Signal Strip border-top
     (무대높이 100 − 오버랩 40 = 60svh)보다 6svh 위 — 레일이 스트립 테두리로 녹아드는
     바통터치가 그만큼 느슨해진다. 오버랩 46svh로 늘리면 정합은 되찾지만 스트립 진입이
     p 0.68→0.63으로 당겨져 "엠블럼 드로잉(~p 0.64) 완료 후 진입" 불변식이 깨져 채택 안 함 */
  .hero-rail {
    display: block;
    position: absolute;
    top: 56%;
    left: 0;
    right: 0;
    height: 2px;
    z-index: -1;
    background: linear-gradient(
      90deg,
      rgba(34, 118, 255, 0),
      var(--blue) 18%,
      var(--cyan) 82%,
      rgba(3, 144, 238, 0)
    );
    box-shadow: 0 0 18px rgba(3, 144, 238, 0.45);
    opacity: var(--hrla, 0);
    transform: scaleX(var(--hrl, 0));
    transform-origin: 70% 50%;
    pointer-events: none;
  }

  /* 40svh 오버랩 — 후행 섹션이 핀 무대 위로 슬라이드 인하며 레일과 바통터치.
     ★60→40으로 축소: 무대가 덮이기 전 깨끗한 구간이 271px→464px로 늘어 심볼 드로잉과
     메시지 2개가 화면이 넘어가기 전에 모두 끝날 수 있다(트랙 길이는 240svh 유지).
     p=1 시점 strip border-top = 무대높이 100 − 40 = 60svh.
     ★레일이 56%로 올라간 뒤로는 레일 착지점(54svh)과 6svh 어긋난다 — 위 .hero-rail 주석 참조 */
  .signal-strip {
    margin-top: -40vh;
    margin-top: -40svh;
  }

  /* 오버랩 구간의 후행 섹션은 핀 무대 위에 페인트 — WHY는 자체 base에서 relative 처리 */
  .about-section {
    position: relative;
  }

  .hero-copy {
    transform: translate3d(0, calc(var(--hs, 0) * var(--hero-drift)), 0)
      scale(calc(1 - var(--hs, 0) * 0.04));
    /* 완전 소등 — 무대 중앙 브리지 캡션과의 잔상 겹침 방지 */
    opacity: calc(1 - var(--hs, 0));
  }

  /* 스크럽 메시지 비트 — 막2·막3 중반의 서사 공백을 채우는 챕터 카피(카피 자리 승계) */
  .hero-beats {
    display: block;
    position: absolute;
    inset: 0;
    z-index: 1;
    pointer-events: none;
  }

  .hero-beat {
    position: absolute;
    left: max(24px, calc((100% - var(--max)) / 2));
    top: 50%;
    margin: 0;
    max-width: 620px;
    font-size: clamp(28px, 3vw, 42px);
    line-height: 1.34;
    font-weight: 700;
    color: var(--text-d-2);
    word-break: keep-all;
    opacity: var(--b, 0);
    transform: translateY(calc(-50% + (1 - var(--b, 0)) * 44px));
    will-change: transform, opacity;
  }

  .hero-beat strong {
    display: inline-block;
    margin-top: 6px;
    color: var(--white);
    font-weight: 900;
  }

  .hero-beat-1 {
    --b: var(--hb1, 0);
  }

  .hero-beat-2 {
    --b: var(--hb2, 0);
  }

  /* 챕터 도트 — 우측 미드라인. 현재 막을 캡슐로 확장 표시, exit와 함께 소등 */
  .hero-chapters {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    position: absolute;
    right: 30px;
    top: 50%;
    transform: translateY(-50%);
    z-index: 2;
    opacity: calc(1 - var(--hx, 0) * 2);
    pointer-events: none;
  }

  .hero-chapters span {
    width: 6px;
    height: 6px;
    border-radius: 3px;
    background: rgba(255, 255, 255, 0.22);
    transition:
      background 0.3s ease,
      height 0.3s var(--ease-out);
  }

  .hero-chapters span.on {
    height: 20px;
    background: var(--cyan);
    box-shadow: 0 0 10px rgba(3, 144, 238, 0.5);
  }

  /* 브리지 캡션 — 통과 직후(막 4) 서사의 결론으로 등장.
     비트와 동급 스케일 + 하단 정박(크기 변경에도 정합 유지). 정박점 62%→56%:
     레일(62%) 위 30px에 붙이면 광학 중심이 ~56%라 심볼이 비운 상단 아래로 처져 보인다는
     피드백(2026-08-26) — 비트와 같은 50% 부근에 서고 레일은 아래 지평선으로 분리 */
  .hero-bridge {
    position: absolute;
    left: 50%;
    top: 56%;
    width: max-content;
    max-width: 84vw;
    padding: 0;
    font-size: clamp(26px, 2.6vw, 40px);
    font-weight: 800;
    color: var(--white);
    opacity: var(--hbr, 0);
    transform: translate(-50%, calc(-100% - 30px + (1 - var(--hbr, 0)) * 18px));
  }

  .hero-bridge-core {
    text-shadow: 0 0 26px rgba(3, 144, 238, 0.45);
  }

  .hero-scrollcue {
    opacity: calc(1 - var(--hcue, 0));
  }

  /* 인트로 스킵 — 바로 본문을 보고 싶은 방문자용. 챕터 도트와 동일하게 exit에서 소등 */
  .hero-skip {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    position: absolute;
    right: 26px;
    bottom: 24px;
    z-index: 3;
    padding: 9px 16px;
    border: 1px solid var(--border-2);
    border-radius: var(--r-pill);
    background: rgba(5, 7, 13, 0.42);
    color: var(--text-d-2);
    font-family: inherit;
    font-size: 12.5px;
    font-weight: 700;
    letter-spacing: 0.05em;
    cursor: pointer;
    opacity: calc(1 - var(--hx, 0) * 2);
    transition:
      border-color var(--dur) ease,
      color var(--dur) ease;
  }

  .hero-skip::after {
    content: "↓";
    font-size: 12px;
  }

  .hero-skip:hover,
  .hero-skip:focus-visible {
    border-color: var(--border-3);
    color: var(--white);
  }
}

@keyframes scrollCue {
  0%,
  100% {
    transform: scaleY(0.4);
    opacity: 0.4;
    transform-origin: top;
  }
  50% {
    transform: scaleY(1);
    opacity: 1;
    transform-origin: top;
  }
}

/* =========================================================
   SIGNAL STRIP
   ========================================================= */
.signal-strip {
  position: relative;
  overflow: hidden;
  background: var(--surface-0);
  color: var(--white);
  border-top: 1px solid var(--border-1);
  border-bottom: 1px solid var(--border-1);
  padding-bottom: 6px;
}

.strip-label {
  display: block;
  padding: 16px max(24px, calc((100% - var(--max)) / 2)) 0;
  color: var(--text-d-4);
  font-size: 12px;
  font-weight: 800;
  letter-spacing: var(--t-label-ls);
  text-transform: uppercase;
}

.strip-mask {
  overflow: hidden;
  mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
}

.strip-track {
  display: flex;
  gap: var(--gap-2);
  width: max-content;
  padding: 12px 24px 16px;
  /* 항목 11→13개 확장에 맞춰 13/11 비율로 재조정(체감 속도 유지) */
  animation: stripMove 38s linear infinite;
}

.signal-strip:hover .strip-track {
  animation-play-state: paused;
}

.strip-track span {
  display: inline-flex;
  align-items: center;
  gap: var(--gap-1);
  min-height: 38px;
  padding: 0 16px;
  border: 1px solid var(--border-2);
  border-radius: var(--r-pill);
  color: var(--text-d-2);
  font-size: 14px;
  font-weight: 700;
  white-space: nowrap;
}

.strip-track span::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--blue);
}

.strip-track span.ds::before {
  background: var(--cyan);
}

/* 아이콘 칩: dot를 단색 마스크 로고로 대체 (마퀴 가독성 위해 컬러 대신 currentColor=화이트 72%)

   이 띠만 모노로 남는 근거 — 정보 블록(06·07)에서는 30개 자산 중 28개가 이미 브랜드
   컬러로 칠해져 있어, 색을 품은 googleads·coupang을 원본으로 돌리면 '컬러 계열'에
   합류한다. 여기는 정반대다: 13칩 전부 currentColor 백색 하나로 칠해진 모노 계열이고,
   색을 가진 자산은 그중 2개뿐이라 원본 규칙을 들이면 백색 11 + 컬러 2가 되어 띠 안에
   없던 불일치가 새로 생긴다. 경계는 면의 장식성이 아니라 '주변 아이콘 계열이 컬러냐
   모노냐'다 — 그래서 한 브랜드가 두 계열에 걸쳐도 각 계열 안에서는 예외가 0이다.
   덧붙여 이 띠는 라벨부터 영문(Operating Channels & Data Stack)이고 칩 문안도 13개
   전부 로마자라, 본문(한글) 계열과 애초에 다른 언어면으로 분리돼 있다 */
.strip-track span.has-ico::before {
  width: 17px;
  height: 17px;
  border-radius: 0;
  background: currentColor;
  -webkit-mask-size: contain;
  mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
}

.strip-track span.ico-googleads::before {
  -webkit-mask-image: url("assets/logos/platforms/googleads.svg");
  mask-image: url("assets/logos/platforms/googleads.svg");
}
.strip-track span.ico-meta::before {
  -webkit-mask-image: url("assets/logos/platforms/meta.svg");
  mask-image: url("assets/logos/platforms/meta.svg");
}
.strip-track span.ico-youtube::before {
  -webkit-mask-image: url("assets/logos/platforms/youtube.svg");
  mask-image: url("assets/logos/platforms/youtube.svg");
}
.strip-track span.ico-tiktok::before {
  -webkit-mask-image: url("assets/logos/platforms/tiktok.svg");
  mask-image: url("assets/logos/platforms/tiktok.svg");
}
.strip-track span.ico-naver::before {
  -webkit-mask-image: url("assets/logos/platforms/naver.svg");
  mask-image: url("assets/logos/platforms/naver.svg");
}
.strip-track span.ico-googleanalytics::before {
  -webkit-mask-image: url("assets/logos/platforms/googleanalytics.svg");
  mask-image: url("assets/logos/platforms/googleanalytics.svg");
}
.strip-track span.ico-googlebigquery::before {
  -webkit-mask-image: url("assets/logos/platforms/googlebigquery.svg");
  mask-image: url("assets/logos/platforms/googlebigquery.svg");
}
/* 로고 사용 승인 완료(2026-07) — 카카오 심볼 + 데이터 스택 3종 추가 */
.strip-track span.ico-kakao::before {
  -webkit-mask-image: url("assets/logos/platforms/kakao.svg");
  mask-image: url("assets/logos/platforms/kakao.svg");
}
/* 쿠팡은 정사각 심볼이 아닌 가로형 워드마크(약 4.4:1) → 17px 정사각에 넣으면 뭉개지므로
   해당 칩만 실제 비율대로 박스를 넓혀 마스크 */
.strip-track span.ico-coupang::before {
  width: 48px;
  height: 11px;
  -webkit-mask-image: url("assets/logos/platforms/coupang.svg");
  mask-image: url("assets/logos/platforms/coupang.svg");
}
.strip-track span.ico-appsflyer::before {
  -webkit-mask-image: url("assets/logos/platforms/appsflyer.svg");
  mask-image: url("assets/logos/platforms/appsflyer.svg");
}
.strip-track span.ico-airbridge::before {
  /* 공식 SVG 심볼 미제공 → 앱 아이콘 기반 투명 마스크 PNG(알파) 사용 */
  -webkit-mask-image: url("assets/logos/platforms/airbridge.png");
  mask-image: url("assets/logos/platforms/airbridge.png");
}
.strip-track span.ico-amplitude::before {
  -webkit-mask-image: url("assets/logos/platforms/amplitude.svg");
  mask-image: url("assets/logos/platforms/amplitude.svg");
}

@keyframes stripMove {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(-50%);
  }
}

/* =========================================================
   SNAPSHOT
   ========================================================= */
/* 증거 밴드 — Solution(라이트)과 Works(라이트) 사이 다크 구두점 */
/* 생성 이미지 앰비언트는 클라이언트 지시(2026-08-26)로 전면 철수 — 재도입 금지 */
.reference-snapshot {
  position: relative;
  background: var(--surface-0);
  /* 상속 색 안전망 — 이 블록은 `.section` 클래스가 없어 다크 섹션 잉크 규칙을 못 받는다.
     그래서 배경은 #05070d인데 상속되는 color는 라이트용 --text-l-1(#0a1020)이었다.
     현재는 자식이 전부 색을 재지정해 실害가 없지만, 여기에 텍스트를 한 줄만 더해도
     즉시 배경과 같은 잉크로 보이지 않게 된다(T1이 11에 h2·KPI를 심는 지점이라 더 그렇다).
     다크 면 기본 잉크를 명시해 둔다 — 기존 자식 선언이 전부 이 값을 덮으므로 렌더 변화 0 */
  color: var(--text-d-2);
  border-top: 1px solid var(--border-1);
  border-bottom: 1px solid var(--border-1);
  background-image: var(--mesh-blue);
}

/* Solution과의 이음매 헤어라인은 SECTIONS(generic)의 SEAM 규칙이 일괄 담당 */

/* 맥락 캡션 — 맨숫자 고아 방지: 직전 Solution의 시스템을 결과 요약으로 인계 */
.snapshot-head {
  padding: 52px max(24px, calc((100% - var(--max)) / 2)) 0;
}

/* T1이 p → h2로 승격만 해두고 급 조정은 여기로 넘긴 요소.
   11은 챕터 번호를 달고도 유일하게 h2가 없던 섹션이라, 태그만 h2가 되고 렌더가
   19/w600/rgba(.72)로 남으면 아웃라인과 눈에 보이는 위계가 계속 어긋난다.
   다른 14개 섹션 h2와 같은 문법으로 맞춘다 — 클램프·웨이트·자간·행간·잉크·max-width 전부.
   문자열은 손대지 않는다. 52px 밴드 상단 패딩은 "증거 밴드"의 정체성이라 그대로 두고,
   헤딩 → 첫 블록 간격만 전 섹션 불변값 48px(--gap-4)으로 맞춘다(.snapshot-inner) */
.snapshot-lead {
  max-width: 920px;
  margin: 0;
  color: var(--white);
  font-size: clamp(32px, 5vw, 60px);
  line-height: 1.08;
  font-weight: 900;
  letter-spacing: -0.01em;
  word-break: keep-all;
}

.snapshot-inner {
  width: 100%;
  /* 상단 48px = 전 섹션 "헤딩 → 첫 본문 블록" 불변값(--gap-4).
     하단 여백은 뒤따르는 .snapshot-note가 이어받음 */
  padding: var(--gap-4) max(24px, calc((100% - var(--max)) / 2)) 20px;
  display: grid;
  /* 지표 5종 — 07 AD PRODUCTS가 들어오며 '광고 상품 수'가 한 칸 추가됐다.
     1200px 본문 기준 카드 폭 228.8px(4칸일 때 292.5px), 내부 폭은 패딩 48을 뺀 180.8px.
     공용 RESPONSIVE의 ≤1024 2열 규칙은 그대로 살아 3+2로 접힌다 */
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: var(--gap-2);
}

.snapshot-inner article {
  position: relative;
  min-height: 168px;
  padding: 28px 24px 30px;
  border: 1px solid var(--border-2);
  border-radius: var(--r-md);
  background: var(--surface-2);
  box-shadow: var(--e-dark-1);
  overflow: hidden;
  /* transform은 데스크탑 패럴랙스가 점유 — 리프트는 translate 축으로 분리 */
  transition:
    translate var(--dur) var(--ease-out),
    border-color var(--dur) ease,
    box-shadow var(--dur) ease;
}

/* 지표 카드도 콘텐츠 카드 패밀리 — 상단 2px 라인 상시 노출 */
.snapshot-inner article::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: var(--card-line);
  opacity: 0.55;
  transition: opacity var(--dur) ease;
}

.snapshot-inner article:hover {
  translate: 0 var(--card-lift);
  border-color: var(--border-3);
  box-shadow: var(--e-dark-2);
}

.snapshot-inner article:hover::before {
  opacity: 1;
}

/* 수치가 카드의 주인공 — 라벨보다 한 위계가 아니라 두 위계 위에 둔다.
   큰 자소에서 벌어져 보이는 자간은 -0.02em으로 조인다 */
.snapshot-inner strong {
  display: block;
  color: var(--white);
  font-size: clamp(48px, 6vw, 86px);
  line-height: 1;
  font-weight: 900;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}

/* 5칸이 실제로 서는 구간에서만 수치를 줄인다 — 4칸일 때의 상한 86px은
   5칸(1440px 기준 카드 내부 폭 180.8px)에서 세 자리 값이 줄바꿈된다.
   ≤1024는 공용 RESPONSIVE가 2열로 접어 카드가 다시 넓어지므로 원래 스케일을 그대로 둔다 */
@media (min-width: 1025px) {
  .snapshot-inner strong {
    /* 62px — 66px에서는 "10년+"의 필요 폭이 181.3px로 카드 내폭 180px를 1.3px
       초과해 +가 둘째 줄로 밀렸다(CJK 줄바꿈은 한글자 뒤 분리를 허용).
       62px이면 170px로 10px 여유가 생긴다 */
    font-size: clamp(42px, 4.3vw, 62px);
  }
}

/* 라벨은 카드 직계 span만 — 내부 .nowrap이 블록으로 떨어지지 않도록 스코프 한정 */
.snapshot-inner article > span {
  display: block;
  margin-top: var(--gap-2);
  color: var(--text-d-3);
  font-size: 15px;
  font-weight: 700;
  word-break: keep-all;
}

/* 영문 보조 라벨 — 국문 라벨의 지시 대상을 한 줄로 보강 */
.snap-sub {
  display: block;
  margin-top: 6px;
  color: var(--text-d-4);
  font-size: 11.5px;
  line-height: 1.45;
  font-style: normal;
  font-weight: 600;
  letter-spacing: 0.02em;
}

/* 지표 산정 기준 각주 */
.snapshot-note {
  width: 100%;
  margin: 0;
  padding: 0 max(24px, calc((100% - var(--max)) / 2)) 48px;
  color: var(--text-d-4);
  font-size: 12.5px;
  line-height: 1.6;
  word-break: keep-all;
}

.snapshot-inner article::after {
  content: "";
  position: absolute;
  left: 24px;
  right: 24px;
  bottom: 16px;
  height: 2px;
  background: var(--grad-line);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur-slow) var(--ease-out);
}

.snapshot-inner article.counted::after {
  transform: scaleX(1);
}

/* =========================================================
   SECTIONS (generic)
   ========================================================= */
.section {
  width: min(100%, var(--max));
  margin: 0 auto;
  padding: var(--section-y) 24px;
}

/* --- SEAM — 섹션 이음매 헤어라인(시그니처) ---
   소개서가 페이지마다 상단 룰로 챕터를 끊듯, 배경 톤이 바뀌는 모든 경계에 --grad-line 1px을 깐다.
   배경 순서: 히어로(D) → 스트립(D) → 01 WHY(D) → 02 About(L) → 03 Framework(D) → 04 Service(L)
             → 05 Solution(D) → 06 Snapshot(D) → 07 Works(D) → 08 Client(L) → 09 Insight(L)
             → 10 Contact(D) → Footer(D)
   신규 6곳은 다크↔라이트 전환 경계, Snapshot/Works/Footer 3곳은 다크 연속 구간의 기존 구두점.
   전환이 없는 이음매(스트립→WHY, Client→Insight)와 히어로 경계는 손대지 않는다
   — 히어로↔스트립은 스트립의 border-top이 이미 담당 */
.about-section,
.framework-section,
.service-section,
.solution-section,
.reference-section,
.contact-section {
  position: relative;
}

.about-section::before,
.framework-section::before,
.service-section::before,
.solution-section::before,
.reference-section::before,
.contact-section::before,
.reference-snapshot::before,
.works-section::before,
.site-footer::before {
  content: "";
  position: absolute;
  top: -1px;
  left: 0;
  right: 0;
  height: 1px;
  background: var(--grad-line);
}

.section-heading {
  max-width: 820px;
  margin-bottom: var(--gap-4);
}

.section-heading.compact {
  max-width: 920px;
}

.section-heading h2 {
  margin: 0;
  color: var(--text-l-1);
  font-size: clamp(32px, 5vw, 60px);
  line-height: 1.08;
  font-weight: 900;
  letter-spacing: -0.01em;
  word-break: keep-all;
}

.section-heading p:not(.eyebrow) {
  margin: 18px 0 0;
  color: var(--text-l-2);
  font-size: 18px;
  line-height: 1.75;
  word-break: keep-all;
}

/* =========================================================
   WHY AQNET (풀블리드 다크 매니페스토)
   ========================================================= */
.why-section {
  /* 핀 무대(sticky) 위에 배경까지 페인트 — reference-snapshot/about과 동일한 오버랩 처리 */
  position: relative;
  width: 100%;
  max-width: none;
  background: var(--surface-0);
  background-image: var(--mesh-cyan), var(--mesh-blue);
  color: var(--white);
}

/* 밴드 정렬 — 콘텐츠가 .why-stage 래퍼 안으로 이동했으므로 기준을 스테이지 직계로.
   모바일/핀 비활성에서 기존 렌더 동일 유지(회귀 방지) */
.why-stage > .section-heading,
.why-stage > .why-log,
.why-stage > .why-pains,
.why-stage > .why-define {
  width: min(100%, var(--max));
  margin-left: auto;
  margin-right: auto;
}

/* 광고주 문제 인식 — [질문 필 → 사실 재진술] 2단 3열.
   폄하 금지 원칙: 타사가 아니라 광고주의 고민을 주어로 삼는다. 정적(모션 없음) */
.why-pains {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  /* 알약 크롬을 걷어내면 칸을 가르던 보더가 사라지므로 거터가 분절을 대신한다 */
  gap: var(--gap-3);
  margin-top: var(--gap-editorial);
  padding: 0;
  list-style: none;
}

.why-pains li {
  display: flex;
  flex-direction: column;
  gap: var(--gap-2);
}

/* 질문 — 01의 타이포 계단(h2 60 → .why-def 44 → .why-line 31 → .why-tick 29 →
   .why-promise 23)에서 15px로 1.53배 끊기던 자리를 20px로 이어 붙인다.
   칩 크롬(채움·1px 보더·radius)은 전부 제거: 01은 .why-line이 배경도 보더도 없이
   좌측 룰 하나로 서는 매니페스토 면이고, 무엇보다 01에 아주르 '채움'을 두면
   05 .diff-to의 아주르 면(=자사 해법)과 값어치가 정반대로 뒤집힌다.
   남는 것은 .why-line과 같은 계열의 좌측 2px 아주르 룰뿐 */
.wp-q {
  margin: 0;
  padding: 0 0 0 16px;
  border-left: 2px solid rgba(3, 144, 238, 0.75);
  color: var(--white);
  font-size: 20px;
  line-height: 1.45;
  font-weight: 700;
  word-break: keep-all;
}

/* 사실 재진술 — 룰 없이 질문의 글머리(16px 패딩 + 2px 룰 = 18px)에 맞춰 정렬해
   두 줄이 한 들여쓰기 축을 공유하게 한다. 지반 #05070d 위 4.5:1 이상(실측 5.31:1) */
.wp-a {
  margin: 0;
  padding: 0 0 0 18px;
  color: var(--text-d-3);
  font-size: 15px;
  line-height: 1.65;
  word-break: keep-all;
}

@media (max-width: 900px) {
  .why-pains {
    grid-template-columns: 1fr;
  }
}

.why-stage > .section-heading {
  max-width: var(--max);
}

/* About 챕터 진입 라벨 — 다른 섹션보다 한 단계 크게(클라이언트 요청) */
.why-section .eyebrow {
  font-size: clamp(15px, 1.6vw, 18px);
  letter-spacing: 0.1em;
}

/* 다크 배경 — 헤딩 화이트(라인마스크는 .h-line 공통 규칙이 자동 적용) */
.why-section .section-heading h2 {
  max-width: 940px;
  color: var(--white);
}

/* 변화의 축 3개 — 세로 목록 v2를 "구획"으로 재편.
   한 축 = [상단 액센트 룰 → 넘버 인덱스 → 문장]. 소개서 프로세스 박스(.pm-step)의
   "상단 룰 + 번호 + 제목" 문법을 그대로 다크로 옮긴 것이라 새 언어가 아니다.
   ≥760px에서 3열로 펴지면 세 축이 병렬로 읽히고, 끊긴 상단 룰 3개가 한 줄의 편집 룰이 된다.
   마크업은 손대지 않았다 — 비어 있던 <i class="why-tick">를 넘버 슬롯으로 되살려 쓴다 */
.why-log {
  counter-reset: whyidx;
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: clamp(24px, 3.2vw, 34px);
  font-size: clamp(21px, 2.6vw, 26px);
}

.why-line {
  position: relative;
  counter-increment: whyidx;
  padding-top: clamp(16px, 1.8vw, 22px);
  color: var(--text-d-1);
  font-size: inherit;
  line-height: 1.34;
  font-weight: 700;
  letter-spacing: -0.01em;
  word-break: keep-all;
}

/* 축 상단 룰 — 좌측 시안 캡 + 헤어라인. .pm-step의 border-top 2px 라인을 다크 팔레트로 옮겼다 */
.why-line::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: linear-gradient(
    90deg,
    var(--cyan) 0 clamp(44px, 5.5vw, 78px),
    rgba(255, 255, 255, 0.18) clamp(44px, 5.5vw, 78px)
  );
}

/* 축 인덱스 — decimal-leading-zero 표기는 유지하되 고스트 아웃라인을 걷고
   단색 시안 넘버 배지로 세운다(룰 바로 아래에서 구획의 머리 역할) */
.why-tick {
  display: block;
  margin-bottom: clamp(10px, 1.2vw, 16px);
  color: var(--cyan);
  /* <i>의 기본 이탤릭 해제 — 넘버는 반드시 정체 */
  font-style: normal;
  /* 인덱스는 항상 문장보다 한 단계 작게 — 배지가 본문을 이기지 않도록 전 뷰포트에서 고정 */
  font-size: clamp(19px, 2.35vw, 24px);
  line-height: 1;
  font-weight: 900;
  letter-spacing: 0;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

.why-tick::before {
  content: counter(whyidx, decimal-leading-zero);
}

/* 주어 앵커 — 그라디언트 텍스트(술어는 뮤트 유지). 상단 룰이 액센트를 이미 들고 있어
   언더라인은 글로우를 걷고 한 단계 눌렀다(정의 플레이트가 클라이맥스를 갖도록) */
.why-subj {
  position: relative;
  font-weight: 900;
  letter-spacing: -0.015em;
  background: linear-gradient(90deg, var(--cyan), var(--blue));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.why-subj::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -0.1em;
  height: 1.5px;
  background: rgba(3, 144, 238, 0.55);
}

/* 정의 플레이트 — 섹션의 클라이맥스.
   지금까지 맨 텍스트로 흘렀던 "AQ = Adaptability Quotient" 정의를
   사이트 카드 문법(상단 2px --card-line + --grad-accent-surface + --e-dark-1)으로 세워
   위 구획(축 3개)과 층을 분리한다. 블록 자체는 --max 풀폭 유지 */
.why-define {
  position: relative;
  margin-top: clamp(40px, 5.4vw, 72px);
  padding: clamp(28px, 3.4vw, 46px) clamp(22px, 3vw, 44px);
  border: 1px solid var(--border-1);
  border-radius: var(--r-lg);
  background:
    var(--grad-accent-surface),
    var(--surface-1);
  box-shadow: var(--e-dark-1);
  overflow: hidden;
}

.why-define::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: var(--card-line);
  opacity: 0.7;
}

.why-def {
  position: relative;
  z-index: 1;
  margin: 0;
  max-width: 900px;
  font-size: clamp(25px, 3.4vw, 44px);
  line-height: 1.24;
  font-weight: 900;
  letter-spacing: -0.012em;
  color: var(--white);
  word-break: keep-all;
}

/* 리드의 앞 절은 뮤트, 뒤 절은 최고 강조 — 읽는 순서를 만드는 대비.
   마크업을 건드리지 않고 <br/> 기준 첫 줄("AQNET의 AQ는")만 눌렀다 */
.why-def::first-line {
  color: var(--text-d-2);
}

/* 정의어 밑줄 — 그라디언트 텍스트 위 액센트 언더라인.
   의사요소가 아니라 text-decoration이라 줄바꿈이 생겨도 따라 끊긴다 */
.why-def .grad {
  text-decoration: underline;
  text-decoration-color: rgba(3, 144, 238, 0.7);
  text-decoration-thickness: 2px;
  text-underline-offset: 0.14em;
}

/* 클로징 약속 — 플레이트 안에서 정의와 헤어라인 하나로 갈린다 */
.why-promise {
  position: relative;
  z-index: 1;
  margin: clamp(22px, 2.8vw, 32px) 0 0;
  max-width: 820px;
  padding-top: clamp(20px, 2.4vw, 28px);
  color: var(--text-d-2);
  font-size: clamp(17px, 1.9vw, 23px);
  line-height: 1.65;
  font-weight: 600;
  word-break: keep-all;
}

/* 정의 ↔ 약속 구분 — 사이트 시그니처 헤어라인(--grad-line, SEAM과 같은 값) */
.why-promise::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 1px;
  background: var(--grad-line);
}

/* 축 3개를 병렬로 — 태블릿부터 3열. 세 개의 상단 룰이 한 줄로 끊겨 읽힌다 */
@media (min-width: 760px) {
  .why-log {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    align-items: start;
    gap: var(--gap-3);
  }
}

/* =========================================================
   WHY AQNET — 데스크탑 리디자인 (첫 버전 레이아웃 유지)
   배치는 v1 세로 스택(헤딩 → 레일 로그 → 정의) 그대로.
   시각 보강만 추가: 히어로 계열 텍스처·경계, 우측 궤도 워터마크 데코(의사요소).
   등장 연출은 없앴고(REVEAL / MOTION 참고) 정적 상태로만 렌더된다.
   모바일 ≤1024px는 기본형 그대로.
   ========================================================= */
@media (min-width: 1025px) {
  /* 섹션 연속성 — 78px 그리드 텍스처 + 하단 헤어라인(검증된 처리 유지)
     ※ 생성 이미지 앰비언트는 여기 금지 — 본문·시안 액센트가 전폭에 깔려 있어
     배경 발광이 조금만 얹혀도 AA(시안 5.1:1, 여유 0)가 깨진다(2026-08-26 실측 탈락) */
  .why-section {
    background-image:
      var(--mesh-cyan),
      var(--mesh-blue),
      linear-gradient(rgba(255, 255, 255, 0.03) 1px, transparent 1px),
      linear-gradient(90deg, rgba(255, 255, 255, 0.03) 1px, transparent 1px);
    background-size: auto, auto, 78px 78px, 78px 78px;
    border-bottom: 1px solid var(--border-1);
  }

  /* 변화의 축 — 3열 구조는 760px 블록이 이미 세웠고 여기서는 크기만 한 단계 키운다.
     같은 vw 기울기를 base에도 써서 1024→1025 경계에서 자연 연속(점프 없음) */
  .why-log {
    gap: var(--gap-4);
    font-size: clamp(26px, 2.6vw, 31px);
  }

  .why-section .why-line {
    padding-top: clamp(18px, 1.8vw, 26px);
  }

  .why-tick {
    font-size: clamp(24px, 2.3vw, 29px);
  }

  /* 정의 플레이트 — 로그 축소분만큼 클라이맥스 진입 여백을 늘려 위계 계단 강화(데스크탑 한정) */
  .why-define {
    margin-top: clamp(48px, 6vw, 84px);
  }
}

/* =========================================================
   ABOUT
   ========================================================= */
.about-section {
  width: 100%;
  max-width: none;
  background-color: var(--surface-l0);
  /* 라이트 섹션 공통 텍스처 — 상단에서만 도트가 보이고 아래로 갈수록 서피스가 덮으며 사라진다 */
  background-image:
    linear-gradient(180deg, rgba(255, 255, 255, 0), var(--surface-l0) 520px),
    var(--dot-light);
  background-size:
    auto,
    var(--dot-light-size);
}

.about-section > .section-heading,
.about-section > .about-grid {
  width: min(100%, var(--max));
  margin-left: auto;
  margin-right: auto;
}

/* 진단/실행/자동화/학습 4스텝(.timeline) 삭제로 1열 — 스테이트먼트 패널 하나만 남는다 */
.about-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--gap-3);
  align-items: stretch;
}

.about-statement {
  position: relative;
  padding: clamp(28px, 4vw, 46px);
  border-radius: var(--r-lg);
  background:
    var(--grad-accent-surface),
    var(--ink-2);
  color: var(--white);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  overflow: hidden;
  box-shadow: var(--e-dark-1);
}

/* 상단 카드 라인 — 형제 노드(.af-out)·다크 지표 카드와 같은 2px 문법.
   ::before는 도트 텍스처가 점유 중이라 ::after를 쓴다 */
.about-statement::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: var(--card-line);
  opacity: 0.8;
}

.about-statement::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image: radial-gradient(rgba(255, 255, 255, 0.06) 1.1px, transparent 1.1px);
  background-size: 22px 22px;
  mask-image: linear-gradient(135deg, #000, transparent 70%);
  opacity: 0.5;
}

.statement-body {
  position: relative;
  z-index: 1;
}

.why-label {
  display: inline-flex;
  align-items: center;
  gap: var(--gap-2);
  margin: 0 0 18px;
  color: var(--cyan);
  font-size: 12px;
  font-weight: 800;
  letter-spacing: var(--t-label-ls);
  text-transform: uppercase;
}

.why-label::after {
  content: "";
  width: 22px;
  height: 2px;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--cyan), transparent);
}

/* 운영 요약 리드 — 무엇을 연결하는지(카드 상단 본문) */
.statement-sub {
  margin: 0;
  font-size: clamp(16px, 1.62vw, 17px);
  line-height: 1.7;
  font-weight: 600;
  color: var(--text-d-2);
  word-break: keep-all;
}

/* 클로징 선언 — 패널의 착지점(포지셔닝 선언).
   16px + 좌측 2px 바 조합이던 이전 처리는 리드(19px)보다 작아 섹션에서 가장 중요한
   문장이 '각주 인용'으로 읽혔다. 리드를 한 단계 양보시키고 이 문장을 패널에서 가장
   크고 굵은 흰 텍스트로 올려 위계를 제자리로 돌린다 */
.statement-close {
  position: relative;
  margin: clamp(22px, 2.2vw, 30px) 0 0;
  padding-top: clamp(20px, 2vw, 26px);
  border-top: 1px solid var(--border-2);
  color: var(--white);
  font-size: clamp(19px, 1.4vw, 20px);
  line-height: 1.5;
  font-weight: 800;
  word-break: keep-all;
}

/* 결론 표식 — 구분선 위에 .why-label::after와 같은 시안 그라디언트 마크를 얹어
   이 줄이 리드의 연장이 아니라 패널의 결론임을 표시한다(좌측 인용 바의 대체) */
.statement-close::before {
  content: "";
  position: absolute;
  top: -1px;
  left: 0;
  width: 46px;
  height: 2px;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--cyan), transparent);
}

/* 포뮬러 — 클로징 선언을 세 축의 곱으로 한 번 더 압축하는 서명 줄.
   선언(19~20px/800 화이트)과 경쟁하지 않도록 크기를 절반 가까이 내리고 자간만 벌려
   "문장"이 아니라 "표기"로 읽히게 한다. × 기호를 살려야 하므로 text-transform은 두지 않는다
   (uppercase는 ×에 영향이 없지만, 이 줄은 이미 대문자 고유명사라 규칙 자체를 두지 않는다).
   대비: --cyan on --ink-2 5.62 / 패널 상단 azure 0.16 그라디언트 구간에서도 4.63 (AA 통과).
   실제로는 클로징 아래(패널 높이 54% 지점 아래 = 그라디언트가 이미 투명)에 놓인다 */
.statement-formula {
  margin: 12px 0 0;
  color: var(--cyan);
  font-size: 13px;
  line-height: 1.5;
  font-weight: 700;
  /* × 앞뒤 리듬 — 자간만으로는 곱셈 기호가 단어에 붙어 읽히므로 word-spacing을 함께 준다 */
  letter-spacing: var(--t-label-ls);
  word-spacing: 0.14em;
  word-break: keep-all;
  /* 좁은 폭에서 두 줄이 될 때 자연 줄바꿈은 "… × Growth / Operating System"으로 접혀
     셋째 항이 두 동강 난다. balance는 두 줄 길이를 맞추면서 "… × / Growth Operating System"
     으로 끊어 세 항의 경계를 지킨다(미지원 브라우저는 자연 줄바꿈으로 폴백) */
  text-wrap: balance;
}

/* 공용 RESPONSIVE(720 이하)가 이 문단을 15px/좌패딩 12px로 되돌리므로, 좁은 뷰에서도
   클로징이 리드보다 크게 남는 하한만 패널 스코프로 고정한다. 좌측 바를 걷어낸 지금
   좌패딩은 리드와의 좌측 정렬을 깨뜨리기만 하므로 함께 0으로 */
@media (max-width: 720px) {
  .about-statement .statement-close {
    padding-left: 0;
    font-size: 17.5px;
  }

  /* 720px 패널 안에서는 한 줄, 375px에서는 두 줄이 된다(한 줄에 필요한 폭 351px > 283px).
     11px까지 내리면 한 줄에 앉지만 서명 줄이 각주 크기가 되므로 두 줄을 택하고,
     대신 자간만 좁혀 두 줄의 길이를 맞춘다 — 끊기는 위치는 위 text-wrap: balance가 잡는다 */
  .about-statement .statement-formula {
    font-size: 12.5px;
    letter-spacing: 0.05em;
    word-spacing: 0.1em;
  }
}

/* 주장(메인+서브) ↔ 근거(역량 태그) 위계 — 가로줄 대체 */
.proof {
  position: relative;
  z-index: 1;
  margin-top: 28px;
}

.proof-label {
  display: inline-flex;
  align-items: center;
  gap: var(--gap-2);
  margin: 0 0 16px;
  color: var(--text-d-2);
  font-size: 12px;
  font-weight: 800;
  letter-spacing: var(--t-label-ls);
  text-transform: uppercase;
}

.proof-label::before {
  content: "";
  width: 18px;
  height: 2px;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--cyan), transparent);
}

/* 알약 나열 → 2열 구획 셀. 아이콘 슬롯이 생겨 네 역량이 한눈에 스캔된다 */
.proof-points {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--gap-1);
}

/* 네 역량이 "면 채우는 잔 항목"으로 읽히던 것을 카드 문법(상단 2px 라인 + 리프트 호버)까지
   갖춘 구획 셀로 올린다 — 아래 운영 도식과 같은 밀도를 갖게 하는 것이 목적 */
.proof-points li {
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: center;
  gap: var(--gap-1);
  min-height: 74px;
  padding: 0 16px;
  border-radius: var(--r-sm);
  border: 1px solid var(--border-2);
  background: rgba(255, 255, 255, 0.05);
  color: var(--white);
  font-size: 14.5px;
  line-height: 1.3;
  font-weight: 800;
  word-break: keep-all;
  transition:
    translate var(--dur) var(--ease-out),
    border-color var(--dur) ease,
    box-shadow var(--dur) ease;
}

/* 상단 액센트 라인 — .fw-card와 같은 카드 언어(상시 노출, hover에서 선명해짐) */
.proof-points li::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: var(--card-line);
  opacity: 0.45;
  transition: opacity var(--dur) ease;
}

.proof-points li:hover {
  translate: 0 var(--card-lift);
  border-color: var(--border-3);
  box-shadow: var(--e-dark-1);
}

.proof-points li:hover::before {
  opacity: 1;
}

.proof-ic {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border-radius: var(--r-xs);
  border: 1px solid rgba(3, 144, 238, 0.3);
  background: rgba(3, 144, 238, 0.14);
  color: var(--cyan);
}

.proof-ic svg {
  width: 19px;
  height: 19px;
}

/* ---------------------------------------------------------
   운영 도식 — "네 신호 → 하나의 기준 → 통합 매출 구조"
   삭제한 4스텝 타임라인 자리를, 헤딩과 위 서술문을 그대로 옮긴 흐름도로 채운다.
   과한 연출 대신 사이트에 이미 있는 문법만 재사용한다:
   · 노드 카드 = .mp-card / .pm-step의 라이트 카드
   · 셰브런 = FRAMEWORK .fw-flow의 45° 회전 보더
   · 종착 다크 카드 = 위 .about-statement와 같은 잉크 면
   등장 연출 없이 처음부터 최종 상태로 렌더된다(REVEAL / MOTION 참고)
   --------------------------------------------------------- */
.about-flow {
  position: relative;
  display: flex;
  align-items: stretch;
  gap: var(--gap-2);
  padding: clamp(24px, 2.8vw, 34px);
  border: 1px solid var(--border-l2);
  /* 도식이 흰 섹션 위에서 "빈 면"으로 흩어지지 않도록 상단 2px 라인으로 블록을 선언한다
     (.pm-step 라이트 카드 문법). 위 스테이트먼트 패널과 같은 무게로 읽히는 것이 목적 */
  border-top: 2px solid var(--blue);
  border-radius: var(--r-lg);
  /* 서피스를 l1 → l2로 한 단계 내려 흰 노드가 바닥에서 떠오르게 한다 */
  background:
    radial-gradient(560px 240px at 50% 0%, rgba(15, 99, 234, 0.05), transparent 72%),
    var(--surface-l2);
  box-shadow: var(--e-2);
}

/* 위 패널 → 도식 연결 셰브런 — .about-grid의 gap 한가운데.
   두 블록이 별개의 슬래브가 아니라 한 흐름이라는 표시 */
.about-flow::before {
  content: "";
  position: absolute;
  top: -24px;
  left: calc(50% - 6px);
  width: 12px;
  height: 12px;
  border-top: 2px solid rgba(15, 99, 234, 0.5);
  border-right: 2px solid rgba(15, 99, 234, 0.5);
  transform: rotate(135deg);
  pointer-events: none;
}

/* 좌: 함께 읽는 네 신호(2×2) */
.af-signals {
  flex: 1 1 48%;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--gap-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

/* 입력 신호 4개 — 상단 액센트는 옅게. 아래 hub(강) · out(시그니처)로 갈수록 세져
   "신호 → 기준 → 결과"가 강도의 계단으로도 읽힌다 */
.af-node {
  display: flex;
  align-items: center;
  gap: var(--gap-2);
  /* 위 역량 셀(.proof-points li)과 같은 모듈 높이 — 두 블록이 같은 격자로 읽힌다 */
  min-height: 74px;
  padding: 0 18px;
  border: 1px solid var(--border-l2);
  border-top: 2px solid rgba(15, 99, 234, 0.34);
  border-radius: var(--r-sm);
  background: var(--surface-l0);
  color: var(--text-l-1);
  font-size: 16px;
  line-height: 1.3;
  font-weight: 800;
  word-break: keep-all;
  box-shadow: var(--e-1);
  transition:
    translate var(--dur) var(--ease-out),
    border-color var(--dur) ease,
    box-shadow var(--dur) ease;
}

.af-node:hover {
  translate: 0 var(--card-lift);
  border-color: var(--border-l3);
  border-top-color: var(--blue);
  box-shadow: var(--e-2);
}

/* 라이트 면 위 액센트는 --blue 계열 — 시안(#0390ee)은 흰 배경에서 3.37:1이라 --blue로 내린다 */
.af-ic {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border-radius: var(--r-xs);
  border: 1px solid rgba(15, 99, 234, 0.2);
  background: rgba(15, 99, 234, 0.08);
  color: var(--blue);
}

.af-ic svg {
  width: 19px;
  height: 19px;
}

/* 진행 셰브런 — .fw-flow와 같은 각도. 도식 안에서 눈에 걸리도록 한 단계 키웠다 */
.af-chev {
  flex: 0 0 auto;
  align-self: center;
  width: 13px;
  height: 13px;
  border-top: 2px solid rgba(15, 99, 234, 0.62);
  border-right: 2px solid rgba(15, 99, 234, 0.62);
  transform: rotate(45deg);
}

/* 중: 네 신호가 모이는 단일 기준 — 도식에서 가장 강한 액센트 면.
   외곽 링 하나로 "모이는 지점"임을 표시한다 */
/* 허브·아웃 노드 — 신호 4개만 아이콘을 갖고 정작 결론 두 노드가 맨 텍스트라
   비대칭이라는 피드백. 같은 .af-ic 언어로 아이콘을 세로 스택(아이콘 위, 라벨 아래) */
.af-hub {
  position: relative;
  overflow: hidden;
  flex: 1 1 26%;
  display: grid;
  place-content: center;
  justify-items: center;
  row-gap: var(--gap-2);
  margin: 0;
  padding: 18px 16px;
  border: 1.5px solid rgba(15, 99, 234, 0.5);
  border-radius: var(--r-sm);
  background: rgba(15, 99, 234, 0.08);
  box-shadow: 0 0 0 5px rgba(15, 99, 234, 0.05);
  color: var(--text-l-1);
  font-size: clamp(17px, 1.8vw, 21px);
  line-height: 1.3;
  font-weight: 900;
  text-align: center;
  word-break: keep-all;
}

/* 우: 종착점 — 위 스테이트먼트 패널과 같은 잉크 면으로 결과를 못박는다.
   상단 2px 카드 라인까지 물려 도식 안에서 유일하게 다크로 끊는다 */
.af-out {
  position: relative;
  overflow: hidden;
  flex: 1 1 26%;
  display: grid;
  place-content: center;
  justify-items: center;
  row-gap: var(--gap-2);
  margin: 0;
  padding: 18px 16px;
  border-radius: var(--r-sm);
  background:
    var(--grad-accent-surface),
    var(--ink-2);
  color: var(--white);
  font-size: clamp(17px, 1.8vw, 21px);
  line-height: 1.3;
  font-weight: 900;
  text-align: center;
  word-break: keep-all;
  box-shadow: var(--e-dark-1);
}

/* 아웃 노드는 다크 잉크 면이라 라이트용 칩 토큰이 묻힌다 — 흰 저알파 면 + 시안 글리프(5.62:1) */
.af-out .af-ic {
  border-color: rgba(255, 255, 255, 0.22);
  background: rgba(255, 255, 255, 0.08);
  color: var(--cyan);
}

.af-hub .af-ic {
  box-shadow: 0 0 0 4px rgba(15, 99, 234, 0.06);
}

/* 형제 .af-out과 같은 상단 2px — 허브만 맨 면이라 비대칭이었다 */
.af-hub::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: var(--card-line);
  opacity: 0.8;
}

.af-out::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: var(--card-line);
  opacity: 0.8;
}

/* 4스텝이 빠져 패널이 폭 전체를 쓰게 되었으므로, 데스크탑에서는 한 줄이 지나치게
   길어지지 않도록 주장(좌) · 근거(우) 2열로 나눈다. 태블릿 이하는 기존 세로 스택 유지 */
@media (min-width: 1025px) {
  /* flex-start였을 때 주장 열이 위로 붙어 좌측 하단에 역량 2x2와의 높이차(약 51px)가
     통째로 공백으로 남았다. center로 두면 그 차이가 위아래로 반씩 나뉜다 */
  .about-statement {
    flex-direction: row;
    align-items: center;
    gap: var(--gap-4);
  }

  .statement-body {
    flex: 1 1 58%;
  }

  /* 역량 셀이 커진 만큼 우측 컬럼도 함께 넓힌다(라벨이 두 줄로 접히는 빈도를 줄임) */
  .proof {
    flex: 1 1 42%;
    margin-top: 0;
  }
}

/* 도식 반응형 — 가로 흐름이 좁아지면 세로 스택으로 접고 셰브런만 아래로 돌린다 */
@media (max-width: 1024px) {
  .about-flow {
    flex-direction: column;
  }

  .af-chev {
    transform: rotate(135deg);
  }
}

@media (max-width: 560px) {
  .af-signals {
    grid-template-columns: minmax(0, 1fr);
  }

  .proof-points {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* =========================================================
   AQ FRAMEWORK (C·O·R·E)
   ========================================================= */
.framework-section {
  /* 카드 그리드의 gap을 섹션 토큰으로 둔다 — 셰브런 오버레이와 결론 플레이트가
     같은 간격 문법을 공유해야 결론부가 그리드의 '다음 행'으로 읽힌다 */
  --fw-gap: var(--gap-2);
  width: 100%;
  max-width: none;
  background: var(--surface-0);
  background-image: var(--mesh-cyan), var(--mesh-blue);
  color: var(--white);
}

.framework-section > .section-heading,
.framework-grid {
  width: min(100%, var(--max));
  margin-left: auto;
  margin-right: auto;
}

.framework-section > .section-heading {
  max-width: var(--max);
}

.framework-section .section-heading h2 {
  max-width: 920px;
  color: var(--white);
}

/* 인트로 2문장이 두 덩어리로 끊겨 보이지 않도록 줄폭 확대(760→900) */
.framework-section .section-heading p:not(.eyebrow) {
  max-width: 900px;
  color: var(--text-d-2);
}

.framework-grid {
  /* 셰브런 오버레이가 카드와 동일한 트랙·gap(--fw-gap, 섹션 토큰)을 재사용한다 */
  --fw-chev: 7px;
  position: relative;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--fw-gap);
}

.fw-card {
  position: relative;
  min-height: 216px;
  padding: 26px 26px 24px;
  border: 1px solid var(--border-2);
  border-radius: var(--r-md);
  background: var(--surface-2);
  box-shadow: var(--e-dark-1);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  transition:
    translate var(--dur) var(--ease-out),
    border-color var(--dur) ease,
    box-shadow var(--dur) ease;
}

.fw-card:hover {
  translate: 0 var(--card-lift);
  border-color: var(--border-3);
  box-shadow: var(--e-dark-2);
}

/* 카드 상단 2px 블루 라인 — 소개서 카드 언어(상시 노출, hover에서 선명해짐).
   카드가 overflow:hidden이라 radius로 자동 클리핑됨 */
.fw-card::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: var(--card-line);
  opacity: 0.55;
  transition: opacity var(--dur) ease;
}

.fw-card:hover::before {
  opacity: 1;
}

.fw-initial {
  position: absolute;
  top: 2px;
  right: 16px;
  font-size: 92px;
  line-height: 1;
  font-weight: 900;
  background: var(--grad-brand);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  opacity: 0.2;
  pointer-events: none;
  transition: opacity var(--dur) ease;
}

.fw-card:hover .fw-initial {
  opacity: 0.42;
}

.fw-card h3 {
  margin: 0;
  color: var(--white);
  font-size: var(--t-sub-1);
  line-height: var(--t-sub-1-lh);
  font-weight: 800;
}

.fw-card > p {
  margin: 10px 0 0;
  color: var(--ice);
  font-size: 16px;
  line-height: 1.6;
  font-weight: 600;
  word-break: keep-all;
}

.fw-tags {
  list-style: none;
  margin: auto 0 0;
  padding: 18px 0 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--gap-1);
}

.fw-tags li {
  padding: 4px 10px;
  border: 1px solid var(--border-1);
  border-radius: var(--r-pill);
  background: rgba(255, 255, 255, 0.04);
  color: var(--text-d-3);
  font-size: 12.5px;
  font-weight: 700;
}

/* --- 진행 셰브런 오버레이 — 카드 그리드와 같은 트랙을 깔고 gap 중앙에 화살촉 배치.
   그리드의 절대 배치 자식은 셀을 점유하지 않으므로 4장 레이아웃에 영향 없음 --- */
.fw-flow {
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  grid-template-rows: 1fr;
  gap: var(--fw-gap);
  pointer-events: none;
}

/* 셰브런 3개가 1~3열에 자동 배치 → 각 열 오른쪽 끝에서 gap 중앙으로 밀어냄.
   화살촉 형태는 .mp-rail::after(여정 레일)와 동일한 border 기법 */
.fw-flow i {
  align-self: center;
  justify-self: end;
  width: var(--fw-chev);
  height: var(--fw-chev);
  margin-right: calc(-1 * (var(--fw-gap) / 2 + var(--fw-chev) / 2));
  border-top: 1.5px solid rgba(3, 144, 238, 0.62);
  border-right: 1.5px solid rgba(3, 144, 238, 0.62);
  transform: rotate(45deg);
}

/* --- 학습 순환 되돌림 라인 — E(4번)에서 C(1번)로 돌아가는 헤어라인.
   좌우 반쪽 라인 사이에 캡션을 끼워 넣어, 배경 위에 칩을 덧대지 않고도 선이 끊긴다 --- */
.fw-outro {
  width: min(100%, var(--max));
  margin: 0 auto;
}

.fw-cycle {
  --fw-cycle-h: 38px;
  --fw-line: rgba(3, 144, 238, 0.4);
  /* 카드 하단과 브래킷 사이 숨구멍 — 도착 화살촉이 카드 밑변에 박히지 않고
     소개서 p12처럼 카드 아래에서 올려다보는 형태가 된다 */
  margin-top: 12px;
  display: flex;
  align-items: flex-end;
  gap: var(--gap-2);
}

.fw-cycle-line {
  position: relative;
  flex: 1 1 auto;
  height: var(--fw-cycle-h);
  border-bottom: 1px solid var(--fw-line);
}

/* 양끝 세로 스텁 — 카드 하단에서 되돌림 라인까지 내려오는 구간 */
.fw-cycle-line.is-left {
  border-left: 1px solid var(--fw-line);
  border-bottom-left-radius: 12px;
}

.fw-cycle-line.is-right {
  border-right: 1px solid var(--fw-line);
  border-bottom-right-radius: 12px;
}

/* 도착 화살촉 — 스텁 '위쪽 끝'에서 C(Control) 카드로 다시 올라간다.
   소개서 p12가 되돌림 경로를 카드로 재진입시키는 방식 그대로이며,
   위치·기법 모두 06 .pm-loop::before와 같아 두 섹션의 순환 문법이 일치한다.
   크기는 C→O→R→E 진행 셰브런(--fw-chev: 7px)과 맞춰 같은 흐름의 기호로 읽히게 했다 */
.fw-cycle-line.is-left::after {
  content: "";
  position: absolute;
  left: -3px;
  top: -3px;
  width: 7px;
  height: 7px;
  border-top: 1.5px solid rgba(3, 144, 238, 0.62);
  border-left: 1.5px solid rgba(3, 144, 238, 0.62);
  transform: rotate(45deg);
}

/* 출발 기점 — 흐름이 E(Endurance)에서 빠져나가는 지점.
   화살촉(도착)과 점(출발)이 짝을 이뤄야 브래킷이 '한 번 되돌아감'이 아니라
   방향을 가진 순환으로 읽힌다(06 .pm-loop::after와 동일 규칙) */
.fw-cycle-line.is-right::after {
  content: "";
  position: absolute;
  right: -3px;
  top: -3px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: rgba(3, 144, 238, 0.62);
}

/* 라인 사이 캡션 — flex-end 정렬이라 padding-bottom이 라인 위 여백이 된다 */
.fw-cycle-cap {
  flex: 0 0 auto;
  margin: 0;
  padding-bottom: 3px;
  color: var(--text-d-2);
  font-size: 13.5px;
  line-height: 1;
  font-weight: 700;
  letter-spacing: 0.02em;
  white-space: nowrap;
}

/* 순환 기호 — 브래킷이 '반복해서 돈다'로 읽히게.
   06 .pm-loop-cap::before와 같은 글리프·같은 alt 처리(빈 문자열이라 낭독에 끼어들지 않음)로
   두 섹션의 루프 캡션 형식을 맞춘다 */
.fw-cycle-cap::before {
  content: "↻" / "";
  margin-right: 7px;
  color: var(--cyan);
  font-size: 13.5px;
  font-weight: 800;
}

/* --- 마무리 문장 — 되돌림 브래킷 아래 결론 플레이트.
   앞선 두 번은 이 자리를 '밴드'로 보고 선과 워시를 더 세게 가져갔지만, 어긋난 것은
   강도가 아니라 재질이었다. 카드는 그림자를 가진 불투명한 물체인데 결론부만
   빛나는 투명한 면이라, 카드 그룹이 아니라 섹션 프레임(SEAM) 계열로 읽혔다.
   그래서 더하지 않고 뺀다 — 면·보더·라디우스·그림자를 .fw-card와 똑같이 주고
   radial 워시와 하단 헤어라인은 걷어낸다. 위 간격까지 --fw-gap으로 맞추면
   결론부가 별도 층이 아니라 그리드의 '다섯 번째 플레이트'로 읽힌다 --- */
.fw-closing {
  position: relative;
  /* 간격 문법까지 그리드와 동일 — 카드 사이 gap과 같은 값이라 C·O·R·E 네 장 다음 행으로 앉는다 */
  margin-top: var(--fw-gap);
  /* 상자를 걷어낸 열린 마무리 — 면·보더·그림자 없이 타이포와 상단 라인만 남긴다.
     C·O·R·E 네 장이 이미 상자이므로, 결론까지 상자로 두면 다섯 번째 카드가 되어
     "끝맺음"이 아니라 "항목 하나 더"로 읽힌다 */
  padding: 30px 26px 4px;
  text-align: center;
}

/* 상단 마크 — 전폭 2px 라인은 카드 상단 라인과 짝이 되는 문법이었는데,
   상자를 걷어내자 기댈 면이 없어 허공에 뜬 막대로 보였다. 폭을 40px로 줄여
   중앙에 놓으면 상자 없이도 결론의 시작점을 찍는 마크로 읽힌다 */
.fw-closing::before {
  content: "";
  position: absolute;
  top: 0;
  left: 50%;
  width: 40px;
  height: 2px;
  translate: -50% 0;
  background: var(--card-line);
  opacity: 0.75;
}

.fw-closing-lead {
  margin: 0;
  color: var(--white);
  font-size: 24px;
  line-height: 1.3;
  font-weight: 900;
  letter-spacing: -0.02em;
}

/* 순서 교체 — 짧은 선언(sub)이 위, 결론(lead)이 아래로 내려와
   "한 번의 성과에서 → AQ의 철학은 이어집니다"가 설정에서 결론으로 읽힌다.
   위아래가 바뀌었으니 간격도 아래쪽으로 옮긴다 */
.fw-closing-sub {
  margin: 0 0 10px;
  color: var(--text-d-2);
  font-size: 16px;
  line-height: 1.6;
  font-weight: 600;
  word-break: keep-all;
}

/* 액센트 — 슬랩(면) + 언더라인(선) + 시안(색)의 3중 강조는 플레이트 안에서 과밀했다.
   면을 걷어내고 선 하나로 감량한다. 2px는 카드 상단 라인과 같은 강조 규격이고,
   시안 텍스트는 --surface-2 위에서 5.3:1로 AA를 통과한다 */
.fw-closing-sub strong {
  padding-bottom: 5px;
  border-bottom: 2px solid rgba(3, 144, 238, 0.62);
  color: var(--cyan);
  font-weight: 800;
}

/* =========================================================
   SERVICE
   ========================================================= */
.service-section {
  width: 100%;
  max-width: none;
  background-color: var(--surface-l1);
  /* 상단에서만 은은한 도트 텍스처 — 아래 페이드 레이어가 도트를 서서히 덮음.
     도트 자체는 라이트 섹션 공통 토큰으로 통일(About·Client·Insight와 같은 결) */
  background-image:
    linear-gradient(180deg, rgba(248, 251, 255, 0), var(--surface-l1) 560px),
    var(--dot-light);
  background-size:
    auto,
    var(--dot-light-size);
}

.service-section > .section-heading,
.service-grid {
  width: min(100%, var(--max));
  margin-left: auto;
  margin-right: auto;
}

.service-section > .section-heading,
.works-section > .section-heading,
.reference-section > .section-heading,
.about-section > .section-heading,
.solution-section > .section-heading,
.insight-section > .section-heading {
  max-width: var(--max);
}

.service-section > .section-heading h2,
.works-section > .section-heading h2,
.reference-section > .section-heading h2,
.solution-section > .section-heading h2,
.insight-section > .section-heading h2 {
  max-width: 920px;
}

/* ABOUT만 예외 — 클라이언트 확정 2줄 구조(…미디어 / 운영을…연결합니다)에서
   둘째 줄이 920px를 넘어 3줄로 접히므로 헤딩 폭만 넓혀 2줄을 유지한다 */
.about-section > .section-heading h2 {
  max-width: 1080px;
}

.service-section > .section-heading p:not(.eyebrow),
.works-section > .section-heading p:not(.eyebrow),
.reference-section > .section-heading p:not(.eyebrow),
.about-section > .section-heading p:not(.eyebrow),
.solution-section > .section-heading p:not(.eyebrow),
.insight-section > .section-heading p:not(.eyebrow) {
  max-width: 760px;
}

/* 12만 예외 — 둘째 문장이 24px 모자라 3줄이 됐다. 09와 같은 폭으로 맞춰 두 줄로 떨어뜨린다 */
.reference-section > .section-heading p:not(.eyebrow) {
  max-width: 830px;
}

.service-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--gap-2);
}

.service-card {
  position: relative;
  min-height: 340px;
  padding: 28px;
  border: 1px solid var(--border-l2);
  border-radius: var(--r-md);
  background: var(--surface-l0);
  box-shadow: var(--e-1);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  transition:
    translate var(--dur) var(--ease-out),
    border-color var(--dur) ease,
    box-shadow var(--dur) ease;
}

/* 상단 2px 라인 — hover 연출이 아니라 3장 공통 상시 표기(소개서 카드 문법).
   선두 영역(01)의 위계는 라인이 아니라 틴트·보더·그림자로만 구분한다 */
.service-card::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: var(--card-line);
}

/* 헤더 구분선 — 아이콘·인덱스가 놓인 상단 밴드를 본문에서 끊는다.
   카드가 "헤더(아이콘·인덱스) / 정체성(제목·정의·설명·실행) / 키워드"의 3존으로 읽혀야
   스캔 순서가 생긴다. ::before는 상단 2px 라인이 점유하므로 이 선은 ::after로 그린다.
   top = 카드 패딩 28 + 아이콘 46 + 여백 16 (아이콘 높이가 고정이라 폭과 무관하게 맞는다) */
.service-card::after {
  content: "";
  position: absolute;
  top: 90px;
  left: 28px;
  right: 28px;
  height: 1px;
  background: var(--border-l1);
  transition: background var(--dur) ease;
}

.service-card:hover {
  translate: 0 var(--card-lift);
  border-color: var(--border-l3);
  box-shadow: var(--e-2);
}

.service-card:hover::after {
  background: var(--border-l3);
}

.svc-icon {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  border-radius: var(--r-sm);
  /* 세 장 동일 — 1번만 솔리드였을 때 "선택된 카드"로 읽혔다.
     흰 글리프 / 블루 면 5.26:1 */
  background: var(--blue);
  color: var(--white);
  transition: background var(--dur) ease;
}

.svc-icon svg {
  width: 19px;
  height: 19px;
}

.service-card:hover .svc-icon {
  background: var(--blue-deep);
}

/* 인덱스 — 13px 회색 각주였던 것을 아이콘 높이에 맞춘 넘버 플레이트로 키운다.
   아이콘(좌) ↔ 인덱스(우)가 한 밴드에서 마주보며 헤더행을 만들고, 그 아래 구분선이
   제목으로 시선을 넘긴다. 아이콘과 짝이 되도록 세 장 모두 블루(흰 면 5.26:1) */
.svc-index {
  position: absolute;
  top: 28px;
  right: 28px;
  display: grid;
  place-items: center;
  height: 46px;
  color: var(--blue);
  font-size: 24px;
  line-height: 1;
  font-weight: 800;
  letter-spacing: 0.01em;
  font-variant-numeric: tabular-nums;
  transition: color var(--dur) ease;
}

/* 헤더 밴드(28+46) + 구분선 여백 16 + 선 1 + 16 = 107 → 아이콘 하단(74)에서 33px */
.service-card h3 {
  margin: 33px 0 0;
  color: var(--text-l-1);
  font-size: var(--t-sub-1);
  line-height: var(--t-sub-1-lh);
  font-weight: 800;
}

/* 설명 문단만 한 단계 내려 정의(16/700 블루) → 실행 항목(16/600 진한) → 설명(15/400)의
   계단을 만든다. .svc-def/.svc-keys는 더 구체적인 셀렉터가 있어 영향 없음 */
.service-card p {
  margin: 12px 0 0;
  color: var(--text-l-2);
  font-size: 15px;
  line-height: 1.7;
  word-break: keep-all;
}

/* 영역 정의 한 줄 — 영문 영역명 바로 아래 한국어 정의 */
.service-card .svc-def {
  margin: 9px 0 0;
  color: var(--blue);
  font-size: 16px;
  line-height: 1.5;
  font-weight: 700;
}

/* 실행 항목 — auto 마진으로 항목~키워드 묶음을 카드 하단에 정렬 */
.service-card ul {
  margin: auto 0 0;
  padding: 22px 0 0;
  list-style: none;
  display: grid;
  gap: var(--gap-2);
}

.service-card li {
  display: flex;
  align-items: center;
  gap: var(--gap-2);
  color: var(--text-l-1);
  font-size: 16px;
  line-height: 1.45;
  font-weight: 600;
}

/* 실행 항목 표식 — 체크. 전에는 같은 border 기법의 셰브런(∨)이었는데, 07 프로세스 층이
   같은 형태를 '다음 단계'라는 뜻으로 쓰게 되면서 한 페이지에 같은 글리프가 두 뜻으로
   놓였다. 이 목록은 순서가 아니라 수행 항목이므로 체크가 뜻에 맞다(2026-08-29).
   비율 5:9는 45° 회전 뒤 획 길이가 1:2로 보이는 표준 체크 형태다 */
.service-card li::before {
  content: "";
  flex: 0 0 auto;
  width: 5px;
  height: 9px;
  margin-top: -2px;
  border-right: 1.75px solid var(--blue);
  border-bottom: 1.75px solid var(--blue);
  transform: rotate(45deg);
}

/* 하단 키워드 줄 — 헤어라인 위 소형 텍스트로 개별 서비스명 유지 */
.service-card .svc-keys {
  margin: 18px 0 0;
  padding: 14px 0 0;
  border-top: 1px solid var(--border-l1);
  color: var(--text-l-3);
  font-size: 13.5px;
  line-height: 1.6;
  font-weight: 700;
  letter-spacing: 0.01em;
}

/* =========================================================
   PERFORMANCE MARKETING — SERVICE에서 분리한 3개 섹션
   "SERVICE가 유독 길다"는 피드백에 따라 채널 운영 / 운영 프로세스 / 운영의 변화를
   각각 독립 섹션으로 세분화했다. 라이트 3연속(04~06)은 배경 명도 차가 5% 남짓이라
   그것만으로는 한 덩어리로 읽힌다 — 새 색을 만드는 대신 섹션 배경과 패널의 관계를
   한 섹션씩 뒤집어(면 반전) 경계를 만들고,
   전환 경계마다 다른 섹션과 같은 --grad-line 이음매를 깐다.
     · 04 SERVICE  영역 카드    → 배경 l1 + 카드 l0 (틴트 배경 위 화이트 카드)
     · #pm-detail  채널 운영    → 배경 l0 + 패널 l1 (화이트 배경 위 틴트 패널 — 반전)
     · #pm-process 운영 프로세스 → 배경 l2 + 카드 l0 (다시 틴트 배경 위 화이트 카드, 한 단계 더 깊게)
     · #pm-shift   운영의 변화   → 네이비(결론 블록 + 뒤 SOLUTION 블랙으로 연결)
   ========================================================= */
.pm-section {
  position: relative;
  width: 100%;
  max-width: none;
  background-color: var(--surface-l0);
  background-image:
    linear-gradient(180deg, rgba(255, 255, 255, 0), var(--surface-l0) 520px),
    var(--dot-light);
  background-size:
    auto,
    var(--dot-light-size);
}

/* 두 번째 PM 섹션은 서피스를 한 단계 내려 라이트 구간 안에서도 경계가 보이게 한다 */
/* 04(l1) → 05(l0) → 06(l2). 04~06이 라이트 3연속이라 l1/l0/l1로는 명도 차가
   1.5뿐이었다. 가운데를 두 단계 내려 05→06 경계를 3.2로 벌린다(아인스미디어식 명도 계단) */
#pm-process.pm-section {
  background-color: var(--surface-l2);
  background-image:
    linear-gradient(180deg, rgba(241, 246, 253, 0), var(--surface-l2) 520px),
    var(--dot-light);
}

/* 섹션 이음매 헤어라인 — 다른 전환 경계와 동일한 --grad-line 1px */
.pm-section::before {
  content: "";
  position: absolute;
  top: -1px;
  left: 0;
  right: 0;
  height: 1px;
  background: var(--grad-line);
}

.pm-section > .section-heading,
.pm-section > .media-products {
  width: min(100%, var(--max));
  margin-left: auto;
  margin-right: auto;
}

.pm-section > .section-heading {
  max-width: var(--max);
}

.pm-section > .section-heading h2 {
  max-width: 920px;
}

/* ---- 상세 본문 폭 래퍼 ---- */
.media-products {
  width: min(100%, var(--max));
  margin: 0 auto;
}

/* 섹션 리드 — 타이포는 .section-heading p 공통 규칙을 따르고 폭만 따로 제한한다 */
.mp-lead {
  max-width: 760px;
  word-break: keep-all;
}

/* 3단(매체·프로세스·차별점)을 각각 독립 섹션으로 분리하면서
   블록 소제목(.pm-sub)은 각 섹션의 h2로 승격되어 사라졌다 */

/* (1) 고객 여정 4단계 — 채널 나열이 아니라 '단계별로 무엇을 해주는가'로 읽히는 트랙.
   바로 아래 운영 프로세스 5스텝(.pm-step)과 혼동되지 않도록 UI 언어를 분리한다.
   · 여정: 카드 밖 헤더(노드+레일)로 4장을 하나의 흐름으로 잇고, 패널은 플랫(그림자·리프트 없음)
   · 프로세스: 독립 카드 5장 + 블루 숫자 + hover 리프트/상단 바(기존 유지) */
.mp-grid {
  /* 레일이 gap을 건너 다음 단계까지 이어지므로 gap 값을 토큰화해 계산에 재사용 */
  /* ※ 스페이싱 사다리 예외(1/2) — 14px 유지.
     --gap-2(16px)로 올리면 4열 카드가 각 1.5px 좁아지면서 .mp-note가 2줄→3줄로 접힌다
     (1440·1280 실측). 감사 권고는 "14 vs 16 병합 시 16"이었으나 개행 보존이 우선이라
     기존 검증값 14px를 남긴다. 카드 폭이 늘어나면 --gap-2로 복귀할 것 */
  --mp-gap: 14px;
  --mp-pad: 20px;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--mp-gap);
}

/* 카드가 아니라 '단계' — 헤더행 + 본문 패널의 2단 구성 */
.mp-card {
  display: flex;
  flex-direction: column;
}

/* 단계 헤더: 노드(::before) + STAGE 번호 + 다음 단계로 이어지는 레일.
   회색 라벨 + 0.24 알파 레일로는 "4장이 한 여정"이라는 흐름이 읽히지 않았다(직전 피드백).
   라벨을 라이트 섹션 액센트(--blue, 흰 면 5.26:1)로 올려 STAGE 01→04가 하나의 열로 스캔되게 하고,
   노드에는 정거장 헤일로를, 레일 끝에는 굵은 셰브런을 붙여 방향을 명시한다.
   프로세스(06)의 블루 숫자 .pm-no와는 트래킹 라벨/숫자 배지로 여전히 구분된다 */
.mp-stage {
  display: flex;
  align-items: center;
  gap: var(--gap-1);
  margin: 0 0 12px;
  padding-left: 1px;
  color: var(--blue);
  font-size: 12px;
  line-height: 1;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  letter-spacing: var(--t-label-ls);
}

/* 정거장 노드 — 링 + 저알파 헤일로로 레일 위의 '역'처럼 읽히게 */
.mp-stage::before {
  content: "";
  flex: 0 0 auto;
  width: 9px;
  height: 9px;
  border: 2px solid var(--blue);
  border-radius: var(--r-pill);
  background: var(--surface-l0);
  box-shadow: 0 0 0 3px rgba(34, 118, 255, 0.1);
  transition:
    background var(--dur) ease,
    box-shadow var(--dur) ease;
}

/* 종착 단계(STAGE 04)만 노드를 채워 여정의 끝을 표기 — 방향의 도착점.
   ※ :last-child가 아니라 :last-of-type이다. 사분면 그리드의 마지막 자식은 카드가 아니라
   .gxq-axis / .gxq-journey span이라 :last-child는 한 장도 맞지 않았고, 채움 노드가
   조용히 사라져 있었다. 카드만 article이므로 :last-of-type이 두 배치에서 모두 STAGE 04다.
   아래 레일 규칙 3개도 같은 이유로 함께 옮긴다 */
.mp-card:last-of-type .mp-stage::before {
  background: var(--blue);
}

.mp-card:hover .mp-stage::before {
  background: var(--blue);
  box-shadow: 0 0 0 4px rgba(34, 118, 255, 0.16);
}

/* 레일 — 남는 폭을 채우는 hairline(좌→우 진행감).
   #2276ff 0.24(흰 면 1.36:1)는 사실상 보이지 않아 라이트 액센트인 --blue 0.55로 올린다(2.38:1) */
.mp-rail {
  position: relative;
  flex: 1 1 auto;
  height: 1px;
  background: rgba(15, 99, 234, 0.55);
}

/* 마지막 단계를 제외하고 gap만큼 연장 — 다음 단계 노드 바로 앞까지 이어짐.
   헤더행은 패널(.mp-body) 밖이라 카드 패딩이 걸리지 않으므로 gap 폭만 보정 */
.mp-card:not(:last-of-type) .mp-rail {
  margin-right: calc(-1 * var(--mp-gap));
}

/* 레일 끝 셰브런 — 방향을 실제로 지시하는 유일한 표식이라 레일보다 한 단계 진하게(4.06:1) */
.mp-card:not(:last-of-type) .mp-rail::after {
  content: "";
  position: absolute;
  top: 50%;
  right: 2px;
  width: 6px;
  height: 6px;
  border-top: 1.5px solid rgba(15, 99, 234, 0.85);
  border-right: 1.5px solid rgba(15, 99, 234, 0.85);
  transform: translateY(-50%) rotate(45deg);
}

/* 마지막 레일은 이어질 곳이 없으므로 끝에서 사라지게 — 여정의 종결 */
.mp-card:last-of-type .mp-rail {
  background: linear-gradient(90deg, rgba(15, 99, 234, 0.55), rgba(15, 99, 234, 0));
}

/* 본문 패널 — 화이트 섹션 배경(--surface-l0) 위 틴트 플랫 패널(--surface-l1).
   앞뒤 라이트 섹션(04·06)이 "틴트 배경 + 화이트 카드"이므로 여기서만 면 관계를 뒤집어,
   배경값을 바꾸지 않고 04→05→06 경계를 만든다.
   .pm-step과 달리 그림자·리프트 없음, 반경도 한 단계 작게 */
.mp-body {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  padding: var(--mp-pad);
  /* 화이트 위 l1 패널이라 --border-l1(1.18:1)로는 패널 윤곽이 사라진다 — l2로 한 단계 올림 */
  border: 1px solid var(--border-l2);
  border-radius: var(--r-sm);
  background: var(--surface-l1);
  transition:
    border-color var(--dur) ease,
    background var(--dur) ease;
}

/* 리프트 없는 패널이라 hover는 면을 한 단계 눌러 응답한다(l1 → l2) */
.mp-card:hover .mp-body {
  border-color: var(--border-l3);
  background: var(--surface-l2);
}

/* 단계명 — 영문 대문자(단계) + 국문 목표 한 줄 */
.mp-card h3 {
  margin: 14px 0 0;
  color: var(--text-l-1);
  font-size: var(--t-sub-2);
  line-height: var(--t-sub-2-lh);
  font-weight: 800;
  letter-spacing: 0.02em;
}

.mp-goal {
  display: block;
  margin-top: 7px;
  color: var(--text-l-2);
  font-size: 14.5px;
  line-height: 1.45;
  font-weight: 700;
  letter-spacing: 0;
  word-break: keep-all;
}

/* 채널 태그 — 패널 안을 "단계 정체성 / 채널 / 운영 포인트" 3존으로 끊는다.

   [2026-08-29] 그 경계를 헤어라인에서 여백(29px)으로 바꿨다. 카드 하나에 같은 값
   (1px · --border-l2)의 가로선이 넉 줄 있었다 — 카드 테두리 상·하, 칩 위, 운영 포인트 위.
   내부 두 줄이 테두리와 굵기·색이 한 값이라 존을 나누는 대신 카드가 세 칸으로 잘려 보였고,
   그것이 클라이언트가 지적한 "가로줄이 어색하다"의 실체다. 07 매체 카드는 같은 3존
   구조를 내부선 한 줄(.prod-media p의 border-top)로 세우므로, 06도 그 한 줄에 맞춘다 —
   남기는 쪽은 바닥 고정 블록 위(.mp-note)로, 07과 같은 자리다.
   간격은 건드리지 않아(14 + 15) 카드 4장의 높이 균일은 그대로다.

   margin-bottom 14는 아래 .mp-note의 auto 마진에 '바닥값'을 주는 장치다.
   auto 마진만으로는 남는 높이가 0인 카드에서 칩 행 밑변과 다음 구분선이 0px로 붙어
   (실측 1440·1280에서 3/4장, 390에서 4/4장) 칩이 위 14 / 아래 0의 비대칭 존에 갇혔다 —
   클라이언트가 지적한 "라벨이 하단에 붙어 있다"가 이 수치다.
   플렉스 항목의 마진은 상쇄되지 않으므로 실측 간격은 항상 14 + 남는 높이가 된다 */
.mp-tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--gap-1);
  margin: 14px 0;
  padding: 14px 0 0;
  list-style: none;
}

/* 패널이 l1으로 뒤집혔으므로 태그는 l0 — 패널과 동색으로 겹쳐 사라지지 않게 반대로 든다 */
.mp-tags li {
  display: inline-flex;
  align-items: center;
  gap: var(--gap-1);
  padding: 4px 10px;
  border: 1px solid var(--border-l2);
  border-radius: var(--r-pill);
  background: var(--surface-l0);
  color: var(--text-l-2);
  font-size: 12.5px;
  line-height: 1.4;
  font-weight: 700;
  white-space: nowrap;
}

/* 운영 포인트 — margin-top auto로 패널 하단 정렬(행 내 기준선 일치).
   구분선은 태그 상단 헤어라인과 같은 무게(--border-l2)로 통일.

   설명문 줄 수 차이(카드마다 1~2줄)로 생기는 높이 편차를 흡수하는 카드 안의 유일한 지점이
   여기다 — 나머지 세로 간격(21 / 14 / 14 / 14 / 14 / 21)은 4장에서 전부 고정값이다.
   바닥값 14는 .mp-tags의 margin-bottom이 대고, auto는 그 위로만 늘어난다 */
.mp-note {
  margin: auto 0 0;
  padding: 14px 0 0;
  border-top: 1px solid var(--border-l2);
  color: var(--text-l-2);
  font-size: 14.5px;
  line-height: 1.6;
  word-break: keep-all;
}

/* 매체 로고 행: 브랜드 컬러 상시 표기(대표 피드백 — hover로 색이 들어오는 방식 폐기).
   카카오 심볼은 브라운(#3C1E1E)이라 라이트 카드 배경에서도 대비가 충분하다 */
.mp-logos {
  display: flex;
  align-items: center;
  gap: var(--gap-2);
  min-height: 18px;
}

/* 06·07의 마크도 13 라인업과 같은 타일 표기다(소개서 p21). 세 곳이 같은 계약을 쓰므로
   한 브랜드가 면을 옮겼다고 다르게 보이는 일이 없다 — 상자·라운드·바탕·안쪽 비율까지 같고
   치수만 24px(라인업은 28px)이다. 상단 스트립만 예외로 남는다(currentColor 마스크) */
.mp-ico {
  display: grid;
  place-items: center;
  box-sizing: border-box;
  width: var(--mp-tile-w, var(--mp-tile, 24px));
  height: var(--mp-tile, 24px);
  border-radius: 6px;
  background: var(--tile, var(--surface-l0));
  box-shadow: inset 0 0 0 1px rgba(10, 16, 32, 0.08);
  overflow: hidden;
}

.mp-ico::before {
  content: "";
  width: var(--logo-w, 76%);
  height: var(--logo-w, 76%);
  background: var(--brand);
  -webkit-mask: var(--ico) center / contain no-repeat;
  mask: var(--ico) center / contain no-repeat;
}

/* 가로 워드마크형 로고(쿠팡 등): 높이는 유지하되 폭을 넓혀 비율 보존 */
/* 앱 아이콘이 없어 가로 워드마크를 그대로 쓰는 칩 — 라인업의 --lu-tile-w와 같은 처리 */
.mp-ico.wide {
  width: 48px;
}

/* 폴리크롬 예외 — 라인업의 .lu-ico.is-original과 한 글자도 다르지 않은 계약이다.
   같은 브랜드가 면을 옮겼다고 다르게 보이면 안 되므로 두 규칙은 반드시 같이 움직인다.

   대상 판정은 취향이 아니라 자산 실측이다: platforms/ 30개 자산 중 색을 품은 것은
   googleads.svg(4색)·coupang.svg(5색) 둘뿐이고, 나머지 24 SVG는 fill 선언이 아예 없는
   글리프, 4 PNG는 순수 검정 알파 실루엣이다(불투명 픽셀 색 버킷 1종). 즉 그 28개는
   마스크를 풀면 브랜드 컬러가 아니라 '검정'이 된다 — 단색 마스크가 그쪽의 정본이다.

   ── [2026-08-29] 공식 자산 웹 재확보 — 결론: 계약 유지, 컬러 전환 0칩 ──────────────
   클라이언트 지시("카카오 포함 로고 웹에서 직접 검색")로 공식 자산을 다시 전수 탐색했다
   (Wikimedia Commons 파일검색 + 각 사 브랜드/프레스 리소스 페이지). 확보한 후보를 전부
   3배율로 래스터해 잉크 커버리지를 실측했다. 색을 넣지 '않기로' 한 판단의 근거는 이 숫자다.

   [1] 컬러 형태가 '꽉 찬 앱아이콘 타일'뿐이라 못 쓰는 것: 카카오와 틱톡이다.
       실측 커버리지가 카카오 99.5% · 틱톡 95.9%(참고로 인스타 타일본 95.8%)인데,
       현행 28칩 밴드는 27.4~83.8%이고 같은 행 이웃은 27~70%다 — 타일을 끼우면 그 칩만
       이웃의 1.4~3.6배 질량이 되어, 이 주석이 이미 기록한 회귀가 그대로 재현된다.
       틱톡은 투명 3색이 '노트+워드마크' 락업으로만 있고 거기서 노트만 떼는 것은 가이드가
       금지하는 변형이라, 형태로도 막힌다.
   [1-b] 인스타그램은 사정이 다르다 — 공식 팩(IG_brand_asset_pack_2023)에 투명 그라디언트
       글리프가 실제로 있고(팩에 타일은 없다) 일반 디지털 사용에 사전 허가도 필요 없다.
       즉 이 칩만은 컬러 전환이 기술적·법적으로 가능하다. 그런데도 하지 않는다:
       같은 SOCIAL 행의 메타는 단독 심볼 배포가 없고 모든 사용에 Brand Review 승인이,
       틱톡은 사전 서면 허가가 걸려 따라올 수 없다. 인스타 하나만 컬러로 돌리면
       5칩 중 1칩만 폴리크롬이 되어, 방금 0으로 만든 계열 내 예외가 되살아난다.
       '자산이 없어서'가 아니라 '혼자만 갈 수 없어서' 보류하는 항목이니, 나중에 메타·틱톡
       승인이 나면 세 칩을 함께 전환하는 것이 정답이다.
   [2] 반대편 선택지인 '28칩 전부 타일 통일'도 성립하지 않는다. 11번가·옥션·SSG·롯데온·
       무신사·몰로코·빅쿼리는 출처가 분명한 공식 벡터를 찾지 못했고, 워드마크 8칩은
       타일 형태 자체가 존재하지 않는다. 확보율이 통일선에 닿지 못한다.
   [3] 나머지 후보는 마크가 달랐다 — 크리테오·G마켓·GA·메타·앱스플라이어, 그리고 3색
       틱톡본까지 전부 [심볼+글자] 가로 락업이라 심볼 슬롯에 넣으면 종횡비와 행 리듬이
       깨진다. 네이버 공식 그린 N은 현행 마스크 렌더와 결과가 같아 교체 이득이 없다.
   따라서 컬러 전환은 한 칩도 하지 않는다. 단색 마스크가 계속 정본이다.
   [4] 다만 '단색으로 칠하되 칠하는 색이 틀린' 칩이 하나 잡혔다 — 올리브영이다.
       공식 AI 파일(corp.oliveyoung.com/img/introduction/cjoliveyoung_bi.ai)의 콘텐츠
       스트림에는 색 연산자가 `0 0 0 rg` 하나뿐이고, 프리뷰 PNG(762x132)는 전 픽셀이
       순수 검정이다. 2023년 리뉴얼로 심볼 락업이 워드마크 단독이 되면서 흰·초록·컬러
       변형은 아예 배포되지 않는다. 우리가 쓰던 #95BB2F는 CI 페이지가 '올리브 그린'으로
       소개하는 팔레트 색이지 로고 색이 아니었다 — 즉 브랜드가 배포하지 않는 색 변형을
       우리가 만들어 쓰고 있었다. 순수 #000 대신 이 프로젝트의 로고 잉크 기준값 #1A1A1A로
       맞춘다(앱스플라이어 칩과 같은 값). 밝은 타일 대비도 함께 좋아진다.
       같은 성격의 후보가 둘 더 있으나 이번엔 건드리지 않는다 — 11번가는 공식 배포본에
       플랫 단색이 없고(그라디언트/Black/White뿐, 밝은 배경 권장은 Black) 우리는 #FF0058을
       쓰고 있으며, 모비온은 공식 사이트 SVG가 검정인데 우리는 #80AF4E를 쓴다. 둘 다
       바꾸면 커머스 행이 8칩 중 5칩 근검정이 되어 계열 인상이 크게 달라지므로,
       클라이언트 확인 뒤에 처리한다.

   [카카오 — 클라이언트 명시 항목 / 판정: 현행 자산이 이미 맞다]
   소개서의 '노란 면 + 갈색 말풍선'은 재현하지 않는다. 노란 면은 [1]의 99.5% 타일로만
   나오기 때문이다. 그리고 카카오 공식 디자인 가이드가 현행 형태를 직접 지지한다
   (developers.kakao.com/docs/ko/kakaosync/design-guide): "카카오를 상징하는 말풍선 모양의
   심볼을 기본으로 사용합니다 … 카카오톡의 심볼이나 카카오 CI를 심볼로 적용할 수 없습니다
   … 아웃라인만 있는 심볼을 사용할 수 없습니다." 카카오는 세 마크를 구분한다 —
   카카오 심볼(민무늬 말풍선) / 카카오톡 심볼(TALK 앱아이콘) / 카카오 CI(워드마크) —
   이고 뒤의 둘을 심볼 자리에 쓰는 것을 명시적으로 금지한다. 우리 칩이 가리키는 것은
   메신저가 아니라 광고 플랫폼(카카오모먼트·키워드광고)이므로 민무늬 말풍선이 정답이다.
   칠에 쓰는 #3C1E1E도 카카오가 배포하는 공유 버튼 PNG에서 그대로 뽑히는 정품 잉크다.
   (앱아이콘의 TALK 레터링을 evenodd 녹아웃으로 되살린 대안을 만들어 실측까지 마쳤으나
   — 커버리지 69.2%→58.3%, 종횡비 1.083 불변 — 위 금지 조항에 걸려 폐기했다. 덧붙여
   kakao.svg는 02 시그널 스트립(17px 백색 모노)이 공유하는 자산이라, 손댔다면 승인 완료로
   고정된 그 띠까지 함께 바뀌었을 것이다.)
   [브랜드 사용 승인이 필요한 곳 — 클라이언트 고지용 목록]
   메타(모든 사용에 Brand Review 승인) · 틱톡(사전 서면 허가) · 카카오(사전 승인, 미디어킷
   자료는 상업적 이용 불가 명시) · G마켓(가이드 내용 직접 복제 불가, 필요 시 문의) ·
   11번가(색상·형태·비례 변형 불가, 의문 시 유관부서 문의) · 롯데(사전 협의) ·
   Google(전체 규정이 파트너 로그인 게이트 뒤에 있음). 네이버는 동의 후 다운로드 ZIP을
   공개하되 제3자 재배포·AI 학습 사용을 금지한다. 즉 '다운로드 가능'과 '무상 사용 허가'는
   별개다. 07 라인업 하단에는 이미 "로고는 운영 경험이 있는 매체·플랫폼 예시이며 공식
   파트너십을 의미하지 않습니다" 고지가 붙어 있고, 현재 사용은 그 지명적 표기 전제 위에 선다.

   [라이선스 — 클라이언트 고지 사항] 카카오 미디어킷의 CI 항목은 kakao.png(8000×4500
   불투명 래스터) 하나뿐이고 "제공하는 모든 이미지와 영상, 자료는 상업적으로 이용할 수
   없습니다", "카카오의 브랜드를 사용하기 위해서는 반드시 사전 승인을 받아야 합니다"라고
   명시한다. 즉 카카오는 라이선스된 투명 단독 글리프를 배포하지 않는다. 현행 자산의
   출처는 Wikimedia Commons의 퍼블릭 도메인 심볼이며, 매체명 표기 목적의 지명적 사용이라는
   전제 위에 서 있다 — 방어 가능한 단순화이지만 공식 라이선스 자산은 아니다.

   이전 라운드 회귀 사유를 그대로 지킨다: 면·테두리·라운드 금지. 흰 면 + 1px 테두리 +
   4px 라운드로 두던 앱아이콘 타일은 옆의 18px 심볼칩과 질량 격차를 만들었고, 같은
   쿠팡이 07 패널에서는 면 없이 나와 한 브랜드가 두 형태로 갈렸다.
   sizing도 84% → contain으로 되돌린다: 07 패널의 마스크 쿠팡이 48x18 상자 안에서
   48x10.9로 그려지므로, 같은 상자·같은 잉크 크기로 맞아떨어진다(상자 치수는 불변 —
   border-box라 테두리를 떼도 48x18 그대로다) */
.mp-ico.is-original::before {
  -webkit-mask-image: none;
  mask-image: none;
  background: var(--ico) center / contain no-repeat;
}

/* 아이콘 자체가 타일인 자산 — 바탕과 인셋 테두리를 걷고 상자를 꽉 채운다 */
.mp-ico.is-full {
  box-shadow: none;
}

.mp-ico.is-full::before {
  width: 100%;
  height: 100%;
}

/* 여정 블록 로컬 반응형 — 공용 RESPONSIVE는 이미 행 끝(2n·1열) 레일 연장·셰브런을 끊는다.
   끊긴 자리에서 레일만 진하게 남으면 "다음이 있는데 화살표가 없는" 상태로 보이므로,
   마지막 단계와 같은 페이드 종결로 맞춘다 */
@media (max-width: 1024px) {
  .mp-card:nth-child(2n) .mp-rail {
    background: linear-gradient(90deg, rgba(15, 99, 234, 0.55), rgba(15, 99, 234, 0));
  }
}

@media (max-width: 720px) {
  .mp-card .mp-rail {
    background: linear-gradient(90deg, rgba(15, 99, 234, 0.55), rgba(15, 99, 234, 0));
  }
}

/* =========================================================
   07 AD PRODUCTS — 매체별 광고 상품 구조
   06 채널 운영(l0)과 08 운영 프로세스(l2) 사이에 들어가는 라이트 섹션.
   라이트 4연속(04~08) 구간의 명도 사다리에서 이 섹션이 가운데 칸을 맡는다:
     04 SERVICE l1 → 06 채널 운영 l0 → 07 AD PRODUCTS l1 → 08 운영 프로세스 l2
   배경 문법은 04 SERVICE와 동일한 3레이어(면 + 상단 페이드 + 공통 도트)이고
   전환 경계에는 다른 섹션과 같은 --grad-line 이음매를 깐다.

   UI 언어 분리 — 이 섹션은 06(여정 레일)·08(넘버 카드)과 같은 페이지에 있으므로
   흐름 표식을 새로 만들지 않는다. 탭(선택) + 패널(상세)이라는 다른 축을 쓰고,
   패널 안에서만 06/08에서 이미 쓰는 문법(블루 넘버·셰브런·상단 2px 카드 라인)을 축소해 재사용한다.
   ========================================================= */
.products-section {
  position: relative;
  width: 100%;
  max-width: none;
  background-color: var(--surface-l1);
  background-image:
    linear-gradient(180deg, rgba(248, 251, 255, 0), var(--surface-l1) 520px),
    var(--dot-light);
  background-size:
    auto,
    var(--dot-light-size);
}

/* 섹션 이음매 헤어라인 — SEAM 공통 규칙과 같은 --grad-line 1px */
.products-section::before {
  content: "";
  position: absolute;
  top: -1px;
  left: 0;
  right: 0;
  height: 1px;
  background: var(--grad-line);
}

/* 풀블리드 섹션 안에서 본문 폭을 다시 --max로 묶는다(04·11과 같은 처리) */
.products-section > .section-heading,
.prod-tabs,
.prod-panel,
.prod-lineup {
  width: min(100%, var(--max));
  margin-left: auto;
  margin-right: auto;
}

.products-section > .section-heading {
  max-width: var(--max);
}

.products-section > .section-heading h2 {
  max-width: 920px;
}

.products-section > .section-heading p:not(.eyebrow) {
  max-width: 760px;
}

/* ---- 탭 ----
   활성 표기는 11 WORKS 필터 칩과 같은 문법(블루 채움 그라디언트 + 흰 글자).
   칩이 아니라 3등분 카드형인 이유는 탭 하나가 "영문 라벨 + 국문 요약" 두 줄을 갖기 때문 —
   알약형으로 두면 줄바꿈이 생겨 필터 칩과 같은 UI로 읽힌다 */
.prod-tabs {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--gap-2);
  /* 탭은 컨트롤 스트립이고 그 아래는 본문이다 — 24px로 붙여 두면 활성 탭(채운 블루)과
     패널 헤드가 한 덩어리로 읽혀 헤드가 자기 자리를 못 갖는다. 섹션 내부 최대 갭으로 끊는다 */
  margin-bottom: var(--gap-4);
}

.prod-tab {
  display: flex;
  flex-direction: column;
  gap: var(--gap-1);
  padding: 14px 18px;
  border: 1px solid var(--border-l2);
  border-radius: var(--r-sm);
  /* 섹션 배경이 l1이라 비활성 탭은 l0으로 한 단계 들어 올린다 */
  background: var(--surface-l0);
  color: var(--text-l-2);
  font-family: inherit;
  font-size: 15.5px;
  line-height: 1.2;
  font-weight: 800;
  letter-spacing: 0.02em;
  text-align: left;
  cursor: pointer;
  /* 모션 금지 — 리프트·스케일 없이 면·보더·글자색만 응답한다 */
  transition:
    background var(--dur) ease,
    border-color var(--dur) ease,
    color var(--dur) ease;
}

.prod-tab span {
  display: block;
  color: var(--text-l-3);
  /* 07 안에서 [심볼 + 이름] 칩이 쓰는 13px/700과 같은 단 — 탭 부제만 12.5로 남으면
     섹션 안에 캡션 급이 두 개가 된다 */
  font-size: 13px;
  line-height: 1.45;
  font-weight: 700;
  letter-spacing: 0;
  word-break: keep-all;
  transition: color var(--dur) ease;
}

.prod-tab:hover {
  border-color: var(--border-l3);
  color: var(--blue);
}

.prod-tab:hover span {
  color: var(--text-l-2);
}

.prod-tab:focus-visible {
  outline: none;
  box-shadow: var(--e-focus);
}

/* 활성 탭 — .tab-button.is-active와 같은 채움(블루 → 블루딥) */
.prod-tab.is-active {
  background: linear-gradient(135deg, var(--blue) 0%, var(--blue-deep) 100%);
  border-color: transparent;
  color: var(--white);
}

/* 국문 요약만 한 톤 눌러 두 줄의 위계를 남긴다.
   그라디언트의 밝은 끝(--blue)에서 재는 값이 하한이라 0.92보다 내리면 AA를 잃는다
   (0.92 → 4.69:1, 0.88 → 4.43:1) */
.prod-tab.is-active span {
  color: rgba(255, 255, 255, 0.92);
}

/* ---- 패널 ----
   데스크탑은 한 번에 하나만 노출. ≤768px에서는 탭 자체를 걷고 세 패널을 모두 세로로 편다
   (좁은 화면에서 탭 3개는 라벨이 접혀 읽히지 않고, 상품 구조는 비교보다 통독이 낫다) */
.prod-panel {
  display: none;
  /* [하단 마감] 세 패널의 마지막 블록이 서로 다르다 — SEARCH·COMMERCE는 12.5px 각주,
     DISPLAY는 48px 칩 행에서 끝난다. 각주는 제 아래 여백이 0이라 DISPLAY만 굵은 행이
     라인업 경계에 그대로 붙어 '뒤가 잘린' 인상을 줬다. 패널 자체에 같은 마감 여백을 줘
     어떤 블록으로 끝나든 종결 리듬이 같아진다(빈 자리를 만드는 min-height 대신 여백 균형) */
  padding-bottom: var(--gap-3);
}

.prod-panel.is-active {
  display: block;
}

/* 모바일 전용 패널 헤더 — 데스크탑에서는 탭 라벨이 같은 역할을 하므로 숨긴다 */
.prod-cap {
  display: none;
}

/* 패널 헤드 — 세 지적이 겹쳐 있던 자리.
   실측: .prod-head는 margin·padding·border·background가 전부 0으로, 패널에서 유일하게
   장치가 없는 블록이었다(props는 상단 헤어라인 + 24px 블루 넘버, media는 l0 카드 + 2px 카드룰,
   band는 l2 면 + 보더, note는 각주 색). 위아래 여백도 24/26px로 거의 같아 헤드가 자기 공간을
   갖지 못하고 활성 탭과 첫 카드 행 사이에 끼인 캡션처럼 읽혔다.

   소개서 p16~19의 헤드는 [대시 레일 + 블루 캡스 라벨]로 열리는데, 데스크탑에서는 .prod-cap을
   접어 그 표식이 통째로 사라진다. 라벨을 다시 띄우면 탭에 있는 문장이 화면에 두 번 서므로
   글자 없이 표식만 남긴다 — 28×2px 블루 룰.
   05 .diff-cap(채운 헤더 바, 20px 라운드)도 08 .pm-flow-head(20px 라운드 필)도 아닌 제3의 장치이고,
   07 자신이 .lineup-row dt::before에서 쓰는 14×2px 블루 대시의 패널 헤드 판이다 */
.prod-head::before {
  content: "";
  display: block;
  width: 28px;
  height: 2px;
  margin: 0 0 var(--gap-2);
  background: var(--blue);
}

.prod-head h3 {
  margin: 0;
  color: var(--text-l-1);
  font-size: var(--t-sub-1);
  line-height: var(--t-sub-1-lh);
  font-weight: 800;
  letter-spacing: -0.01em;
  word-break: keep-all;
}

/* 사이트의 리드는 전부 18px/400/1.75(.section-heading p:not(.eyebrow))인데 여기만 16px/1.7이라
   헤드 아래가 한 단 주저앉아 h3가 홀로 떠 보였다 — 리드 규격으로 되돌린다 */
.prod-head p {
  margin: var(--gap-2) 0 0;
  max-width: 820px;
  color: var(--text-l-2);
  font-size: 18px;
  line-height: 1.75;
  word-break: keep-all;
}

/* ---- 운영 포인트 3~4칸 ----
   카드로 두면 아래 매체 카드(.prod-media)와 같은 무게가 되므로, 상단 헤어라인 + 대형 넘버만 있는
   '번호가 붙은 칼럼'으로 남긴다. 넘버는 08 프로세스의 32px 블루 넘버를 24px로 줄인 축소판.

   마크업 계약이 `.prod-props`를 리스트 자체로 둘지 리스트를 감싼 래퍼로 둘지 열려 있어
   두 경우 모두 성립하도록 썼다 — 래퍼일 때는 안쪽 ol이 전 칸을 가로지르고,
   실제 칸 분할은 그 ol이 맡는다 */
.prod-props,
.prod-props > ol {
  display: grid;
  /* 칸 수는 --prop-cols 하나로만 조작한다 — 항목 수 규칙과 반응형 규칙의 특이도가
     엇갈려 서로를 못 이기는 사태를 막기 위한 단일 창구.

     [칸 수 = 항목 수] 한동안 4로 고정했다. 근거는 "칸 수를 항목 수에 맡기면 3항목 패널은
     389px, 4항목 패널은 288px가 되어 탭을 바꿀 때 카드 폭이 바뀐다"였고, 그때는 스텝이
     테두리 없는 텍스트 덩어리라 빈 네 번째 칸이 그냥 여백으로 읽혔다. 스텝이 상자를 갖게
     되자 그 칸은 '빠진 상자'가 되었고, 클라이언트가 "어떤 건 3개 어떤 건 4개여서 정리 안 된
     느낌"으로 지적했다(2026-08-29). 소개서도 p17은 3장, p18은 4장으로 각각 전폭을 채운다 —
     프로세스 열의 본질은 폭의 항상성이 아니라 '끊기지 않고 끝까지 간다'는 쪽이다 */
  grid-template-columns: repeat(var(--prop-cols, 3), minmax(0, 1fr));
  gap: var(--prop-gap);
  padding: 0;
  list-style: none;
}

.prod-props {
  /* 셰브런이 gap 한가운데 놓이도록 gap 값을 토큰화해 계산에 재사용(08과 같은 방식).
     16 → 24: 상자 사이에 10px 화살촉이 들어가야 하므로 16에서는 좌우 3px밖에 남지 않아
     테두리에 붙는다. 24에서 7px씩 확보된다 */
  --prop-gap: var(--gap-3);
  /* 헤드 → 본문은 --gap-4, 본문 블록끼리는 --gap-3 — 26/26/22/14px의 눈금 없는 여백을
     토큰 사다리로 세운다. 헤드가 본문보다 넓은 여백을 갖는 것이 헤드 위계의 실체 */
  margin: var(--gap-4) 0 0;
}

.prod-props > ol {
  margin: 0;
  grid-column: 1 / -1;
}

.prod-props:has(> li:nth-child(4)),
.prod-props:has(> ol > li:nth-child(4)) {
  --prop-cols: 4;
}

/* [셰브런 복원 — 세 패널 전부] 한때 COMMERCE만 갖고 있던 .is-chain 변형을 걷은 적이 있고,
   그 근거는 셋이었다: (a) 한 패널에만 붙어 '이 패널만 다른 종류'로 읽힌다, (b) 세 패널 모두
   순서 있는 흐름인데 하나에만 사슬을 그으면 나머지 둘이 순서 없음으로 잘못 읽힌다,
   (c) ≤1024px에서 스스로 사라지는 데스크탑 전용 장식이다.

   클라이언트가 이 층을 "PPT에서 많이 쓰는 프로세스 가로형"으로 요청해(2026-08-29) 되살리되,
   기각 사유를 그대로 통과하는 형태로만 되살린다 — (a)(b)는 예외 없이 세 패널에 다 그으면
   해소되고, (c)는 그 사이 트랙이 1024·768에서도 4칸으로 고정되어 행이 갈리지 않게 바뀌었으므로
   더는 성립하지 않는다(실제로 사라지는 지점은 1열로 접히는 ≤720px 하나뿐이다).

   화살촉은 li 상단 헤어라인의 y에 앉는다 — 칸마다 끊겨 있던 네 도막의 선이 화살표로 이어져
   하나의 프로세스 축이 된다. 잉크는 --blue 0.7로 눌러 순서의 주역인 01~04 넘버(솔리드 --blue,
   24px/900)보다 한 단 아래에 둔다. 형태·기법은 05 .mp-rail::after의 border 화살촉과 같다 */
/* 스텝 상자 — 아웃라인 카드. 전에는 상단 헤어라인 하나에 텍스트가 얹힌 형태였는데,
   클라이언트가 "01, 02, 03 쉐이프가 안 잡혀 디자인이 덜 된 느낌"으로 지적했다(2026-08-29).
   소개서에서도 이 층(p17~19의 상단 단계 행)은 상자다.

   무게는 아래 매체 카드보다 한 단 아래로 둔다 — 매체 카드가 [흰 면 + 테두리 + 그림자 +
   상단 2px 룰]인 '채운 카드'라면, 이쪽은 [면 없음 + 테두리]뿐인 '아웃라인 카드'다. 섹션
   지면이 --fog이므로 면을 비우는 것만으로 두 층의 랭크가 갈린다. 예전에 이 층을 카드로
   두기를 미뤘던 이유("매체 카드와 같은 무게가 된다")는 면과 그림자를 주지 않는 한 생기지
   않는다 */
.prod-props li {
  position: relative;
  padding: 20px;
  border: 1px solid var(--border-l2);
  border-radius: var(--r-sm);
}

.prod-props li:not(:last-child)::after {
  content: "";
  position: absolute;
  /* 10px 상자를 45° 돌린 것이라 시각 중심 = 상자 중심. 스텝이 상자가 된 뒤로는 그 중심을
     상자 세로 중앙에 두고(전에는 상단 헤어라인 위), right는 상자 절반(5)만큼 더 밀어
     gap(--prop-gap) 한가운데에 세운다.
     잉크 0.85는 05 .mp-rail::after와 같은 '방향 표식' 값이다(l1 면에서 비텍스트 3:1 통과) */
  top: calc(50% - 5px);
  right: calc(var(--prop-gap) / -2 - 5px);
  width: 10px;
  height: 10px;
  border-top: 2px solid rgba(15, 99, 234, 0.85);
  border-right: 2px solid rgba(15, 99, 234, 0.85);
  rotate: 45deg;
}

.prod-props b {
  display: block;
  color: var(--blue);
  font-size: 24px;
  line-height: 1;
  font-weight: 900;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0;
}

.prod-props strong {
  display: block;
  margin-top: 10px;
  color: var(--text-l-1);
  font-size: 16px;
  line-height: 1.35;
  font-weight: 800;
  word-break: keep-all;
}

/* DISPLAY 패널의 라벨만 라틴 대문자다(EXPERIMENT/MESSAGE/LEARN). 문안은 verbatim이라
   글자는 못 바꾸고, 대신 '같은 급으로 보이는 것'을 광학적으로 맞춘다.
   실측(Pretendard 800, canvas actualBoundingBoxAscent): 한글 잉크 높이 0.8125em,
   라틴 대문자 0.7188em — 같은 16px에서 라틴이 13% 낮게 앉아 한 급 작은 라벨로 읽혔다.
   16 × (0.8125 / 0.7188) = 18.08px에서 두 잉크 높이가 13.0px로 같아진다.
   line-height는 16px 기준값(16 × 1.35 = 21.6px)에 못박아 행 높이는 한글 패널과 동일하게
   유지한다 — 명목 크기가 아니라 잉크 높이를 맞추는 것이 목적이고, 그 대가로 줄 높이가
   달라지면 props 블록 높이가 패널마다 어긋나 통일이 다시 깨진다.
   letter-spacing 0.01em은 대문자 조판의 기본 보정(굵은 대문자는 자간 0에서 뭉친다).
   색·굵기는 손대지 않는다 — 이미 한글 라벨과 같은 값이다.
   :lang(en)으로 잡는 이유는 이 처리가 'DISPLAY 패널의 예외'가 아니라 '라틴 대문자 라벨의
   조판 규칙'이기 때문 — 어느 패널이 영문 라벨을 갖든 같은 보정을 받는다 */
.prod-props strong:lang(en) {
  font-size: 18px;
  line-height: 21.6px;
  letter-spacing: 0.01em;
}

/* 04 .service-card p(15px/1.7)와 같은 단 — 카드 본문이 14px로 남으면 07만 한 급 작다 */
.prod-props p {
  margin: 7px 0 0;
  color: var(--text-l-2);
  font-size: 15px;
  line-height: 1.7;
  word-break: keep-all;
  overflow-wrap: break-word;
}

/* ---- 매체 카드 3장 ----
   상단 2px --card-line + l0 면 = 사이트 공통 '주인공 카드' 문법(04 서비스 카드와 같은 계열).
   섹션 배경이 l1이므로 카드가 한 겹 떠 보인다.

   세 패널이 모두 이 문법을 쓴다. DISPLAY는 한동안 같은 자리를 6칸 칩 로스터로 채웠는데
   (p19의 ACTIVATION CHANNELS 스트립을 그대로 옮긴 것), 그 층만 48px이라 패널이 다른 둘보다
   110.6px 짧았다 — 세 패널의 나머지 층(헤드 154.6 · 프롭 105.1 · 밴드 49.6 · 각주 20)은
   이미 값이 같았으므로 높이 차 110.5는 전부 이 한 층에서 나왔다. 칩을 택했던 이유는
   "매체별 역할·상품 문안이 없다"였고, 그 문안을 세운 뒤로는 성립하지 않는다 */
.prod-media,
.prod-media > ul {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--gap-2);
  padding: 0;
  list-style: none;
}

.prod-media {
  margin: var(--gap-3) 0 0;
}

.prod-media > ul {
  margin: 0;
  grid-column: 1 / -1;
}

.prod-media li {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: 20px 18px;
  border: 1px solid var(--border-l2);
  border-radius: var(--r-sm);
  background: var(--surface-l0);
  box-shadow: var(--e-1);
  overflow: hidden;
  transition:
    translate var(--dur) var(--ease-out),
    border-color var(--dur) ease,
    box-shadow var(--dur) ease;
}

.prod-media li::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: var(--card-line);
}

.prod-media li:hover {
  translate: 0 var(--card-lift);
  border-color: var(--border-l3);
  box-shadow: var(--e-2);
}

/* 매체 심볼 — 06 여정 카드의 18px 마스크 칩 규칙(.mp-ico)을 그대로 상속하고 배치만 준다 */
.prod-media .mp-ico {
  /* 타일이 된 뒤로 display는 grid여야 한다 — block으로 덮으면 안쪽 마크(::before)의
     정렬이 풀려 타일만 남고 로고가 사라진다 */
  margin: 0 0 12px;
}

/* 카드 제목은 사이트의 L2 카드 제목단(--t-sub-2 18px) — 06 .mp-card h3, 10 .os-mod h3와 같다.
   15px로 두면 카드 제목이 본문(15px)과 같은 크기가 되어 카드 안에서 위계가 사라진다 */
.prod-media b {
  display: block;
  color: var(--text-l-1);
  font-size: var(--t-sub-2);
  line-height: var(--t-sub-2-lh);
  font-weight: 800;
}

/* 06 .mp-goal / 10 .os-mod p와 같은 14.5px 단.
   margin-bottom 14는 아래 .prod-media p의 auto 마진에 '바닥값'을 주는 장치다 — 06 .mp-tags와
   똑같은 처방이다. auto만으로는 남는 높이가 0인 카드에서 역할 줄 밑변과 구분선이 0.9px로
   붙었다(실측 1440, 세 패널 전부). 블록 마진은 형제의 margin-top과 상쇄되지만 여기서는
   p가 margin-top:auto라 상쇄가 일어나지 않아, 실측 간격은 항상 14 + 남는 높이가 된다 */
.prod-media span {
  display: block;
  margin-top: 7px;
  margin-bottom: 14px;
  color: var(--text-l-2);
  font-size: 14.5px;
  line-height: 1.55;
  font-weight: 700;
  word-break: keep-all;
}

/* 상품 나열 — auto 마진으로 카드 바닥에 붙여 3장의 구분선 높이를 맞춘다(.mp-note와 같은 처리) */
.prod-media p {
  margin: auto 0 0;
  padding: 12px 0 0;
  border-top: 1px solid var(--border-l1);
  color: var(--blue);
  font-size: 13.5px;
  line-height: 1.6;
  font-weight: 700;
  word-break: keep-all;
  overflow-wrap: break-word;
}

/* ---- 하단 밴드 ----
   패널의 결론 한 줄. 카드(l0)보다 한 단계 내린 l2 면이라 카드 아래에서 바닥처럼 읽힌다 */
.prod-band {
  margin: var(--gap-3) 0 0;
  padding: 14px 20px;
  border: 1px solid var(--border-l2);
  border-radius: var(--r-sm);
  background: var(--surface-l2);
}

.prod-band,
.prod-band > ul {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--gap-1) var(--gap-3);
  list-style: none;
}

.prod-band > ul {
  flex: 1 1 100%;
  margin: 0;
  padding: 0;
}

.prod-band li {
  display: flex;
  align-items: baseline;
  gap: var(--gap-1);
  color: var(--text-l-1);
}

.prod-band b {
  font-size: 14px;
  line-height: 1.4;
  font-weight: 800;
}

/* l2 면에서 --text-l-3은 4.68:1 — AA 하한을 넘는 마지막 단계라 여기서 더 내리지 않는다 */
.prod-band span {
  color: var(--text-l-3);
  font-size: 12.5px;
  line-height: 1.4;
  font-weight: 700;
  word-break: keep-all;
}

/* 각주 — 11 WORKS·12의 라이트 각주와 같은 규격.
   각주류 행간은 1.5/1.6/1.7 세 값이 섞여 있었다. 중앙값이자 이미 두 곳(10·11)이
   쓰던 1.6으로 모은다 — 크기(12.5)·색(--text-l-3)은 이미 공통 */
.prod-note {
  margin: var(--gap-2) 0 0;
  color: var(--text-l-3);
  font-size: 12.5px;
  line-height: 1.6;
  word-break: keep-all;
}

/* ---- 전체 라인업 ----
   탭 패널이 "고른 하나"를 보여준다면 이 표는 "전부"를 한 화면에 편다.

   [블록 분리] 클라이언트가 "섹션을 나눠야 하지 않나"라고 본 지점이다. 번호를 새로 주면
   08~15와 내비·스크롤스파이 계약이 전부 밀리므로 번호는 그대로 두고, 07 안에서 시각적으로만
   독립시킨다. 장치는 세 가지이고 전부 사이트가 이미 쓰는 문법이다:
     (a) 상단 이음매를 --border-l2 실선에서 --grad-line으로 바꾼다 — 사이트가 배경 톤이 바뀌는
         모든 섹션 경계에 까는 시그니처 헤어라인이라, 이 선 하나로 "여기서 장이 바뀐다"가 읽힌다.
     (b) 위 여백을 --gap-editorial(72, 챕터 안 장 전환)에서 --section-y-tight로 올린다 —
         섹션 간 리듬의 값이다. 이음매 위 96 + 아래 56 = 헤드까지 152px.
     (c) 헤드 위계를 패널 헤드(--t-sub-1)보다 한 단 올린다(아래 h3 참조). */
/* 라인업 이음매 — ::before 1px 선을 사이에 두고 위아래를 같은 값으로 맞춘다.
   전에는 선 위 120px(패널 padding-bottom 24 + --section-y-tight 96) · 아래 56px으로
   2:1이 넘게 어긋나 있었고, 합 176px은 이 섹션의 블록 간격 단위(헤딩→탭 48, 탭→패널 48)의
   3.7배였다. 위쪽 몫에서 패널이 이미 낸 24px를 빼면 선 위아래가 항상 같아진다 —
   폭이 줄어 clamp가 36px까지 내려가도 대칭이 유지된다(2026-08-29) */
.prod-lineup {
  --lineup-seam: clamp(36px, 4.4vw, 56px);
  position: relative;
  margin-top: calc(var(--lineup-seam) - 24px);
  padding-top: var(--lineup-seam);
}

.prod-lineup::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 1px;
  background: var(--grad-line);
}

/* 직전 판의 --t-sub-1(24)은 바로 위 .prod-head h3(탭 패널 헤드)와 같은 값이었다 —
   블록을 여는 머리글이 자기가 딸린 패널의 머리글과 동급이면 "또 하나의 카드"로 읽히지
   섹션으로 읽히지 않는다. 섹션 h2(clamp 32~60)와 패널 헤드(20~24) 사이에 한 칸을 낸다.

   [이번 판] 클라이언트가 "타이틀·서브타이틀에 디자인이 필요하거나 신규 섹션으로 분리해야
   할 것 같다"고 본 지점. 번호를 새로 주면 08~15의 번호·내비·스크롤스파이 계약이 전부
   밀리므로 번호는 그대로 두고, 헤드만 섹션급으로 마감한다. 30 → 38로 한 단 더 올려
   패널 헤드(24)와의 간격을 1.25배에서 1.58배로 벌린다 — 섹션 h2(최대 60)는 넘지 않으므로
   07 안의 위계는 [섹션 h2 60 > 라인업 h3 38 > 패널 h3 24]로 세 단이 또렷해진다 */
.prod-lineup h3 {
  margin: 0;
  color: var(--text-l-1);
  font-size: clamp(28px, 3.4vw, 38px);
  line-height: 1.22;
  font-weight: 800;
  letter-spacing: -0.008em;
  word-break: keep-all;
}

/* 헤드의 시각 장치 — 소개서 p21은 이 블록을 [대시 + PLATFORM LINE-UP 아이브로우] 한 줄로
   열지만 신규 문안이 0이라 라벨을 만들 수 없다. 그래서 라벨은 두고 대시만 가져온다.
   대시는 07이 이미 카테고리 라벨(.lineup-row dt::before, 12×2 --blue)에서 쓰는 장치라
   새 어휘가 아니고, 12×2 → 32×3으로 키워 같은 장치의 상위 랭크로 읽히게 한다.
   05 비교표 헤더 바(솔리드 채움 + r20)나 08 필(r20 솔리드)과는 형태가 겹치지 않는다
   — 저 둘은 '채운 면'이고 이것은 '레일'이다. 라벨 없는 대시 하나가 아이브로우 자리를
   대신하면서, 위의 --grad-line 이음매와 함께 헤드에 장(章)의 첫머리 인상을 준다 */
.prod-lineup h3::before {
  content: "";
  display: block;
  width: 32px;
  height: 3px;
  margin-bottom: clamp(18px, 1.8vw, 24px);
  background: var(--blue);
}

/* 15/1.7은 카드 본문 랭크(.service-card p)였다 — 이 문장은 카드 본문이 아니라 블록을 여는
   리드다. 사이트의 모든 섹션 리드가 쓰는 18/400/1.75로 올린다(.section-heading p와 같은 값).
   폭도 리드 표준인 820으로 맞춘다 */
.prod-lineup > p:not(.prod-note) {
  /* 18px — .section-heading p의 헤딩↔리드 간격과 같은 값(헤드를 섹션급으로 마감하는 이상
     헤드 내부 간격도 섹션 헤드의 값을 쓴다) */
  margin: 18px 0 0;
  max-width: 820px;
  color: var(--text-l-2);
  font-size: 18px;
  line-height: 1.75;
  word-break: keep-all;
}

/* 소개서 p21(PLATFORM LINE-UP)의 [라벨 레일 + 타일 그리드] 문법을 라이트 면으로 옮긴 것.
   평평한 dt/dd 나열로는 "15개 이상"이라는 규모가 읽히지 않았다 — 5열 고정 트랙에 28칩을
   깔면 열 수가 곧 규모의 눈금이 되고, 카테고리 5종은 왼쪽 레일 하나로 갈린다.
   05 비교표의 [고정 좌열 + 행 헤어라인]과 같은 뼈대이되, 05는 면을 채운 행이고
   07은 면을 채운 타일이라 두 섹션의 UI 언어는 겹치지 않는다.

   표 전체를 한 판(패널)으로 닫는 이유: 흰 타일이 흰 지면 위에 1px 보더만 두르고 떠 있으면
   행 헤어라인과 타일 보더가 같은 굵기로 섞여 "선만 그어 둔" 인상이 된다. 살짝 든 지면
   (--surface-l1)을 깔아 타일이 그 위에 얹히게 하면 타일이 물체로 읽히고 표가 닫힌다 */
.lineup-rows {
  /* 열 수만 반응형으로 갈아끼우면 되도록 타일 규격을 토큰으로 묶는다.
     --lu-slot은 로고 폭의 '상한'이다(고정 레인이 아니다 — .lu-ico 참조). 이 값이 워드마크가
     누울 수 있는 최대 폭을 정하고, 종횡비 최대치인 롯데온(6.91)이 하한을 잡는다:
     56px에서 이미 잉크 높이 8.1px이라 더 줄이면 워드마크가 읽히지 않는다 */
  --lu-cols: 5;
  --lu-tile-h: 48px;
  /* 136 → 148. 레일에서 대시(20)와 그 간격(10)을 뺀 글자 가용폭이 106px이었는데,
     "AD NETWORK &"가 108px이라 2px이 모자라 &가 밀리고 그 라벨만 3줄이 됐다
     (나머지 넷은 2줄, 클라이언트 지적 2026-08-29). 148은 가용폭을 118px로 만들어
     그 줄에 10px, 최장 어절 MARKETPLACE(108.9)에도 9px 여유를 준다 */
  --lu-rail: 148px;
  --lu-slot: 56px;
  /* 한때 11px로 좁혔다 — 마크가 28px 타일이던 동안 최장 칩("Google Analytics 4")이 1px
     모자라 접혔기 때문이다. 타일을 06·07과 같은 24px로 내리면서 4px이 돌아와 원래 값으로
     복귀한다(클라이언트 지시 2026-08-29: 라인업 로고를 매체 카드 크기로 통일) */
  --lu-pad: 12px;
  /* 헤드가 섹션급으로 올라간 만큼(h3 30→38) 헤드 덩어리와 표 사이도 함께 벌린다 —
     리드 바로 아래 붙어 있으면 표가 리드의 부속으로 읽힌다 */
  margin: clamp(36px, 3.6vw, 44px) 0 0;
  padding: 0 8px;
  background: var(--surface-l0);
  border: 1px solid var(--border-l2);
  border-radius: var(--r-md);
}

/* dt는 고정폭 라벨 레일 — 5행의 카테고리가 같은 x에서 시작해야 표로 읽힌다 */
.lineup-row {
  display: grid;
  grid-template-columns: var(--lu-rail) minmax(0, 1fr);
  gap: var(--gap-1) 12px;
  align-items: center;
  padding: 16px 0;
  border-bottom: 1px solid var(--border-l2);
}

/* 패널 자신의 보더가 마지막 행의 밑줄을 대신한다 */
.lineup-row:last-child {
  border-bottom: 0;
}

/* 대시 + 라벨 — p21의 카테고리 표기 그대로. 색은 dt가 이미 쓰던 --blue 하나뿐이다 */
.lineup-row dt {
  display: flex;
  gap: 10px;
  margin: 0;
  color: var(--blue);
  font-size: 12.5px;
  line-height: 1.5;
  font-weight: 800;
  letter-spacing: var(--t-label-ls);
  text-transform: uppercase;
  word-break: keep-all;
}

.lineup-row dt::before {
  content: "";
  flex: 0 0 auto;
  width: 20px;
  height: 2px;
  /* 2줄짜리 라벨(COMMERCE & MARKETPLACE 등)에서도 대시가 라벨 덩어리 중심에 오게 —
     p21의 카테고리 표기가 그렇다.

     폭 12 → 20: p21에서 이 대시는 라벨 활자 높이의 1.8배쯤 되는 '표식'인데, 12px면
     라벨보다 짧아 점처럼 읽혔다. 소개서에 없는 행 괘선이 사이트에는 있어서, 짧은 대시가
     그 괘선의 조각처럼 보이던 것이 클라이언트가 걸린 지점이다(2026-08-29) */
  align-self: center;
  background: var(--blue);
}

.lineup-row dd {
  margin: 0;
}

/* 라인업 로고 타일 — 고정 트랙 5열 × 균일 높이 × 표기 규칙 하나.

   [표기 규칙] 28칩 전부 [로고 마크 + 매체명]이다. 직전 판은 심볼형 20칩만 이름을 달고
   워드마크형 8칩(쿠팡·옥션·SSG·롯데온·무신사·올리브영·크리테오·모비온)은 "로고가 곧
   이름"이라며 라벨을 sr-only로 숨겼다 — 한 표 안에 [아이콘+글자]와 [그림만] 두 규칙이
   섞이면서 매체명이 시작하는 x가 12px과 39~68px로 갈렸고, 로고 렌더 폭도 18px에서 90px까지
   5배로 벌어졌다. 클라이언트가 지적한 "일관적이지 않다"의 실체가 이것이다.
   숨긴 라벨을 그대로 표면화해(문안 신설 0) 규칙을 하나로 되돌린다.

   [정렬 축] 워드마크를 심볼과 같은 정사각 슬롯에 넣을 수는 없다(롯데온 종횡비 6.91).
   대신 로고 레인 폭 --lu-slot을 고정하고 그 안에 contain으로 앉힌다 —
   심볼은 슬롯 중앙에 20px 정사각으로, 워드마크는 슬롯 폭을 꽉 채워 눕는다.
   로고의 물리적 크기는 달라도 매체명은 28칩 모두 같은 x에서 시작한다.

   렌더 규칙은 28칩 전부 하나다: 자산은 색이 없는 알파 실루엣이고, 색은 --brand가 준다.
   앞선 라운드에서 9개 칩을 원본 컬러로 돌렸다가 되돌린 이유는 색이 아니라 질량이었다 —
   네이버·카카오·인스타·틱톡은 공식 "앱 아이콘" 락업(꽉 찬 사각 컨테이너 + 흰 녹아웃)이라
   20px 슬롯을 96% 채우는 반면, 같은 줄의 실루엣 칩은 30~42%만 채운다. 3배 차이가
   한 행 안에서 나면 어떤 칩은 배지, 어떤 칩은 아이콘으로 읽혀 라인업의 격이 갈린다.
   그래서 자산은 컨테이너 없는 글리프만 쓴다 — 면을 만드는 일은 타일이 전담한다 */
.lineup-chips {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(var(--lu-cols), minmax(0, 1fr));
  gap: 8px;
}

/* 흰 면 + 1px 보더 — 실루엣이 앉을 자리를 만든다. 로고 자체는 컨테이너를 갖지 않으므로
   (아래 .lu-ico 참조) 면을 만드는 일은 타일 하나가 전담한다.

   ── "로고랑 매체명이 정렬이 안 맞는다"의 실체 (3배율 잉크 bbox 실측) ──────────────
   가로 축은 이미 맞아 있었다: 로고 잉크 좌단 13.0px(26/28칩, 최대편차 +1.3), 매체명 좌단
   77.0px(28/28), 잉크 세로 중심은 타일 중심 대비 ±0.17px. 세 축 모두 균일하다.
   깨져 있던 것은 [로고 잉크 우단 → 매체명 좌단] 간격이었다:
     심볼형 20칩 41.3~46.3px  vs  워드마크형 8칩 8.0px  — 5.5배.
   슬롯(56px)은 28칩 공통이지만 그 안을 심볼은 20px(36%)만, 워드마크는 56px(100%)를 채운다.
   그래서 한 행 안에서 어떤 타일은 로고와 이름이 붙어 있고 어떤 타일은 44px 구멍이 난다.
   가장 심한 곳이 AD NETWORK 행이다 — 44 / 42 / 8 / 41 / 8 로 한 줄에서 번갈아 뛴다.
   ("심볼 뒤 남는 여백은 눈에 보이지 않는다"고 적었던 직전 판의 전제가 틀렸다.)

   ── 이번 판이 뒤집은 것: 축을 좌단에서 '중심'으로 옮긴다 ────────────────────────
   위의 '로고 셀' 판(고정 56px 레인을 --surface-l1로 칠해 [로고 셀 | 매체명] 두 칸을 만든 것)은
   좌단 축 두 개(로고 13.0 / 이름 83.0, 28/28 균일)를 지켰지만 클라이언트는 그 결과를
   "디자인이 안 된 것 같다 — 좌측으로 치우친 로고, 매체명"으로 읽었다. 실측이 그 말을 뒷받침한다
   (1440 · 타일 200.4px 기준):
     · 내용 좌측 패딩은 12px 고정인데 우측 여백은 17.4~107.8px — 편차 90.4px,
       타일 폭의 45%가 오른쪽에만 쌓인다. 평균 우측 여백 73.7px = 좌측의 6.1배.
     · 로고 잉크 우단→이름 좌단 간격은 심볼 20칩 47.5~52.0 vs 워드마크 8칩 14.0 — 3.6배.
       고정 레인 안에서 정사각 심볼은 20/56(36%)만 채우므로 레인 오른쪽 절반이 빈다.
   즉 타일 안에 빈 곳이 두 군데(레인 우측 + 타일 우측) 생기고, 그 사이 37% 지점에 셀 경계가
   세로줄로 지나간다. 소개서 p21은 이 셀 경계가 없다 — 거기선 [로고 + 이름]이 12px 간격으로
   붙은 한 덩어리 락업이고, 남는 여백은 락업 바깥에만 있다.

   [채택] p21의 락업 문법으로 돌아간다. 세 가지가 함께 움직인다:
     (a) 로고 상자를 잉크에 맞춰 줄인다(아래 .lu-ico) — 레인의 빈 오른쪽이 사라져
         로고↔이름 간격이 28칩 전부 12px로 균일해진다.
     (b) 락업을 타일 중앙에 앉힌다 — 좌우 여백이 정의상 같아지므로 '좌측 쏠림'이 소멸한다.
     (c) 칠을 레인에서 타일 전체로 옮긴다 — 같은 --surface-l1을 쓰되 반쪽 띠가 아니라
         타일 한 면을 채운다. 세로 셀 경계가 없어지고, 흰 패널 위 흰 타일이던 것이
         [지면 l1 → 패널 l0 → 타일 l1] 3단으로 갈려 타일이 물체로 읽힌다(p21의 채운 타일).
   [포기] 로고 좌단 13.0 / 이름 좌단 83.0의 x축 정렬과 '셀 경계↔이름 간격 균일'.
   중앙 정렬은 절대 x축을 원리적으로 쓸 수 없다 — 대신 락업 내부 간격이 축이 된다 */
.lineup-chips li {
  display: flex;
  align-items: center;
  /* 좌우 여백을 같게 만드는 한 줄 — 클라이언트가 지적한 '좌측 쏠림'의 직접 해소책 */
  justify-content: center;
  gap: 12px;
  min-width: 0;
  /* min-height로 두면 이름이 두 줄로 접히는 좁은 폭에서도 같은 행의 타일이
     그리드 행 높이를 공유해 함께 자란다 — 균일성이 깨지지 않는다 */
  min-height: var(--lu-tile-h);
  padding: 0 var(--lu-pad);
  background: var(--surface-l1);
  border: 1px solid var(--border-l2);
  border-radius: var(--r-sm);
}

/* :not(.sr-only)는 남겨 둔다 — 라인업 28칩은 전부 표면 라벨이지만
   셀렉터가 다른 sr-only 텍스트를 잘못 물지 않게 하는 가드다 */
.lineup-chips li > span:not(.sr-only) {
  min-width: 0;
  color: var(--text-l-1);
  /* 직전 판이 "4.4px 모자라 접힌다"며 포기한 15px을 이번에 되찾았다. 로고 상자가 잉크로
     줄면서(위 .lu-ico) 최장 칩("네이버 애널리틱스")의 내용 폭이 56+14+100=170에서
     20+12+107=139로 31px 줄어, 200.4px 타일 안에 15px 이름이 한 줄로 들어간다.
     심볼 칩에서 헛돌던 36px 레인을 글자 크기로 환산한 셈이다 */
  font-size: 15px;
  line-height: 1.4;
  /* 700 → 600. 이 열의 이름과 좌측 카테고리 라벨(dt, 12.5/800)이 둘 다 굵어 "어느 쪽이
     머리글인지" 굵기로는 구분되지 않았다(클라이언트 지적, 2026-08-29). 실측으로는 이미
     이름 쪽이 우세했다 — 잉크 높이 14px 대 10px, 대비 18.26:1 대 5.26:1 — 그래서 굵기만
     라벨이 위인 상태가 서로 다른 축에서 맞붙는 모양이었다.
     두 요소를 각자 다른 축에 실어 경쟁을 없앤다: 라벨은 굵기·색·대문자 자간으로 상위,
     이름은 크기로 존재감을 갖는다. 타일의 주역은 로고이고 이름은 그 로고를 읽어 주는
     보조 라벨이므로, 낮추는 쪽은 이름이다 — 라벨을 낮추면 04 영문 영역명(13.5/800)·
     06 STAGE와 같은 계열인 사이트 라벨 문법이 이 한 곳만 어긋난다 */
  font-weight: 600;
  word-break: keep-all;
}

/* 로고 상자를 잉크에 맞춰 줄인다 — --lu-slot은 이제 '고정 레인'이 아니라 '폭 상한'이다.
   contain 마스크의 잉크 크기는 [높이 20px × 종횡비]와 [폭 상한 56px] 중 작은 쪽이 정하므로,
   같은 식을 상자 크기에 그대로 쓰면 상자가 잉크에 딱 맞는다(렌더 크기는 1px도 변하지 않는다.
   바뀌는 것은 잉크 오른쪽에 남던 빈 상자뿐이다):
     심볼(종횡비 0.90~1.13) → 18.0~22.5 × 20px      워드마크(2.33~6.91) → 56 × 8.1~24.0
   종횡비는 자산마다 다르므로 칩 인라인 --ar가 나른다(기본 1 = 정사각 심볼 12칩은 생략).
   빈 상자가 사라지면서 로고 잉크 우단→이름 좌단 간격이 gap 하나로 수렴한다: 28칩 전부 12.0px.
   마스크 정렬도 left에서 center로 돌린다 — 상자가 곧 잉크라 두 값이 같은 결과를 내지만,
   반올림으로 상자가 0.5px 남을 때 잉크가 한쪽으로 쏠리지 않게 중앙을 기준으로 둔다 */
/* 로고 타일 — 소개서 p21의 표기다. 거기서는 모든 마크가 정사각 라운드 타일 안에 앉고,
   타일 바탕은 그 브랜드의 앱 아이콘 색이다(클라이언트 지시 2026-08-29: "전체 로고들이
   소개서처럼 사각형 쉐입 안에 로고 있는 형태로"). 상단 스트립은 지시대로 제외한다 —
   그쪽은 currentColor 마스크라 다크 띠에서 흰 워드마크로 나오는 구조다.

   바탕색은 임의로 고르지 않았다. p21 렌더에서 28칩의 타일 모서리를 좌표로 찍어 전수
   샘플링한 값이다(네이버 #03C75A · 카카오 #FEE500 · 유튜브 #FF0000 · 옥션 #DB2432 …).
   흰 바탕인 칩도 p21에 8개 있다(구글·메타·쿠팡·크리테오·GA4·빅쿼리·메타픽셀·올리브영) —
   그쪽은 마크 자체가 컬러라 바탕을 비우는 것이 원본이다.

   타일은 마크를 감싸는 상자이므로 마스크는 ::before로 내려가고, 이 요소는 바탕과
   라운드만 맡는다. --ar(가로 워드마크 비율)은 ::before의 contain이 대신 처리한다 */
.lu-ico {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  box-sizing: border-box;
  /* 정사각이 기본. 앱 아이콘이 없어 가로 워드마크를 그대로 쓰는 칩만 상자를 넓힌다 —
     쿠팡(4.42:1)·옥션(6.44:1)·올리브영(8.85:1)은 28px 정사각에 contain으로 넣으면 잉크
     높이가 각각 4.8 / 3.3 / 2.4px이 되어 마크가 읽히지 않는다. 상자만 늘리고 라운드·바탕·
     정렬은 정사각 칩과 같은 값이라 '사각 타일'이라는 표기는 유지된다 */
  width: var(--lu-tile-w, var(--lu-tile, 24px));
  height: var(--lu-tile, 24px);
  border-radius: 7px;
  background: var(--tile, var(--surface-l0));
  box-shadow: inset 0 0 0 1px rgba(10, 16, 32, 0.08);
  overflow: hidden;
}

.lu-ico::before {
  content: "";
  width: var(--logo-w, 76%);
  height: var(--logo-w, 76%);
  background: var(--brand, var(--text-l-1));
  -webkit-mask: var(--ico) center / contain no-repeat;
  mask: var(--ico) center / contain no-repeat;
}

/* 폴리크롬 예외 — 28칩 중 22칩은 단색 마크라 마스크가 무손실이지만, 4색 G와
   멀티컬러 워드마크는 단색 실루엣을 통과하면 브랜드 식별이 무너진다(소개서 p21 대조,
   클라이언트 지적 2026-08-29). 같은 판단이 이미 여정 카드에 적용돼 있다
   (.mp-ico.is-original, 2026-08-25 승인) — 쿠팡이 한 페이지에서 두 색으로 나오던
   불일치를 여기서 해소한다.
   마스크만 풀고 같은 벡터를 배경으로 그린다. 상자 치수도 잉크 면적도 1px 변하지 않는다
   (마스크든 배경이든 칠해지는 픽셀은 동일한 벡터 알파다 — 28칩 박스 실측 불변 확인).
   .mp-ico.is-original과 달리 면·테두리·라운드는 두지 않는다: 꽉 찬 앱아이콘 타일은
   심볼칩과 질량 격차를 만들어 이전 라운드에서 회귀했다. 투명 배경 글리프만 허용한다.
   2026-08-29 웹 재확보에서 이 금지선을 숫자로 못박았다 — 공식 타일 자산의 잉크 커버리지는
   카카오 99.5% · 인스타그램 95.8% · 틱톡 95.9%로 28칩 밴드(27.4~83.8%) 바깥이다.
   확보 목록과 판단 근거 전문은 .mp-ico.is-original 주석에 있다 */
.lu-ico.is-original::before {
  -webkit-mask: none;
  mask: none;
  background: var(--ico) center / contain no-repeat;
}

/* 마크가 아니라 아이콘 전체가 타일인 자산(인스타그램 그라디언트 등) — 안쪽 여백 없이
   타일을 꽉 채우고, 자기 색이 곧 바탕이므로 인셋 테두리도 걷는다 */
.lu-ico.is-full {
  box-shadow: none;
}

.lu-ico.is-full::before {
  width: 100%;
  height: 100%;
}

.prod-lineup .prod-note {
  margin-top: var(--gap-2);
}

/* ---- 07 로컬 반응형 ---- */
@media (max-width: 1024px) {
  /* [4칸 유지] 전에는 4항목 패널만 2칸으로 접었는데, 그러면 이 폭에서 3항목 패널은 3칸,
     4항목 패널은 2칸이 되어 카드 폭 차이가 데스크탑보다 오히려 커졌다(389 vs 592).
     세 패널이 같은 트랙을 쓰는 것이 이 라운드의 계약이므로 4칸을 그대로 들고 내려간다 —
     1024px에서 트랙은 232px이고, 가장 긴 라벨("상품 경쟁력 정비")과 설명이 모두 들어간다.
     탭이 걷히는 ≤768px에서 2칸, ≤720px에서 1칸으로 세 패널이 함께 접힌다 */

  /* 레일을 줄이고 트랙을 4열로 — 타일은 [로고 + 최장 매체명] 락업을 한 줄로 들어야 한다.
     --lu-slot(로고 폭 상한)은 어느 폭에서도 손대지 않는다 — 이 값이 흔들리면 워드마크
     8칩의 잉크 높이가 같이 흔들려 심볼 칩과의 질량 차가 폭마다 달라진다 */
  .lineup-rows {
    --lu-cols: 4;
    /* 데스크톱과 같은 148 — 128에서는 "AD NETWORK &"가 가용폭 98px을 10px 넘겨
       이 폭에서만 그 라벨이 다시 3줄로 돌아간다. 4열이라 트랙에 여유가 있어
       레일을 20px 내주고도 최장 칩이 한 줄로 남는다 */
    --lu-rail: 148px;
    --lu-pad: 10px;
  }
}

/* 탭을 걷고 세 패널을 아코디언식으로 모두 편다.
   [hidden] 속성이 붙은 마크업이어도 작성자 스타일이 UA 규칙을 이기므로 그대로 펼쳐진다 */
@media (max-width: 768px) {
  .prod-tabs {
    display: none;
  }

  .prod-panel,
  .prod-panel.is-active {
    display: block;
  }

  .prod-panel + .prod-panel {
    margin-top: 32px;
    padding-top: 28px;
    border-top: 1px solid var(--border-l2);
  }

  /* 이 폭부터는 .prod-cap이 헤드 표식을 맡으므로 28×2px 룰은 걷는다 —
     라벨 위에 대시가 아니라 라벨 아래에 대시가 서면 소개서의 레일 문법이 뒤집힌다 */
  .prod-head::before {
    display: none;
  }

  /* 탭 라벨이 사라진 자리를 대신하는 패널 헤더 — 아이브로우와 같은 트래킹 라벨 문법 */
  .prod-cap {
    display: block;
    margin: 0 0 12px;
    color: var(--blue);
    font-size: 12px;
    line-height: 1.2;
    font-weight: 800;
    letter-spacing: var(--t-label-ls);
    text-transform: uppercase;
  }

  /* 항목 수 규칙(:has, 0-2-0)이 이 한 줄(0-1-0)을 이기므로 같은 형태로 함께 덮는다 —
     위 --prop-cols 주석이 경고한 "특이도가 엇갈려 서로를 못 이기는" 자리가 여기다.
     이 폭부터 4항목 패널은 4열에서 158px까지 눌리고, 3항목 패널은 2행으로 갈린다 */
  .prod-props,
  .prod-props:has(> li:nth-child(4)),
  .prod-props:has(> ol > li:nth-child(4)) {
    --prop-cols: 2;
  }

  /* 칸이 두 행으로 갈리면 가로 사슬은 성립하지 않는다 — 순서는 01~04 넘버가 그대로 진다 */
  .prod-props li:not(:last-child)::after {
    content: none;
  }

  /* 레일을 버리고 dt/dd를 세로로 쌓는다 — 이 폭부터는 고정 레일을 유지하면
     타일이 [슬롯 + 최장 매체명 "네이버 애널리틱스"]를 한 줄로 들 수 없다.
     라벨은 타일 그리드 위 한 줄짜리 머리글이 되고, 대시 + 라벨 문법은 그대로다 */
  .lineup-row {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--gap-1);
    align-items: start;
  }

  .lineup-rows {
    --lu-cols: 3;
  }
}

@media (max-width: 720px) {
  /* 항목 수 규칙과 특이도를 맞춘다(위 @768과 같은 이유). 화살촉은 그 블록이 이미 걷었다 */
  .prod-props,
  .prod-props:has(> li:nth-child(4)),
  .prod-props:has(> ol > li:nth-child(4)) {
    --prop-cols: 1;
  }

  .prod-media,
  .prod-media > ul {
    grid-template-columns: 1fr;
  }

  .prod-band {
    padding: 14px 16px;
  }

  .prod-band,
  .prod-band > ul {
    justify-content: flex-start;
    gap: var(--gap-1) var(--gap-2);
  }

  /* 로고 폭 상한(--lu-slot)과 심볼 높이는 어느 폭에서도 건드리지 않는다 —
     28칩이 같은 렌더 규칙을 쓰는 것이 표기 단일화의 전제다. 좁아지면 열을 줄인다 */
  .lineup-rows {
    --lu-cols: 2;
    --lu-tile-h: 46px;
    padding: 0 8px;
  }
}

/* 사이트의 리드는 이 폭에서 16px로 내려간다(≤420px의 .section-heading p:not(.eyebrow)).
   패널 리드를 18px 그대로 두면 자기를 감싼 섹션 리드보다 커져 위계가 뒤집힌다
   (실측 400px: 섹션 리드 16 / 패널 리드 18). 리드 규격을 따라가는 이상 하강도 같이 따라간다 */
@media (max-width: 420px) {
  .prod-head p {
    font-size: 16px;
  }
}

/* 폰 폭에서는 2열조차 [슬롯 + 최장 매체명]을 한 줄로 못 든다(실측: 2열 유지 하한 ≈ 414px).
   칩을 줄여 규칙을 무너뜨리는 대신 열을 하나로 편다 — 표기 규칙이 28칩 전부 같아야 한다 */
@media (max-width: 460px) {
  .lineup-rows {
    --lu-cols: 1;
  }
}

/* (2) 운영 프로세스 — 세로 1열 필 파이프라인(B안 .b3-proc 문법 이식).
   구 5열 카드 그리드를 걷고 [헤더 필 → ∨ → 스텝 필 ×5 → 리턴 루프] 한 축으로 세운다.
   필 규격은 B안 실측치를 그대로 승계한다: 폭 570 / 헤더 66 / 스텝 68 / ∨ 구간 65 / 필 간격 20.
   ※ 필 안에 드는 것은 [글리프 · 번호 · 제목] 뿐이다. 요약(p)과 수행 항목(.pm-do)이 필 안으로
     들어가면 높이가 68을 넘겨 파이프라인 리듬이 무너지므로 반드시 필 바깥 아래에 쌓는다.
   ※ 05 STAGE 레일(카드 밖 공유 레일)과의 언어 분리는 그대로 유지된다 —
     08은 '필 + 화살표 배선 + 리턴 루프'이고 노드·레일 문법을 쓰지 않는다.

   ── 08 정렬 규칙(불변 · 이 섹션의 모든 요소가 예외 없이 따른다) ─────────────
   (a) 축: 헤더 필 / ∨ / 스텝 필 ×5 / 요약 / 실행 항목 / 배선 / 링 / 캡션의
       중심 x는 전부 --pm-pill-w의 중심 한 점을 쓴다. 좌측 정렬 요소는 08에 없다.
   (b) 텍스트도 축을 지킨다 — 상자만 가운데가 아니라 글자 잉크의 중심까지 (a)의 축에 앉는다.
       필 안 좌측 글리프는 position:absolute라 흐름에서 빠지지만, 글리프가 비켜서라고
       비워 둔 좌측 레인은 우측에도 같은 값으로 되비워 콘텐츠 박스를 필과 동심(同心)으로 만든다.
       ※ 좌우 패딩을 다르게 주면 그 차의 절반만큼 글자가 밀린다(구판 66/28 = 19px 편차,
         헤더 필 글자는 0px라 두 필의 글자 축이 19px 어긋나 보였다 — "디테일이 안 맞는" 실체).
   (c) 셰브런 어휘: 08의 꺾인 마크는 전부 [팔 45° · 획 2px] 하나로 통일한다.
       스텝 배선 화살촉 = 10px 상자, ∨ 구간 마크 = --pm-chev-box 상자, 같은 구성·같은 획.
       폰트 글리프는 쓰지 않는다(문자 ∨는 팔 63.4°·획 1.36px으로 이 어휘 밖이었다).
   (d) 필 아래 설명류(요약 p / 실행 항목 .pm-do / 루프 캡션)는 전부 text-align:center.
       한 요소라도 left로 새면 좁은 폭에서 랩될 때 축이 무너진다 */
.pm-block {
  /* 필 치수 토큰 — 헤더·스텝·루프·캡션이 모두 이 폭 하나를 공유해 중앙축이 한 줄로 선다 */
  --pm-pill-w: 570px;
  --pm-pill-h-head: 66px;
  --pm-pill-h-step: 68px;
  /* 묶음 사이 간격. 전진 배선(라인 + 화살촉)이 정확히 이 구간을 가로지른다.
     20 → --gap-4(48). 20일 때는 묶음 안(10/8)과 묶음 밖(20)의 대비가 2배뿐이었고
     그 20px마저 배선이 통째로 차지해 여백으로 읽히지 않았다 — 다섯 묶음이 한 덩어리로
     뭉쳐 보이던 원인이다. 이제 8(요약↔실행) < 16(필↔요약) < 48(묶음↔묶음) 세 단으로
     토큰 사다리가 서서 위계가 읽힌다 */
  --pm-gap: var(--gap-4);
  /* 마지막 묶음 → 리턴 루프. 링·점선 좌표가 모두 이 값에서 파생된다.
     48 → 48 + 16 = 64. 스텝 구간과 달리 이 한 구간 안에는 [링 · 점선 · 캡션] 세 요소가
     들어간다. 48에서는 lead(12) + 링(12)만으로 24를 쓰고 남은 24를 점선 하나와 간격 둘이
     나눠 가져야 해서, 점선이 10px 토막으로 줄거나 위계(링↔점선 < 점선↔캡션)가 성립하지
     않았다. 전역 토큰을 새로 세우는 대신 사다리 위 두 단(--gap-4 + --gap-2)의 합으로 짓는다 */
  --pm-loop-gap: calc(var(--gap-4) + var(--gap-2));
  /* ── 배선 숨 틈 ────────────────────────────────────────────────────────
     직전 라운드에서 묶음 간격을 20 → 48로 늘렸는데도 "붙어 보인다"가 남은 이유는
     간격이 아니라 그 48을 배선 잉크가 끝에서 끝까지 꽉 채웠기 때문이다. 잉크 기준 실측:
       · 화살촉 꼭짓점 y = 다음 필 보더 바깥면 → 잉크 사이 0.015px(사실상 0)
       · 세로 축 상단 = 앞 묶음 실행 항목 라인박스 하단 → 0px
       · 출발 링은 마지막 묶음 하단선에 걸터앉아 05 실행 항목 글자 잉크와 2.9px 겹쳤다
     → 간격을 더 벌리는 대신 배선을 구간 안쪽으로 들여 앉힌다. 같은 48 안에서 배선 잉크가
       22px만 쓰고 위아래로 12/14를 비우면 그 48이 비로소 여백으로 읽힌다.
     lead(12) < tail(14)은 비대칭이 아니라 잉크를 맞추기 위한 값이다 — 위가 마주보는 것은
     글자(라인박스 하단이 실제 글자 잉크보다 3.13px 아래라 그만큼 이미 벌어 둔 상태)이고,
     아래가 마주보는 것은 필의 1px 보더(여유 0)다. 결과 잉크 간격은 위 15.1 / 아래 14.0 */
  --pm-wire-lead: 12px;
  --pm-wire-tail: 14px;
  /* 리턴 루프 세 요소의 간격 위계 — 기점과 경로는 한 몸으로(6), 경로와 결론은 한 단 떼서(12).
     6 < 12라 [링 + 점선] / [캡션] 두 층으로 갈라 읽힌다 */
  --pm-loop-hop: 6px;
  --pm-loop-drop: 12px;
  /* 링 외곽 지름 — 스텝 화살촉의 외곽 상자(12)와 같은 규격이라 두 마크가 한 어휘로 읽힌다.
     마크를 줄이는 안도 검토했으나, 실측상 붙어 보이던 원인은 크기가 아니라 좌표(꼭짓점 0px ·
     링 겹침)였다. 줄여서 버는 여백은 화살촉 1.7px · 링 2px뿐이고 그 대가로 배선 어휘의
     규격 통일(규칙 c)이 깨진다 — 크기는 두고 좌표만 옮긴다 */
  --pm-ring-o: 12px;
  /* 화살촉 꼭짓점 보정 — 10px 상자 + 2px 보더 = 12×12를 135° 돌리면 꼭짓점이
     중심에서 6√2 = 8.4853px 떨어지고, 중심은 top + 6이다. 즉 top + 14.4853 = 꼭짓점 y.
     배선 top을 이 값으로 역산해 두면 --pm-gap을 바꿔도 촉이 저절로 따라온다 */
  --pm-arrow-vtx: 14.4853px;
  /* ∨ 구간 마크의 상자(content-box). 규칙 (c)에 따라 스텝 화살촉(10px 상자 + 2px 획)과
     같은 구성으로 짓고 치수만 한 단 올린다 — 잉크 폭 (14+2)·√2 = 22.6px으로
     구판 문자 ∨의 잉크 폭 21.5px을 그대로 이어받아 크기 인상은 바뀌지 않는다 */
  --pm-chev-box: 14px;
  display: flex;
  flex-direction: column;
  align-items: center;
}

/* 헤더 필 570×66 솔리드 — 파이프라인 전체의 이름표라 유일하게 면을 채운다.
   흰 글자 / --blue 면은 5.26:1로 AA 통과 */
.pm-flow-head {
  display: flex;
  align-items: center;
  justify-content: center;
  width: min(var(--pm-pill-w), 100%);
  min-height: var(--pm-pill-h-head);
  margin: 0;
  padding: 10px 28px;
  background: var(--blue);
  border: 1px solid var(--blue);
  border-radius: var(--r-lg);
  color: #ffffff;
  font-size: 17px;
  line-height: 1.5;
  font-weight: 600;
  letter-spacing: -0.01em;
  text-align: center;
  word-break: keep-all;
}

/* ∨ 구간 65px — 헤더 필 하단에서 첫 스텝 필 상단까지. 스텝 사이에는 두지 않는다
   (다섯 번 반복하면 무거워진다 — 스텝 사이는 아래 화살표 배선이 잇는다).
   마크는 문자 ∨가 아니라 아래 ::before가 그린다 — 규칙 (c). 문자 글리프는 이 폰트에서
   팔 63.4°·획 1.36px으로 렌더되어 스텝 화살촉(45°·2px)과 다른 마크로 읽혔다.
   문서의 문자 노드 "∨"는 그대로 두고 잉크만 걷는다(마크업·문안 불변, aria-hidden 유지) */
.pm-flow-chev {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 65px;
  color: var(--blue);
  font-size: 0;
  line-height: 0;
}

/* 회전 후 잉크는 상자 중심의 아래쪽 절반에만 남는다(꼭짓점이 아래, 팔 끝이 중심 높이).
   잉크 중심은 상자 중심에서 (외곽 절반)/√2 만큼 아래로 처지므로 그만큼 되올려야
   65px 구간의 정중앙에 앉는다. 상수 대신 --pm-chev-box에서 역산해 치수를 바꿔도 따라온다 */
.pm-flow-chev::before {
  content: "";
  width: var(--pm-chev-box);
  height: var(--pm-chev-box);
  border-top: 2px solid var(--blue);
  border-right: 2px solid var(--blue);
  transform: translateY(calc(-1 * (var(--pm-chev-box) + 2px) / 2 / 1.4142136)) rotate(135deg);
}

.pm-steps {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* li는 투명 래퍼다 — 필은 아래 > strong 이 맡고, li 는 [필 + 요약 + 수행 항목] 묶음을 든다 */
.pm-step {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  width: min(var(--pm-pill-w), 100%);
}

.pm-step + .pm-step {
  margin-top: var(--pm-gap);
}

/* 전진 배선(1/2) — 앞 묶음과 다음 필 사이 48px 구간을 '가로지르는' 대신 그 안쪽에 앉는다.
   상단 lead(12) 아래에서 시작해 화살촉 꼭짓점(= 하단 tail 위)에서 끝나므로 경로 잉크는
   48 − 12 − 14 = 22px이다. 구판은 top:100% / height:var(--pm-gap)으로 구간을 통째로 채워
   위로는 앞 묶음 글자에, 아래로는 다음 필 보더에 잉크가 맞닿아 있었다 —
   간격은 48인데 여백이 0이라 다섯 묶음이 여전히 한 덩어리로 붙어 보이던 실체다.
   두께 2px·잉크 0.75는 구 5열판의 수평 커넥터에서 그대로 옮긴 값(연속 경로 단) */
.pm-step:not(:last-child)::before {
  content: "";
  position: absolute;
  top: calc(100% + var(--pm-wire-lead));
  left: 50%;
  width: 2px;
  height: calc(var(--pm-gap) - var(--pm-wire-lead) - var(--pm-wire-tail));
  margin-left: -1px;
  background: rgba(15, 99, 234, 0.75);
  pointer-events: none;
}

/* 전진 배선(2/2) — 축 끝의 화살촉. top = 100% + gap − tail − 14.4853 이면 꼭짓점 y가
   식(式)으로는 정확히 100% + gap − tail, 즉 다음 필의 보더 바깥면에서 tail(14px)만큼 위다.
   실렌더는 크롬이 top을 LayoutUnit(1/64px)으로 스냅해 0.015px 낮게 앉는데, 이는 상수 5.5를
   박아 두었던 구판과 같은 오차다. 상수 대신 --pm-gap / --pm-wire-tail에서 역산하므로
   간격이든 숨 틈이든 값을 바꾸면 촉이 저절로 따라온다.
   ※ 구판에는 tail 항이 없어 꼭짓점이 다음 필의 보더 바깥면에 그대로 얹혔다 — 잉크 간격
     0.015px, 즉 "01 02 사이 화살표가 너무 붙어있다"는 피드백의 정확한 실체다.
   화살촉 잉크는 꼭짓점에서 위로 6√2 = 8.49px까지 뻗으므로 축 22px의 아래쪽을 겹쳐 문다.
   잉크 0.85는 05 .mp-rail::after와 같은 '방향 표식' 값이며 l2 면에서 3.80:1(비텍스트 3:1 통과) */
.pm-step:not(:last-child)::after {
  content: "";
  position: absolute;
  top: calc(100% + var(--pm-gap) - var(--pm-wire-tail) - var(--pm-arrow-vtx));
  left: 50%;
  width: 10px;
  height: 10px;
  border-top: 2px solid rgba(15, 99, 234, 0.85);
  border-right: 2px solid rgba(15, 99, 234, 0.85);
  transform: translateX(-50%) rotate(135deg);
  pointer-events: none;
}

/* 스텝 필 570×68 — 흰 면 + 1px --blue 아웃라인. 헤더 필과 반전 관계다.
   좌우 패딩은 반드시 같은 값이다 — 규칙 (b). 66은 좌측 글리프(left 24 + 폭 19)가
   비켜서라고 비워 둔 레인이고, 같은 값을 우측에도 되비워야 콘텐츠 박스가 필과 동심이 된다.
   구판 66/28은 그 차의 절반인 19px만큼 [번호 + 제목]을 오른쪽으로 밀어,
   글자가 0px로 정확히 가운데 앉는 헤더 필과 축이 어긋나 있었다.
   좌우 66을 빼도 글자가 쓸 수 있는 폭은 570−132 = 438px(최장 실측 잉크 142.2px)이라
   줄 수는 그대로 1줄이고 필 높이 68은 불변이다 */
.pm-step > strong {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: var(--pm-pill-h-step);
  padding: 12px 66px;
  background: var(--surface-l0);
  border: 1px solid var(--blue);
  border-radius: var(--r-lg);
  color: var(--text-l-1);
  font-size: 17px;
  line-height: 1.5;
  font-weight: 600;
  letter-spacing: -0.01em;
  text-align: center;
  word-break: keep-all;
  transition: border-color var(--dur) ease, background-color var(--dur) ease;
}

/* 호버는 색만 — 리프트·그림자 없음(모션 금지 구간) */
.pm-step > strong:hover {
  background: var(--surface-l1);
}

/* 스텝 번호 — 잉크 하나로만 세운다(면 채움 없음). 마침표는 CSS 글리프라
   문서의 텍스트 노드는 "01"인 채로 원본과 같다 */
.pm-no {
  margin-right: 6px;
  color: var(--blue);
  font-size: inherit;
  line-height: inherit;
  font-weight: inherit;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0;
}

.pm-no::after {
  content: ".";
}

/* 요약 — 필 바깥 아래 --gap-2(16), 필과 같은 폭으로 고정해 중앙 정렬축을 한 줄로 세운다.
   10 → 16: 보더 있는 필 바로 밑 10px는 글이 필에 눌어붙어 보였다. 아래 실행 항목과의
   8px보다 한 단 넓혀 [필] / [요약 + 실행 항목] 두 층으로 갈라 읽히게 한다.
   뮤트 잉크 --text-l-3 / l2 면은 4.68:1로 AA 통과 */
.pm-step > p {
  width: 100%;
  margin: var(--gap-2) 0 0;
  color: var(--text-l-3);
  font-size: 15px;
  line-height: 1.6;
  font-weight: 400;
  letter-spacing: -0.01em;
  text-align: center;
  word-break: keep-all;
}

/* 수행 항목 — A안 고유 정보라 버리지 않는다. 다만 필 안에 넣으면 높이가 무너지고
   요약 아래 세로 목록으로 쌓으면 묶음이 두 배로 길어져 파이프라인이 안 읽힌다.
   → 요약 바로 아래 한 줄짜리 인라인 행으로 눕힌다(데스크탑에서 1행 유지, 실측 최장 409px < 570) */
.pm-do {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 6px 18px;
  width: 100%;
  /* 요약과 한 층으로 묶이는 자리라 사다리의 맨 아랫단(--gap-1 = 8)을 그대로 쓴다 */
  margin: var(--gap-1) 0 0;
  padding: 0;
  border: 0;
  list-style: none;
}

.pm-do li {
  display: flex;
  align-items: flex-start;
  gap: var(--gap-1);
  color: var(--text-l-2);
  font-size: 13.5px;
  line-height: 1.5;
  font-weight: 600;
  word-break: keep-all;
}

.pm-do li::before {
  content: "";
  flex: 0 0 auto;
  width: 5px;
  height: 5px;
  margin-top: 6px;
  border-left: 1.5px solid var(--blue);
  border-bottom: 1.5px solid var(--blue);
  transform: rotate(-45deg);
}

/* 학습 순환 리턴 패스 — [링 기점 + 세로 점선 + 결론 알약].
   구판에서는 이 문법이 ≤720 전용이었고 데스크탑은 5열 그리드를 감싸는 점선 U였다.
   1열 파이프라인에서는 U가 성립하지 않으므로 세로 문법을 전 폭 공통으로 올린다.
   흐름 잉크는 --blue 한 계열 — 점선 경로 0.75, 기점 링 0.9 */
.pm-loop {
  position: relative;
  width: min(var(--pm-pill-w), 100%);
  margin: var(--pm-loop-gap) auto 0;
  text-align: center;
}

/* 리턴 경로 점선 — 링 아래 hop(6)에서 시작해 캡션 위 drop(12)에서 끊는다.
   길이 = 64 − 12(lead) − 12(링) − 6(hop) − 12(drop) = 22px으로, 스텝 구간의 전진 축 22px과
   정확히 같다. 두 구간의 경로 잉크 길이가 같아야 [전진 배선]과 [리턴 배선]이 한 어휘로 읽힌다.
   구판은 링 바닥에서 곧장(0px) 출발해 알약 4px 앞에서 끊겨, 세 요소가 이어 붙은 한 덩어리로
   보였다 — "원형·점선도 붙어있는 느낌"의 실체다.
   좌표를 전부 토큰에서 파생시켜 --pm-loop-gap을 바꿔도 링·점선·알약이 한 축으로 따라온다 */
.pm-loop::before {
  content: "";
  position: absolute;
  top: calc(var(--pm-wire-lead) + var(--pm-ring-o) + var(--pm-loop-hop) - var(--pm-loop-gap));
  left: 50%;
  width: 0;
  height: calc(
    var(--pm-loop-gap) - var(--pm-wire-lead) - var(--pm-ring-o) - var(--pm-loop-hop) -
      var(--pm-loop-drop)
  );
  margin-left: -0.5px;
  border-left: 1px dashed rgba(15, 99, 234, 0.75);
  pointer-events: none;
}

/* 출발 링 도트 — 의사요소는 content-box라 총 지름 8 + 2·2 = 12px(= --pm-ring-o).
   구판은 top = −(gap + 6)으로 링 중심을 마지막 묶음의 하단선에 정확히 얹었다. '기점이 묶음에
   물려 있다'는 뜻은 맞았지만 잉크로 재면 링 상단이 05 실행 항목 글자 잉크보다 2.9px 위여서
   글자와 겹쳐 있었다(가로도 첫 항목 우측 끝과 2.8px 겹침). 기점이라는 뜻은 링이 경로의 맨 위에
   있다는 사실만으로 충분히 서므로, 전진 배선과 같은 lead(12)만큼 내려 앉힌다 —
   글자 잉크 기준 15.1px이 비고 겹침은 사라진다 */
.pm-loop::after {
  content: "";
  position: absolute;
  top: calc(var(--pm-wire-lead) - var(--pm-loop-gap));
  left: 50%;
  width: calc(var(--pm-ring-o) - 4px);
  height: calc(var(--pm-ring-o) - 4px);
  margin-left: calc(var(--pm-ring-o) / -2);
  border: 2px solid rgba(15, 99, 234, 0.9);
  border-radius: 50%;
  /* 링 내부는 섹션 배경과 같은 값 — .pm-loop-cap의 마스크와 같은 규칙 */
  background: var(--surface-l2);
}

/* 캡션 — 순환이 매듭지어지는 결론 노드 */
.pm-loop-cap {
  display: inline-flex;
  align-items: center;
  gap: var(--gap-2);
  max-width: 100%;
  margin: 0;
  padding: 8px 18px;
  border: 1px solid var(--border-l3);
  border-radius: var(--r-pill);
  /* 점선 루프를 가리는 마스크라 섹션 배경(l2)과 반드시 같은 값 */
  background: var(--surface-l2);
  box-shadow: var(--e-1);
  color: var(--text-l-1);
  font-size: 14.5px;
  line-height: 1.4;
  font-weight: 800;
  /* 규칙 (d) — 필 아래 설명류는 전부 중앙. 구판만 left라 좁은 폭에서 캡션이 랩되면
     이 한 요소만 좌측으로 흘러 축이 깨졌다(요약 p·실행 항목은 이미 center였다) */
  text-align: center;
  word-break: keep-all;
}

/* =========================================================
   05 THE AQNET DIFFERENCE — 매체 운영 → 성장 구조 운영 비교
   구 07 OPERATING SHIFT(.pm-shift-section + .pm-diff*)를 04 SERVICE 직후로 옮기며
   교체한 블록. 네이비 문법(--navy 평면 + 화이트 헤딩 + --grad-line 이음매)은 그대로
   승계하고, 표의 언어를 "축 / 전 / 후"에서 "전 / → / 후"의 좌우 비교 프레임으로
   바꾼다. 설명(p)이 각 면 안으로 들어와 항상 노출되므로 별도 설명 열(구 .pm-diff-note)은
   없앴다.

   ── B안(/b/ .b3-diff-*) 문법 이식(대표님 지목: "A안 05에 이 그라인으로 섞어달라") ──
   35:65 이행(shift) 프레임을 접고 B안의 **동폭 표** 문법으로 갈아탄다. B안의 규율은
   "폭·크기·항목수는 좌우 완전 동일, 역할은 색으로만 가른다"이고, 그 규율이 성립하려면
   (a) 캡션 2개가 같은 크기의 솔리드 헤더 바여야 하고 (b) 같은 축의 좌·우가 항상 같은
   행 높이를 공유해야 하며 (c) 셀마다 하단 헤어라인이 좌우로 이어져 표로 닫혀야 한다.
   따라서 to의 azure 틴트 패널·보더·큰 잉크(=폭과 면으로 우열을 인코딩하던 장치)를
   걷고, 두 열 모두 같은 저알파 면 + 같은 타이포로 되돌린다.

   B안은 라이트 지면이었으므로 면·잉크만 다크 문법으로 번역한다:
     좌 헤더 바 = 흰 8% 알파(B안 --navy-soft 자리 — 다크 위에서 --surface-2는 배경보다
                  어두워 헤더로 서지 못한다), 우 헤더 바 = --blue 솔리드(B안과 동일 토큰).
     셀 면 = 기존 A안 diff 패널 톤(흰 3% 알파) 승계.
   좌·우 잉크의 한 단 사다리 차(from 뮤트 / to 화이트)는 유지한다 — B안이 금지한 것은
   폭·굵기에 의한 인코딩이고, 색에 의한 역할 구분은 B안 자신의 규율이다.

   행 정렬은 grid-auto-flow:column 이 아니라 구조가 보증한다 — B안은 열 래퍼가 없는
   평탄 14칸 격자라 행 트랙 명시가 필요했지만, A안은 축마다 li(.diff-row)가 이미 한 행을
   이루므로 align-items:stretch 한 줄로 좌·우가 같은 높이가 된다(자세한 근거는 .diff-row).

   대비 실측(배경 --navy #0d1b32, mesh 없음 — 전 항목 AA 4.5 통과):
     h2·diff-close(--white) 17.21
     diff-cap.is-from(--white, 흰 0.08 바 위 #202d42) 13.81
     diff-cap.is-to(--white, --blue #0f63ea 솔리드 위) 5.25
     eyebrow(--cyan) 5.10 · lead(--text-d-2) 9.34
     diff-from strong(--text-d-3, 0.03 셀 위) 4.99 · diff-from p(--text-d-4, 0.03 셀 위) 4.71
     diff-to strong(--white, 0.03 셀 위) 15.97 · diff-to p(--text-d-2, 0.03 셀 위) 8.85
   최저값이 diff-from p의 4.71이라 승급이 필요한 요소는 없다.
   ※ 우 헤더 바는 --cyan(#0390ee)이 아니라 --blue(#0f63ea)다 — 흰 17/600 은 대형 예외를
      못 받는데 흰색/시안은 3.37:1 로 떨어진다. --blue 라야 5.25:1 로 AA를 통과하고,
      마침 B안 원본의 우 헤더도 같은 --blue 토큰이라 문법까지 일치한다 */
.diff-section {
  position: relative;
  width: 100%;
  max-width: none;
  background: var(--navy);
  color: var(--white);
  scroll-margin-top: var(--header-height);
}

/* 섹션 이음매 헤어라인 — 다른 전환 경계와 동일한 --grad-line 1px(구 pm-shift 로컬 규칙 승계).
   아래쪽(05→06) 이음매는 뒤 섹션의 ::before가 담당하므로 여기서는 상단만 깐다 */
.diff-section::before {
  content: "";
  position: absolute;
  top: -1px;
  left: 0;
  right: 0;
  height: 1px;
  background: var(--grad-line);
}

/* 풀블리드 섹션이라 자식 3종을 각각 본문 폭으로 되돌린다 */
.diff-section > .section-heading,
.diff-section > .diff-frame,
.diff-section > .diff-close {
  width: min(100%, var(--max));
  margin-left: auto;
  margin-right: auto;
}

/* 키워드 강조 — 실행·데이터·시스템. 모바일에서 17px라 대형 텍스트 예외를 못 받으므로
   그라디언트(최저 스톱 4.18) 대신 시안 단색(네이비 위 5.10:1). 같은 섹션의
   화살표와 같은 잉크라 문법도 맞는다 */
.diff-close strong {
  color: var(--cyan);
  font-weight: 800;
}

.diff-section > .section-heading {
  max-width: var(--max);
}

/* 다크 배경 — 헤딩 화이트(WHY 섹션과 같은 처리) */
.diff-section > .section-heading h2 {
  max-width: 920px;
  color: var(--white);
}

/* 공통 .section-heading p:not(.eyebrow)(0,2,1)를 이기도록 같은 형태로 덮는다 */
.diff-section .section-heading p:not(.eyebrow) {
  color: var(--text-d-2);
}

/* from / 화살표 / to — 헤더행과 각 행이 같은 트랙을 공유한다.
   from:to 는 0.35:0.65 → **1:1**(B안 동폭 규율).
   좌측 축 열(176px · 01~06 번호 + 영문 축명 + 글리프)은 클라이언트 지시로 걷었다 —
   비교의 단위가 "축"이 아니라 "쌍"으로 확정되면서, 축 레일은 두 색면을 오른쪽으로
   200px(176 축 열 + 24 거터) 밀어 두는 역할만 남았다. 그 200px 는 두 열이 균등
   흡수한다 — 트랙을 1fr : 24px : 1fr 로 줄이면 남는 폭이 두 fr 에 정확히 반씩 간다.
   열 거터는 B안과 같은 24px, 화살표는 24px 고정 트랙이라 좌·우 색면 사이 고랑은 72px다.
   축을 걷어도 B안 동폭 규율은 그대로 성립한다 — 헤더 바 2개와 6행의 두 셀이 모두 같은
   var(--diff-cols) 위에 서므로 좌우 동폭·행 top 일치는 트랙이 보증하고,
   본문 밴드 정렬은 .diff-frame 이 지는 width:min(100%, var(--max)) 가 그대로 진다 */
.diff-frame {
  --diff-cols: minmax(0, 1fr) 24px minmax(0, 1fr);
  --diff-gap: var(--gap-3);
}

/* 헤더행 — 바 아래로 표가 바로 붙어야 하므로
   구 padding-bottom·border-bottom(헤더를 룰 하나로 긋던 문법)은 걷는다 */
.diff-head {
  display: grid;
  grid-template-columns: var(--diff-cols);
  gap: 0 var(--diff-gap);
}

/* 캡션 = 헤더 바(B안 .b3-diff-cap 이식). 저알파 잉크로 셀 위에 얹혀 있던 동안에는
   11.5px/800 라벨이라 열 제목이 아니라 각주로 읽혔다. 표 헤더 범주로 면을 채우고
   상단만 r20 으로 깎아 아래 표를 연다. 폭·높이·타이포는 좌우 완전 동일하고 색만 가른다 */
.diff-cap {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 58px;
  padding: 10px 20px;
  border-radius: var(--r-lg) var(--r-lg) 0 0;
  color: var(--white);
  font-size: 17px;
  line-height: 1.4;
  font-weight: 600;
  letter-spacing: -0.01em;
  text-align: center;
  word-break: keep-all;
}

/* 좌 = 무채색 바. 아래 셀(흰 0.03)보다 한 단 밝은 흰 0.08 이라야 바가 셀 위로 선다 */
.diff-cap.is-from {
  grid-column: 1;
  background: rgba(255, 255, 255, 0.08);
}

/* 우 = --blue 솔리드. 크기·굵기는 좌와 동일 — 우열은 색으로만 표시한다 */
.diff-cap.is-to {
  grid-column: 3;
  background: var(--blue);
}

.diff-list {
  margin: 0;
  padding: 0;
  list-style: none;
}

/* 같은 축의 좌·우가 같은 높이를 갖는 장치. B안은 열 래퍼 없는 평탄 14칸 격자라
   grid-auto-flow:column + 행 7트랙 명시가 필요했지만, A안은 축마다 li 가 이미 한 행을
   이루므로 그 두 선언이 필요 없다 — align-items 를 center 에서 stretch 로 되돌리는 것만으로
   from·to 가 행 높이까지 늘어난다. center 이던 동안에는 두 면이 각자 내용 높이로 떠서
   짧은 from 이 행 중앙에 뜨고 색면이 계단처럼 끊겼다.
   행 사이 간격은 0 — 셀 하단 헤어라인이 좌우로 끊김 없이 이어져야 표로 읽힌다 */
.diff-row {
  display: grid;
  grid-template-columns: var(--diff-cols);
  gap: 0 var(--diff-gap);
  align-items: stretch;
  padding: 0;
}

/* 두 셀 — 완전히 같은 면·같은 패딩·같은 하단 헤어라인(B안 .b3-diff-item 이식).
   from 이 반경 있는 작은 패널, to 가 azure 틴트 + 보더 + 큰 잉크이던 동안에는
   좌·우가 서로 다른 부품이라 표가 아니라 "패널 12장"으로 읽혔다.
   반경·보더를 걷고 셀을 열 폭에 꽉 채우면, 같은 행을 공유하는 좌·우가 같은 높이로
   늘어나므로(.diff-row align-items:stretch) 셀 단위로 칠해도 통 색면이 된다.
   first/last 예외를 두지 않는 것은 B안에서 옮겨 온 규율이다 — 모든 행이 같은 패딩·같은
   헤어라인을 가지면 대칭을 구조가 보증하고, 마지막 행 헤어라인이 표를 닫는 룰이 된다.

   ※ azure 틴트를 걷어도 to 의 무게는 유지된다: 무게를 지던 세 장치(폭 65% / 틴트 면 /
   보더) 중 폭과 면은 B안 규율상 좌우 동등해야 하므로, 남은 무게는 --blue 헤더 바와
   잉크 사다리(from --text-d-3·--text-d-4 / to --white·--text-d-2)가 진다.
   B안이 금한 것은 폭·굵기로 우열을 인코딩하는 일이고, 색으로 가르는 것은 B안의 방식이다.

   합성 대비 실측 — 셀 면 = --navy(#0d1b32) 위 rgba(255,255,255,0.03) = #142238:
     from strong --text-d-3 4.99 · from p --text-d-4 4.71
     to   strong --white    15.97 · to   p --text-d-2 8.85 (구 틴트 위 14.70/8.26에서 상승) */
.diff-from,
.diff-to {
  padding: 20px 28px;
  border: 0;
  border-bottom: 1px solid var(--border-1);
  border-radius: 0;
  background: rgba(255, 255, 255, 0.03);
}

/* 항목명 17/600 — 좌우 동일. 구 from 15/700 · to 18/800 의 크기·굵기 차가
   B안 규율에서 금지하는 "굵기에 의한 우열 인코딩"이었다 */
.diff-from strong,
.diff-to strong {
  display: block;
  font-size: 17px;
  line-height: 1.5;
  font-weight: 600;
  letter-spacing: -0.01em;
  word-break: keep-all;
}

.diff-from strong {
  color: var(--text-d-3);
}

.diff-to strong {
  color: var(--white);
}

/* 설명은 17 → 15 로 한 단 내려 셀 안쪽 위계를 만든다(B안과 동일).
   웨이트는 B안의 300 을 따르지 않고 본문 400 을 유지한다 — 300 은 라이트 지면
   #1A1A1A 급 잉크에서 성립하는 값이고, 다크 면 위 저알파 흰 잉크에서 300 은
   획이 뭉개져 15px 에서 판독이 무너진다(같은 이유로 다크 섹션 전역이 400 이상이다) */
.diff-from p,
.diff-to p {
  margin: 6px 0 0;
  font-size: 15px;
  line-height: 1.7;
  letter-spacing: -0.01em;
  word-break: keep-all;
}

.diff-from p {
  color: var(--text-d-4);
}

.diff-to p {
  color: var(--text-d-2);
}

/* 화살표 — B안에는 없는 A안 자산. 24px 고정 트랙 안에 남겨 두 색면 사이 고랑이
   "이행(shift)"의 축임을 표시한다. 색면이 행 높이를 채우므로 행마다 중앙에 세운다 */
.diff-arrow {
  align-self: center;
  color: var(--cyan);
  font-size: 15px;
  line-height: 1;
  text-align: center;
}

/* 하단 고정 메시지 — 03 결론부와 같은 처리(상자 없이 헤어라인+타이포만).
   표가 6행에서 끝나면 섹션이 "목록"으로 닫히므로, 같은 --grad-line 룰을 한 번 더 깔아
   이 한 줄을 챕터의 착지점으로 만든다 */
.diff-close {
  position: relative;
  margin: var(--gap-4) auto 0;
  padding-top: clamp(22px, 2.4vw, 30px);
  color: var(--white);
  font-size: clamp(18px, 1.5vw, 20px);
  line-height: 1.6;
  font-weight: 800;
  text-align: center;
  word-break: keep-all;
}

.diff-close::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 1px;
  background: var(--grad-line);
}

/* 중간 구간(1024) 로컬 분기는 두지 않는다 — 축 열이 있던 동안에는 176px 를 유지하면
   셀 폭이 300px 밑으로 떨어져 17px strong 이 3줄로 접혔으므로 축을 행 위로 올려야 했다.
   축을 걷은 뒤 데스크톱 트랙이 이미 1fr : 24px : 1fr 이라 1024 에서 바꿀 것이 없다 */

/* 모바일 — 좌우 비교는 성립하지 않으므로 행마다 카드로 접는다.
   from → ↓ → to 순서로 한 쌍이 카드 하나가 된다. 축을 걷은 뒤 카드 머리 자리는
   from 의 strong(16px/600)이 그대로 진다 — 축명은 원래도 11.5px 라벨이라 카드 제목이
   아니라 머리표였고, 카드 경계(보더+반경+면)가 쌍의 구분을 이미 긋는다.
   따라서 별도의 대체 헤더는 세우지 않는다.

   ※ B안 모바일은 1열 스택(좌 캡션+6 → 우 캡션+6)이라 헤더 바 2개가 그대로 살아 있지만,
   A안은 그 스택을 따르지 않는다: A안 표의 단위는 열이 아니라 **쌍**이고, 1열로 펴면
   같은 쌍의 from 과 to 가 여섯 항목 떨어져 놓여 "이것이 이렇게 바뀐다"는
   쌍 읽기가 통째로 사라진다. 쌍을 살리는 대신 헤더 바를 접고, 좌·우 역할은 각 셀의
   sr-only 라벨(낭독)과 잉크 사다리·화살표 방향(육안)이 진다.
   카드 안에서는 두 셀이 카드 면 위에 얹히므로 셀 각자의 면·헤어라인은 벗는다 —
   그대로 두면 카드 안에 표가 한 겹 더 생겨 면이 세 겹이 된다 */
@media (max-width: 720px) {
  .diff-head {
    display: none;
  }

  .diff-list {
    display: grid;
    gap: var(--gap-2);
  }

  .diff-row {
    grid-template-columns: minmax(0, 1fr);
    row-gap: var(--gap-1);
    padding: 18px 16px;
    border: 1px solid var(--border-1);
    border-radius: var(--r-md);
    background: rgba(255, 255, 255, 0.03);
  }

  .diff-from,
  .diff-to {
    padding: 0;
    border: 0;
    border-radius: 0;
    background: none;
  }

  .diff-from strong,
  .diff-to strong {
    font-size: 16px;
  }

  .diff-from p,
  .diff-to p {
    font-size: 14px;
    line-height: 1.65;
  }

  /* ↓ 방향으로 눕힌다 — 리빌·리프트가 translate를 쓰므로 축이 겹치지 않게 rotate 단독 속성 */
  .diff-arrow {
    justify-self: start;
    margin: 1px 0;
    rotate: 90deg;
  }

  .diff-close {
    font-size: 17px;
    line-height: 1.55;
  }
}

/* =========================================================
   SOLUTION — AQ Growth OS (dark signature)
   ========================================================= */
.solution-section {
  width: 100%;
  max-width: none;
  background: var(--surface-0);
  background-image: var(--mesh-cyan), var(--mesh-blue);
  color: var(--white);
}

.solution-section > .section-heading,
.solution-layout {
  width: min(100%, var(--max));
  margin-left: auto;
  margin-right: auto;
}

.solution-section .section-heading h2 {
  color: var(--white);
}

.solution-section .section-heading p:not(.eyebrow) {
  color: var(--text-d-2);
}

/* Service(04) → Solution(05) 연결 문장.
   헤딩 본문보다 한 단 낮은 톤 + 액센트 룰로 '다리' 역할임을 시각적으로 구분.
   위의 p:not(.eyebrow) 규칙과 특이도가 같으므로 반드시 그 아래에 온다 */
.solution-section .section-heading p.solution-bridge {
  margin: 22px 0 0;
  padding-left: 14px;
  max-width: 780px;
  border-left: 2px solid rgba(3, 144, 238, 0.5);
  color: var(--text-d-3);
  font-size: 15px;
  line-height: 1.7;
  font-weight: 600;
}

.solution-layout {
  display: grid;
  grid-template-columns: minmax(0, 0.88fr) minmax(420px, 1.12fr);
  gap: 24px;
  align-items: stretch;
}

.growth-loop {
  position: relative;
  --loop-active-shift: 4px;
  --loop-cursor-x: 40px;
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 10px;
}

.loop-rail {
  position: absolute;
  left: 40px;
  top: 32px;
  bottom: 32px;
  width: 2px;
  transform: translateX(-1px);
  background:
    repeating-linear-gradient(180deg, rgba(3, 144, 238, 0.5) 0 8px, transparent 8px 16px);
  animation: railFlow 2.5s linear infinite;
}

@keyframes railFlow {
  to {
    background-position-y: 16px;
  }
}

/* 진행 커서 도트 — active 노드 아이콘 중심을 따라 이동 */
.loop-cursor {
  position: absolute;
  /* X를 left(전환 없음), Y를 transform(전환 있음)으로 나눠 두면 가로는 순간이동하고
     세로만 미끄러진다. 두 축을 transform 하나로 합쳐 함께 움직이게 한다 */
  left: 0;
  top: 0;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--cyan);
  box-shadow: var(--glow-cyan);
  z-index: 2;
  transform: translate(calc(var(--cx, 40px) - 50%), calc(var(--cy, 40px) - 50%));
  transition: transform var(--dur-slow) var(--ease-emphasized);
  pointer-events: none;
}

/* Learn → Collect 리턴 패스 — 우측 점선 곡선, Learn 단계에서 점등 */
.loop-return {
  position: absolute;
  right: -14px;
  top: 32px;
  bottom: 32px;
  width: 14px;
  border: 2px dashed rgba(3, 144, 238, 0.22);
  border-left: none;
  border-radius: 0 14px 14px 0;
  transition: border-color var(--dur) ease;
  pointer-events: none;
}

.growth-loop.returning .loop-return {
  border-color: rgba(3, 144, 238, 0.55);
}

.loop-node {
  position: relative;
  overflow: hidden;
  z-index: 1;
  display: grid;
  grid-template-columns: 48px minmax(0, 1fr);
  gap: 16px;
  align-items: center;
  padding: 16px;
  border: 1px solid var(--border-2);
  border-radius: var(--r-md);
  background: var(--surface-2);
  box-shadow: var(--e-dark-1);
  transition:
    background var(--dur) ease,
    border-color var(--dur) ease,
    transform var(--dur) var(--ease-out);
}

/* 상단 카드 라인 — 10 지표 카드와 같은 다크 카드 문법(휴지 0.55) */
.loop-node::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: var(--card-line);
  opacity: 0.55;
}

.loop-ic {
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  border-radius: var(--r-sm);
  background: var(--surface-1);
  border: 1px solid var(--border-2);
  color: var(--signal);
  transition:
    background var(--dur) ease,
    color var(--dur) ease,
    box-shadow var(--dur) ease;
}

/* ※ 아이콘 2종 고정(14/19)에서 유일하게 남은 3번째 값 — 09 SOLUTION은
   p24 1:1 이식본이라 무접촉 구간이다. 실효 획 1.60px로 뭉갬 리스크는 없으므로
   품질 문제는 아니고 순수한 스케일 잔여값. 09 개편이 열릴 때 19px로 합류시킬 것 */
.loop-ic svg {
  width: 22px;
  height: 22px;
}

.loop-body {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.loop-no {
  color: var(--text-d-4);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.08em;
  font-variant-numeric: tabular-nums;
}

/* ※ 20px은 L2 토큰(--t-sub-2 18px)에서 유일하게 벗어난 서브 타이틀이다(R8 감사 1-F "20→18").
   이번 패스의 작업 범위가 09를 무접촉으로 묶고 있어 값은 그대로 둔다 —
   09를 여는 다음 패스에서 --t-sub-2로 편입할 것 */
.loop-body strong {
  color: var(--white);
  font-size: 20px;
  line-height: 1.2;
  font-weight: 800;
}

.loop-body p {
  margin: 4px 0 0;
  color: var(--text-d-3);
  font-size: 14px;
  line-height: 1.5;
  word-break: keep-all;
}

.loop-node.active {
  background: var(--surface-3);
  border-color: var(--border-3);
  transform: translateX(var(--loop-active-shift));
}

.loop-node.active .loop-ic {
  background: var(--grad-action);
  border-color: transparent;
  color: var(--white);
  box-shadow: var(--glow-cyan);
}

.loop-node.active .loop-no {
  color: var(--cyan);
}

/* Console panel — 회사소개서 v2.8 p24(Unified Dashboard) 목업.
   크롬바 / 앱 헤더 / KPI 4종 / 추이 차트+채널 표 / 이상 감지 / 상태바 6존 */
.solution-panel {
  position: relative;
  padding: clamp(20px, 3vw, 28px);
  border-radius: var(--r-lg);
  color: var(--white);
  background: var(--surface-1);
  border: 1px solid var(--border-2);
  box-shadow: var(--e-dark-1);
  display: flex;
  flex-direction: column;
  gap: 12px;
  overflow: hidden;
  transition: border-color var(--dur) ease;
}

.solution-panel.bg-grid {
  background-color: var(--surface-1);
  background-size: 52px 52px;
}

.solution-panel.learning {
  border-color: var(--border-3);
}

/* 존1 — 브라우저 크롬바. DEMO 배지가 항상 우상단에 남아야 하므로
   줄바꿈 없이(주소칸만 줄어드는 구조로) 유지한다 */
.panel-chrome {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: 10px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--border-1);
}

.chrome-dots {
  display: inline-flex;
  gap: 6px;
  flex: 0 0 auto;
}

.chrome-dots i {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.18);
}

.chrome-url {
  flex: 1;
  min-width: 0;
  height: 26px;
  display: flex;
  align-items: center;
  padding: 0 10px;
  border-radius: var(--r-xs);
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid var(--border-1);
  font-size: 12px;
  color: var(--text-d-3);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* 'DEMO · SAMPLE DATA' 알약 — 목업 최상단 우측 고정 고지.
   하단 'UI CONCEPT · SAMPLE DATA' 각주와 병존하며, 스크롤 위치와 무관하게
   패널을 보는 순간 먼저 읽히도록 틴트 배경으로 대비를 올린다 */
.preview-badge {
  flex: 0 0 auto;
  margin-left: auto;
  padding: 4px 10px;
  border: 1px solid rgba(3, 144, 238, 0.5);
  border-radius: var(--r-pill);
  background: rgba(3, 144, 238, 0.14);
  color: var(--cyan);
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: 0.04em;
  white-space: nowrap;
}

/* 좁은 폭에서는 장식용 주소칸을 접어 DEMO 배지 자리를 먼저 확보한다(배지는 항상 노출) */
@media (max-width: 520px) {
  .chrome-url {
    display: none;
  }
}

/* 존2 — 앱 헤더: 화면명 + 조회 필터 칩 */
.dash-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 8px 12px;
}

.dash-title {
  font-size: 13px;
  font-weight: 800;
  letter-spacing: 0.01em;
  color: var(--white);
  white-space: nowrap;
}

.dash-filters {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 6px;
}

.dash-chip {
  padding: 4px 9px;
  border: 1px solid var(--border-1);
  border-radius: var(--r-pill);
  background: rgba(255, 255, 255, 0.05);
  color: var(--text-d-3);
  font-size: 10.5px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* 존3 — KPI 4셀. 값이 ₩·콤마·단위를 포함한 긴 문자열이라
   폭 기준으로 자간·크기를 조인다(4열에서 줄바꿈 금지) */
.panel-kpis {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 8px;
}

.panel-kpis > div {
  padding: 11px 10px;
  border: 1px solid var(--border-1);
  border-radius: var(--r-sm);
  background: rgba(255, 255, 255, 0.04);
  transition:
    border-color var(--dur) ease,
    background var(--dur) ease;
}

.panel-kpis.lit > div {
  border-color: var(--border-3);
  background: rgba(3, 144, 238, 0.08);
}

.panel-kpis span {
  display: block;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.01em;
  color: var(--text-d-3);
  white-space: nowrap;
  overflow: hidden;
}

/* 데스크탑은 좁은 4열 안에 ₩1,773,700,000(14자)까지 한 줄로 들어가야 한다.
   패널 폭이 뷰포트에 비례하므로 vw 클램프로 맞춘다(≤1024/≤720에서 상향 조정) */
.panel-kpis strong {
  display: block;
  margin-top: 5px;
  font-size: clamp(12px, 1.15vw, 15.5px);
  font-weight: 800;
  letter-spacing: -0.02em;
  color: var(--white);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.panel-kpis em {
  display: block;
  margin-top: 3px;
  font-style: normal;
  font-size: 10.5px;
  font-weight: 700;
  color: var(--cyan);
}

/* 존4 — 추이 차트 + 채널 표.
   공유 프리미티브(.ch-track/.ch-fill)는 두 카드가 함께 쓰고,
   드로우온 트리거 [data-bars]는 공통 래퍼 .dash-body가 받는다 */
.dash-body {
  display: grid;
  grid-template-columns: minmax(0, 1.02fr) minmax(0, 0.98fr);
  gap: 10px;
  align-items: stretch;
}

.dash-card {
  display: flex;
  flex-direction: column;
  min-width: 0;
  padding: 12px;
  border: 1px solid var(--border-1);
  border-radius: var(--r-md);
  background: rgba(255, 255, 255, 0.04);
  transition:
    border-color var(--dur) ease,
    background var(--dur) ease;
}

.dash-card.lit {
  border-color: var(--border-3);
  background: rgba(3, 144, 238, 0.08);
}

.dash-card-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 10px;
}

.dash-cap {
  min-width: 0;
  font-size: 11.5px;
  font-weight: 800;
  letter-spacing: 0.01em;
  color: var(--text-d-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.dash-sub {
  flex: 0 0 auto;
  font-size: 10.5px;
  font-weight: 700;
  color: var(--text-d-4);
}

/* 차트 — 9주 세로 바 + ROAS 꺾은선 오버레이 */
.dash-plot {
  position: relative;
  flex: 1;
  min-height: clamp(96px, 9vw, 132px);
  border-bottom: 1px solid var(--border-1);
}

/* 25% 간격 가이드라인 */
.dash-plot::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: repeating-linear-gradient(
    to top,
    rgba(255, 255, 255, 0.055) 0 1px,
    transparent 1px 25%
  );
  pointer-events: none;
}

/* 바 그리드와 꺾은선 SVG를 같은 절대 박스(inset:0)에 겹쳐 x·y 좌표계를 일치시킨다 */
.dash-bars {
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-columns: repeat(9, minmax(0, 1fr));
}

/* gap 없이 9등분 — 열 중심이 정확히 (i+0.5)/9가 되어 SVG 꺾은선 x와 맞는다.
   막대 사이 여백은 열 간격이 아니라 막대 자체의 폭으로 만든다 */
.dash-bar {
  position: relative;
  display: flex;
  align-items: flex-end;
  justify-content: center;
}

.dash-bar .ch-fill {
  width: 54%;
  max-width: 16px;
  height: var(--h, 40%);
  border-radius: 3px 3px 0 0;
  background: linear-gradient(180deg, rgba(3, 144, 238, 0.7), rgba(34, 118, 255, 0.24));
  box-shadow: none;
  transform: scaleY(0);
  transform-origin: bottom;
}

.dash-bar.is-now .ch-fill {
  background: linear-gradient(180deg, var(--cyan), rgba(34, 118, 255, 0.5));
  box-shadow: 0 0 16px rgba(3, 144, 238, 0.32);
}

/* 포인트 도트는 SVG가 아니라 열 안의 CSS 요소 — 비균등 스케일에도 정원 유지 */
.dash-dot {
  position: absolute;
  left: 50%;
  bottom: var(--v, 50%);
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--white);
  box-shadow: 0 0 0 2px rgba(3, 144, 238, 0.85);
  opacity: 0;
  transform: translate(-50%, 50%) scale(0.3);
  transition:
    opacity var(--dur-med) var(--ease-out),
    transform var(--dur-med) var(--ease-out);
  transition-delay: calc(var(--d, 0) * 60ms + 260ms);
}

.dash-bar.is-now .dash-dot {
  width: 7px;
  height: 7px;
}

.dash-line {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
  clip-path: inset(0 100% 0 0);
  transition: clip-path 820ms var(--ease-out) 180ms;
}

.dash-line polyline {
  fill: none;
  stroke: var(--cyan);
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}

/* 리빌 — 세로 바(scaleY)와 가로 게이지(scaleX)를 transform:none 하나로 함께 편다 */
.dash-body.drawn .ch-fill {
  transform: none;
}

.dash-body.drawn .dash-dot {
  opacity: 1;
  transform: translate(-50%, 50%) scale(1);
}

.dash-body.drawn .dash-line {
  clip-path: inset(0 0 0 0);
}

.dash-axis {
  display: grid;
  grid-template-columns: repeat(9, minmax(0, 1fr));
  margin-top: 6px;
  font-size: 9.5px;
  font-weight: 700;
  color: var(--text-d-4);
  text-align: center;
}

.dash-axis span:last-child {
  color: var(--cyan);
}

/* 채널별 성과 표 — 헤더와 행이 같은 열 폭을 공유해야 표로 읽힌다 */
.dt-head,
.dt-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 60px 50px;
  column-gap: 8px;
  align-items: center;
}

.dt-head {
  padding-bottom: 6px;
  border-bottom: 1px solid var(--border-1);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--text-d-4);
}

.dt-head span,
.dt-spend,
.dt-row strong {
  text-align: right;
}

.dt-row {
  row-gap: 5px;
  padding-top: 9px;
}

.dt-row b {
  min-width: 0;
  font-size: 12px;
  font-weight: 700;
  color: var(--text-d-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.dt-spend {
  font-size: 11.5px;
  font-weight: 600;
  color: var(--text-d-3);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.dt-row strong {
  font-size: 12.5px;
  font-weight: 800;
  color: var(--text-d-2);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* ROAS 상위 2개 채널만 블루 강조 */
.dt-row.is-lead strong {
  color: var(--cyan);
}

.dt-row .ch-track {
  grid-column: 1 / -1;
  height: 4px;
}

.dt-row .ch-fill {
  opacity: 0.4;
}

.dt-row.is-lead .ch-fill {
  opacity: 1;
}

.ch-track {
  display: block;
  height: 10px;
  border-radius: var(--r-pill);
  background: rgba(255, 255, 255, 0.06);
  overflow: hidden;
}

.ch-fill {
  display: block;
  width: var(--h, 60%);
  height: 100%;
  border-radius: inherit;
  background: linear-gradient(90deg, var(--blue), var(--cyan));
  box-shadow: 0 0 14px rgba(3, 144, 238, 0.18);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur-slow) var(--ease-out);
}

/* 존5 — 이상 감지 알림 + 추천 액션(구 '개발 로드맵 문의' CTA를 승계) */
.dash-alert {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 10px;
  padding: 10px 12px;
  border: 1px solid var(--border-1);
  border-radius: var(--r-md);
  background: rgba(255, 255, 255, 0.04);
  transition:
    border-color var(--dur) ease,
    background var(--dur) ease;
}

.dash-alert.lit {
  border-color: var(--border-3);
  background: rgba(3, 144, 238, 0.08);
}

.da-pill {
  flex: 0 0 auto;
  padding: 4px 10px;
  border-radius: var(--r-pill);
  background: var(--grad-action);
  color: var(--white);
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: 0.01em;
  white-space: nowrap;
}

.da-msg {
  min-width: 0;
  font-size: 12.5px;
  font-weight: 700;
  color: var(--text-d-2);
  word-break: keep-all;
}

.da-action {
  flex: 0 0 auto;
  margin-left: auto;
  padding: 6px 12px;
  border: 1px solid var(--border-3);
  border-radius: var(--r-pill);
  color: var(--cyan);
  font-size: 12px;
  font-weight: 800;
  white-space: nowrap;
  transition:
    background var(--dur) ease,
    border-color var(--dur) ease,
    color var(--dur) ease;
}

.da-action:hover,
.da-action:focus-visible {
  background: rgba(3, 144, 238, 0.14);
  border-color: var(--cyan);
  color: var(--white);
}

/* 존6 — 앱 상태바(운영 루프 5단계와 동기화) */
.panel-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 16px;
  margin-top: auto;
  padding-top: 10px;
  border-top: 1px solid var(--border-1);
}

.console-status {
  font-size: 11.5px;
  font-weight: 700;
  color: var(--text-d-3);
  font-variant-numeric: tabular-nums;
  transition: color var(--dur) ease;
}

.console-status.lit {
  color: var(--cyan);
}

/* 콘솔 목업 면책 — 예시 화면·샘플 데이터임을 레이아웃 하단에 명시 */
.console-disclaimer {
  width: min(100%, var(--max));
  margin: 18px auto 0;
  padding-left: 14px;
  border-left: 2px solid var(--border-3);
}

.cd-label {
  display: block;
  margin-bottom: 5px;
  color: var(--text-d-3);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.console-disclaimer p {
  margin: 0;
  max-width: 860px;
  color: var(--text-d-4);
  font-size: 12.5px;
  line-height: 1.65;
  word-break: keep-all;
}

/* ---------------------------------------------------------
   모듈 아키텍처 — 좌2 모듈 · 중앙 시스템 노드 · 우2 모듈 3열 도식.
   커넥터(브래킷·스텁·접점 도트)는 전부 의사요소 border로 그린다.
   개발 중 제품이므로 글로우 없이 hairline·틴트로만 위계 표현
   --------------------------------------------------------- */
/* 독립 섹션(#os-arch) — 08 대시보드 데모(다크)와 10 증거 밴드(다크) 사이에 놓이는 라이트 정보층.
   4모듈 구성 설명은 읽히는 도식이라 라이트 면이 맞고, 다크가 다섯 섹션 연속으로 한 덩어리가 되는 것을 끊어
   08 대시보드가 시그니처로 서게 한다.
   이음매 헤어라인은 공용 SEAM 목록을 건드리지 않고 여기서 같은 방식으로 깐다 */
.os-arch-section {
  position: relative;
  width: 100%;
  max-width: none;
  /* 라이트 섹션 공통 텍스처 — .reference-section과 동일 구성(면 → 페이드 → dot) */
  background-color: var(--surface-l1);
  background-image:
    linear-gradient(180deg, rgba(248, 251, 255, 0), var(--surface-l1) 520px),
    var(--dot-light);
  background-size:
    auto,
    var(--dot-light-size);
}

.os-arch-section::before {
  content: "";
  position: absolute;
  top: -1px;
  left: 0;
  right: 0;
  height: 1px;
  background: var(--grad-line);
}

/* 헤딩 폭 규격은 다른 풀블리드 섹션(Service/Works/Solution…)과 동일하게 맞춘다
   — 밴드 1200 / h2 920 / 본문 760. 공용 목록 셀렉터를 건드리지 않고 여기서 재현 */
.os-arch-section > .section-heading,
.os-arch-section > .os-arch-block {
  width: min(100%, var(--max));
  max-width: var(--max);
  margin-left: auto;
  margin-right: auto;
}

.os-arch-section .section-heading h2 {
  max-width: 920px;
}

/* 760px에서는 둘째 문장이 33px 모자라 3줄이 됐다. 첫 문장은 <br>로 고정돼 있으므로
   폭만 벌리면 "정의 / 구성" 두 줄로 떨어진다 */
.os-arch-section .section-heading p:not(.eyebrow) {
  max-width: 830px;
}

/* 도식 지반 슬래브 — 02 .about-flow와 같은 문법(l2 면 + 상단 2px 블루 + --r-lg + --e-2 + 패딩).
   흰 모듈(l0)이 l1 섹션 면 위에 놓였을 때 면 대비가 1.04:1이라 figure/ground가 평탄했고,
   그 결과 도식이 '동급 상자 다섯 개의 배선도'로 읽혔다. 지반을 l2로 한 단계 내려
   흰 모듈·허브가 경계가 선언된 판 위에 뜨게 한다(l0 vs l2 = 1.09:1 + 슬래브 보더·그림자).
   --os-line은 l2 위에서 3.38:1로 비텍스트 3:1을 유지한다 */
.os-arch-block {
  width: min(100%, var(--max));
  margin: 34px auto 0;
  padding: clamp(18px, 2.4vw, 30px);
  border: 1px solid var(--border-l2);
  border-top: 2px solid var(--blue);
  border-radius: var(--r-lg);
  background: var(--surface-l2);
  box-shadow: var(--e-2);
}

/* 섹션 헤딩이 이미 여백을 잡으므로 블록 자체의 상단 마진은 없앤다 */
.os-arch-section > .os-arch-block {
  margin-top: 0;
}

.os-arch {
  /* 커넥터가 gap 절반을 정확히 가로지르므로 gap은 고정값으로 토큰화 */
  --os-gap: 56px;
  --os-row: var(--gap-2);
  /* 다크에서 옮겨온 azure 값(0.34)이 라이트 면에서 1.48:1까지 내려앉아 도식선이 사라졌다.
     라이트 섹션 액센트인 --blue(#0f63ea)로 바꾸고 알파를 올려 비텍스트 3:1을 넘긴다.
     선 3.49:1 / 접점 도트 4.29:1 — 굵기는 1px 유지(1x 디스플레이에서 정수 픽셀로 떨어져야 또렷하다).
     모듈 상단 라인·중앙 노드 프레임도 같은 값을 써서 도식 전체가 한 번에 그려진 선으로 읽히게 한다 */
  --os-line: rgba(15, 99, 234, 0.78);
  --os-dot: rgba(15, 99, 234, 0.9);
  display: grid;
  /* 중앙 열이 모듈 열보다 좁아서 주인공이 제일 작은 위계 역전이 있었다 —
     허브 열을 40px 넓혀 첫 시선이 좌상단 MODULE 01이 아니라 가운데로 떨어지게 한다.
     커넥터는 브래킷·스텁 모두 고정값 --os-gap에서만 길이를 얻으므로 열 폭이 변해도 정합은 유지된다 */
  grid-template-columns: minmax(0, 1fr) minmax(272px, 332px) minmax(0, 1fr);
  column-gap: var(--os-gap);
  align-items: stretch;
}

/* 두 모듈의 높이를 강제로 균등화 — 브래킷이 만나는 지점(열 중앙)과
   노드 중앙이 항상 같은 y에 오도록 하는 전제 */
.os-col {
  display: grid;
  grid-template-rows: repeat(2, minmax(0, 1fr));
  row-gap: var(--os-row);
}

/* 잉크 역할 분리 — --os-line은 '도면 잉크' 전속이 된다(커넥터·접점·허브 프레임).
   직전까지는 모듈 상단 2px·허브 프레임 2px·커넥터 1px이 전부 같은 잉크라
   네 모듈과 허브가 같은 필압으로 그려졌고, 그래서 허브가 주어로 서지 못했다.
   모듈은 뉴트럴 1px 4면 보더로 내려 '면'이 되고, 선은 전부 허브 쪽으로 몰린다.
   블루는 MODULE 배지에만 남는다 — 본문·제목·태그 색은 그대로라 텍스트 대비는 불변 */
.os-mod {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: 17px 19px 15px;
  border: 1px solid var(--border-l2);
  border-radius: var(--r-md);
  background: var(--surface-l0);
  box-shadow: var(--e-1);
  transition:
    border-color var(--dur) ease,
    box-shadow var(--dur) ease;
  /* 상단 카드 라인 — ::before(접점 도트)·::after(브래킷)가 점유라 배경 스트립으로.
     --card-line과 같은 두 색의 0.55 알파판(카드 휴지 상태와 동일 강도) */
  background-image: linear-gradient(135deg, rgba(34, 118, 255, 0.55), rgba(3, 144, 238, 0.55));
  background-size: 100% 2px;
  background-repeat: no-repeat;
  background-position: top center;
}

/* 리프트 없음 — 브래킷·접점 도트가 카드에 물려 있어 2px만 올려도
   중앙 노드 스텁과 커넥터가 어긋난다. 보더·그림자만으로 응답 */
.os-mod:hover {
  border-color: var(--border-l3);
  box-shadow: var(--e-2);
}

/* 접점 도트 — 커넥터가 카드에서 출발하는 지점(.mp-stage::before와 동일한 링 표현).
   선을 진하게 올린 만큼 접점도 8px/2px로 키워 커넥터의 기점이 먼저 눈에 걸리게 한다.
   의사요소는 * { box-sizing } 대상이 아니라 content-box — 총 지름 8+2·2 = 12px이므로 중심 보정은 -6px */
.os-mod::before {
  content: "";
  position: absolute;
  top: 50%;
  width: 8px;
  height: 8px;
  margin-top: -6px;
  border: 2px solid var(--os-dot);
  border-radius: 50%;
  /* 링 내부는 지반 슬래브와 같은 색 — 여기가 남으면 라이트 배경에 다크 점이 찍힌다.
     슬래브가 l1 → l2로 내려갔으므로 이 값도 함께 내린다 */
  background: var(--surface-l2);
}

/* 브래킷 — 카드 중앙에서 가로로 나와 열 중앙(노드 높이)까지 꺾여 내려/올라간다.
   끝 +3px는 위·아래 브래킷이 보더 두께 오차 없이 겹쳐 만나게 하는 여유분 */
.os-mod::after {
  content: "";
  position: absolute;
  width: calc(var(--os-gap) / 2);
  height: calc(50% + var(--os-row) / 2 + 3px);
  border: 0 solid var(--os-line);
}

.os-mod:first-child::after {
  top: 50%;
  border-top-width: 1px;
}

.os-mod:last-child::after {
  bottom: 50%;
  border-bottom-width: 1px;
}

.os-col.is-left .os-mod::before {
  left: 100%;
  margin-left: -6px;
}

.os-col.is-left .os-mod::after {
  left: 100%;
  border-right-width: 1px;
}

.os-col.is-left .os-mod:first-child::after {
  border-top-right-radius: 10px;
}

.os-col.is-left .os-mod:last-child::after {
  border-bottom-right-radius: 10px;
}

.os-col.is-right .os-mod::before {
  right: 100%;
  margin-right: -6px;
}

.os-col.is-right .os-mod::after {
  right: 100%;
  border-left-width: 1px;
}

.os-col.is-right .os-mod:first-child::after {
  border-top-left-radius: 10px;
}

.os-col.is-right .os-mod:last-child::after {
  border-bottom-left-radius: 10px;
}

/* 모듈 번호 — 회색 소형 텍스트는 카드 안에서 태그와 같은 무게로 흩어져 순서가 읽히지 않았다.
   넘버 배지로 올려 MODULE 01→04가 카드의 첫 스캔 지점이 되게 한다(l2 면 위 --blue 4.84:1).
   flex 컬럼 안이라 stretch를 끊어야 배지가 글자 폭만 차지한다 */
.os-mod-no {
  align-self: flex-start;
  padding: 3px 8px;
  border-radius: var(--r-xs);
  background: var(--surface-l2);
  color: var(--blue);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: var(--t-label-ls);
  font-variant-numeric: tabular-nums;
}

.os-mod h3 {
  margin: 9px 0 0;
  color: var(--text-l-1);
  font-size: var(--t-sub-2);
  line-height: var(--t-sub-2-lh);
  font-weight: 800;
  letter-spacing: 0.01em;
}

.os-mod p {
  margin: 7px 0 0;
  color: var(--text-l-2);
  font-size: 14.5px;
  line-height: 1.55;
  word-break: keep-all;
}

.os-mod-tags {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: var(--gap-1);
  margin: auto 0 0;
  padding: 13px 0 0;
}

/* 태그 — 번호가 배지로 올라간 만큼 태그는 윤곽만 한 단계 잡아 배지와 구분한다 */
.os-mod-tags li {
  padding: 4px 10px;
  border: 1px solid var(--border-l2);
  border-radius: var(--r-pill);
  background: var(--surface-l1);
  color: var(--text-l-2);
  font-size: 12.5px;
  font-weight: 700;
}

/* 중앙 시스템 노드 — 라이트에서는 모듈과 같은 화이트 면을 쓰고
   azure 틴트 + 블루 보더로만 허브 위계를 세운다.
   1px --border-l3(1.57:1)로는 네 모듈과 같은 무게라 허브로 읽히지 않았다 —
   프레임을 2px로 올리고 커넥터와 같은 --os-line을 써서 "선이 모여 만든 노드"로 보이게 한다.
   선 굵기를 올려도 허브가 서지 않았던 원인은 대비가 아니라 위계였다. 모듈을 감쇠시키지 않고
   허브만 면적·타이포·그림자 세 축에서 동시에 올리는 '+' 조치로 주종을 만든다 */
.os-core {
  /* 하단 인풋 베이가 카드 패딩을 정확히 되짚어 나가야 해서 패딩을 토큰으로 잡는다 */
  --os-core-py: 30px;
  --os-core-px: 24px;
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: var(--os-core-py) var(--os-core-px);
  border: 2px solid var(--os-line);
  border-radius: var(--r-md);
  background-color: var(--surface-l0);
  /* 같은 azure의 알파만 조정(0.07 → 0.12) — 새 색을 만들지 않고 허브 면만 한 단계 진하게.
     최고 농도(y=0) 지점에서도 그 위에 놓이는 .os-cap이 4.58:1로 AA를 넘긴다 */
  background-image: linear-gradient(180deg, rgba(3, 144, 238, 0.12), rgba(3, 144, 238, 0) 62%);
  /* 모듈 평상시 --e-1보다 두 단계, 모듈 호버 --e-2보다도 한 단계 위 —
     어떤 상태에서도 허브가 가장 높이 떠 있다 */
  box-shadow: var(--e-3);
  text-align: center;
}

/* 남는 세로 여유를 이름 그룹 위와 인풋 베이 위로 균등 분배한다.
   auto 마진이 free space를 전부 흡수하므로 위의 justify-content는 이 시점에 무효 —
   엔진 그룹은 상단 면 가운데에, 베이는 카드 바닥에 고정된다 */
.os-core > .os-cap:first-child {
  margin-top: auto;
}

/* 노드 좌우 스텁 — gap 절반을 가로질러 모듈 브래킷 수직선과 겹쳐 물린다.
   right/left:100%는 패딩 박스 기준이라 프레임이 2px가 되면 시작점이 안쪽으로 1px 밀린다 —
   여유분을 +2px에서 +3px로 늘려 브래킷 수직선과 다시 정확히 맞물리게 한다 */
.os-core::before,
.os-core::after {
  content: "";
  position: absolute;
  top: 50%;
  width: calc(var(--os-gap) / 2 + 3px);
  border-top: 1px solid var(--os-line);
}

.os-core::before {
  right: 100%;
}

.os-core::after {
  left: 100%;
}

/* 허브 캡션 — 회색이면 모듈 본문과 같은 무게라 노드 안이 평평했다.
   라이트 액센트로 올려 허브 프레임·커넥터와 같은 계열로 묶는다.
   틴트를 0.12로 올린 뒤 대비: 그라디언트 최상단(글자가 놓이지 않는 지점) 4.58:1 /
   캡션이 실제 앉는 위치 4.91:1 / 하단 밴드(l1)의 DATA SOURCE 5.07:1 — 셋 다 AA 통과 */
.os-cap {
  display: block;
  color: var(--blue);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: var(--t-label-ls);
}

/* 허브 이름 — 21px는 모듈 h3(18px)와 3px 차이뿐이라 도식의 주어로 읽히지 않았다.
   최소 24px(모듈 h3의 1.33배)에서 시작해 넓은 화면에서 28px까지 올린다.
   색은 --text-l-1 그대로 — CI azure는 흰 면에서 3.37:1이라 글자에 못 쓰고,
   그라디언트 텍스트도 같은 이유로 배제한다 */
.os-core-name {
  display: block;
  /* 아래 여백은 인풋 베이 헤어라인과의 최소 간격 —
     ≤1024에서는 카드가 내용 높이로 줄어 auto 마진이 0이 되므로 이 값이 유일한 완충이 된다 */
  margin: 10px 0 18px;
  color: var(--text-l-1);
  font-size: clamp(24px, 2vw, 28px);
  line-height: 1.18;
  font-weight: 800;
  letter-spacing: 0.01em;
}

/* DATA SOURCE — 이름과 한 상자 안에서 경쟁하던 칩 5개를 카드 하단 전폭 밴드로 내린다.
   음수 마진으로 좌우·아래 패딩을 되짚어 나가 면 자체를 갈라놓으면
   허브가 '컨테이너'가 아니라 '엔진 + 그 아래 인풋 베이'라는 종속 구조로 읽힌다 */
.os-src-cap {
  margin: auto calc(var(--os-core-px) * -1) 0;
  padding: 15px var(--os-core-px) 0;
  border-top: 1px solid var(--border-l2);
  background: var(--surface-l1);
}

.os-src {
  list-style: none;
  /* flex + 중앙 정렬 — 3열 그리드는 전체는 가운데여도 둘째 행(상품·고객)이
     1~2열에 배치돼 왼쪽에 붙었다. flex는 각 줄을 독립적으로 가운데 맞추므로
     .os-src-break로 3개 뒤를 끊으면 두 줄 모두 중앙 정렬된다 */
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--gap-1);
  /* 아래로도 패딩만큼 되짚어 카드 바닥까지 밴드를 채운다.
     안쪽 반경은 프레임 2px을 뺀 값 — overflow:hidden은 좌우 커넥터 스텁을 잘라내므로 쓸 수 없다 */
  margin: 0 calc(var(--os-core-px) * -1) calc(var(--os-core-py) * -1);
  padding: 11px var(--os-core-px) var(--os-core-py);
  border-radius: 0 0 calc(var(--r-md) - 2px) calc(var(--r-md) - 2px);
  background: var(--surface-l1);
}

/* 밴드가 l1이 되었으므로 칩 면은 l0으로 반전 — 베이 안에서 개별 소스가 다시 떠오른다
   (텍스트 --text-l-2는 l0에서 9.21:1) */
.os-src li {
  padding: 4px 10px;
  border: 1px solid var(--border-l2);
  border-radius: var(--r-pill);
  background: var(--surface-l0);
  color: var(--text-l-2);
  font-size: 12.5px;
  font-weight: 700;
}

/* 줄바꿈 강제자 — 폭에 따라 접히는 지점이 달라지지 않도록 커머스 뒤를 고정한다.
   높이 0의 전폭 아이템이라 시각적 흔적이 없고, 각 줄은 justify-content가 가운데로 맞춘다 */
.os-src .os-src-break {
  flex-basis: 100%;
  height: 0;
  padding: 0;
  border: 0;
  background: none;
}

/* ≤1024에서는 공용 RESPONSIVE가 허브 패딩을 22/18로 되돌린다 —
   밴드가 되짚는 값이 어긋나지 않도록 같은 수치를 토큰에도 반영한다.
   (공용 블록은 손대지 않고 이 범위 안에서만 스코프) */
@media (max-width: 1024px) {
  .os-core {
    --os-core-py: 22px;
    --os-core-px: 18px;
  }
}

.os-arch-cap {
  margin: 24px 0 0;
  text-align: center;
  color: var(--text-l-2);
  font-size: 15px;
  line-height: 1.6;
  font-weight: 600;
  word-break: keep-all;
}

/* 액센트 색은 아이브로우와 같은 관례 — 라이트 섹션 var(--blue) / 다크 섹션 var(--cyan) */
.os-arch-cap strong {
  color: var(--blue);
  font-weight: 800;
}

/* 블록 CTA — 클라이언트 지정 라벨(개발 로드맵 문의) 상시 노출 */
.os-arch-cta {
  margin: 14px 0 0;
  text-align: center;
}

.os-arch-cta a {
  color: var(--blue);
  font-size: 15px;
  font-weight: 800;
}

.os-arch-cta a:hover,
.os-arch-cta a:focus-visible {
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* 각주 — 콘솔 면책과 동일 톤(개발 단계 명시).
   라이트 각주 관례(.pm-diff-note/.mp-note)와 같은 --text-l-2 —
   대응 토큰인 --text-l-3은 이 면에서 4.20:1로 AA 미달이라 한 단계 올렸다(8.88:1) */
.os-arch-note {
  margin: 9px 0 0;
  text-align: center;
  color: var(--text-l-2);
  /* 크기만 각주 공통값(12.5)으로 편입 — 색은 위 주석의 AA 근거가 있어 예외 유지 */
  font-size: 12.5px;
  line-height: 1.6;
  word-break: keep-all;
}

/* =========================================================
   WORKS
   ========================================================= */
.works-section {
  position: relative;
  width: 100%;
  max-width: none;
  background-color: var(--surface-l0);
  /* 라이트 섹션 공통 텍스처 — About·Insight와 같은 결(상단 도트 + 아래로 덮는 페이드).
     이음매 헤어라인은 SEAM ::before가 담당하므로 border-top은 두지 않는다(이중선) */
  background-image:
    linear-gradient(180deg, rgba(255, 255, 255, 0), var(--surface-l0) 520px),
    var(--dot-light);
  background-size:
    auto,
    var(--dot-light-size);
}

/* Snapshot(다크)과의 이음매 헤어라인은 SECTIONS(generic)의 SEAM 규칙이 일괄 담당 */

.works-section > .section-heading,
.work-tabs,
.work-grid,
.works-note {
  width: min(100%, var(--max));
  margin-left: auto;
  margin-right: auto;
}

/* 헤딩·리드 문단은 SECTIONS(generic)의 라이트 기본값을 그대로 상속 — 섹션 오버라이드 없음 */

/* 업종 필터 칩 — 활성 상태 전환은 script.js(.is-active 토글)가 담당 */
.work-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: var(--gap-2);
  margin-bottom: var(--gap-3);
}

.tab-button {
  padding: 10px 22px;
  border: 1px solid var(--border-l2);
  border-radius: var(--r-pill);
  background: var(--surface-l0);
  color: var(--text-l-2);
  font-family: inherit;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.01em;
  cursor: pointer;
  transition:
    background var(--dur) ease,
    border-color var(--dur) ease,
    color var(--dur) ease;
}

.tab-button:hover {
  border-color: var(--border-l3);
  color: var(--blue);
}

.tab-button:focus-visible {
  outline: none;
  box-shadow: var(--e-focus);
}

/* 활성 칩은 시안이 아니라 블루 채움(예시안 기준) */
.tab-button.is-active {
  background: linear-gradient(135deg, var(--blue) 0%, var(--blue-deep) 100%);
  border-color: transparent;
  color: var(--white);
}

/* 칩 9종 — 데스크탑은 wrap(1200px 기준 1줄, 좁은 데스크탑에서도 최대 2줄),
   모바일은 줄바꿈 대신 한 줄 가로 스크롤.
   공용 RESPONSIVE 블록이 아니라 섹션 로컬 @media로 둔다(WORKS 블록 관례) */
@media (max-width: 720px) {
  .work-tabs {
    flex-wrap: nowrap;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch;
    scroll-snap-type: x proximity;
    /* 스크롤바는 숨기고 스와이프만 남긴다 */
    scrollbar-width: none;
    -ms-overflow-style: none;
  }

  .work-tabs::-webkit-scrollbar {
    display: none;
  }

  .tab-button {
    flex: 0 0 auto;
    scroll-snap-align: start;
    white-space: nowrap;
  }
}

/* 사례가 4개에서 9개로 늘어 2열이면 5행(2618px)이 된다.
   필터가 하나의 그리드를 공유해야 해서 섹션 분할은 불가하므로 열 수로 높이를 잡는다 */
.work-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--gap-2);
}

.work-card {
  position: relative;
  /* 좌우 26px — 3열에서 침구 사례의 둘째 절이 8px 모자라 3줄로 넘어갔다.
     클라이언트가 지정한 개행 위치를 지키려면 폭을 벌리는 쪽이 맞고,
     26px은 .fw-card·.service-card가 이미 쓰는 값이라 카드 문법과도 맞는다 */
  padding: 30px 26px;
  border: 1px solid var(--border-l2);
  border-radius: var(--r-md);
  background: var(--surface-l0);
  box-shadow: var(--e-1);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  /* 리프트는 transform이 아니라 translate — 리빌·스크럽이 transform을 점유하므로
     축을 분리해 서로의 값을 덮어쓰지 않게 한다(토큰 주석의 카드 문법) */
  transition:
    translate var(--dur) var(--ease-out),
    border-color var(--dur) ease,
    box-shadow var(--dur) ease,
    opacity var(--dur) ease;
}

/* 상단 2px 라인 — 서비스 카드와 동일한 상시 표기(소개서 카드 문법) */
.work-card::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: var(--card-line);
}

.work-card:hover {
  translate: 0 var(--card-lift);
  border-color: var(--border-l3);
  box-shadow: var(--e-2);
}

/* 필터 비대상 카드 숨김(script.js 계약) */
.work-card.hidden {
  display: none;
}

/* 전략 태그 — 아웃라인 알약(블루). 업종 엠블럼(생성 이미지)은 클라이언트 지시로 철수 —
   카드 식별은 .case-letter(A~I)와 태그가 담당(원 승인 레이아웃 복원) */
.case-tag {
  display: inline-flex;
  align-self: flex-start;
  align-items: center;
  padding: 6px 14px;
  border-radius: var(--r-pill);
  border: 1px solid rgba(34, 118, 255, 0.5);
  background: transparent;
  color: var(--blue);
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: 0.02em;
  word-break: keep-all;
}

.work-card h3 {
  margin: 16px 0 0;
  color: var(--text-l-1);
  font-size: var(--t-sub-1);
  line-height: var(--t-sub-1-lh);
  font-weight: 800;
  word-break: keep-all;
}

/* 사례 식별자(A~I) — 제목 끝에 붙던 "브랜드 A"를 제목 앞 브랜드 ID로 올린다.
   9장이 필터로 섞이는 그리드라 카드의 첫 스캔 지점이 식별자가 되어야 한다.
   line-height·font-size는 h3에서 상속받아 줄 높이를 건드리지 않고(인라인, 세로 패딩 0)
   색·간격만으로 배지 역할을 낸다. 라이트 카드(--surface-l0) 위 --blue 5.26:1.
   구분점(·)은 두지 않는다 — 8px 간격과 색 대비만으로 분절이 충분하고,
   반투명 점을 쓰면 AA 감사에 걸리는 저대비 글리프가 하나 늘어난다 */
.case-letter {
  margin-right: 8px;
  color: var(--blue);
  font-weight: 800;
  letter-spacing: 0.01em;
  font-variant-numeric: tabular-nums;
}

/* 지표 2종 — 과시형 막대 대신 차분한 보더 박스 */
.case-metrics {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--gap-2);
  margin-top: 22px;
}

.case-metric {
  /* 3열 그리드에서 화살표형 수치("365% → 472%")가 한 줄에 들어가도록
     좌우 패딩을 14px로 좁힌다(가용 126px → 130px) */
  padding: 18px 14px;
  border: 1px solid var(--border-l1);
  border-radius: var(--r-sm);
  background: var(--surface-l1);
}

.case-metric span {
  display: block;
  color: var(--text-l-2);
  font-size: 14px;
  font-weight: 600;
  word-break: keep-all;
}

/* 값은 "21만원 절감"처럼 서술형이라 카운트업 없이 정적 텍스트.
   표기가 화살표형("2.1% → 2.8%")과 증감형("+38%")으로 이원화되면서
   최대 글자수가 늘어 수치 크기를 한 단계 낮춘다(28 → 23px).
   두 형식이 같은 박스 높이 안에서 한 줄로 마무리되게 하는 상한값 */
.case-metric strong {
  display: block;
  margin-top: 10px;
  /* 그라디언트 텍스트는 라이트 서피스에서 통과 구간이 없다 —
     grad-brand의 #7ab7ff는 2.09:1, grad-action의 azure 끝단도 3.37:1.
     사례 카드의 KPI는 이 페이지에서 가장 중요한 숫자라 단색 --blue(5.26:1)로 확정한다.
     다크 섹션의 그라디언트 수치 표기(스냅샷 등)는 그대로 둔다 */
  color: var(--blue);
  /* 화살표형은 23px에서 161px가 필요해 3열(가용 130px)에서 줄바꿈됐다.
     "숫자가 너무 크다"는 클라이언트 피드백과도 맞물려 18px로 낮춘다 */
  font-size: clamp(17px, 1.25vw, 18px);
  line-height: 1.2;
  font-weight: 800;
  letter-spacing: -0.01em;
  word-break: keep-all;
}

/* 기간·비교 기준 한 줄 — 수치가 어느 구간의 값인지 바로 받아준다 */
.case-basis {
  margin: 12px 0 0;
  color: var(--text-l-3);
  font-size: 12.5px;
  line-height: 1.6;
  letter-spacing: 0.01em;
  word-break: keep-all;
}

.case-desc {
  margin: var(--gap-2) 0 0;
  color: var(--text-l-2);
  /* 15px — 15.5px에서는 침구 사례의 둘째 절이 가용 폭과 정확히 같아(335/335)
     반올림에 따라 3줄로 넘어갔다. 클라이언트 지정 개행을 지키려면 여유가 필요하다 */
  font-size: 15px;
  line-height: 1.6;
  word-break: keep-all;
}

.works-note {
  margin: var(--gap-3) auto 0;
  color: var(--text-l-3);
  font-size: 12.5px;
  line-height: 1.6;
  word-break: keep-all;
}

/* 필터 조작 후 stagger 재생(깜빡임) 방지 — 모바일 media의 animation-name
   재지정(0,3,0)을 이기도록 .works-section을 덧붙여 (0,4,0)로 올림 */
.works-section [data-stagger].work-grid.stagger-done > * {
  animation: none;
  opacity: 1;
}

/* 태블릿 2열 · 모바일 1열 — 공용 반응형 블록보다 뒤/높은 특이도가 아니라
   해당 목록에서 .work-grid를 빼고 여기서 섹션 로컬로 관리 */
@media (max-width: 1024px) {
  .work-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 720px) {
  .work-grid {
    grid-template-columns: 1fr;
  }
}

/* 지표 박스는 모바일에서도 2열 유지, 초협폭에서만 1열 */
@media (max-width: 420px) {
  .case-metrics {
    grid-template-columns: 1fr;
  }
}

/* 중간 전환 CTA 밴드 — 라이트 본문 속 다크 아일랜드(밴드 문법 유지).
   그림자만 라이트 문맥 토큰으로 — e-dark-1의 45% 블랙은 화이트 면에서 과하다 */
.cta-band {
  position: relative;
  width: min(100%, var(--max));
  margin: var(--gap-4) auto 0;
  padding: clamp(24px, 3vw, 34px) clamp(24px, 3vw, 38px);
  border: 1px solid var(--border-2);
  border-radius: var(--r-lg);
  background:
    linear-gradient(135deg, rgba(34, 118, 255, 0.16), rgba(3, 144, 238, 0.05)),
    var(--surface-2);
  box-shadow: var(--e-2);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--gap-2);
}

.cta-band strong {
  display: block;
  color: var(--white);
  font-size: clamp(18px, 2.2vw, 24px);
  font-weight: 800;
  word-break: keep-all;
}

.cta-band p {
  margin: 8px 0 0;
  color: var(--text-d-3);
  font-size: 13px;
  word-break: keep-all;
}

/* 상단 시그니처 헤어라인 — works-section/site-footer와 동일 패턴으로 밴드를 문의 진입점으로 표시 */
.cta-band::before {
  content: "";
  position: absolute;
  top: -1px;
  left: 0;
  right: 0;
  height: 1px;
  background: var(--grad-line);
}

/* 문의 동선 앵커 — 공용 .button 대비 소폭만 상향(정보 탐색형 톤 유지) */
.cta-band .button {
  min-height: 54px;
  padding: 0 30px;
}

/* =========================================================
   CLIENT NETWORK (logo wall)
   ========================================================= */
/* 11 WORKS(l0) → 12(여기) → 13 INSIGHT(l0)로 라이트 3연속이라 가운데가 l1이면
   명도 계단이 ΔL* 1.5뿐 — 큰 면에서는 감지 한계 아래라 세 섹션이 한 덩어리로 읽혔다.
   l2로 한 단계 더 내려 l0→l2→l0(ΔL* 3.3)로 벌린다. 04~06의 l1/l0/l2 계단과 같은 처방이며
   로고 타일은 l0 화이트 그대로라 l2 면 위에서 오히려 한 겹 더 떠 보인다 */
.reference-section {
  width: 100%;
  max-width: none;
  background-color: var(--surface-l2);
  /* 라이트 섹션 공통 텍스처 — 로고월이 화이트 셀이라 텍스처는 월 바깥에만 남는다 */
  background-image:
    linear-gradient(180deg, rgba(241, 246, 253, 0), var(--surface-l2) 520px),
    var(--dot-light);
  background-size:
    auto,
    var(--dot-light-size);
}

.reference-section > .section-heading,
.logo-wall {
  width: min(100%, var(--max));
  margin-left: auto;
  margin-right: auto;
}

.logo-wall {
  position: relative;
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 1px;
  overflow: hidden;
  border: 1px solid var(--border-l2);
  border-radius: var(--r-lg);
  background: var(--border-l1);
  box-shadow: var(--e-2);
}

/* 월 가장자리 페이드 — 섹션 면이 월 위로 번져 들어오는 마스크라 섹션 배경과 같은 값이어야 한다.
   섹션이 l1 → l2로 내려갔으므로 여기 rgba도 #f8fbff → #f1f6fd로 함께 내린다 */
.logo-wall::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 2;
  background:
    linear-gradient(90deg, rgba(241, 246, 253, 0.96), transparent 8%, transparent 92%, rgba(241, 246, 253, 0.96)),
    linear-gradient(180deg, transparent 82%, rgba(241, 246, 253, 0.92));
  opacity: 0.35;
}

.logo-tile {
  position: relative;
  min-height: 116px;
  margin: 0;
  padding: 18px;
  background: var(--surface-l0);
  display: flex;
  align-items: center;
  justify-content: center;
  isolation: isolate;
  transition:
    transform var(--dur) ease,
    box-shadow var(--dur) ease;
}

.logo-tile img {
  display: block;
  width: 100%;
  max-width: 150px;
  height: 60px;
  object-fit: contain;
  mix-blend-mode: multiply;
  filter: grayscale(1);
  opacity: 0.55;
  transition:
    filter var(--dur) ease,
    opacity var(--dur) ease;
}

.logo-tile.priority img {
  filter: grayscale(0.35);
  opacity: 0.82;
}

.logo-tile:hover {
  z-index: 3;
  transform: translateY(-2px);
  box-shadow: var(--e-2);
}

.logo-tile:hover img {
  filter: grayscale(0);
  opacity: 1;
}

/* 접힘 상태 — JS가 .is-collapsed를 부여한다(JS 없으면 70장 전부 노출).
   데스크탑은 28장(7열 × 4행)까지, 모바일은 priority 타일만 — 기준이 뷰포트별로
   다르므로 JS 재계산 없이 CSS가 직접 가른다(리사이즈 안전).
   28장 컷을 데스크탑 폭에만 가두는 이유 — priority 18장의 마지막이 34번 타일이라
   컷이 40에서 28로 내려오면 모바일 규칙과 겹쳐 18장이 17장으로 깎인다 */
@media (min-width: 721px) {
  .logo-wall.is-collapsed > .logo-tile:nth-child(n + 29) {
    display: none;
  }
}

/* 더 보기 / 접기 토글 — 로고월 바로 아래 중앙 */
.logo-more {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--gap-2);
  width: min(100%, 260px);
  min-height: 48px;
  margin: var(--gap-2) auto 0;
  padding: 0 24px;
  border: 1px solid var(--border-l2);
  border-radius: var(--r-pill);
  background: var(--surface-l0);
  color: var(--text-l-2);
  font-family: inherit;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.01em;
  cursor: pointer;
  transition:
    border-color var(--dur) ease,
    color var(--dur) ease,
    box-shadow var(--dur) ease;
}

.logo-more:hover {
  border-color: var(--border-l3);
  color: var(--blue);
  box-shadow: var(--e-1);
}

.logo-more:focus-visible {
  outline: none;
  box-shadow: var(--e-focus);
}

/* 셰브런 — 펼침 상태에서 뒤집는다 */
.logo-more::after {
  content: "";
  width: 7px;
  height: 7px;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  translate: 0 -2px;
  rotate: 45deg;
  transition:
    rotate var(--dur) ease,
    translate var(--dur) ease;
}

.logo-more[aria-expanded="true"]::after {
  translate: 0 2px;
  rotate: -135deg;
}

/* 모바일 접힘 — priority 18장만 남겨 스크롤 길이를 줄인다 */
@media (max-width: 720px) {
  .logo-wall.is-collapsed > .logo-tile:not(.priority) {
    display: none;
  }
}

/* =========================================================
   INSIGHT
   ========================================================= */
.insight-section {
  width: 100%;
  max-width: none;
  background-color: var(--surface-l0);
  /* 라이트 섹션 공통 텍스처 — 행 카드가 흰 면이라 텍스처는 카드 사이 여백에만 남는다 */
  background-image:
    linear-gradient(180deg, rgba(255, 255, 255, 0), var(--surface-l0) 520px),
    var(--dot-light);
  background-size:
    auto,
    var(--dot-light-size);
}

.insight-section > .section-heading,
.insight-section > .insight-list {
  width: min(100%, var(--max));
  margin-left: auto;
  margin-right: auto;
}

.insight-list {
  display: grid;
  gap: var(--gap-2);
}

/* 행 카드 = [태그 | 제목/요약 | 상태] 3열 2행 — 헤어라인 대신
   사이트 라이트 섹션 공통 카드 서피스(보더+라운드+섀도)로 행 구조 강화 */
.insight-list article {
  position: relative;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-areas:
    "tag title soon"
    "tag desc soon";
  column-gap: var(--gap-3);
  row-gap: var(--gap-1);
  align-items: center;
  align-content: center;
  min-height: 112px;
  padding: 26px 28px;
  border: 1px solid var(--border-l2);
  border-radius: var(--r-md);
  background: var(--surface-l0);
  box-shadow: var(--e-1);
}

.i-tag {
  grid-area: tag;
  display: inline-flex;
  align-items: center;
  align-self: center;
  justify-self: start;
  padding: 6px 12px;
  border-radius: var(--r-pill);
  font-size: 12px;
  font-weight: 800;
}

.tag-report {
  background: rgba(34, 118, 255, 0.1);
  color: var(--blue);
}

/* 태그 글자색은 라이트 배경 AA(4.5:1) 기준으로 명도만 하향 —
   #0aa6cc는 2.86:1, #3f72c8은 4.14:1로 미달이었다(색조·배경 틴트는 유지) */
.tag-strategy {
  background: rgba(3, 144, 238, 0.12);
  color: #0a6b85;
}

.tag-ai {
  background: rgba(122, 183, 255, 0.16);
  color: #345f9e;
}

/* 제목 — 리스트 항목 위계로 축소(헤딩이 아닌 목록의 톤) */
.insight-list strong {
  grid-area: title;
  color: var(--text-l-1);
  font-size: var(--t-sub-2);
  line-height: var(--t-sub-2-lh);
  font-weight: 800;
  letter-spacing: -0.01em;
  word-break: keep-all;
}

/* 요약 1줄 — 제목 아래 뮤트 톤(3단 위계: 제목 l-1 → 요약 l-2 → 메타 l-3) */
.i-desc {
  grid-area: desc;
  margin: 0;
  color: var(--text-l-2);
  font-size: 14px;
  line-height: 1.5;
  font-weight: 500;
  word-break: keep-all;
  max-width: 60ch;
}

/* 발행 전 상태 라벨 — 죽은 클릭 어포던스 대신 정직한 상태 표기 */
.i-soon {
  grid-area: soon;
  justify-self: end;
  padding: 5px 11px;
  border: 1px solid var(--border-l2);
  border-radius: var(--r-pill);
  color: var(--text-l-3);
  font-size: 11px;
  font-weight: 700;
  white-space: nowrap;
}

/* 절제된 hover — 아직 링크가 아니므로 서피스 강조만(transform은 스크럽과 충돌 금지) */
@media (hover: hover) {
  .insight-list article {
    transition:
      background-color var(--dur) var(--ease-out),
      border-color var(--dur) ease,
      box-shadow var(--dur) ease;
  }

  .insight-list article:hover {
    background-color: var(--surface-l1);
    border-color: var(--border-l3);
    box-shadow: var(--e-2);
  }
}

/* =========================================================
   CONTACT (dark close)
   ========================================================= */
.contact-section {
  width: 100%;
  background: var(--surface-0);
  background-image: var(--mesh-cyan), var(--mesh-blue);
  color: var(--white);
  /* 좌우 여백: 콘텐츠를 다른 섹션과 동일한 1200px 밴드로 정렬 */
  padding: var(--section-y) max(24px, calc((100% - var(--max)) / 2));
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(360px, 1fr);
  gap: var(--gap-editorial);
  align-items: start;
}

/* 클로징 앰비언트(생성 이미지)는 클라이언트 지시(2026-08-26)로 철수 — 베이스 mesh만 유지 */

.contact-copy {
  position: sticky;
  top: 110px;
  width: auto;
  margin: 0;
}

.contact-section .section-heading h2 {
  color: var(--white);
}

/* 2열 구간에서는 좌측 카피 컬럼이 약 534px까지 좁아져 60px 상한이 헤딩을 3줄(+widow)로 밀어낸다.
   의미 단위 2줄(성장 구조를 함께 설계할 / 준비가 되었습니다.)이 들어가도록 이 섹션만 상한을 낮춘다.
   1열로 스택되는 ≤1024px에서는 공통 스케일(clamp(32px, 5vw, 60px)) 유지 */
@media (min-width: 1025px) {
  .contact-section .section-heading h2 {
    font-size: clamp(32px, 4.1vw, 52px);
  }
}

.contact-section .section-heading p:not(.eyebrow) {
  color: var(--text-d-2);
}

/* eyebrow + 회신 SLA 한 줄 — 헤딩보다 먼저 읽히는 위치에 배치 */
.contact-eyebrow {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--gap-2);
  margin-bottom: var(--gap-2);
}

.contact-eyebrow .eyebrow {
  margin-bottom: 0;
}

/* 진단 회신 SLA — 아이콘과 텍스트가 각각 플렉스 아이템이라 그 사이 공백 텍스트 노드가
   붕괴돼 "이내1차"로 붙어 있었다. 텍스트 전체를 .sla-text 한 아이템으로 묶어
   내부를 정상 인라인 흐름으로 되돌리고, 아이콘 간격은 gap이 맡는다(히어로 브리지 전례).
   위치도 헤딩 위 → 3스텝 도식 바로 위로 내려 회신 서사와 붙였다(2026-08-28) */
.sla-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  /* contact-meta 안에서 이메일 행 오른쪽에 앉으므로 자체 세로 마진은 갖지 않는다 */
  margin: 0;
  padding: 5px 12px;
  border: 1px solid rgba(3, 144, 238, 0.4);
  border-radius: var(--r-pill);
  background: rgba(3, 144, 238, 0.1);
  color: var(--text-d-2);
  font-size: 12.5px;
  font-weight: 800;
  letter-spacing: 0.01em;
  word-break: keep-all;
}

.contact-meta {
  display: flex;
  flex-wrap: wrap;
  /* 이메일 행과 SLA 배지를 한 줄에 — 배지가 아래로 떨어져 있던 때보다
     "어디로 보내면 언제 답이 오는가"가 한 눈에 붙어 읽힌다(2026-08-28) */
  align-items: center;
  gap: var(--gap-3);
  margin-top: 32px;
}

.contact-meta div {
  display: grid;
  gap: 4px;
}

.contact-meta strong {
  font-size: 18px;
  font-weight: 800;
  color: var(--white);
}

.contact-meta span {
  font-size: 13px;
  color: var(--text-d-3);
}

.contact-form {
  width: auto;
  margin: 0;
  display: grid;
  gap: var(--gap-2);
  padding: clamp(24px, 4vw, 38px);
  border: 1px solid var(--border-2);
  border-radius: var(--r-lg);
  background: var(--surface-glass);
  backdrop-filter: blur(20px);
  box-shadow: var(--e-dark-1);
}

.contact-form label {
  display: grid;
  gap: var(--gap-1);
}

.contact-form label > span {
  color: var(--text-d-2);
  font-size: 14px;
  font-weight: 800;
  transition: color var(--dur) ease;
}

.contact-form label > span em,
.contact-form legend em {
  font-style: normal;
  font-weight: 600;
  font-size: 12px;
  color: var(--text-d-4);
}

.contact-form label:focus-within > span {
  color: var(--cyan);
}

/* 광고 종류 / 예산 선택 그룹 */
.form-group {
  margin: 0;
  padding: 0;
  border: 0;
  min-width: 0;
}

.form-group legend {
  padding: 0;
  margin-bottom: 8px;
  color: var(--text-d-2);
  font-size: 14px;
  font-weight: 800;
}

.check-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--gap-1);
}

.contact-form label.check {
  display: flex;
  align-items: center;
  gap: var(--gap-1);
  min-height: 46px;
  padding: 0 14px;
  border: 1px solid var(--border-2);
  border-radius: var(--r-sm);
  background: var(--surface-2);
  color: var(--text-d-2);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition:
    border-color var(--dur-fast) ease,
    background var(--dur-fast) ease,
    color var(--dur-fast) ease;
}

.check:hover {
  border-color: var(--border-3);
}

.check input {
  width: 16px;
  height: 16px;
  margin: 0;
  flex: 0 0 auto;
  accent-color: var(--blue);
}

.check:has(input:checked) {
  border-color: var(--border-3);
  background: rgba(3, 144, 238, 0.08);
  color: var(--white);
}

/* :has() 미지원 브라우저 폴백 — JS가 .checked를 미러링 (별도 규칙 필수) */
.check.checked {
  border-color: var(--border-3);
  background: rgba(3, 144, 238, 0.08);
  color: var(--white);
}

/* ── 커스텀 드롭다운(디스클로저 버튼 + 스크롤 팝오버) ── */
.select {
  position: relative;
}

.select-toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--gap-2);
  width: 100%;
  min-height: 46px;
  padding: 0 14px;
  border: 1px solid var(--border-2);
  border-radius: var(--r-sm);
  background: var(--surface-2);
  color: var(--white);
  font-size: 14px;
  font-weight: 600;
  text-align: left;
  cursor: pointer;
  transition:
    border-color var(--dur-fast) ease,
    background var(--dur-fast) ease,
    box-shadow var(--dur-fast) ease;
}

/* 셰브런도 아이콘 2종 체계에 포함 — 마크업이 18px 속성으로 들고 오는 것을
   라벨(14px)과 같은 아래 단으로 스코프에서 되받는다 */
.select-toggle svg {
  width: 14px;
  height: 14px;
}

.select-toggle:hover {
  border-color: var(--border-3);
}

.select-toggle:focus-visible {
  outline: none;
  border-color: var(--border-3);
  box-shadow: var(--e-focus);
}

/* 열림 상태 — 토글 강조 */
.select.is-open .select-toggle {
  border-color: var(--border-3);
  box-shadow: var(--e-focus);
}

.select-value {
  flex: 1 1 auto;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  color: var(--text-d-4);
}

.select-value.is-filled {
  color: var(--white);
}

.select-caret {
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  color: var(--text-d-3);
  transition: transform var(--dur-fast) var(--ease-out);
}

.select.is-open .select-caret {
  transform: rotate(180deg);
}

.select-panel {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  right: 0;
  z-index: 20;
  max-height: 264px;
  overflow-y: auto;
  padding: 6px;
  border: 1px solid var(--border-2);
  border-radius: var(--r-md);
  background: var(--surface-3);
  box-shadow: var(--e-dark-2);
  /* 다크 스크롤바 */
  scrollbar-width: thin;
  scrollbar-color: var(--border-2) transparent;
}

.select-panel[hidden] {
  display: none;
}

.select-panel::-webkit-scrollbar {
  width: 10px;
}

.select-panel::-webkit-scrollbar-thumb {
  background: var(--border-2);
  border: 3px solid transparent;
  background-clip: padding-box;
  border-radius: var(--r-pill);
}

.select-panel::-webkit-scrollbar-thumb:hover {
  background: var(--border-3);
  border: 3px solid transparent;
  background-clip: padding-box;
}

.select-list {
  display: grid;
  grid-template-columns: 1fr;
  gap: 4px;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* 리스트 안에서는 칩이 아니라 풀폭 행으로 보이도록 오버라이드 */
.contact-form .select-list .check {
  min-height: 44px;
  border-color: transparent;
  background: transparent;
}

.contact-form .select-list .check:hover {
  border-color: transparent;
  background: var(--surface-2);
}

.contact-form .select-list .check:has(input:checked),
.contact-form .select-list .check.checked {
  border-color: transparent;
  background: rgba(3, 144, 238, 0.08);
  color: var(--white);
}

/* 모션 줄이기 — 새 드롭다운의 캐럿/토글 전환만 즉시 처리(히어로 정책과 무관) */
@media (prefers-reduced-motion: reduce) {
  .select-caret,
  .select-toggle {
    transition: none;
  }
}

.contact-form input:not([type="checkbox"]):not([type="radio"]),
.contact-form textarea {
  width: 100%;
  border: 1px solid var(--border-2);
  border-radius: var(--r-sm);
  background: var(--surface-2);
  color: var(--white);
  padding: 14px;
  outline: none;
  transition:
    border-color var(--dur-fast) ease,
    box-shadow var(--dur-fast) ease;
}

.contact-form input::placeholder,
.contact-form textarea::placeholder {
  color: var(--text-d-4);
}

.contact-form input:not([type="checkbox"]):not([type="radio"]):focus,
.contact-form textarea:focus {
  border-color: var(--border-3);
  box-shadow: var(--e-focus);
}

.contact-form textarea {
  resize: vertical;
  min-height: 150px;
}

.contact-form .consent {
  grid-template-columns: auto 1fr;
  align-items: start;
  gap: var(--gap-2);
  margin-top: 2px;
}

.contact-form .consent input {
  width: 18px;
  height: 18px;
  margin-top: 2px;
  accent-color: var(--blue);
}

.contact-form .consent span {
  font-weight: 600;
  font-size: 13px;
  color: var(--text-d-3);
  line-height: 1.5;
}

/* 개인정보 수집·이용 상세 — 동의 체크박스의 '형제' 요소.
   (라벨 안에 두면 details 토글 클릭이 체크박스 토글로 위임돼 서로 간섭한다)
   푸터 개인정보처리방침 링크의 앵커 대상이라 :target에서 테두리를 밝혀 위치를 알린다 */
.consent-detail {
  margin-top: -6px;
  padding: 12px 14px;
  border: 1px solid var(--border-1);
  border-radius: var(--r-sm);
  background: rgba(255, 255, 255, 0.03);
  scroll-margin-top: 110px;
  transition: border-color var(--dur) ease;
}

.consent-detail:target,
.consent-detail[open] {
  border-color: var(--border-3);
}

.consent-detail > summary {
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: var(--gap-1);
  color: var(--text-d-2);
  font-size: 13px;
  font-weight: 700;
  list-style: none; /* 네이티브 삼각형 제거 — 아래 .cd-hint가 유일한 어포던스 */
}

.consent-detail > summary::-webkit-details-marker {
  display: none;
}

.consent-detail > summary:focus-visible {
  outline: 2px solid var(--cyan);
  outline-offset: 3px;
  border-radius: var(--r-xs);
}

/* 단일 어포던스 — 접힘 "자세히 보기 ▾" / 펼침 "접기 ▴".
   문구가 상태를 말하므로 삼각형과 중복되지 않는다 */
.consent-detail .cd-hint {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: var(--gap-1);
  color: var(--cyan);
  font-weight: 700;
}

.consent-detail .cd-hint::before {
  content: "자세히 보기";
}

.consent-detail[open] .cd-hint::before {
  content: "접기";
}

.consent-detail .cd-hint::after {
  content: "";
  width: 6px;
  height: 6px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: translateY(-2px) rotate(45deg);
  transition: transform var(--dur) var(--ease-out);
}

.consent-detail[open] .cd-hint::after {
  transform: translateY(1px) rotate(-135deg);
}

.consent-terms {
  margin: 12px 0 0;
  display: grid;
  gap: var(--gap-1) var(--gap-2);
  font-size: 12.5px;
  line-height: 1.65;
  word-break: keep-all;
}

.consent-terms dt {
  color: var(--text-d-2);
  font-weight: 800;
}

.consent-terms dd {
  margin: 2px 0 0;
  color: var(--text-d-3);
}

.consent-right {
  margin: 12px 0 0;
  padding-top: 10px;
  border-top: 1px solid var(--border-1);
  color: var(--text-d-4);
  font-size: 12.5px;
  line-height: 1.65;
  word-break: keep-all;
}

@media (min-width: 561px) {
  .consent-terms {
    grid-template-columns: 116px minmax(0, 1fr);
    align-items: baseline;
  }

  .consent-terms dd {
    margin-top: 0;
  }
}

.contact-form .button {
  width: 100%;
  margin-top: 4px;
  border: 0;
}

.form-note {
  margin: 0;
  color: var(--text-d-3);
  font-size: 14px;
  text-align: center;
}

/* =========================================================
   FOOTER
   ========================================================= */
.site-footer {
  position: relative;
  background: var(--surface-0);
  border-top: 1px solid var(--border-1);
  color: var(--text-d-2);
}

/* Contact(다크)과의 이음매 헤어라인은 SECTIONS(generic)의 SEAM 규칙이 일괄 담당 */

/* Follow 열을 숨겨둔 동안(마크업 주석 참고) 3열 — SNS 실주소가 확정돼
   Follow 열을 되살리면 1.5fr 1fr 1.3fr 1fr로 되돌릴 것 */
.footer-top {
  display: grid;
  grid-template-columns: 1.6fr 1fr 1.4fr;
  gap: var(--gap-4);
  padding: clamp(48px, 6vw, 76px) max(24px, calc((100% - var(--max)) / 2)) 44px;
}

.footer-brand .brand {
  width: 168px;
  min-width: 168px;
  height: 44px;
  margin-bottom: 18px;
}

.footer-tagline {
  margin: 0 0 22px;
  max-width: 280px;
  color: var(--text-d-3);
  font-size: 14px;
  line-height: 1.6;
  word-break: keep-all;
}

.footer-cta {
  display: inline-flex;
  align-items: center;
  gap: var(--gap-1);
  min-height: 42px;
  padding: 0 18px;
  border: 1px solid var(--border-2);
  border-radius: var(--r-pill);
  color: var(--white);
  font-size: 13px;
  font-weight: 800;
  transition:
    background var(--dur) ease,
    border-color var(--dur) ease;
}

.footer-cta:hover,
.footer-cta:focus-visible {
  background: rgba(255, 255, 255, 0.06);
  border-color: var(--border-3);
}

.footer-h {
  margin: 0 0 16px;
  color: var(--text-d-4);
  font-size: 12px;
  font-weight: 800;
  letter-spacing: var(--t-label-ls);
  text-transform: uppercase;
}

.footer-col ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--gap-1);
}

.footer-col a {
  color: var(--text-d-2);
  font-size: 14px;
  font-weight: 600;
  transition: color var(--dur) ease;
}

.footer-col a:hover,
.footer-col a:focus-visible {
  color: var(--cyan);
}

.footer-contact li {
  display: flex;
  gap: var(--gap-1);
  color: var(--text-d-2);
  font-size: 14px;
  line-height: 1.5;
  word-break: keep-all;
}

.footer-contact li span {
  /* 글자 머리(E/A)를 한글 라벨(이메일:/주소:)로 바꾸며 고정 12px 폭을 해제 */
  flex: 0 0 auto;
  color: var(--text-d-4);
  font-weight: 800;
}

.footer-social {
  display: flex !important;
  gap: var(--gap-2);
}

.footer-social a {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border: 1px solid var(--border-2);
  border-radius: var(--r-sm);
  color: var(--text-d-2);
  transition:
    background var(--dur) ease,
    border-color var(--dur) ease,
    color var(--dur) ease;
}

.footer-social a:hover,
.footer-social a:focus-visible {
  background: rgba(255, 255, 255, 0.05);
  border-color: var(--border-3);
  color: var(--cyan);
}

.footer-social svg {
  width: 14px;
  height: 14px;
}

.footer-bottom {
  display: flex;
  flex-direction: column;
  gap: var(--gap-2);
  padding: 22px max(24px, calc((100% - var(--max)) / 2)) 36px;
  border-top: 1px solid var(--border-1);
}

.footer-legal {
  margin: 0;
  color: var(--text-d-4);
  font-size: 12px;
  line-height: 1.7;
  word-break: keep-all;
}

.footer-meta {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: var(--gap-2);
  color: var(--text-d-4);
  font-size: 12px;
}

.footer-policy {
  display: inline-flex;
  gap: var(--gap-2);
}

.footer-policy a {
  color: var(--text-d-3);
  transition: color var(--dur) ease;
}

.footer-policy a:first-child {
  color: var(--text-d-2);
  font-weight: 700;
}

.footer-policy a:hover,
.footer-policy a:focus-visible {
  color: var(--cyan);
}

/* =========================================================
   REVEAL / MOTION
   스크롤 등장 연출(비액티브 → 액티브 전환)은 전량 제거 — 반복 노출 시 부담된다는
   대표 피드백 반영. 모든 블록은 처음부터 최종 상태로 렌더된다.
   HTML의 data-reveal / data-stagger / data-scrub 속성과 script.js 옵저버는
   콘솔 차트 드로우·카운트업이 같은 옵저버에 물려 있어 그대로 둔다(스타일만 무효화).
   호버 반응(카드 리프트·보더·섀도)은 각 섹션 블록에서 그대로 유지.
   ========================================================= */

/* 헤딩 라인 래핑 — script.js가 h2의 <br>을 제거하고 .h-line 스팬으로 재래핑하므로
   이 display:block이 데스크탑 헤딩 줄바꿈을 담당한다(마스크·translate만 걷어냄) */
.h-line {
  display: block;
}

.lines-ready .h-line-inner {
  display: block;
}

/* =========================================================
   RESPONSIVE
   ========================================================= */
@media (max-width: 1024px) {
  .site-header {
    grid-template-columns: auto 1fr auto;
    gap: var(--gap-2);
    padding: 0 clamp(16px, 3vw, 28px);
  }

  .nav-links,
  .header-cta {
    display: none;
  }

  .menu-toggle {
    display: inline-block;
    justify-self: end;
  }

  .solution-layout,
  .contact-section {
    grid-template-columns: 1fr;
  }

  /* 콘솔이 1열 폭 전체를 쓰므로 KPI 값을 다시 키운다 */
  .panel-kpis strong {
    font-size: clamp(13px, 1.9vw, 18px);
  }

  /* 1열 스택에서는 리턴 패스(우측 돌출) 숨김 */
  .loop-return {
    display: none;
  }

  /* 모듈 아키텍처 — 노드 상단 + 모듈 2열.
     열 래퍼를 display:contents로 풀어 4장이 그리드에 직접 배치되게 한다 */
  .os-arch {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--gap-2);
  }

  .os-col {
    display: contents;
  }

  .os-core {
    order: -1;
    grid-column: 1 / -1;
    padding: 22px 18px;
  }

  /* 3열 전제가 사라지므로 커넥터는 전부 숨김 */
  .os-mod::before,
  .os-mod::after,
  .os-core::before,
  .os-core::after {
    display: none;
  }

  .hero-inner {
    align-items: start;
    padding-top: calc(var(--header-height) + 48px);
  }

  .framework-grid,
  .mp-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  /* 2열에서는 C→O→R→E 행 흐름이 끊기므로 진행 셰브런·되돌림 라인은 성립하지 않음.
     순환의 의미만 캡션으로 남긴다 */
  .fw-flow,
  .fw-cycle-line {
    display: none;
  }

  .fw-cycle {
    justify-content: center;
    margin-top: 20px;
  }

  .fw-cycle-cap {
    font-size: 12px;
  }

  .fw-closing {
    margin-top: var(--gap-2);
  }

  /* 영역 3장은 2열에서 한 장이 남으므로 가로 1열 행으로 스택,
     대신 실행 항목을 2열로 펴서 행 높이를 줄임 */
  .service-grid {
    grid-template-columns: 1fr;
  }

  .service-card ul {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: var(--gap-2);
  }

  /* 여정 4단계가 2열(2+2)로 접히므로 행 끝(짝수) 단계의 레일 연장·화살촉은 끊음 */
  .mp-card:nth-child(2n) .mp-rail {
    margin-right: 0;
  }

  .mp-card:nth-child(2n) .mp-rail::after {
    display: none;
  }

  .logo-wall {
    grid-template-columns: repeat(5, minmax(0, 1fr));
  }

  .snapshot-inner {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .footer-top {
    grid-template-columns: 1fr 1fr;
    row-gap: var(--gap-3);
  }

  .footer-brand {
    grid-column: 1 / -1;
  }

  .contact-copy {
    position: static;
  }

  .hero-scrollcue {
    display: none;
  }
}

@media (max-width: 720px) {
  :root {
    --header-height: 66px;
  }

  .site-header {
    padding: 0 12px 0 18px;
  }

  .brand {
    width: 132px;
    min-width: 132px;
    height: 40px;
  }

  .hero {
    --hero-drift: -22px;
  }

  .hero-stage {
    min-height: auto;
  }

  .hero-inner {
    padding: calc(var(--header-height) + 36px) 18px 40px;
  }

  .hero-title {
    font-size: clamp(30px, 9vw, 46px);
  }

  .lead-desktop {
    display: none;
  }

  .lead-mobile {
    display: inline;
  }

  /* 의미 단위 강제 개행(데스크탑 전용) — 좁은 폭에서는 짧은 줄만 남아 어색해지므로
     자연 줄바꿈에 맡긴다. 마크업에서 <br class="br-desktop" /> 뒤 개행을 유지할 것 */
  .br-desktop {
    display: none;
  }

  .hero-actions {
    display: grid;
    grid-template-columns: 1fr;
  }

  .service-grid,
  .framework-grid,
  .mp-grid {
    grid-template-columns: 1fr;
  }

  /* 여정 1열 세로 스택 — 가로 연결선은 의미가 없으므로 카드 안 hairline으로만 남김 */
  .mp-card:not(:last-of-type) .mp-rail {
    margin-right: 0;
  }

  .mp-card:not(:last-of-type) .mp-rail::after {
    display: none;
  }

  /* 콘솔 — KPI 4→2열, 차트/표 세로 스택 */
  .panel-kpis {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  /* 2열이라 카드 폭이 다시 좁아진다 — 320px까지 ₩ 값이 안 넘치는 하한 */
  .panel-kpis strong {
    font-size: clamp(12px, 3.4vw, 18px);
  }

  .solution-panel {
    padding: 18px;
  }

  .dash-body {
    grid-template-columns: minmax(0, 1fr);
  }

  .dash-plot {
    min-height: 110px;
  }

  .dash-bar .ch-fill {
    max-width: 22px;
  }

  /* 모듈 아키텍처 1열 스택 */
  .os-arch {
    grid-template-columns: 1fr;
  }

  .os-arch-block {
    margin-top: 26px;
  }

  .os-arch-cap {
    font-size: 14.5px;
  }

  /* 지표 4종은 2×2로 유지 — '대시보드감' 보존 */
  .snapshot-inner {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--gap-2);
  }

  .snapshot-inner article {
    min-height: 124px;
    padding: 20px 18px 22px;
  }

  /* 카운트업 밑줄은 카드 여백과 같은 선에서 시작·끝나야 한다 */
  .snapshot-inner article::after {
    left: 18px;
    right: 18px;
  }

  .snapshot-inner strong {
    font-size: clamp(38px, 11.5vw, 54px);
  }

  .snapshot-inner article > span {
    margin-top: 10px;
    font-size: 13px;
  }

  .snap-sub {
    font-size: 11px;
  }

  .snapshot-note {
    font-size: 11.5px;
  }

  /* 로고월 3열 축소 — 모바일 스크롤 길이 약 47% 단축 */
  .logo-wall {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .section,
  .contact-section {
    padding-left: 18px;
    padding-right: 18px;
  }

  .statement-close {
    font-size: 15px;
    padding-left: 12px;
  }

  .service-card,
  .work-card {
    min-height: 280px;
  }

  .service-card ul {
    grid-template-columns: 1fr;
  }

  .logo-tile {
    min-height: 78px;
    padding: 10px;
  }

  .logo-tile img {
    max-width: 104px;
    height: 42px;
  }

  /* 모바일 스택 — 상단 칩 북엔드(태그↔상태) → 제목 → 요약 */
  .insight-list article {
    grid-template-columns: 1fr auto;
    grid-template-areas:
      "tag soon"
      "title title"
      "desc desc";
    column-gap: var(--gap-2);
    row-gap: var(--gap-2);
    align-content: start;
    min-height: 0;
    padding: 22px 20px;
  }

  .i-tag {
    align-self: center;
  }

  .i-soon {
    align-self: center;
  }

  .insight-list strong {
    font-size: 17px;
    line-height: 1.4;
  }

  .i-desc {
    font-size: 13.5px;
  }

  .footer-top {
    grid-template-columns: 1fr 1fr;
    row-gap: var(--gap-3);
  }

  .footer-brand {
    grid-column: 1 / -1;
  }
}

@media (max-width: 480px) {
  /* 좁은 화면에서 예산/광고종류 칩 오버플로 방지 */
  .check-grid {
    grid-template-columns: 1fr;
    gap: var(--gap-1);
  }

  .contact-form label.check {
    min-height: 44px;
  }
}

@media (max-width: 420px) {
  /* .snapshot-lead(11 h2)는 .section-heading 밖에 있어 이 축소를 못 받고
     혼자 클램프 하한 32px에 남았다 — 다른 14개와 같은 30px으로 */
  .section-heading h2,
  .snapshot-lead {
    font-size: 30px;
  }

  .hero-sub,
  .section-heading p:not(.eyebrow) {
    font-size: 16px;
  }
}

/* =========================================================
   모션 접근성 — OS 동작 줄이기(prefers-reduced-motion) 준수
   마퀴·캔버스 루프·패럴랙스·등장 애니메이션을 정적 상태로 축소.
   (script.js 대응: 캔버스 정지 프레임 / --sp·--fwp 고정 / 카운트업 즉시 완료)
   ========================================================= */
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  /* 채널 마퀴 정지 — 첫 화면 분량만 정적 노출 */
  .strip-track {
    animation: none;
  }

  .ch-fill,
  .dash-dot,
  .dash-line {
    transition: none !important;
  }

  /* 장식 무한 루프 정지 */
  .hero-scrollcue span {
    animation: none;
  }
}

/* 데스크탑 핀 스크럽 해제 — 히어로를 정적 1화면 구성으로(캔버스는 정지 프레임 유지) */
@media (prefers-reduced-motion: reduce) and (min-width: 1025px) {
  .hero {
    height: auto;
  }

  .hero-stage {
    position: relative;
    top: auto;
    height: auto;
    min-height: 100vh;
    min-height: 100svh;
    overflow: visible;
    transform: none !important;
  }

  .signal-strip {
    margin-top: 0;
  }

  .hero-beats,
  .hero-bridge,
  .hero-rail,
  .hero-chapters,
  .hero-scrollcue,
  .hero-skip,
  .hero-videos {
    display: none;
  }

  .hero-copy {
    opacity: 1;
    transform: none;
  }
}

/* =========================================================
   GX — 그래픽 층(공용 클래스 + 섹션 배치 + 모바일 커넥터 복원)

   2차 웨이브에서 마크업(A)이 심는 글리프·도식·로고 클러스터의 스타일 계약.
   원칙 셋만 지킨다.
     1) 새 색을 만들지 않는다 — 칩 면·보더·잉크는 기존 .proof-ic(다크) /
        .af-ic(라이트) 값을 그대로 옮기고, 면별 차이는 커스텀 프로퍼티 세 개로만 갈아끼운다.
     2) 커넥터는 기존 어휘만 쓴다 — 45° 셰브런(border 2px 회전) / 링 도트(8px+2px) /
        1px dashed rgba(15,99,234,.75). 새 각도·두께·점선 패턴을 만들지 않는다.
     3) 도식(.gx-fig)은 모바일에서 숨기지 않는다. 좁은 폭에서는 자리를 옮기거나 줄일 뿐이다.
   @keyframes·스크롤 모션·신규 transition 없음(호버 제외).
   ========================================================= */

/* --- 면(face) 팔레트 — 섹션 스코프.
   "면 확정"에 따라 다크(01 WHY · 03 C.O.R.E · 05 DIFFERENCE · 11 SNAPSHOT · 15 CONTACT/푸터)와
   라이트(07 · 08 · 10 · 12 · 14)를 나눈다. 값은 두 기존 칩 규칙에서 그대로 가져왔다:
     다크 = .proof-ic(면 .14 / 보더 .3 / 잉크 --cyan)
     라이트 = .af-ic(면 .08 / 보더 .2 / 잉크 --blue) — 시안은 흰 배경 3.37:1이라 금지.
   --gx-line은 선 자산(화살표·도식) 전용 잉크로 칩 잉크와 분리한다 --- */
#about,
#framework,
#difference,
.reference-snapshot,
#contact,
.site-footer {
  --gx-face: rgba(3, 144, 238, 0.14);
  --gx-edge: rgba(3, 144, 238, 0.3);
  --gx-ink: var(--cyan);
  --gx-line: rgba(122, 183, 255, 0.9);
}

/* ※ #service(04)·#pm-detail(06)은 라이트 면인데도 두 그룹 어디에도 없어
   --gx-* 폴백(다크값)을 받고 있었다. T1이 06에 사분면 훅, 04에 분할 행 훅을 심으면서
   실제로 쓰이게 되므로 라이트 그룹에 넣는다. 두 섹션에 기존 gx-* 요소는 없어 렌더 변화 0 */
#service,
#pm-detail,
#ad-products,
#pm-process,
#os-arch,
#works,
#insight {
  --gx-face: rgba(15, 99, 234, 0.08);
  --gx-edge: rgba(15, 99, 234, 0.2);
  --gx-ink: var(--blue);
  --gx-line: rgba(15, 99, 234, 0.85);
}

/* ---------------------------------------------------------
   1. 공용 클래스
   --------------------------------------------------------- */

/* ── 아이콘 렌더 크기 2종 고정 (R8 감사 4-A) ─────────────────────────
   전 글리프가 24-단위 뷰박스인데 렌더가 12·14·16·18·19·22px 6종으로 갈려 있었다.
   같은 계열의 실효 획이 0.88 / 1.02 / 1.17 / 1.31 / 1.39 / 1.60px 6단으로 흩어지고,
   특히 12px 슬롯의 0.88px는 1px 미만이라 비레티나에서 회색으로 뭉갠다.
   → 렌더를 두 단계로만 고정한다.
       19px = 칩 안에 드는 주 글리프(.gx-ic / .proof-ic / .af-ic / .svc-icon / 07 탭)
       14px = 인라인·보조 글리프(.gx-ic--sm / 화살표 / 알약 안쪽 / 푸터)
   두 값 모두 기존에 쓰이던 검증값이라 새 치수를 만들지 않는다.
   실효 획은 24뷰박스 1.75 기준 14px에서 1.02px, 19px에서 1.39px — 전부 1px 이상.
   ※ 잔여 예외 1건: 09 SOLUTION `.loop-ic`(22px ×5)는 무접촉 구간이라 손대지 않았다.
   ─────────────────────────────────────────────────────────────── */

/* 아이콘 칩 — .proof-ic / .af-ic와 같은 상자(38px, radius --r-xs, 1px 보더).
   A가 `gx-ic gx-ic--sm`으로 쓰든 `gx-ic--sm` 단독으로 쓰든 같은 결과가 나오도록
   두 셀렉터에 기본 상자를 깔고 --sm이 뒤에서 치수만 덮는다 */
.gx-ic,
.gx-ic--sm {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border-radius: var(--r-xs);
  border: 1px solid var(--gx-edge, rgba(3, 144, 238, 0.3));
  background: var(--gx-face, rgba(3, 144, 238, 0.14));
  color: var(--gx-ink, var(--cyan));
}

.gx-ic > svg,
.gx-ic--sm > svg {
  width: 19px;
  height: 19px;
}

.gx-ic--sm {
  width: 28px;
  height: 28px;
}

.gx-ic--sm > svg {
  width: 14px;
  height: 14px;
}

/* 맨 글리프 — 칩과 달리 크롬(면·1px 보더·radius)이 전무하고 선만 남는 마크.
   크기는 22 → 19px(주 글리프 단). 여전히 .why-tick 카운터보다 작아
   "글리프가 위아래로 삐져나오지 않는다"는 아래 배치 규칙의 전제는 그대로다.
   01 WHY처럼 배경도 보더도 없이 좌측 룰 하나로 서는 매니페스토 면에서는
   38px 칩 상자가 번호 옆에 서는 순간 구획 문법이 깨진다 — 상자를 걷고 글리프만 남긴다.
   잉크는 면 팔레트의 --gx-ink, 즉 01에서는 .why-tick 카운터와 같은 --cyan */
.gx-mark {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--gx-ink, var(--cyan));
}

.gx-mark > svg {
  width: 19px;
  height: 19px;
}

/* 방향 화살표 — 텍스트 "→"를 대체하므로 인라인 흐름에 맞춰 세운다 */
.gx-arrow {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--gx-line, rgba(122, 183, 255, 0.9));
}

.gx-arrow > svg {
  width: 14px;
  height: 14px;
}

/* 도식 — 폭만 변형별로 잡고 높이는 viewBox 비율에 맡긴다.
   max-width는 자산 카탈로그의 렌더 치수와 1:1이다(확대하면 획이 같이 굵어진다) */
.gx-fig {
  margin: 0;
  color: var(--gx-line, rgba(122, 183, 255, 0.9));
}

.gx-fig > svg {
  display: block;
  width: 100%;
  height: auto;
}

/* gx-fig--adapt·scatter·converge(점·수렴선 계열)는 클라이언트 지시로 철수 —
   생성 이미지와 같은 시각 언어라 함께 제거(2026-08-26). 03 순환 도식(cycle)도
   같은 날 철수해 캡션+점선 브래킷 원형으로 되돌렸다 — 남는 도해형은 flow3·ins */
.gx-fig--ins-1,
.gx-fig--ins-2,
.gx-fig--ins-3 {
  /* 160x120 */
  max-width: 160px;
}

.gx-fig--flow3 {
  /* 240x56 — 재작도판. .gx-flow3 래퍼와 같은 260px라 라벨 트랙과 폭이 1:1로 맞는다 */
  max-width: 260px;
}

.gx-fig--os-flow {
  /* 24x40 */
  max-width: 24px;
}

/* 도식 안에 박힌 stroke="var(--cyan)" 액센트를 라이트 면에서 --blue로 되돌린다.
   커스텀 프로퍼티를 도형 subtree에만 재선언하는 것이라 섹션의 다른 --cyan 사용처는 그대로다 */
#os-arch .gx-fig,
#insight .gx-fig {
  --cyan: var(--blue);
}

/* 인라인 글리프 래퍼 4종 — 전부 currentColor 상속(알약·탭의 상태색을 따라간다).
   크기만 다르므로 상자는 한 규칙으로 공유한다 */
.gx-tab-ic,
.gx-src-ic,
.gx-tag-ic,
.gx-ft-ic {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: inherit;
}

.gx-tab-ic > svg {
  width: 14px;
  height: 14px;
}

/* 07 상품 탭은 라벨이 15.5px/800이라 글리프도 한 단계 크게 — 2종 체계의 위 단(19px) */
.prod-tab .gx-tab-ic > svg {
  width: 19px;
  height: 19px;
}

.gx-src-ic > svg,
.gx-tag-ic > svg {
  width: 14px;
  height: 14px;
}

.gx-ft-ic > svg {
  width: 14px;
  height: 14px;
}

/* 알약 안쪽 글리프는 라벨과 6px — .os-src/.i-tag/.sla-badge가 공유하는 간격 */
.gx-tag-ic {
  margin-right: 6px;
}

/* 플랫폼 심볼 클러스터 — 06 여정 카드의 18px 마스크 칩(.mp-ico)을 가로로 2~4개 나열한다.
   .mp-ico 자체 규칙은 건드리지 않고 배치만 준다 */
.mp-icos {
  display: flex;
  align-items: center;
  gap: var(--gap-1);
  min-height: 18px;
}

/* 07 COMMERCE 미디어 행 — 단일 .mp-ico가 쓰던 아래 여백을 클러스터가 그대로 이어받는다.
   .prod-media span(display:block)이 같은 요소를 잡으므로 display도 이 스코프에서 다시 세운다 */
.prod-media .mp-icos {
  display: flex;
  margin: 0 0 12px;
}

.prod-media .mp-icos .mp-ico {
  margin: 0;
}

/* 10 허브 심볼 — 개발중 포지셔닝이라 로고를 키우지 않는다.
   40px는 .os-cap(11px) 세 줄 남짓 높이로, 허브 이름(24~28px)보다 크지 않다 */
.gx-core-mark {
  display: block;
  width: 40px;
  height: 40px;
  margin: 0 auto 12px;
}

/* 심볼이 .os-core의 첫 자식이 되면 .os-cap:first-child의 auto 마진이 풀린다 —
   같은 역할을 심볼로 옮겨 상단 여유 배분을 유지한다 */
.os-core > .gx-core-mark:first-child {
  margin-top: auto;
}

/* 15 문의 흐름 3노드 — 폼 옆 소형 가로 스트립.
   라벨은 재작도판 노드(cx 28 / 120 / 212 of 240)에 맞춰 중심을 맞춘다.
   대칭 3트랙 a:b:a에서 양끝 칸의 중심은 a/2 — 28/240 = 0.1167이므로 a = 0.2333,
   b = 1 - 2a = 0.5333. 30등분하면 정확히 7 : 16 : 7이다(중앙 칸 중심은 자동으로 0.5 = 120) */
.gx-flow3 {
  max-width: 260px;
  margin-top: 26px;
}

.gx-flow3-labels {
  display: grid;
  /* 2:7:2 — 열 중심이 재작도 도식의 노드 cx 21.8/120/218.2(뷰박스 240)와 일치 */
  grid-template-columns: 2fr 7fr 2fr;
  margin: 7px 0 0;
  padding: 0;
  list-style: none;
  color: var(--text-d-3);
  font-size: 11px;
  line-height: 1.3;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-align: center;
  white-space: nowrap;
}

/* ---------------------------------------------------------
   2. 섹션별 배치
   --------------------------------------------------------- */

/* --- 01 WHY — 글리프가 넘버 왼쪽에 같은 행으로 앉고, 문장은 아래 행 전폭.
   구획 문법([상단 룰 → 번호 → 문장])은 그대로다. 번호 행만 [글리프 + 번호]가 된다.
   정렬은 center가 아니라 baseline — 22px 글리프의 아랫변이 카운터의 베이스라인에 맞아
   숫자와 한 활자처럼 붙는다(center면 글리프가 숫자보다 위로 뜬다).
   글리프 위/아래로 삐져나오는 부분이 없어 행 높이는 카운터 단독일 때와 같다 --- */
.why-line:has(> .gx-mark) {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: baseline;
  column-gap: var(--gap-2);
}

.why-line > .gx-mark {
  grid-column: 1;
  grid-row: 1;
}

.why-line:has(> .gx-mark) > .why-tick {
  grid-column: 2;
  grid-row: 1;
  margin-bottom: 0;
}

/* 문장 래퍼도 span이라 글리프와 셀렉터가 겹친다 — :not으로 갈라낸다 */
.why-line:has(> .gx-mark) > span:not(.gx-mark) {
  grid-column: 1 / -1;
  grid-row: 2;
  margin-top: clamp(10px, 1.2vw, 16px);
}

/* --- 03 C.O.R.E --- */
.fw-card > .gx-ic {
  align-self: flex-start;
  margin-bottom: 14px;
}

/* --- 05 DIFFERENCE --- */
/* 텍스트 "→"를 대체한 SVG — 그리드 자리(28px 열)와 중앙 정렬은 .diff-arrow가 그대로 갖는다 */
.diff-arrow.gx-arrow {
  color: var(--gx-line);
}

/* --- 07 AD PRODUCTS ---
   .prod-tab span(부제 색)이 아이콘 래퍼까지 잡는다 — 글리프는 부제가 아니라
   탭 라벨의 상태색(휴지 --text-l-2 / hover --blue / 활성 흰색)을 따라가야 한다 */
.prod-tab > .gx-tab-ic,
.prod-tab.is-active > .gx-tab-ic {
  align-self: flex-start;
  margin-bottom: 2px;
  color: inherit;
}

/* --- 08 PROCESS --- */
/* 스텝 글리프 — 필 안 좌측 여백에 절대 배치한다. 흐름에 두면 플렉스 아이템이 되어
   [번호 + 제목] 중앙 정렬축이 글리프 폭만큼 밀린다.
   칩 크롬(38px 상자·면·1px 보더)은 여기서 걷는다 — 1px 아웃라인 필 안에 또 하나의
   상자가 서면 구획이 두 겹이 된다. 01 WHY에서 .gx-mark를 만든 것과 같은 사유이고,
   잉크는 필 안 번호와 같은 --blue 한 값으로 맞춘다(새 색 없음) */
.pm-step > strong > .gx-ic {
  position: absolute;
  top: 50%;
  left: 24px;
  width: auto;
  height: auto;
  border: 0;
  border-radius: 0;
  background: none;
  color: var(--blue);
  transform: translateY(-50%);
}

/* 루프 캡션 — 칩이 들어오면 ::before의 ↻ 텍스트 글리프와 같은 뜻이 두 번 나온다 */
.pm-loop-cap:has(> .gx-ic--sm) {
  display: inline-flex;
  align-items: center;
  gap: var(--gap-2);
}

.pm-loop-cap:has(> .gx-ic--sm)::before {
  content: none;
}

/* --- 10 OS ARCH --- */
.os-mod > .gx-ic {
  align-self: flex-start;
  margin: 10px 0 0;
}

.os-src li:has(> .gx-src-ic) {
  display: inline-flex;
  align-items: center;
  gap: var(--gap-1);
}

/* --- 11 SNAPSHOT — 칩 없음.
   무채색으로 아무리 눌러도 카드 다섯 장 위쪽에 상자가 한 줄로 늘어서면
   카운트업 수치(이 밴드의 유일한 주인공)와 시선이 갈라진다. 칩 스코프 규칙은 삭제했다. --- */

/* --- 12 WORKS — 업종 칩은 태그 행 우측.
   카드가 flex 컬럼이라 태그와 칩을 한 행으로 묶을 래퍼가 없다. 음수 마진으로
   칩이 차지할 높이를 정확히 되돌려(28 - 28.5 + 0.5 = 0) h3 이하 흐름이 1px도 밀리지 않게 하고,
   태그 알약(29px)과 칩(28px)의 중심을 0.5px 오차로 맞춘다.
   썸네일과 경쟁하지 않도록 면·보더는 한 단계 눌렀다(잉크 --blue 4.83:1은 유지) --- */
.case-tag + .gx-ic--sm {
  --gx-face: rgba(15, 99, 234, 0.06);
  --gx-edge: var(--border-l2);
  align-self: flex-end;
  margin-top: -28.5px;
  margin-bottom: 0.5px;
}

/* --- 14 INSIGHT — 도식을 카드 좌측 세로 전폭 슬롯으로.
   기존 3열(태그/본문/상태) 앞에 fig 열을 하나 더 붙인다 --- */
.insight-list article:has(> .gx-fig) {
  grid-template-columns: auto auto minmax(0, 1fr) auto;
  grid-template-areas:
    "fig tag title soon"
    "fig tag desc soon";
  column-gap: var(--gap-2);
}

/* 도식은 흰 카드 위에 선만으로 떠 있으면 카드에 얹힌 낙서처럼 읽힌다 —
   라이트 면 틴트 플레이트를 깔아 "썸네일" 한 장으로 묶는다.
   면은 라이트 팔레트 --gx-face(.08)의 절반인 .04, 보더는 카드 보더(--border-l2)보다
   한 단계 여린 --border-l1 — 카드 안의 상자가 카드 자신보다 또렷해지지 않게 */
.insight-list article > .gx-fig {
  grid-area: fig;
  align-self: center;
  width: 124px;
  padding: 12px;
  border: 1px solid var(--border-l1);
  border-radius: 10px;
  background: rgba(15, 99, 234, 0.04);
}

/* --- 15 CONTACT + 푸터 --- */
/* 메타 행은 [라벨 span / 값 strong] 2행 그리드 — 아이콘이 첫 자식으로 들어오면
   3행이 되므로 아이콘 열을 따로 세우고 텍스트 두 줄은 2열에 묶는다 */
.contact-meta div:has(> .gx-ft-ic) {
  grid-template-columns: auto minmax(0, 1fr);
  column-gap: var(--gap-1);
  align-items: center;
}

.contact-meta .gx-ft-ic {
  grid-column: 1;
  grid-row: 1;
}

.contact-meta div:has(> .gx-ft-ic) > strong {
  grid-column: 2;
  grid-row: 1;
}

/* 아이콘 래퍼도 span이라 라벨 span과 셀렉터가 겹친다 — :not으로 갈라낸다 */
.contact-meta div:has(> .gx-ft-ic) > span:not(.gx-ft-ic) {
  grid-column: 2;
  grid-row: 2;
}

/* 푸터 연락처 — li가 이미 flex(gap 10px)라 아이콘은 첫 자식으로 그대로 선다 */
.footer-contact li > .gx-ft-ic {
  align-self: flex-start;
  margin-top: 3px;
}

/* ---------------------------------------------------------
   3. 반응형 — 중간 폭
   --------------------------------------------------------- */
/* ---------------------------------------------------------
   4. 반응형 — 모바일 커넥터 복원

   경계는 768이 아니라 720px이다. 이 파일에서 03·08·10이 실제로 1열로 접히는 지점이
   ≤720이고(공용 RESPONSIVE), 721~768 구간은 아직 2·3열이라 세로 커넥터가 성립하지 않는다.
   즉 "모바일에서 커넥터가 사라진다"는 문제가 발생하는 구간 전체를 덮는다.
   --------------------------------------------------------- */
@media (max-width: 720px) {
  /* --- 03 C.O.R.E — 진행 셰브런을 카드 사이 세로로 전환 ---
     오버레이(.fw-flow)는 절대 배치라 카드의 실제 행 높이를 알 수 없다.
     그래서 카드 행을 1fr로 균등화해 오버레이의 repeat(4, 1fr)와 트랙을 일치시킨다.
     셰브런은 같은 45° 보더 기호를 90° 더 돌린 것뿐 — 크기(--fw-chev 7px)·잉크·두께 불변 */
  .framework-grid {
    grid-auto-rows: 1fr;
  }

  .fw-flow {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: repeat(4, 1fr);
  }

  .fw-flow i {
    justify-self: center;
    align-self: end;
    margin-right: 0;
    /* 행 하단에서 gap 중앙까지 — 데스크탑의 가로 계산식을 축만 바꿔 그대로 쓴다 */
    margin-bottom: calc(-1 * (var(--fw-gap) / 2 + var(--fw-chev) / 2));
    transform: rotate(135deg);
  }

  /* --- 08 PROCESS — 필 폭만 100%로 풀고 배선 문법은 데스크탑 그대로 간다 ---
     ∨ 구간은 65 → 48로 줄여 좁은 화면에서 헤더와 첫 스텝이 멀어지지 않게 한다.
     수행 항목은 한 줄에 두 개가 들어가지 않으므로 세로로 세워 묶음 높이를 균일하게 맞춘다 */
  .pm-flow-chev {
    height: 48px;
  }

  .pm-do {
    flex-direction: column;
    align-items: center;
    /* 세로로 서면 4px는 두 줄이 한 줄처럼 엉킨다 — 사다리 맨 아랫단(--gap-1)으로 올린다.
       묶음 간격은 데스크탑과 같은 --gap-4를 그대로 상속받는다 */
    gap: var(--gap-1);
  }

  /* --- 10 OS ARCH — 세로 스택 커넥터 신설 ---
     데스크탑 브래킷(가로 1px + 접점 링 도트)을 축만 바꿔 옮긴다.
     도트는 카드 상단 보더 중앙에, 선은 그 위 gap 14px를 채워 앞 카드까지 닿는다.
     .os-col은 ≤1024에서 display:contents라 네 모듈이 허브 아래로 한 줄에 쌓인다 */
  .os-arch .os-col.is-left .os-mod::before,
  .os-arch .os-col.is-right .os-mod::before {
    display: block;
    top: 0;
    bottom: auto;
    left: 50%;
    right: auto;
    margin: -6px 0 0 -6px;
  }

  .os-arch .os-col.is-left .os-mod::after,
  .os-arch .os-col.is-right .os-mod::after {
    display: block;
    top: auto;
    bottom: 100%;
    left: 50%;
    right: auto;
    width: 0;
    /* ≤1024 공용 규칙의 .os-arch gap과 같은 값 */
    height: 14px;
    margin: 0 0 0 -0.5px;
    border: 0 solid var(--os-line);
    border-left-width: 1px;
    border-radius: 0;
  }

  /* 마크업이 같은 자리에 os-flow 도식을 실어 오면 커넥터가 두 겹이 된다 — 그때는 도식에 양보 */
  .os-arch:has(.gx-fig--os-flow) .os-col .os-mod::before,
  .os-arch:has(.gx-fig--os-flow) .os-col .os-mod::after {
    display: none;
  }


  /* --- 14 INSIGHT — 모바일 3행 스택 좌측에 도식 열을 붙인다(숨기지 않는다) --- */
  .insight-list article:has(> .gx-fig) {
    grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-areas:
      "fig tag soon"
      "fig title title"
      "fig desc desc";
    column-gap: var(--gap-2);
  }

  /* 플레이트 폭(=fig 열)은 그대로 두고 안쪽 패딩만 한 단계 줄인다 —
     76px 열에서 12px을 그대로 쓰면 그림이 50px로 접혀 형태를 잃는다 */
  .insight-list article > .gx-fig {
    width: 76px;
    padding: 8px;
  }
}

/* =========================================================
   3. T1 신설 구조 (마크업 커밋 40fd0d5 계약)

   T1이 심은 19개 훅의 스타일 계약. 원칙은 위 GX 층과 동일하다 —
   새 색·새 각도·새 모션 없음, 기존 토큰과 부품 문법만 재조합한다.
   ========================================================= */

/* ---------------------------------------------------------
   3-1. 도식 프레임 — 최우선 교정
   `.gx-fig > svg { width: 100% }`가 부모 폭까지 늘리기 때문에, 변형 클래스가
   max-width를 주지 않으면 120단위 뷰박스가 01에서 ~360px로 3배 확대되고
   획도 같이 3배 굵어진다(1.4 → 4.2px 실효). 카탈로그 렌더 치수와 1:1로 못박는다.
   --------------------------------------------------------- */

/* 03 C.O.R.E 원칙별 고유 도식(p13) — 120x56, 카드당 1점.
   태그 열과 간격이 0이라 도식이 태그에 얹혀 보였다 — 카드 안에서 도식은
   태그와 다른 층이므로 --gap-3(24)로 띄운다(태그 사이 간격 8보다 확실히 큰 단) */
.gx-fig--core-c,
.gx-fig--core-o,
.gx-fig--core-r,
.gx-fig--core-e {
  max-width: 120px;
  /* 카드 폭 324에 도식 120이라 좌측 정렬로는 우측에 177px 공백이 남아
     네 카드의 도식이 전부 왼쪽 벽에 붙어 보였다 — 카드 중앙으로 정박한다.
     제목·설명·태그는 좌측 정렬 그대로: 텍스트는 읽기 축, 도식은 카드 축을 따른다 */
  margin: var(--gap-3) auto 0;
}

/* 01 WHY 미니 문제 도식(p8) — 120x40.
   답변 줄 수가 카드마다 달라(3번은 1줄) 도식이 답변 뒤에 그대로 붙으면
   세 도식의 밑선이 어긋난다 — auto 마진으로 li 바닥에 정박시킨다 */
/* 세로 auto는 세 도식을 카드 바닥에 나란히 앉히고(베이스라인 일치), 가로 auto는 열 안에서
   가운데로 보낸다 — 120px 상자가 열 폭보다 훨씬 좁아 좌측에 붙어 있었다(2026-08-29) */
.gx-fig--why-1,
.gx-fig--why-2,
.gx-fig--why-3 {
  max-width: 120px;
  margin: auto auto 0;
}

/* ---------------------------------------------------------
   3-2. 06 사분면 좌표계 (소개서 p20)
   4장을 1열로 늘어놓던 배치를 십자 축 위 2x2로 옮긴다.
   --------------------------------------------------------- */

/* 축 2줄과 중앙 필의 기준 상자. 열 거터를 --gap-editorial로 벌려
   세로 축이 지나갈 "빈 복도"를 만든다 — p20에서 축은 카드 사이 여백을 관통한다.

   grid-auto-rows: 1fr — 두 행을 같은 높이로 못박는다. 행 높이는 내용이 정하게 두면
   윗행이 아랫행보다 1.19px 높아졌고(칩 배지 높이 차), 그러면 top:50%에 앉는 가로축과
   중앙 필이 거터 한가운데를 0.59px 빗나가 필의 상하 여백이 7.66/8.84로 갈렸다.
   대칭을 내용에 맡기지 않고 그리드에서 보장한다 — 이 배치에서 "카드 높이 편차"는
   행이 아니라 카드 안 한 지점(.mp-note 위 여백)에서만 흡수되는 것이 계약이다 */
.mp-grid.gxq-quad {
  position: relative;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-auto-rows: 1fr;
  column-gap: var(--gap-editorial);
  row-gap: var(--gap-4);
}

/* 사분면 배정 — p20의 읽기 순서(좌상 → 우상 → 좌하 → 우하) */
.gxq-q1 {
  grid-area: 1 / 1;
}

.gxq-q2 {
  grid-area: 1 / 2;
}

.gxq-q3 {
  grid-area: 2 / 1;
}

.gxq-q4 {
  grid-area: 2 / 2;
}

/* 4장을 잇던 레일은 축이 대신한다 — 레일이 세로 축을 가로지르면 흐름 표식 둘이
   같은 자리에서 충돌한다. 노드(정거장)와 STAGE 라벨은 그대로 두고 레일만 페이드로 종결해
   "4장이 한 여정"이라는 읽기(직전 피드백 반영분)는 유지한다.

   ※ 선택자에 .mp-card를 끼운 이유(특정도 교정) — 이 블록은 그동안 한 줄도 적용되지 않았다.
   상대인 `.mp-card:not(:last-of-type) .mp-rail`은 클래스 2 + 의사클래스 1로 (0,3,0),
   구 `.gxq-quad .mp-rail`은 (0,2,0)이라 매번 졌다. 그 결과 1440·1280 실측에서
   4장 전부 레일이 카드 오른쪽 밖으로 14px(=--mp-gap) 삐져나오고, 알파가 0으로 사라진
   레일 끝에 셰브런만 홀로 떠 있었다(우열은 본문 폭 1120 바깥, 좌열은 세로축 22px 앞).
   이제 4장의 레일이 라벨 뒤 8px에서 시작해 카드 오른쪽 변에서 정확히 끝나는 한 부품이 된다 */
.mp-grid.gxq-quad .mp-card .mp-rail {
  margin-right: 0;
  background: linear-gradient(90deg, rgba(15, 99, 234, 0.55), rgba(15, 99, 234, 0));
}

.mp-grid.gxq-quad .mp-card .mp-rail::after {
  content: none;
}

/* 십자 헤어라인 2줄 — 셀을 차지하지 않는 절대 배치 자식(03 .fw-flow와 같은 계약).
   잉크는 라이트 면 보더 토큰(--border-l2). 축은 '선'이지 '획'이 아니라
   글리프 잉크(--gx-line)를 쓰면 도식보다 진해져 좌표계가 전경으로 튀어나온다 */
.gxq-axis {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.gxq-axis::before,
.gxq-axis::after {
  content: "";
  position: absolute;
  background: var(--border-l2);
}

/* 세로 축 — 열 거터 한가운데 */
.gxq-axis::before {
  top: 0;
  bottom: 0;
  left: 50%;
  width: 1px;
  margin-left: -0.5px;
}

/* 가로 축 — 행 거터 한가운데. 좌우로 --gap-3만큼 넘겨 카드 폭보다 넓게 그어
   "면을 가르는 축"으로 읽히게 한다(p20에서 가로축은 본문 폭 전체를 가로지른다) */
.gxq-axis::after {
  left: calc(-1 * var(--gap-3));
  right: calc(-1 * var(--gap-3));
  top: 50%;
  height: 1px;
  margin-top: -0.5px;
}

/* 중앙 축 필 — 교차점에 앉아 두 축을 마스크한다(면색 배경이 곧 마스크).
   라벨은 텍스트 노드가 아니라 data-label이라 ::after로 렌더한다 —
   추출 텍스트 증감 0을 지키려는 T1 인계 계약.
   중앙 정렬은 transform이 아니라 translate 축을 쓴다(사이트 규약: transform은 패럴랙스 몫) */
.gxq-journey {
  position: absolute;
  left: 50%;
  top: 50%;
  translate: -50% -50%;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  gap: var(--gap-1);
  padding: 9px 18px;
  border: 1px solid var(--border-l3);
  border-radius: var(--r-pill);
  background: var(--surface-l0);
  color: var(--blue);
  font-size: 11.5px;
  line-height: 1;
  font-weight: 800;
  letter-spacing: var(--t-label-ls);
  white-space: nowrap;
}

/* 앞머리 azure 점 — p20의 필 문법(보더 + 선행 도트) */
.gxq-journey::before {
  content: "";
  flex: 0 0 auto;
  width: 8px;
  height: 8px;
  border-radius: var(--r-pill);
  background: var(--blue);
}

.gxq-journey::after {
  content: attr(data-label);
}

/* ---------------------------------------------------------
   3-3. 04 SERVICE 분할 행 (소개서 p15)
   카드 3장을 3열로 늘어놓던 것을 "좌 요약 / 우 상세" 3행으로 세운다.
   --------------------------------------------------------- */
/* ※ :has() 가드 필수 — 이 블록은 T1의 .svc-sum/.svc-detail 래퍼가 있을 때만 성립한다.
   가드 없이 .service-card에 grid 2열을 걸면 래퍼가 없는 마크업에서는 카드의 직계 자식
   (아이콘·번호·h3·정의·본문·목록·캡션)이 그대로 2열로 흩어져 실행 항목이 접힌다.
   기존 GX 층이 쓰는 배치 가드 문법(.pm-loop-cap:has(> .gx-ic--sm) 등)을 그대로 따른다 */
/* 04 카드의 활자 위계는 폭과 무관하게 p15를 따른다 — 영문 영역명이 라벨,
   국문 한 줄이 제목이다. 아래 행 배치 안에서만 뒤집으면 861px 경계에서
   같은 카드가 폭에 따라 다른 위계로 읽힌다 */
.service-card .svc-sum h3 {
  color: var(--blue);
  font-size: 13.5px;
  line-height: 1.2;
  font-weight: 800;
  letter-spacing: var(--t-eyebrow-ls);
  text-transform: uppercase;
}

.service-card .svc-sum > .svc-keys {
  text-align: left;
}

.service-card .svc-sum .svc-def {
  margin-top: var(--gap-1);
  color: var(--text-l-1);
  font-size: var(--t-sub-1);
  line-height: var(--t-sub-1-lh);
  font-weight: 800;
}

@media (min-width: 861px) {
  .service-grid:has(.svc-sum) {
    grid-template-columns: minmax(0, 1fr);
  }

  /* 행 = [요약 1fr | 상세 1.35fr]. p15는 좌 요약이 좁고 우 상세가 넓다.
     min-height 340px은 3열 카드가 서로 키를 맞추라고 있던 값이라 행 배치에서는 걷는다
     (그대로 두면 3행 x 340px로 섹션이 세 배가 된다).
     align-items는 start가 아니라 stretch — start로 두면 우열이 제 콘텐츠 높이(57%)에서
     멈춰 카드 하단 우측에 125px 공백이 남고 캡션이 그 한가운데 떠버린다 */
  /* 열 폭 1 : 1.35 → 1.25 : 1. 두 열의 최장 잉크는 좌 285px(영문 태그) · 우 228px(실행
     항목)로 좌가 넓은데, 트랙은 465 : 628로 반대였다 — 그래서 좌열은 61% 차고 우열은
     36%만 차, 오른쪽 절반이 비어 보였다(클라이언트 지적, 2026-08-29). 잉크 비 285:228을
     트랙에 그대로 옮기면 608 : 486이 되어 두 열이 똑같이 47%를 채운다. 카드가 가진 여백의
     총량은 그대로지만 한쪽에 몰리지 않는다 — 04가 이미 세운 "여백은 총량이 아니라 어디에
     모였는지로 읽힌다"는 원칙의 가로 판이다 */
  .service-card:has(> .svc-sum) {
    display: grid;
    grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
    column-gap: var(--gap-4);
    align-items: stretch;
    min-height: 0;
  }

  /* 헤더 구분선(::after)은 3열 카드에서 "아이콘 밴드"를 본문에서 끊으라고
     top:90px / left·right 28px에 고정돼 있던 값이다. 행 배치에서는 좌우 두 열을
     가로질러 상세 2행째 바로 위에 얹혀, 어느 요소에도 속하지 않는 밑줄로 남는다 */
  .service-card:has(> .svc-sum)::after {
    content: none;
  }

  /* 좌 요약 — p15는 [칩][번호 영문영역명]이 한 행에서 라벨 한 덩어리를 이루고,
     그 아래 국문 제목, 다시 아래 설명으로 3단이다.
     흐름 배치로 두면 칩/번호/영문명이 각자 한 줄씩 차지해 5단 세로 스택이 되고
     좌열만 235px로 솟아 우열과의 균형이 깨진다 */
  .service-card > .svc-sum {
    display: grid;
    grid-template-columns: auto auto minmax(0, 1fr);
    column-gap: var(--gap-1);
    align-content: start;
  }

  .service-card > .svc-sum > .svc-icon {
    grid-area: 1 / 1;
    margin-right: var(--gap-1);
  }

  /* 번호는 카드 우상단 절대 배지가 아니라 p15의 "번호 eyebrow"로 —
     행 배치에서 우상단은 상세 패널 위라 요약과 분리돼 버린다.
     영문 영역명과 같은 급·같은 색으로 맞춰 둘이 라벨 한 줄로 읽히게 한다 */
  .service-card:has(> .svc-sum) .svc-index {
    grid-area: 1 / 2;
    position: static;
    align-self: center;
    height: auto;
    margin: 0;
    font-size: 13.5px;
    letter-spacing: var(--t-eyebrow-ls);
  }

  .service-card .svc-sum h3 {
    grid-area: 1 / 3;
    align-self: center;
    margin: 0;
  }

  /* 국문 제목은 라벨 행 아래 제 단으로 — L1 서브타이틀 급은 위 공통 규칙이 준다 */
  .service-card .svc-sum .svc-def {
    grid-area: 2 / 1 / 3 / -1;
    margin: var(--gap-3) 0 0;
  }

  /* 영문 분류 태그는 설명문과 같은 3행에 얹혀 글자가 서로 관통했다(2026-08-28).
     제 행(4행)을 주고 위 단과 --gap-3 만큼 띄운다 */
  .service-card .svc-sum > .svc-keys {
    grid-area: 4 / 1 / 5 / -1;
    margin: var(--gap-3) 0 0;
  }

  .service-card .svc-sum > p:not(.svc-def):not(.svc-keys) {
    grid-area: 3 / 1 / 4 / -1;
    margin: var(--gap-2) 0 0;
  }

  /* 우 상세 — 스펙 표가 열 상단에 앉는 세로 골격.
     (구 주석의 "캡션이 바닥에 앉는다"는 직전 라운드에서 영문 태그가 좌열 4행으로
     옮겨간 뒤로 성립하지 않는다 — 이 열의 내용물은 실행 항목 목록 하나뿐이다) */
  .service-card > .svc-detail {
    display: flex;
    flex-direction: column;
    min-height: 0;
  }

  /* 상세 실행 항목 2열 행 그리드 — p15의 "2열x2행".
     padding-top 22px는 3열 카드에서 설명문 다음에 오던 간격이라 행 배치에서는
     우열 첫 행만 아이콘보다 22px 내려앉게 만든다(좌우 상단 기준선 불일치).

     행 높이는 1fr이 아니라 콘텐츠 기준이다. 1fr로 두면 우열이 좌 요약의 높이(226px)를
     두 행에 균등 분배해, 한 줄(23.2px)짜리 항목이 113px 행에 앉는다 — 잉크 비중 20.5%,
     두 글줄 사이 94.7px, 그 한가운데 헤어라인만 떠 있는 상태가 클라이언트가 지적한
     "너무 넓은 여백감"의 실체다(2026-08-29). 같은 목록이 861px 미만에서는 이미
     콘텐츠 높이(행 23.2 / 피치 39.2)로 정상이라, 데스크톱만 어긋나 있었다.
     2열 2행을 1열 4행으로 바꾼 것은 그 수리의 나머지 절반이다. 항목이 "라벨-값"이
     아니라 완결된 한 문장이라 2열로 나눌 축이 없었고, 2행짜리 목록(104px)은 좌 요약
     (226px)보다 122px 짧아 열 하단에 카드 높이의 43%가 비었다. 1열 4행은 전폭 괘선
     행이 되어 레퍼런스의 표 문법(엠피 46px 행)과 같은 것을 읽히게 하고, 높이도 좌열과
     맞는다. 남는 몫은 space-between이 행 사이로 균등 배분해 좌우 하단이 함께 끝난다
     — 배분값은 행 4개·간격 3개 기준 약 22px로, row-gap 24의 바닥값에서 2px 이내다 */
  .service-card .svc-detail ul {
    flex: 1 1 auto;
    margin: 0;
    padding: 0;
    grid-template-columns: minmax(0, 1fr);
    align-content: space-between;
    row-gap: var(--gap-3);
  }

  /* [2026-08-29] 행 밑줄 폐기. 전폭 4행으로 바꾸면서 각 항목에 헤어라인을 붙였는데,
     그러면 카드 안 가로선이 좌열 두 줄(설명 위·영문 태그 위)에 우열 네 줄이 더해져 여섯이
     되고, 06 여정 카드에서 고친 것과 같은 증상이 된다 — 같은 값의 선이 반복되면 목록이
     아니라 잘린 표로 읽힌다. 항목의 경계는 체크 표식과 space-between이 나누는 간격이 지고,
     861px 미만이 이미 쓰던 무괘선 목록과도 표기가 하나로 합쳐진다 */
  .service-card .svc-detail li {
    align-items: center;
  }

  .service-card .svc-detail li::before {
    margin-top: 0;
  }
}

/* ---------------------------------------------------------
   3-4. 11 SNAPSHOT — KPI 그리드 + 리드 h2 승격
   --------------------------------------------------------- */

/* p30 KEY FIGURES 문법의 마지막 한 조각 — 수치와 라벨 사이 짧은 azure 룰.
   카드 상단 accent(::before)와 대형 수치는 .snapshot-inner article이 이미 갖고 있다 */
.gx-kpi-card > strong::after {
  content: "";
  display: block;
  width: 28px;
  height: 2px;
  margin-top: 14px;
  background: var(--card-line);
}

/* (구 h2.snapshot-lead 급 보류 블록 — 제거됨)
   T1은 태그만 p → h2로 올리고 렌더를 19/w600에 묶어 두었다. 이번 패스에서
   "11을 섹션 h2 급으로 편입" 지시를 받아 급을 확정했으므로, 그 보류 오버라이드는
   .snapshot-lead 본 선언(위 SNAPSHOT 블록)과 값이 충돌하기만 한다.
   UA 기본 h2(2em / 0.83em 마진 / bold)는 본 선언이 전부 덮는다 */

/* ---------------------------------------------------------
   3-6. T1 구조 로컬 반응형
   --------------------------------------------------------- */

/* 사분면은 좌표계라 1열로 접으면 의미가 사라진다 — 2x2는 태블릿까지 유지하고
   축·필은 1열로 내려갈 때만 걷는다(GX 원칙 3: 도식을 숨기지 않고 자리를 옮긴다) */
@media (max-width: 1024px) {
  .mp-grid.gxq-quad {
    /* 행 거터를 --gap-3(24)로 좁히면 31.5px짜리 중앙 필이 거터보다 커져
       위아래 카드를 3.75px씩 파고든다(721~1024 구간 실측). 두 거터를 --gap-4로 맞춰
       십자의 팔 길이를 같게 두고, 필은 데스크톱과 같은 8.25px 여유를 갖는다 */
    column-gap: var(--gap-4);
    row-gap: var(--gap-4);
  }
}

@media (max-width: 720px) {
  .mp-grid.gxq-quad {
    grid-template-columns: minmax(0, 1fr);
    /* 1열에서는 행 균등이 "가장 긴 카드에 4장이 전부 끌려가는" 규칙이 된다 —
       맞출 좌우 짝도, 가운데를 지날 축도 없으므로 내용 높이로 되돌린다 */
    grid-auto-rows: auto;
    column-gap: 0;
    row-gap: var(--gap-2);
  }

  .gxq-q1,
  .gxq-q2,
  .gxq-q3,
  .gxq-q4 {
    grid-area: auto;
  }

  /* 1열에서는 십자가 성립하지 않는다 */
  .gxq-axis,
  .gxq-journey {
    display: none;
  }
}
