@charset "UTF-8";
/* ==========================================================================
   proto.css — 메인 프로토타입 컴포넌트
   전제: xc-tokens.css 가 먼저 로드되어 있어야 한다.
   이 파일의 값은 전부 토큰(--xc-*)에서 가져온다. 하드코딩 금지.
   ========================================================================== */

*, *::before, *::after { box-sizing: border-box; }
html {
  scroll-behavior: smooth;
  /* 스크롤바 자리를 항상 확보 — 스크롤을 잠글 때 화면이 밀리지 않는다 */
  scrollbar-gutter: stable;
  /* 해시로 들어온 대상이 고정 GNB 뒤로 파묻히지 않게 한다 */
  scroll-padding-top: calc(var(--gnb-top) + var(--gnb-row) + 20px);
}
/* 전체메뉴가 열려 있는 동안 페이지 스크롤 차단 */
html.is-locked { overflow: hidden; }

/* ⚠️ 절대 규칙 — 가로 스크롤 금지
   어느 화면에서도 페이지가 좌우로 밀리면 안 된다.
   넓은 콘텐츠(표·다이어그램·코드)는 자기 컨테이너 안에서만 가로 스크롤한다. */
html, body { max-width: 100%; overflow-x: clip; }
body {
  margin: 0;
  /* 한글은 기본값(normal)에서 어절 중간이 끊긴다 — '회사가' 가 '회 / 사가' 로 갈라진다.
     keep-all 은 띄어쓰기에서만 끊고, 끊을 수 없는 긴 문자열만 아래 규칙이 받아 준다. */
  word-break: keep-all;
  overflow-wrap: break-word;
  background: var(--xc-bg);
  color: var(--xc-text);
  font-family: var(--xc-font-ko);
  font-size: var(--xc-fs-body);
  line-height: var(--xc-lh-body);
  letter-spacing: var(--xc-ls-body);
  -webkit-font-smoothing: antialiased;
}
h1, h2, h3, p, ul, ol, dl, dd, figure, address { margin: 0; padding: 0; }
ul, ol { list-style: none; }
address { font-style: normal; }
a { color: inherit; text-decoration: none; }
/* ⚠️ 폼 요소는 font 를 상속하지 않는다. 브라우저 기본 스타일이 13.333px Arial 을 박아 넣는다.
   상속시키지 않으면 <button> 안의 글자만 프리텐다드에서 빠진다 — 한글은 시스템 폰트로
   대체돼 얼핏 멀쩡해 보이지만 영문·숫자가 Arial 로 나와 다른 글에 섞이면 티가 난다.
   실제로 수상·인증 카드 67개와 필터 탭 전부가 여기 걸려 있었다. */
button, input, select, textarea { font: inherit; letter-spacing: inherit; color: inherit; }
img, svg { max-width: 100%; }
:focus-visible { outline: 2px solid var(--xc-focus); outline-offset: 3px; }

.xc-skip {
  position: absolute; left: -9999px; top: 0; z-index: var(--xc-z-modal);
  background: var(--xc-navy); color: #fff; padding: 12px 20px;
}
.xc-skip:focus { left: 0; }

/* ── 공통 타이포 ──────────────────────────────────────── */
.xc-eyebrow {
  font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-semibold);
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--xc-text-weak); margin-bottom: 14px;
}
.xc-h2 {
  font-size: var(--xc-fs-h2); font-weight: var(--xc-fw-bold);
  line-height: var(--xc-lh-heading); letter-spacing: var(--xc-ls-heading);
  text-wrap: balance;
}
/* ── 줄바꿈 ────────────────────────────────────────────
   마지막 줄에 한 어절만 떨어지는 것(고아 줄)을 막는다.
   · 가운데 정렬 문단은 balance (줄 길이를 고르게)
   · 좌측 정렬 본문은 pretty (줄 수를 유지하며 마지막 줄만 보정)
     balance 를 좌측 본문에 쓰면 4줄 넘는 문단에서 브라우저가 손을 놓는다.
   미지원 브라우저에서는 무시되므로 기존 동작 그대로다. */
/* 넓은 화면에서만 강제 줄바꿈. 좁아지면 브라우저 판단에 맡긴다.
   고정 <br> 은 폭이 줄면 오히려 마지막 줄에 한 어절만 남기는 원인이 된다. */
@media (max-width: 1280px) { .xc-br-lg { display: none; } }

.xc-hero__lead, .xc-body, .xc-add__ko,
.xc-footer__desc {
  text-wrap: pretty;
}
/* 2~4줄짜리 짧은 문단은 balance 가 낫다. pretty 는 줄 수를 유지하며 마지막 줄만
   손보므로 2줄 문단(마지막 줄 15%)에서는 손댈 여지가 없다.
   ⚠️ 라인업 카드 설명에 써도 안전하다. 패널 폭이 clamp 로 고정돼 있어
      카드가 벌어지는 동안 재계산이 일어나지 않는다. */
.xc-lead, .xc-two__tag, .xc-two__desc,
.xc-card__tag, .xc-card__desc,
.xc-add__step p, .xc-biz__sum, .xc-footer__list span {
  text-wrap: balance;
}

/* 가운데 정렬 문단에서 마지막 줄에 한 어절만 떨어지는 것을 막는다.
   word-break: keep-all 과 함께 쓰면 어절 단위로 균형을 맞춘다. */
.xc-two__head .xc-lead,
.xc-lineup__head .xc-lead,
.xc-clients__head .xc-lead { text-wrap: balance; }

.xc-lead {
  font-size: var(--xc-fs-lead); line-height: 1.65;
  color: var(--xc-text-sub); margin-top: 20px; max-width: 62ch;
}
.xc-body { margin-top: 18px; color: var(--xc-text-sub); max-width: 62ch; }
.xc-body strong { color: var(--xc-text); font-weight: var(--xc-fw-semibold); }

.xc-mark {
  background: var(--xc-gradient);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
/* 다크 섹션 위에서 그라디언트 텍스트를 그대로 쓴다
   (밝은 배경에서는 대비가 부족해 밑줄로 대체했었다) */

.xc-link {
  display: inline-flex; align-items: center; gap: 8px;
  margin-top: 26px; font-weight: var(--xc-fw-semibold);
  font-size: var(--xc-fs-sm); color: var(--xc-text);
  border-bottom: 1px solid var(--xc-border-strong); padding-bottom: 4px;
  transition: var(--xc-trans-fast);
}
.xc-link::after { content: "→"; transition: var(--xc-trans-fast); }
.xc-link:hover { border-bottom-color: var(--xc-accent); }
.xc-link:hover::after { transform: translateX(4px); }
.xc-link--invert { color: #fff; }

.xc-btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 52px; padding: 0 30px; border-radius: var(--xc-radius-sm);
  font-size: var(--xc-fs-sm); font-weight: var(--xc-fw-semibold);
  transition: var(--xc-trans-fast);
}
.xc-btn--fill { background: var(--xc-accent-fill); color: var(--xc-accent-on); }
.xc-btn--fill:hover { filter: brightness(1.06); transform: translateY(-2px); }
.xc-btn--line { border: 1px solid var(--xc-border-strong); color: var(--xc-text); }
.xc-btn--line:hover { border-color: var(--xc-accent); }

/* ── 원형 확장 호버 (재사용 유틸) ──────────────────────────
   커서가 들어온 지점에서 원이 부풀어 버튼을 채우고, 나갈 때는 나간 지점으로 줄어든다.
   참고: mondrian.ai 의 .circleHoverBtn (실제 구현을 브라우저에서 확인해 옮김)

   · 원 위치(--hc-x/y)만 JS 가 커서에서 넣는다. 확장은 :hover / :focus-visible 로 CSS 가 한다
     → 키보드로도 동작하고, JS 가 죽으면 '가운데에서 퍼지는' 형태로 자연스럽게 폴백된다
   · --hc-size 는 지름 기준. 모서리에서 진입해도 반대편까지 덮으려면 200% 이상이어야 한다 */
.xc-hover-circle {
  position: relative; overflow: hidden; isolation: isolate;
  --hc-x: 50%; --hc-y: 50%;
  --hc-size: 220%;
  --hc-fill: var(--xc-white);
}
.xc-hover-circle::after {
  content: ""; position: absolute; z-index: 0;
  left: var(--hc-x); top: var(--hc-y);
  width: var(--hc-size); aspect-ratio: 1;
  border-radius: 50%; background: var(--hc-fill);
  transform: translate(-50%, -50%) scale(0);
  transition: transform var(--xc-dur-slow) linear;   /* 모션 최소화 시 토큰이 .01ms 로 바뀐다 */
  pointer-events: none;
}
.xc-hover-circle:is(:hover, :focus-visible)::after { transform: translate(-50%, -50%) scale(1); }
/* ⚠️ 라벨은 반드시 요소로 감싼다. 맨 텍스트(텍스트 노드)는 z-index 를 못 받아
   position 이 있는 ::after 원 밑으로 깔린다 — 글자가 원에 덮인다. */
.xc-hover-circle > * { position: relative; z-index: 1; }

/* ── 섹션 CTA — 원통형 버튼 ────────────────────────────────
   각 섹션의 큰 버튼을 하나로 통일한다(히어로 · 두 갈래 · ADD · 사업분야).
   호버는 위 .xc-hover-circle 과 조합해서 쓴다.

   기본형(메인)은 배경 없이 테두리만 둔다. 색은 토큰에 맡겨 라이트/다크가 자동으로 뒤집힌다.
     원   --hc-fill: var(--xc-text)  → 라이트=네이비 / 다크=흰색
     글자 :hover color: var(--xc-bg) → 라이트=흰색   / 다크=네이비 */
/* ⚠️ background 를 비워 두면 안 된다. <a> 에서는 투명이지만 <button> 은 브라우저 기본값
   buttonface(#f0f0f0)가 남아 회색 알약이 된다. 실제로 수상·인증의 '더보기'만
   메인 버튼들과 다르게 보였다(2026-07-31 수정). 채움형은 아래 .xc-pill--fill 이 덮는다. */
.xc-pill {
  background: none;
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  min-height: 54px; padding: 0 32px;
  border-radius: var(--xc-radius-full);
  border: 1px solid var(--xc-border-strong);
  color: var(--xc-text);
  font-size: var(--xc-fs-sm); font-weight: var(--xc-fw-semibold);
  white-space: nowrap;
  --hc-fill: var(--xc-text);
  --hc-size: 260%;      /* 가로로 긴 알약이라 모서리 진입까지 덮으려면 크게 잡는다 */
  transition: color var(--xc-dur-base) var(--xc-ease-standard),
              border-color var(--xc-dur-base) var(--xc-ease-standard);
}
.xc-pill__arw { transition: transform var(--xc-dur-fast) var(--xc-ease-out); }
.xc-pill:is(:hover, :focus-visible) { color: var(--xc-bg); border-color: var(--xc-text); }

/* ── 서브페이지 : 흰 알약 ──────────────────────────────────
   메인은 배경 없이 두고 서브페이지에서만 흰 면을 깐다.
   ⚠️ 배경을 고정하면 색을 토큰에 맡길 수 없다. 다크 문맥에서 --xc-text 가 흰색으로
      뒤집혀 흰 배경에 흰 글자가 된다. 글자·테두리·호버 원까지 네이비로 함께 고정한다.
   ⚠️ 서브페이지 pill 은 전부 .xc-sub 안에 있다(2026-08-02 전수 확인).
      바깥에 새 버튼을 놓으면 이 규칙을 못 받으니 위치를 확인할 것. */
.xc-sub .xc-pill:not(.xc-pill--fill):not(.xc-pill--solid) {
  background: var(--xc-white);
  border-color: rgba(22, 29, 41, .28);
  color: var(--xc-navy);
  --hc-fill: var(--xc-navy);
}
.xc-sub .xc-pill:not(.xc-pill--fill):not(.xc-pill--solid):is(:hover, :focus-visible) {
  color: var(--xc-white); border-color: var(--xc-navy);
}
.xc-pill:is(:hover, :focus-visible) .xc-pill__arw { transform: translateX(3px); }

/* ── 오렌지 글로우 (재사용 유틸) ──────────────────────────
   호버하면 카드 밖으로 웜 오렌지 그림자가 번진다.

   · ⚠️ pseudo 로 만들면 안 된다 — .xc-two__card 는 overflow:hidden 이라
        자식 pseudo 의 box-shadow 가 카드 경계에서 잘린다.
        요소 자신의 box-shadow 는 자기 overflow 에 잘리지 않으므로 카드에 직접 건다.
   · 색은 --xc-grad-2(오렌지) / --xc-grad-3(코랄) 두 겹. 가까운 그림자 + 멀리 퍼지는 그림자. */
.xc-glow {
  --gl-1: 249, 168, 92;     /* 오렌지 */
  --gl-2: 242, 131, 107;    /* 코랄 */
  transition: box-shadow var(--xc-dur-base) var(--xc-ease-standard);
}
/* --gl-y = 0 이면 그림자가 카드 위아래로 같은 양만큼 번져 글로우 중심이 카드 중심과 맞는다.
   양수로 밀면 아래로 처져 '떠 있는 그림자'가 되고 중심이 카드 밖으로 내려간다. */
.xc-glow:is(:hover, :has(:focus-visible)) {
  box-shadow:
    0 var(--gl-y, 0px) 30px rgba(var(--gl-1), var(--gl-near, .34)),
    0 var(--gl-y, 0px) 70px rgba(var(--gl-2), var(--gl-far,  .22));
}
/* 다크 카드 보정 — 물리적으로는 라이트 카드와 같은 세기다(실측 변화량 (2,-22,-36) vs (2,-21,-34)).
   다만 어두운 면 바로 옆에서는 같은 웜 컬러가 더 연해 보인다(동시대비). 지각을 맞추려 알파를 올린다. */
.xc-glow.xc-dark { --gl-near: .52; --gl-far: .34; }

/* 강조. 히어로 주 CTA. 바탕이 이미 채워져 있으므로 원만 흰색으로 덮는다.
   ⚠️ border-color: transparent 로 감추면 안 된다 —
      background-clip 기본값이 border-box 라 그라디언트가 테두리 자리까지 칠해지고,
      둥근 모서리에서 투명 테두리가 안티에일리어싱되며 배경(히어로의 웜 광원)이
      1px 띠로 비쳐 나온다. 평소엔 우측 끝에 밝은 실선으로, 호버 시 흰 원이 차면
      어두운 실선으로 보인다. 테두리를 아예 없애야 사라진다.
      box-sizing: border-box 라서 없애도 바깥 크기는 그대로다. */
.xc-pill--fill {
  background: var(--xc-accent-fill); color: var(--xc-accent-on);
  /* 평소엔 안 보이는 테두리. 자리를 미리 잡아 둬야 호버에서 색만 켤 수 있다.
     border:0 으로 두면 호버 때 1px 이 생기면서 글자가 밀린다 */
  border: 1px solid transparent;
  --hc-fill: var(--xc-white);
}

/* 채움 · 기본색. 강조색(--fill 은 오렌지)을 쓰기엔 과하고 외곽선으로는 약한 자리.
   서브페이지의 주 동작 버튼(문의 제출 등)이 여기 해당한다.
   ⚠️ 배경을 --xc-text 로 두지 않는다. 다크 문맥에서 흰색으로 뒤집혀
      흰 배경에 흰 글자가 된다. 위 .xc-sub .xc-pill 규칙과 같은 이유로 네이비를 고정한다.
   ⚠️ 테두리 자리를 미리 잡아 둔다(--fill 과 같은 이유). 호버에서 색만 켠다. */
.xc-pill--solid {
  background: var(--xc-navy); color: var(--xc-white);
  border: 1px solid transparent;
  --hc-fill: var(--xc-white);
}
.xc-pill--solid:is(:hover, :focus-visible) {
  color: var(--xc-navy); border-color: var(--xc-navy);
}
/* ⚠️ 호버하면 흰 원이 차오른다. 글자를 그대로 두면 흰 글자가 흰 원에 묻혀 사라진다
      (--xc-accent-on 이 흰색인 기본 문맥에서 실제로 안 보였다).
      원 색과 같은 계열로 두지 말고 오렌지로 뒤집고, 테두리도 같이 켜서 알약 윤곽을 남긴다. */
.xc-pill--fill:is(:hover, :focus-visible) {
  color: var(--xc-orange); border-color: var(--xc-orange);
}

.xc-badge {
  display: inline-flex; align-items: center; gap: 8px; margin-top: 26px;
  padding: 9px 18px; border-radius: var(--xc-radius-full);
  border: 1px solid var(--xc-border); background: var(--xc-bg-soft);
  font-size: var(--xc-fs-sm); color: var(--xc-text-sub);
}

/* ══════════════════ GNB ══════════════════
   레퍼런스: i-bricks.co.kr — Glass 캡슐 헤더 + 확장형 메가메뉴
   확장 애니메이션은 clip-path(합성 가능) + transform/opacity 로만 처리한다.
   height 는 보이지 않는 히트영역에만 즉시 적용된다.
   ────────────────────────────────────────────────── */
:root {
  /* 값 출처: i-bricks.co.kr 의 common.min.css / main.min.css 실측 */
  --gnb-top:      40px;   /* .header padding-top */
  --gnb-max:    1840px;   /* .header .container max-width */
  --gnb-side:    clamp(20px, 2vw, 40px);   /* 고정 40px 이면 1025px 에서 여유가 4.7px 뿐 */
  --gnb-row:      80px;   /* .header-wrap max-height (닫힘) */
  --gnb-line:     26px;   /* 텍스트 1줄 — 슬라이드 클리핑 창 */
  --gnb-r:        40px;   /* border-radius */

  /* 배경 — 열리면 흰 오버레이가 짙어지고 블러는 오히려 약해진다 */
  --gnb-blur:            20px;
  --gnb-blur-open:       20px;   /* 반경을 바꾸지 않는다 — 전폭 backdrop-filter 애니메이션은 매우 비싸다 */
  --gnb-tint:            rgba(255, 255, 255, .05);
  --gnb-tint-open:       rgba(255, 255, 255, .85);   /* .70 은 영상 위에서 #555 대비 3.8:1 (AA 미달) */

  /* 좌우 여백·간격은 유동으로. 고정값이면 1281px 부근에서
     메뉴 min-content 폭이 캡슐을 넘어 우측 유틸(언어·전체메뉴)이 화면 밖으로 밀린다.
     상한은 레퍼런스 실측값(60/20/30). */
  --gnb-padx:    clamp(24px, 3.2vw, 60px);   /* .header-wrap padding-inline */
  --gnb-gap:     clamp(4px,  1.0vw, 20px);   /* nav-list--depth1 gap */
  --gnb-link-px: clamp(10px, 1.6vw, 30px);   /* depth-1 link padding-inline */
  --gnb-d2-row:   26px;   /* depth-2 행 높이 (padding 5px 0 + line 1.3) */
  --gnb-d2-top:   10px;   /* 헤더행 → 첫 하위항목 */
  --gnb-d2-bot:   40px;   /* .header-wrap padding-bottom (열림) */
  --gnb-ease:     cubic-bezier(.22, 1, .36, 1);
  --gnb-dur:      .5s;    /* 패널 확장 */
  --gnb-hide-dur: .3s;    /* 스크롤 시 숨김/노출 */
  --gnb-d2-delay: .24s;   /* 패널이 95.5% 열린 시점 — 거의 다 내려온 뒤 */
  --gnb-d2-dur:   .32s;   /* 하위메뉴 페이드+슬라이드 */
  --gnb-d2-step:  .04s;   /* 컬럼 간 지연 (좌→우) */
}

/* 바깥 여백을 padding 으로 잡는다 (레퍼런스와 동일).
   스크롤하면 padding 이 0 으로 수렴하며 전체 폭 바가 된다. */
.xc-gnb {
  position: fixed; top: 0; left: 0; right: 0;
  z-index: var(--xc-z-header);
  padding: var(--gnb-top) var(--gnb-side) 0;
  pointer-events: none;
  transition: padding var(--gnb-hide-dur) ease,
              transform var(--gnb-hide-dur) ease;
}
/* 아래로 스크롤 → 위로 밀어 올려 감춤 (레퍼런스 .header.hide)
   padding 이 요소 높이에 포함되므로 -100% 만으로 완전히 빠진다. */
.xc-gnb.is-hide { transform: translateY(-100%); }

/* 스크롤 상태 — 상단에 딱 붙는 전체 폭 흰 바 */
.xc-gnb.is-solid {
  padding: 0;
  --gnb-r: 0px;               /* border-radius + clip-path round 동시 반영 */
}

.xc-gnb__shell {
  position: relative;
  max-width: var(--gnb-max);
  margin-inline: auto;
  height: var(--gnb-row);          /* 닫힘: 히트영역 = 1줄 */
  pointer-events: auto;
  transition: max-width var(--gnb-hide-dur) ease;
}
/* px 로 해석되는 100vw 를 써야 1840px → 전체폭 이 보간된다 (100% 는 보간 안 됨) */
.xc-gnb.is-solid .xc-gnb__shell { max-width: 100vw; }
.xc-gnb.is-open .xc-gnb__shell { height: var(--gnb-open-h, var(--gnb-row)); }

/* ── 블러 패널 ──
   테두리·틴트·채도 보정 없음. backdrop-filter: blur() 만 적용한다.
   배경이 그대로 비치므로 글자색은 뒤에 오는 것에 따라 바뀐다. */
.xc-gnb__bg {
  position: absolute; top: 0; left: 0; right: 0;
  height: var(--gnb-open-h, var(--gnb-row));
  border-radius: var(--gnb-r);
  background: var(--gnb-tint);
  border: 0;
  -webkit-backdrop-filter: blur(var(--gnb-blur));
  backdrop-filter: blur(var(--gnb-blur));
  /* 닫힘: 아래쪽을 잘라내 1줄만 보이게 */
  clip-path: inset(0 0 var(--gnb-clip, 0px) 0 round var(--gnb-r));
  transition: clip-path var(--gnb-dur) var(--gnb-ease),
              background-color var(--gnb-dur) var(--gnb-ease),
              border-radius var(--gnb-hide-dur) ease,
              box-shadow var(--gnb-hide-dur) ease;
  pointer-events: none;
}
/* 열림 — 흰 오버레이가 짙어지고 블러는 약해진다 (오버레이가 대신 가려주므로) */
.xc-gnb.is-open .xc-gnb__bg {
  background: var(--gnb-tint-open);
  clip-path: inset(0 0 0 0 round var(--gnb-r));
}
/* 스크롤 후 — 캡슐을 풀고 전체 폭 흰 바로 (레퍼런스 .scrolled 동작) */
.xc-gnb.is-solid .xc-gnb__bg {
  background: #fff;
  box-shadow: 0 1px 0 rgba(0, 0, 0, .07);
}
/* 사이트맵이 열리면 GNB 블러를 끈다.
   backdrop-filter 두 겹이 쌓이면 사이트맵 열림 애니메이션이 눈에 띄게 버벅인다. */
.xc-gnb.is-covered .xc-gnb__bg {
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}

/* ── 헤더 행 ── */
.xc-gnb__inner {
  position: relative; z-index: 2;
  height: var(--gnb-row);
  padding-inline: var(--gnb-padx);
  display: flex; align-items: center;
}

.xc-gnb__logo { flex: none; font-size: 0; line-height: 0; }
.xc-gnb__logo img {
  width: clamp(132px, 9vw, 168px); height: auto; display: block;
  transition: filter var(--gnb-dur) var(--gnb-ease);
}
/* 레퍼런스는 filter:invert(1) 로 뒤집지만, 우리 로고는 흰색+오렌지라
   invert 하면 오렌지가 파랑이 된다. 검정 모노로 처리한다. (다크 버전 파일 필요) */
.xc-gnb.is-open  .xc-gnb__logo img,
.xc-gnb.is-solid .xc-gnb__logo img { filter: brightness(0); }

/* ── 상단 메뉴 ── */
/* min-width:0 — flex 아이템 기본값 auto 는 min-content 아래로 안 줄어든다.
   그대로 두면 좁은 폭에서 우측 유틸을 밀어낸다. */
.xc-gnb__nav { flex: 1; min-width: 0; }
/* 큰메뉴는 평소에는 글자 길이대로 두고, 메가메뉴가 열릴 때만 좌우로 벌어진다.
   ⚠️ 글자 길이 그대로면 하위 컬럼이 서로 겹친다. 컬럼은 부모 중앙(left:50%)에 붙는데
      부모 사이 간격은 컬럼 폭을 모르기 때문이다. 영문 1600px 에서 xCalibur 와 Solution 이
      12px 겹쳤고 1366px 에서는 22px 겹쳤다. 국문도 1366px 에서 겹쳤다.
   ⚠️ 여백을 더하는 방식으로는 못 푼다. 1366px 에서 38px 을 더 벌려야 하는데
      남는 자리가 58px 뿐이라 넘친다. 그래서 「더하지 않고 나눠 갖는」 방식을 쓴다.
      열릴 때 링크 안쪽 여백을 줄여 자리를 내놓고(6칸 × 좌우 = 약 216px),
      그 자리를 flex-grow 로 여섯 칸이 똑같이 나눠 가진다. 전체 폭은 그대로다.
   ⚠️ flex-basis 는 건드리지 않는다. auto ↔ 0 은 값이 이어지지 않아 뚝 끊긴다.
      grow(숫자)와 padding(길이)만 바꾸면 부드럽게 벌어진다. */
.xc-gnb__d1 {
  display: flex; justify-content: center; align-items: flex-start;
  gap: var(--gnb-gap); flex-wrap: nowrap;
}
/* 열렸을 때 벌어지는 폭의 상한.
   ⚠️ 링크 안쪽 여백으로는 못 줄인다. flex-grow 가 남는 자리를 전부 나눠 갖기 때문에
      여백을 키우면 남는 자리가 그만큼 줄어서 결과 폭이 똑같다(실측으로 확인).
      벌어지는 양을 줄이려면 「남는 자리」 자체를 묶어야 한다.
   ⚠️ 1160px 은 1600px 화면에서 자연스럽게 나오던 폭이다. 그보다 넓은 화면에서도
      같은 폭으로 멈춘다. 1920px 에서 칸이 272 → 228 로 줄고, 영문
      「AI Driven Development」가 한 줄로 늘어붙지 않고 두 줄로 접힌다.
   ⚠️ 이 값보다 좁은 화면에서는 상한이 걸리지 않는다. 그대로 둔다. */
.xc-gnb.is-open .xc-gnb__d1 {
  max-width: 1160px;
  margin-inline: auto;
}
/* ⚠️ flex-grow 에 transition 을 걸어도 소용없다. 여섯 칸이 남는 자리를 같은 비율로
      나눠 가지므로 grow 가 0.01 이든 1 이든 결과 폭이 똑같다. 값이 0 을 벗어나는 순간
      최종 폭으로 한 번에 튄다. 그래서 자리는 즉시 잡고, 눈에 보이는 이동만
      transform 으로 되돌렸다 푸는 방식(FLIP)을 main.js 에서 쓴다. 여기서는 그 길만 열어 둔다. */
.xc-gnb__item {
  position: relative; flex: 0 1 auto; min-width: 0;
  /* 패널이 내려오는 시간·곡선을 그대로 쓴다. 둘이 다르면 글자와 판이 따로 논다 */
  transition: transform var(--gnb-dur) var(--gnb-ease);
}
.xc-gnb.is-open .xc-gnb__item { flex-grow: 1; }

.xc-gnb__link {
  display: flex; align-items: center; justify-content: center;
  height: var(--gnb-row);
  width: 100%;
  padding-inline: var(--gnb-link-px);
  font-size: var(--xc-fs-16); font-weight: var(--xc-fw-semibold);
  letter-spacing: -.4px; line-height: 140%;
  color: #fff;
  transition: color var(--gnb-dur) var(--gnb-ease);
}
/* 열리면 안쪽 여백을 내놓는다. 그 자리를 여섯 칸이 나눠 갖는다.
   ⚠️ 여기에 transition 을 걸지 않는다. 폭은 즉시 바뀌고 움직임은 FLIP 이 그린다.
      둘 다 애니메이션하면 글자가 두 번 움직인다. */
.xc-gnb.is-open .xc-gnb__link { padding-inline: 4px; }
.xc-gnb.is-open  .xc-gnb__link,
.xc-gnb.is-solid .xc-gnb__link { color: #111; }

/* 텍스트 슬라이드 — 같은 글자가 이어서 올라오는 느낌
   클리핑 창은 텍스트 1줄(--gnb-line)로 제한한다.
   창이 행 전체(80px)면 움직이는 글자가 줄 밖에서도 보인다. */
.xc-gnb__slide {
  display: block; position: relative;
  overflow: hidden;
  height: var(--gnb-line);
}
.xc-gnb__t {
  display: block;
  height: var(--gnb-line); line-height: var(--gnb-line);
  white-space: nowrap;
  transition: transform var(--gnb-dur) var(--gnb-ease);
}
.xc-gnb__t + .xc-gnb__t {
  position: absolute; top: 0; left: 0; right: 0;
  transform: translateY(100%);
}
.xc-gnb__item:hover .xc-gnb__t,
.xc-gnb__item:focus-within .xc-gnb__t { transform: translateY(-100%); }
.xc-gnb__item:hover .xc-gnb__t + .xc-gnb__t,
.xc-gnb__item:focus-within .xc-gnb__t + .xc-gnb__t { transform: translateY(0); }

/* ── 메가메뉴 컬럼 ──
   패널(clip-path .5s)이 거의 다 내려온 뒤에 등장한다.
   easing 이 front-loaded 라 .26s 시점이면 패널은 이미 ~88% 열려 있다.
   닫힐 때는 지연 없이 먼저 사라져야 패널 밖에 글자가 남지 않는다. */
.xc-gnb__d2 {
  position: absolute; top: var(--gnb-row); left: 50%;
  padding-top: var(--gnb-d2-top);
  /* 부모 칸 안에 가둔다. 14px 은 이웃 컬럼과의 최소 간격이다 */
  width: max-content; max-width: calc(100% - 14px);
  text-align: center; white-space: normal;
  opacity: 0; pointer-events: none;
  transform: translateX(-50%) translateY(-12px);
  transition: opacity .16s var(--gnb-ease),
              transform .16s var(--gnb-ease);
  transition-delay: 0s;
}
.xc-gnb.is-open .xc-gnb__d2 {
  opacity: 1; pointer-events: auto;
  transform: translateX(-50%) translateY(0);
  transition: opacity var(--gnb-d2-dur) var(--gnb-ease),
              transform var(--gnb-d2-dur) var(--gnb-ease);
  transition-delay: calc(var(--gnb-d2-delay) + var(--gnb-d2-step) * var(--i, 0));
}
/* 하위 메뉴 — 상단 메뉴(#111)보다 연한 어두운 색 */
.xc-gnb__d2 > li > a {
  display: block;
  padding: 5px 0; line-height: 1.3;
  white-space: normal; word-break: keep-all;
  font-size: var(--xc-fs-14); font-weight: var(--xc-fw-regular); letter-spacing: -.01em;
  color: var(--xc-gray-700);
  transition: color .2s var(--gnb-ease);
}
.xc-gnb__d2 > li > a:hover,
.xc-gnb__d2 > li > a:focus-visible { color: var(--xc-orange); }

/* ── 우측 유틸 ── */
.xc-gnb__util { flex: none; display: flex; align-items: center; gap: 22px; }

.xc-gnb__lang {
  display: flex; gap: 7px;
  font-size: var(--xc-fs-12); font-weight: var(--xc-fw-semibold); letter-spacing: .04em;
  color: rgba(255, 255, 255, .72);
  transition: color var(--gnb-dur) var(--gnb-ease);
}
.xc-gnb.is-open  .xc-gnb__lang,
.xc-gnb.is-solid .xc-gnb__lang { color: #555; }
.xc-gnb__lang li + li::before { content: "/"; opacity: .45; margin-right: 7px; }
.xc-gnb__lang a { color: inherit; }
.xc-gnb__lang .is-cur a { color: #fff; }
.xc-gnb.is-open  .xc-gnb__lang .is-cur a,
.xc-gnb.is-solid .xc-gnb__lang .is-cur a { color: #111; }

/* 3×3 그리드 아이콘 */
.xc-gnb__all {
  width: 26px; height: 26px; padding: 0; border: 0; background: none; cursor: pointer;
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px;
  color: #fff; transition: color var(--gnb-dur) var(--gnb-ease);
}
.xc-gnb.is-open  .xc-gnb__all,
.xc-gnb.is-solid .xc-gnb__all { color: #111; }
.xc-gnb__all span {
  width: 4px; height: 4px; border-radius: 50%;
  background: currentColor; justify-self: center; align-self: center;
}

/* ── 누르는 영역 넓히기 (보이는 모습은 그대로) ──
   ⚠️ 모바일 실측(390px): KOR·ENG 는 26×15, 둘 사이가 21px 이라 손가락으로 골라 누르기 어려웠다.
      전체메뉴 26×26, 로고 132×16. 헤더 캡슐이 62px 높이라 세로로 넓힐 자리가 있다.
   ⚠️ 박스를 키우지 않고 ::after 로 투명한 판을 덧댄다. padding 으로 키우면
      글자 기준선과 gap 이 같이 움직여 배치가 흔들린다.
   ⚠️ KOR·ENG 는 가로로 너무 늘리지 않는다. 둘 사이 21px 안에서 서로 겹치면
      가운데를 눌렀을 때 뒤에 있는 쪽이 잡힌다. 좌우 8px 씩이면 5px 이 남는다. */
.xc-gnb__logo a,
.xc-gnb__lang a,
.xc-gnb__all { position: relative; }
.xc-gnb__logo a::after,
.xc-gnb__lang a::after,
.xc-gnb__all::after {
  content: ""; position: absolute; top: 50%; left: 50%;
  transform: translate(-50%, -50%);
}
.xc-gnb__logo a::after { width: 100%; height: 44px; }
.xc-gnb__lang a::after { width: calc(100% + 16px); height: 44px; }
.xc-gnb__all::after   { width: 44px; height: 44px; }

/* ══════════════════ 전체메뉴 (사이트맵) ══════════════════
   값 출처: i-bricks .pc-sitemap 실측
   우상단(버튼 위치)에서 원형 clip-path 로 퍼지며 열린다. */
:root {
  /* 세로 값은 vh 에 물리되, 배율을 1000px 높이에서 상한(레퍼런스 실측값)에 닿도록 잡았다.
     즉 일반적인 화면(≥1000px)에서는 레퍼런스 그대로 보이고,
     그보다 낮은 화면에서만 필요한 만큼 압축된다. */
  --sm-pad-y:    clamp(32px, 6vh, 60px);
  --sm-pad-b:    clamp(36px, 8vh, 80px);
  --sm-pad-x:      80px;
  --sm-d1-w:      360px;   /* depth-1 고정 폭 */
  --sm-d1-fs:    clamp(26px, 4vh, 40px);
  --sm-row-py:   clamp(14px, 3vh, 30px);
  --sm-head-gap: clamp(16px, 3vh, 30px);
  --sm-dur:       .4s;   /* 오버레이 페이드 */
  --sm-content:  .28s;   /* 내용 등장 */
  --sm-delay:    .14s;   /* 오버레이가 거의 찼을 때 */
  --sm-ease:     cubic-bezier(.4, 0, .2, 1);
}

/* ⚠️ clip-path 원형 확장은 쓰지 않는다.
   backdrop-filter 가 걸린 전체화면 요소에 clip-path 애니메이션을 얹으면
   컴포지터가 레이어를 타일로 쪼개 처리하다 일부 타일을 다시 그리지 않아
   화면이 세로로 잘려 보이는 결함이 난다(원형 경계와 무관한 '직선' 이음매).
   블러를 별도 레이어로 분리해도 재현되므로, 확장 대신 페이드로 처리한다. */
.xc-sitemap {
  position: fixed; top: 0; left: 0; z-index: var(--xc-z-overlay);
  width: 100%; height: 100dvh;
  padding: var(--sm-pad-y) var(--sm-pad-x) var(--sm-pad-b);
  background: rgba(6, 10, 16, .55);
  -webkit-backdrop-filter: blur(15px);
  backdrop-filter: blur(15px);
  opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity var(--sm-dur) var(--sm-ease),
              visibility 0s linear var(--sm-dur);
}
.xc-sitemap.is-open {
  opacity: 1; visibility: visible; pointer-events: auto;
  transition: opacity var(--sm-dur) var(--sm-ease),
              visibility 0s linear 0s;
}

/* 내용은 패널이 다 퍼진 뒤에 (0.52s 지연) */
/* 내용은 오버레이가 거의 찬 뒤에 살짝 올라오며 등장 */
/* 로고·X 는 위에 그대로 두고, 메뉴만 남은 높이의 세로 가운데에 앉힌다.
   ⚠️ 그냥 블록으로 두면 메뉴가 헤더 바로 밑에 붙고 남는 높이가 전부 아래로 간다.
      2560x1440 에서 위 30 / 아래 510 이었다.
   ⚠️ 높이를 100% 로 고정하되 메뉴에는 flex-shrink: 0 을 준다. 줄어들게 두면
      좁은 화면에서 메뉴가 눌려 스크롤이 안 생기고 잘린다 — 1024 이하는 이미 넘치는 상태다. */
.xc-sitemap__content {
  min-height: 100%; max-height: 100%;
  display: flex; flex-direction: column;
  /* overflow-y 만 지정하면 overflow-x 가 auto 로 계산돼,
     X 버튼 회전 같은 미세 초과에도 가로 스크롤바가 생긴다. 명시적으로 막는다. */
  overflow-y: auto; overflow-x: hidden;
  opacity: 0; transform: translateY(12px);
  transition: opacity .16s var(--sm-ease) 0s,
              transform .16s var(--sm-ease) 0s;
}
.xc-sitemap.is-open .xc-sitemap__content {
  opacity: 1; transform: translateY(0);
  transition: opacity var(--sm-content) var(--sm-ease) var(--sm-delay),
              transform var(--sm-content) var(--sm-ease) var(--sm-delay);
}

.xc-sitemap__head {
  flex: none;                    /* 로고·X 는 자기 높이 그대로, 위에 붙어 있는다 */
  display: flex; align-items: center; justify-content: space-between;
}
.xc-sitemap__logo img { width: 197px; height: auto; display: block; }
.xc-sitemap__close {
  width: 40px; height: 40px; padding: 0; border: 0; background: none;
  color: #fff; cursor: pointer;
  transition: transform var(--xc-dur-base) var(--gnb-ease),
              color var(--xc-dur-base) var(--gnb-ease);
}
.xc-sitemap__close:hover { transform: rotate(90deg); color: var(--xc-orange); }
.xc-sitemap__close svg { width: 100%; height: 100%; display: block; fill: none; }

/* 남은 높이를 다 차지하고 그 안에서 메뉴를 세로 가운데로.
   flex: 1 0 auto — 남으면 늘어나고(가운데 정렬이 생김), 모자라도 줄지 않는다(넘쳐서 스크롤된다).

   ⚠️ 헤더와의 간격을 margin-top 으로 주면 안 된다. 그만큼 가운데가 아래로 밀린다
      (2560 에서 30px 치우쳤다). padding 으로 위아래 같이 줘야 정확히 가운데에 온다.
      좁아서 넘칠 때는 이 padding 이 헤더·바닥과 붙지 않게 하는 최소 간격 노릇을 한다. */
.xc-sitemap__body {
  flex: 1 0 auto;
  display: flex; flex-direction: column; justify-content: center;
  padding-block: var(--sm-head-gap);
  padding-left: 40px; color: #fff;
}
.xc-sitemap__d1 { display: flex; flex-direction: column; }
.xc-sitemap__d1 > li {
  display: flex; align-items: center;
  padding-block: var(--sm-row-py);
}
/* 대분류(GNB 항목) — 호버해도 색이 바뀌지 않는다. 하위 메뉴만 반응한다. */
.xc-sitemap__d1 > li > a {
  flex: none; width: var(--sm-d1-w);
  font-size: var(--sm-d1-fs); font-weight: var(--xc-fw-semibold);
  line-height: 150%; letter-spacing: -1px; color: #fff;   /* 레퍼런스 값 */
}

.xc-sitemap__d2 {
  flex: 1; min-width: 0;
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 15px 60px;
}
.xc-sitemap__d2 > li > a {
  font-size: var(--xc-fs-16); font-weight: var(--xc-fw-semibold);
  line-height: 140%; letter-spacing: -.4px;
  color: rgba(255, 255, 255, .78);
  transition: color .3s var(--gnb-ease);
}
.xc-sitemap__d2 > li > a:hover { color: var(--xc-orange); }
/* 줄 사이 빈 곳을 눌러도 링크가 잡히게 한다. 보이는 모습은 그대로다.
   ⚠️ 모바일 실측(390px): 링크 높이 18px 에 줄 간격이 12~15px 라, 그 사이를 누르면
      아무 일도 없었다. 투명한 판을 위아래로 줄 간격의 절반(6px)만큼 덧대면
      이웃 줄과 겹치지 않고 빈 곳이 사라진다. 좌우는 칸 간격(50~60px)의 안쪽으로만 댄다.
   ⚠️ 판을 더 크게 잡지 않는다. 이웃 링크와 겹치면 뒤에 그려진 쪽이 누름을 가져간다. */
.xc-sitemap__d2 > li > a { position: relative; }
.xc-sitemap__d2 > li > a::after {
  content: ""; position: absolute; inset: -6px -12px;
}

@media (prefers-reduced-motion: reduce) {
  .xc-sitemap { transition-duration: .01ms; }
  .xc-sitemap__content,
  .xc-sitemap.is-open .xc-sitemap__content {
    transition-duration: .01ms; transition-delay: 0s !important;
  }
}

/* ══════════════════ ① 히어로 ══════════════════ */
:root {
  --hero-frame:     20px;   /* 액자 여백 (레퍼런스: calc(100vw - 40px) = 좌우 20px) */
  --hero-frame-r:   20px;   /* 액자 라운드 */
  --hero-frame-dur:    2s;  /* 로드 후 액자로 들어가는 시간 */
}

.xc-hero { position: relative; height: 100dvh; overflow: hidden; }

/* ── 배경 영상 ── */
.xc-hero__media { position: absolute; inset: 0; z-index: 0; overflow: hidden; }
/* ⚠️ 원본 우하단에 생성 도구의 AI 마크(별)가 박혀 있다.
      실측 1280×720 기준 x 1140~1180 · y 576~623 — 오른쪽 끝에서 100px,
      아래 끝에서 97px 자리다. 지우려면 오른쪽 140px(10.9%)을 걷어내야 한다.
      왼쪽 위를 고정해 키우면 오른쪽·아래만 잘린다. 1.16 이면 오른쪽 13.8%가
      빠져 마크 왼쪽 끝(1140)보다 37px 더 안쪽까지 지워진다.
   ⚠️ 상자 비율이 달라져도 안전하다. cover 는 좌우를 같은 폭으로 깎으므로
      어떤 비율에서도 오른쪽이 이 값보다 덜 잘리는 경우가 없다.
   ⚠️ 근본 해결은 아니다. 원본 화소는 파일에 그대로 있다. 영상을 교체하거나
      ffmpeg 로 잘라 굽는 것이 맞다. 이건 그 전 단계다. */
.xc-hero__video {
  width: 100%; height: 100%; object-fit: cover; display: block;
  transform: scale(1.16); transform-origin: 0 0;
  /* 영상 로드 전에는 네이비가 보이도록 */
  background: var(--xc-navy);
}
/* 스크림 — 흰 글자 가독성 확보 + 브랜드 톤 유지.
   위쪽은 GNB 가 얹히므로 조금 더 어둡게, 우상단에 웜 광원. */
.xc-hero__scrim {
  position: absolute; inset: 0;
  background:
    radial-gradient(ellipse 60% 50% at 80% 0%, rgba(249, 168, 92, .18), transparent 70%),
    linear-gradient(180deg, rgba(22, 29, 41, .80) 0%, rgba(22, 29, 41, .72) 38%, rgba(22, 29, 41, .80) 100%);
}

/* 액자 마스크 — 히어로 자체를 clip-path 로 잘라 바깥에 페이지 배경(흰색)을 드러낸다.
   이전에는 100px spread 그림자를 깔고 width/height 를 2초간 트랜지션했는데,
   ① 레이아웃 유발 속성 애니메이션 ② 매 프레임 거대 그림자 재페인트 로 비쌌다.
   clip-path 는 레이아웃을 유발하지 않고, 별도 마스크 요소도 필요 없다.
   (페인트 무효화는 있으므로 '합성만'은 아니다.) */
.xc-hero {
  clip-path: inset(0 round 0);
  transition: clip-path var(--hero-frame-dur) var(--xc-ease-out);
}
.xc-hero.is-framed {
  clip-path: inset(var(--hero-frame) round var(--hero-frame-r));
}
/* stage 자체를 세로 중앙 정렬 컨테이너로 둔다.
   ⚠️ copy 를 position:absolute + inset:0 으로 두면 안 된다 —
   절대요소의 컨테이닝 블록은 조상의 '패딩 박스'라 padding-inline 이 무시되고,
   글자가 화면 끝까지 붙어 액자(z-index 3)에 잘린다. */
/* ⚠️ 옆 여백은 **액자 두께만큼 더** 준다. 히어로는 clip-path 로 가장자리를 잘라 내므로
   보이는 모서리가 화면 끝이 아니라 --hero-frame 만큼 안쪽이다. var(--xc-pad) 만 주면
   보이는 모서리에서 4~10px 밖에 안 떨어져 글자가 붙어 보인다(실측 2026-09-17:
   1440 에서 10px · 768 에서 4px · 390 에서 10px). 더하면 다른 섹션과 같은 여백이 된다. */
.xc-hero__stage {
  position: relative; z-index: 2; height: 100%;
  max-width: var(--xc-area); margin-inline: auto;
  padding-inline: calc(var(--xc-pad) + var(--hero-frame));
  display: flex; flex-direction: column; justify-content: center;
}
/* 카피는 첫 로드부터 보인다. 등장 애니메이션의 초기 상태는 JS 가 설정한다
   (CSS 로 opacity:0 을 두면 JS 실패 시 콘텐츠가 영영 안 보인다). */
.xc-hero__copy { width: 100%; }
.xc-hero__title {
  font-size: var(--xc-fs-display); font-weight: var(--xc-fw-extra);
  line-height: 1.1; letter-spacing: var(--xc-ls-display);
}
.xc-hero__title .ch { display: inline-block; will-change: transform, opacity; }
.xc-hero__lead {
  margin-top: 26px; font-size: var(--xc-fs-lead);
  color: var(--xc-text-sub); line-height: 1.7;
}
.xc-hero__lead strong {
  color: #fff; font-weight: var(--xc-fw-semibold);
}
.xc-hero__cta { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 38px; }

.xc-hero__scroll {
  position: absolute; z-index: 2; left: 50%; bottom: 34px; transform: translateX(-50%);
  display: grid; justify-items: center; gap: 10px;
  font-size: var(--xc-fs-12); letter-spacing: .18em; text-transform: uppercase;
  color: rgba(255, 255, 255, .5);
}
.xc-hero__scroll span:last-child {
  width: 1px; height: 42px; background: rgba(255, 255, 255, .3); position: relative; overflow: hidden;
}
.xc-hero__scroll span:last-child::after {
  content: ""; position: absolute; inset: 0; background: var(--xc-gradient);
  animation: scrollDot 2s var(--xc-ease-in-out) infinite;
}
@keyframes scrollDot {
  0%   { transform: translateY(-100%); }
  100% { transform: translateY(100%); }
}


/* ══════════════════ ② 두 갈래 (브랜드 2열) ══════════════════
   MATE(라이트·오렌지) / xCalibur(다크·그라디언트) 를 같은 크기로 나란히 둔다.
   브랜드 스코프 클래스만 바꿔 강조색이 자동 전환된다. */
/* 등장 모션에서 카드가 좌우 밖으로 나간다 — 세로는 그림자를 위해 열어 둔다 */
.xc-two { background: var(--xc-bg); overflow-x: clip; overflow-y: visible; }
.xc-two__head { text-align: center; max-width: 62ch; margin-inline: auto; }
.xc-two__head .xc-lead { margin-inline: auto; }

.xc-two__grid {
  margin-top: clamp(36px, 4vw, 60px);
  display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--xc-gap);
  align-items: stretch;
}
.xc-two__card {
  position: relative; overflow: hidden;
  border-radius: var(--xc-radius-lg);
  padding: clamp(28px, 3vw, 48px);
  display: flex; flex-direction: column;
  /* ⚠️ transform 을 넣으면 안 된다 — 등장 모션(GSAP 스크럽)이 매 프레임
     transform 을 쓰는데 트랜지션에 걸려 늘어진다. */
  /* ⚠️ box-shadow 를 여기 함께 적어야 한다 — .xc-glow 와 명시도가 같은데
     이 규칙이 파일 뒤쪽이라, 빠뜨리면 유틸의 transition 을 덮어써 글로우가 툭 켜진다. */
  transition: background-color var(--xc-dur-base) var(--xc-ease-standard),
              border-color var(--xc-dur-base) var(--xc-ease-standard),
              box-shadow var(--xc-dur-base) var(--xc-ease-standard);
}
.xc-two__card:has(.xc-two__link:focus-visible) {
  outline: 2px solid var(--xc-focus); outline-offset: 3px;
}

.xc-two__card--mate { background: var(--xc-bg-soft); border: 1px solid var(--xc-border-weak); }

.xc-two__eyebrow {
  font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-semibold);
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--xc-text-weak);
}
.xc-two__name {
  margin-top: 12px;
  font-size: var(--xc-fs-two-name); font-weight: var(--xc-fw-extra);
  letter-spacing: -.025em; color: var(--xc-text);
}
.xc-two__tag {
  margin-top: 8px; font-size: var(--xc-fs-lead);
  font-weight: var(--xc-fw-semibold); color: var(--xc-text);
}
.xc-two__desc {
  margin-top: 16px; font-size: var(--xc-fs-sm);
  color: var(--xc-text-sub); line-height: 1.7;
  transition: color .28s var(--xc-ease-standard);
}

/* 솔루션 이름 칩 — 분류 라벨 없이 한 줄기로 편다.
   MATE 쪽만 분류 라벨 4줄을 갖고 있어 두 카드 구조가 어긋나 있었다. */
.xc-two__tags {
  margin-top: 26px; flex: 1; align-content: flex-end;
  display: flex; flex-wrap: wrap; gap: 6px;
}
/* 태그 칩 — 알약 버튼과 구분되는 축은 '채움 대 외곽선'이다.
   ⚠️ 이전에는 background 가 var(--xc-bg-soft) 라 라이트 카드에서 카드면과 거의 같은 값
   (카드 248,249,251 / 칩 255,255,255 → 대비 1.03:1)이 되어 채움이 안 보이고
   테두리만 남아 버튼처럼 읽혔다. 반투명 면색으로 바꾸고 테두리를 없앤다. */
.xc-two__tags li {
  padding: 5px 12px; border-radius: var(--xc-radius-full);
  border: 0;
  background: var(--xc-chip-bg);
  color: var(--xc-text-sub);
  font-size: var(--xc-fs-12); font-weight: var(--xc-fw-medium); line-height: 18px;
  white-space: nowrap;
}

/* 알약은 안쪽 span(.xc-pill)이 맡는다 — 링크는 배치와 카드 오버레이만 담당 */
/* 카드 전체가 링크다. 보이는 CTA 라벨은 없애고 카드를 덮는 빈 링크만 남겼다.
   커서가 VIEW 를 띄우므로 라벨이 중복이었다.
   ⚠️ 요소 자체는 지우면 안 된다 — 이 <a> 가 카드의 유일한 링크이고 키보드 포커스 대상이다.
      aria-label 로 이름을 준다. */
.xc-two__link { position: absolute; inset: 0; z-index: 2; }
/* ══════════════════ ③ AI 개발 방법론 · ADD ══════════════════
   핀 구간. 내용을 화면 높이 안에 세로 중앙으로 앉힌다.

   ⚠️ padding-block 을 주면 안 된다. 내용이 705px 인데 위아래 120px 을 더하면 945px 가
      되어 화면 높이 750px 짜리 노트북에서 핀 되는 동안 아래가 잘린다.
      min-height: 100dvh + align-items: center 만으로 여백이 생긴다
      (화면이 900이면 위아래 97px, 750이면 22px 로 알아서 줄어든다). */
.xc-add { position: relative; }
.xc-add__pin {
  min-height: 100dvh;
  display: flex; align-items: center;
}
.xc-add__inner { width: 100%; }
/* 비주얼 컨테이너와 액션 버튼 사이 여백 */
.xc-add__inner > .xc-pill { margin-top: clamp(30px, 3.6vw, 56px); }
.xc-add__head { max-width: 62ch; }
.xc-add__body {
  display: grid; grid-template-columns: minmax(280px, 460px) 1fr;
  gap: clamp(36px, 5vw, 90px); align-items: center;
  margin-top: clamp(34px, 4vw, 56px);
}

/* ── 좌측 : 세로로 쌓인 입체 판 ──
   판 3장이 일정한 간격으로 쌓여 있고, 맨 아래가 01 이다.
   스크롤이 단계를 옮기면 해당 판만 살아나고 나머지는 물러난다. */
.xc-add__stage {
  position: relative; aspect-ratio: 6 / 5;
  border-radius: clamp(20px, 2.4vw, 32px);
  border: 1px solid var(--xc-border);
  overflow: hidden;
  /* ⚠️ place-items:center 를 쓰면 안 된다 —
     그리드 영역 높이가 불확정이 되어 자식의 height:% 가 무대 대신
     'SVG 자기 종횡비 높이'를 기준으로 풀린다. 실측에서 무대 383px 인데 SVG 가 473px 로
     커져 위아래가 잘렸다. stretch(기본값) 로 두고 자식이 100% 를 채운다. */
  display: grid;

  /* 바닥 13% — 거울면(SVG y=229)이 무대 87% 지점에 온다.
     iso 가 무대를 꽉 채우고 viewBox(33~258, 높이 225)가 높이 기준으로 맞춰지므로
     (229 - 33) / 225 = 0.871.
     ⚠️ viewBox 나 접지면 y 를 바꾸면 이 값을 다시 계산해야 한다. */
  --add-horizon: 87.1%;

  /* ── 라이트 무대 (2026-08-28) ──
     그전에는 #070A10 → 네이비로 떨어지는 어두운 무대였다. 밝기 방향을 뒤집었다.
     ⚠️ 어두운 무대의 값을 그대로 반전하면 안 된다. 어두운 무대에서는 '바닥이 밝아서'
        접지면이 읽혔는데, 밝은 무대에서는 반대로 '바닥이 한 단계 가라앉아야' 읽힌다.
        그래서 위가 가장 밝고 접지면 아래가 가장 어둡다 — 램프 방향이 뒤집혔다.
     경계는 선이 아니라 '밝기가 바뀌는 구간'이다. 1px 선이나 급격한 색 전환을 두면
     종이를 붙여 놓은 것처럼 보인다. 거울면 위아래로 폭을 넓게 잡아 완만하게 풀었다. */
  /* ── 오렌지 계열 · 대각 그라디언트 (2026-08-31 · 사용자 지시) ──
     그전에는 쿨 앰비언트(좌상단 파랑) + 웜 광원(우하단) 두 개를 얹은 구조였다.
     🔴 어색했던 진짜 이유는 **색 하나가 아니라 배경이 웜/쿨 두 벌로 쪼개져 있던 것**이다.
        판·광원은 웜인데 바닥 램프(#EDF1F7)와 도트(네이비)는 쿨이었다.
        **앰비언트만 오렌지로 바꾸면 왼쪽 아래가 그대로 푸르다** — 반쪽만 고치는 것이다.
        바닥·도트·접지 그림자(마크업의 slabGround*)까지 **같이** 웜으로 옮겨야 한다.

     🔴 그리고 **대각 그라디언트 하나로 다 덮으면 안 된다.** 그것만 남기면 '판이 어디에
        놓여 있는지' 가 사라진다 — 대각선은 세로 위치와 무관하게 흐르므로 접지면을 못 담는다.
        **색의 흐름(대각)과 접지면(세로)은 하는 일이 다르다. 그래서 겹을 나눈다.** */
  background:
    /* ③ 거울면 바로 위를 흰색으로 한 겹 밝힌다 — 아래로 가라앉는 바닥과 갈라져
       접지면이 '밝기가 꺾이는 자리'로 읽힌다.
       ⚠️ 어두운 무대에서 쓰던 rgba(255,255,255,.07) 은 여기서 눈에 안 보인다.
          흰 바탕 위 흰빛이라 불투명도를 크게 올려야 몫이 생긴다. */
    linear-gradient(to bottom,
      transparent calc(var(--add-horizon) - 38%),
      rgba(255, 255, 255, .9) calc(var(--add-horizon) - 20%),
      transparent calc(var(--add-horizon) - 2%)),
    /* ② 접지면 아래로 한 단계 가라앉는 바닥.
       ⚠️ 불투명한 색이 아니라 **반투명 웜 그레이**다. ① 의 대각 그라디언트가 이 아래로
          그대로 비쳐야 색의 흐름이 안 끊긴다. 불투명하게 두면 아래쪽만 딴 판이 된다.
       ⚠️ 스톱을 --add-horizon + N% 로만 두면 100% 를 넘어 램프가 잘린다. 끝은 100% 로 물린다.
       ⚠️ 이 세기(.28)와 마크업의 접지 그림자 세기는 한 묶음이다. 한쪽만 되돌리지 말 것. */
    linear-gradient(to bottom,
      transparent calc(var(--add-horizon) - 14%),
      rgba(216, 186, 152, .28) calc(var(--add-horizon) - 2%),
      rgba(216, 186, 152, .28) 100%),
    /* ① 바탕 — 대각선 하나로 흐르는 웜 그라디언트. 좌상단 골드 → 가운데 흰색 → 우하단 피치.
       ⚠️ 채도를 더 올리면 안 된다. 판이 같은 오렌지 계열이라 배경이 진해지는 만큼
          판의 실루엣이 배경에 묻힌다. 가운데를 순백으로 비워 두는 것이 판을 세우는 장치다.
       ⚠️ 145deg 는 판의 광원 방향(좌상단)과 맞춘 것이다. 뒤집으면 아래에서 빛이 오는
          것처럼 보여 판의 음영과 어긋난다. */
    linear-gradient(145deg,
      #FEF6E2 0%,
      #FFFBF2 24%,
      #FFFFFF 50%,
      #FFFAF4 72%,
      #FDF0E4 100%);
}
/* ── 도트 매트릭스 (2026-08-31) ──
   흰 무대가 비어 보이던 것을 메운다. 어두운 무대 시절의 '불티' 를 대신하는 자리다.

   ⚠️ background 레이어로 넣으면 안 된다. 바닥 램프(① )가 0% 부터 불투명이라 그 아래에
      깔면 통째로 안 보이고, 위에 얹으면 접지면까지 도트가 그대로 내려와 바닥이 지저분해진다.
      레이어 하나만 따로 깎을 방법이 background 에는 없다 — 그래서 제 겹으로 뺐다.
   ⚠️ .xc-add__stage 가 display:grid 다. position:absolute 라야 그리드 항목이 안 되고
      트랙을 하나 더 만들지 않는다.
   ⚠️ 이 겹이 SVG 를 덮으면 안 된다. .xc-add__iso 에 z-index 를 줘서 위로 올린다. */
.xc-add__stage::before {
  content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  /* ⚠️ 도트도 웜이어야 한다. 네이비 도트를 웜 바탕에 두면 배경만 파랗게 떠 보인다 —
     쿨 앰비언트를 걷어낸 이유와 같다(2026-08-31). */
  background: radial-gradient(rgba(150, 100, 60, .15) 1px, transparent 1.4px) 0 0 / 18px 18px;
  /* 접지면(87%) 으로 갈수록 사라진다 — 바닥은 깨끗해야 판이 놓인 자리가 읽힌다 */
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 34%, rgba(0, 0, 0, .35) 62%, transparent 78%);
          mask-image: linear-gradient(to bottom, #000 0%, #000 34%, rgba(0, 0, 0, .35) 62%, transparent 78%);
}
/* 무대를 꽉 채우고, viewBox 가 무대보다 세로로 길어 높이 기준으로 맞춰진다. */
/* z-index — 도트 겹(::before) 위에 놓는다 */
.xc-add__iso { width: 100%; height: 100%; display: block; position: relative; z-index: 1; }

/* ⚠️ 여기 있던 '배경에서 올라오는 불티' 16개는 2026-08-28 에 걷어냈다.
   불씨는 rgba(251,227,138,.95) 에 웜 글로우를 두른 점이라 **밝은 무대에서는 보이지 않는다**.
   어두운 무대를 전제로 한 장치다. 무대를 다시 어둡게 만들 때만 되살릴 것.
   되살리려면 마크업 세 벌(new/index.html · ko/en main_xc.blade.php)의 .xc-add__embers 와
   main.js 의 IntersectionObserver(화면 밖 정지)가 같이 온다. */


/* 반사는 원본보다 훨씬 옅다. 아래로 갈수록 마스크가 걷어낸다 */
/* 블러로 번지면 체감 밝기가 떨어지므로 불투명도를 조금 올려 준다 */
.xc-add__mirror { opacity: .42; --glow-vis: hidden; }   /* 바닥에 비친 상. 판이 진해진 만큼 같이 올린다 */

/* 판은 처음엔 없다. 단계가 올 때마다 위에서 내려와 제자리에 얹힌다.
   한 번 놓인 판은 그대로 남아, 스크롤이 끝나면 세 장이 쌓여 있다.
   ⚠️ SVG 안의 transform 단위는 user unit(viewBox 기준)이다 — px 로 써도 화면 px 이 아니다. */
.xc-slab {
  transform-box: fill-box; transform-origin: center;
  opacity: 0; transform: translateY(-22px);
  transition: opacity .4s var(--xc-ease-out),
              transform .55s cubic-bezier(.34, 1.32, .64, 1);
  /* ⚠️ 블러(filter: url(#slabSoft))를 걸지 않는다 —
     매트한 유리는 실루엣이 선명하다. 흐림은 면 안쪽 그라디언트와 반투명에서 오고,
     형태를 블러하면 '유리'가 아니라 '초점이 안 맞은 그림'이 된다. */
}
/* ⚠️ 투과는 면(fill-opacity)이 아니라 그룹 opacity 로 준다 —
   면마다 주면 둥글리기용 stroke 와 fill 이 겹쳐 테두리에 이중으로 어두운 띠가 생긴다.
   그룹은 한 번만 합성되므로 균일하게 비친다. */
.xc-slab.is-on { opacity: .93; transform: none; }   /* .82 → .93 (더 불투명하게) */

/* 광원은 방금 놓인 판에만 — 셋 다 빛나면 어디가 지금인지 사라진다.
   ⚠️ visibility 를 --glow-vis 로 받는다 — 거울 <use> 는 이 값을 hidden 으로 넘겨
      광원 타원을 반사에서 제외한다. 판(172 유닛)보다 넓은 소프트 타원(rx 116)이
      함께 뒤집히면 반사가 형태 없는 띠로 뭉개진다(확대 확인).
      <use> 안쪽은 선택자로 못 잡지만, 상속되는 값(커스텀 프로퍼티)은 전달된다. */
.xc-slab__glow {
  visibility: var(--glow-vis, visible);
  opacity: 0; transition: opacity .45s var(--xc-ease-out);
}
.xc-slab.is-cur .xc-slab__glow { opacity: 1; }

/* ── 프로스티드 글래스 질감 ──
   ① 모서리 둥글리기 : 같은 그라디언트로 굵게 stroke 하고 linejoin:round.
      paint-order:stroke 라 fill 이 안쪽 절반을 덮어, 실루엣만 2.5 유닛 부풀며 꼭지가 둥글어진다.
      (path 를 arc 로 다시 그리는 것보다 3판 × 3면 = 9개를 한 규칙으로 처리한다)
   ② 칼선 제거 : 1px 흰 테두리가 '벡터 판'처럼 보이게 하던 주범이라 크게 낮췄다
   ③ 확산 : 윗면에 sheen(부드러운 흰 광) + 그룹 전체에 약한 블러 */
/* 모서리는 살짝만 둥글린다 — 크게 부풀리면 판 두께를 잡아먹고 간격이 뭉친다 */
.xc-slab__top, .xc-slab__side {
  stroke-width: 4; stroke-linejoin: round; paint-order: stroke;
}
.xc-slab__sheen, .xc-slab__grain, .xc-slab__depth { pointer-events: none; }
/* 서리 결 — 곱하기로 얹어야 알갱이가 면 색을 먹지 않고 산란처럼 보인다 */
.xc-slab__grain { mix-blend-mode: soft-light; opacity: .75; }
.xc-slab[data-step="0"] :is(.xc-slab__top)     { fill: url(#slabTop0);  stroke: url(#slabTop0); }
.xc-slab[data-step="0"] .xc-slab__side         { fill: url(#slabSide0); stroke: url(#slabSide0); }
.xc-slab[data-step="0"] .xc-slab__side--r      { fill: url(#slabSideR0); stroke: url(#slabSideR0); }
.xc-slab[data-step="1"] :is(.xc-slab__top)     { fill: url(#slabTop1);  stroke: url(#slabTop1); }
.xc-slab[data-step="1"] .xc-slab__side         { fill: url(#slabSide1); stroke: url(#slabSide1); }
.xc-slab[data-step="1"] .xc-slab__side--r      { fill: url(#slabSideR1); stroke: url(#slabSideR1); }
.xc-slab[data-step="2"] :is(.xc-slab__top)     { fill: url(#slabTop2);  stroke: url(#slabTop2); }
.xc-slab[data-step="2"] .xc-slab__side         { fill: url(#slabSide2); stroke: url(#slabSide2); }
.xc-slab[data-step="2"] .xc-slab__side--r      { fill: url(#slabSideR2); stroke: url(#slabSideR2); }


/* 윗면 림 — 유리 모서리에 맺히는 밝은 선. 레퍼런스에도 뚜렷하게 있다 */
.xc-slab__edge {
  fill: none; stroke: rgba(255, 255, 255, .3); stroke-width: 1.2;
  transition: stroke .45s var(--xc-ease-out);
}
.xc-slab.is-on .xc-slab__edge { stroke: rgba(255, 255, 255, .55); }

/* ── 우측 : 제목 스택 ── */
.xc-add__steps {
  position: relative;
  display: grid; gap: clamp(10px, 1.4vh, 18px);
  /* 설명문이 들어갈 자리를 미리 비운다 — 단계가 바뀌어도 높이가 변하지 않는다 */
  padding-bottom: clamp(120px, 14vh, 170px);
}
.xc-add__step {
  display: grid;
}
.xc-add__step h3 {
  display: flex; align-items: baseline; flex-wrap: wrap;
  gap: 4px clamp(10px, 1vw, 16px);
  /* 비활성도 읽히는 값으로 — 흰 바탕 위 4.83:1 (#5A6474)
     ⚠️ 어두운 무대 시절 값은 rgba(255,255,255,.55) 였다. 그대로 두면 흰 바탕에서 사라진다. */
  color: var(--xc-gray-600);
  transition: color .35s var(--xc-ease-standard);
}
.xc-add__en {
  font-size: var(--xc-fs-add-en); font-weight: var(--xc-fw-extra);
  letter-spacing: var(--xc-ls-heading); line-height: 1.25;
}
/* 영문 우측에 원래 한글을 작게 — 뜻은 한글이 지고, 크기·무게는 영문이 잡는다 */
.xc-add__ko {
  font-size: var(--xc-fs-sm); font-weight: var(--xc-fw-medium);
  letter-spacing: 0; line-height: 1.4;
  color: var(--xc-gray-600);              /* 흰 바탕 위 4.83:1 */
  transition: color .35s var(--xc-ease-standard);
}
.xc-add__step.is-on .xc-add__ko { color: var(--xc-navy); }   /* 16.9:1 */
.xc-add__step.is-on h3 { color: var(--xc-navy); }

/* 설명문 — 목록 하단 한 자리에 겹쳐 두고 활성 것만 */
.xc-add__step p {
  position: absolute; left: 0; right: 0; bottom: 0;
  max-width: 52ch;
  font-size: var(--xc-fs-body); color: var(--xc-gray-600); line-height: 1.7;
  opacity: 0; transform: translateY(8px);
  transition: opacity .4s var(--xc-ease-out), transform .4s var(--xc-ease-out);
}
.xc-add__step.is-on p { opacity: 1; transform: none; }

/* ══════════════════ ④ xCalibur 솔루션 7 (세로 아코디언) ══════════════════ */
/* 열린 카드는 언제나 한 장이고, '마지막으로 고른 한 장'이 그대로 남는다.
   처음 열려 있는 것은 첫 장, 손이 닿은 카드가 있으면 그 장, 손을 떼도 되돌아가지 않는다.
   :hover 는 손을 떼는 순간 풀리므로 이 기억은 CSS 로 만들 수 없다. main.js 가
   .is-open 을 한 장에만 붙여 상태로 들고 가고, 여기서는 그 클래스만 그린다.
   ⚠️ 스크립트가 막힌 경우를 위해 :hover 아코디언과 '유휴 = 첫 장' 을 폴백으로 남겨 둔다.
      다만 JS 가 살아 있을 때 둘이 같이 걸리면 두 장이 동시에 펼쳐질 수 있어
      (커서가 이미 다른 카드 위에 얹힌 채로 페이지가 뜬 경우), .is-live 로 폴백을 끈다.
   ⚠️ 이건 순서 위계가 아니다. 일곱 장이 전부 접혀 있으면 카드 안에 무엇이 들어 있는지
      알 수 없어 아무도 손을 대지 않는다. 첫 장은 '카드를 열면 이런 내용이 나온다'를
      보여 주는 견본이고, 어느 카드에 손을 대든 즉시 자리를 내준다.
      7개를 그룹으로 가르거나 한 장만 크게 두는 배치는 여전히 하지 않는다. */
/* ⚠️ 공간 그라디언트(섹션 아래쪽만 투명)로 빠져나가면 안 된다 —
   그라디언트 띠가 스크롤을 따라 지나가므로, 화면 전체가 균일하게 어두워지는
   진입과 성격이 다르고 띠의 끝이 눈에 걸린다.
   들어올 때와 똑같이 배경막 하나로 화면 전체를 되돌린다.
   대신 카드가 화면에서 빠진 뒤에 전환이 일어나도록 아래 여백을 확보한다. */
/* ⚠️ 아래 여백을 따로 주지 않는다. xc-sec-lg 기본값(180px)을 그대로 쓴다.
      전에는 220~340px 로 키워 뒀었다. 물듦이 .xc-biz 상단에서 걷히던 시절, 라인업
      카드가 화면에서 빠진 뒤에 걷히기 시작하도록 두는 자리였다.
      지금은 걷는 자리를 CLIENTS 구간으로 옮겨서(main.js 의 tOut) 그 여유가 필요 없고,
      남겨 두면 라인업 → CLIENTS 사이만 520px 로 벌어져 다른 섹션 사이(180~328px)와
      리듬이 어긋난다. */
.xc-lineup__head { text-align: center; max-width: 70ch; margin-inline: auto; }
.xc-lineup__head .xc-lead { margin-inline: auto; }

/* 패널이 뜨는 시각. 카드가 넓어지기 시작한 뒤 조금 늦게 올라와야 글이 따라오는
   것으로 보인다. 같이 출발하면 좁은 칸에서 글이 먼저 떠 겹쳐 보인다.
   ⚠️ 규칙에 숫자를 직접 쓰지 않는다. 모션 최소화에서는 폭이 즉시 스냅되는데 지연만
      남아 패널이 120ms 뒤에 따로 떠오르고, 그게 두 번 튀는 것으로 보인다.
      아래 prefers-reduced-motion 블록이 이 값을 0 으로 되돌린다
      (--gnb-d2-delay · --sm-delay 와 같은 방식).
   ⚠️ :root 에 둔다. .xc-lineup__acc 에 두면 그쪽 선언이 더 가까워서
      reduce 블록의 :root 재정의가 상속으로 이기지 못한다. */
:root { --card-panel-delay: .12s; }

.xc-lineup__acc {
  /* 아코디언 비율을 한곳에 모아 둔다. 좁은 화면에서는 값만 갈아 끼운다.

     --card-grow  펼친 카드가 접힌 카드 몇 장 몫을 가져가는가.
                  접힌 폭 = (컨테이너 - gap×6) ÷ (6 + grow) 다.
                  1440 이상에서 컨테이너는 1440 - 좌우여백 60 = 1380, gap 60 을 빼면
                  1320px 이므로 5.6 이면 접힌 폭이 1320 ÷ 11.6 = 113.8px 다.
                  ⚠️ 하한을 정하는 건 세로 이름이다. .xc-card__spine 은 좌우 padding
                     20×2 에 이름(최대 25px × line-height 1.5 = 37.5px)과
                     번호(13px × 1.5 = 19.5px)를 space-between 으로 놓으므로
                     접힌 폭이 97px 아래로 내려가면 이름과 번호가 맞붙는다.
                  ⚠️ 여유를 잴 때 카드 좌우 border 1px×2 를 빼야 한다. spine 은
                     absolute 라 담기는 곳이 카드의 border box 가 아니라 padding box 다.
                     이 2px 을 빠뜨린 계산이 한 번 보고된 적이 있다.
                     실측 여유(2026-08-10) : 1281px 에서 9.25px, 1440 이상에서 넉넉.
                     전체에서 제일 빠듯한 곳은 이 구간이 아니라 아래 LG 구간의
                     1025px 이고 여유가 4.91px 다. 그게 이 설계의 기준선이다.
                     이 값을 더 올리려면 spine 의 padding 이나 line-height 를 먼저 줄일 것. */
  --card-grow: 5.6;

  /* 카드 사이 간격. 아래 --card-w-open 계산이 이 값을 그대로 다시 쓰기 때문에
     gap 에 숫자를 직접 쓰지 않는다. LG 구간에서 8px 로 갈아 끼우면 폭 계산도 같이 따라온다. */
  --card-gap: 10px;

  /* ── 펼친 카드의 실제 폭 ──
     카드는 flex: 1 1 0 이라 basis 가 0 이다. 남는 자리를 grow 비율로만 나눠 가지므로
     접힌 6장이 1씩, 펼친 1장이 --card-grow 만큼 → 총 (6 + grow) 몫이다.
       펼친 폭 = (컨테이너 - gap×6) × grow ÷ (6 + grow)
     컨테이너 폭을 100cqw 로 읽는다. 100vw 는 스크롤바 거터(약 15px)를 포함해
     실제 카드 폭보다 넓게 나오고, 이 프로젝트는 scrollbar-gutter 를 쓰므로 항상 어긋난다.
     ⚠️ 나눗셈 오른쪽은 <number> 여야 한다. --card-share 를 따로 두는 이유다
        (--o: ... / var(--tail) 과 같은 방식).
     ⚠️ 검산
               vw1440 → (1380 - 60) × 5.6 ÷ 11.6 = 637.2px, 접힘 113.8px
               vw1025 → (977 - 48) × 4.6 ÷ 10.6 = 403.2px, 접힘  87.6px
        카드에서 테두리를 걷어낸 뒤로 이 값이 사진판 폭이자 펼친 카드의 실제 폭이다.
        테두리가 있던 동안에는 실제 카드가 vw1440 에서 625.22px 로 12px 좁았고
        (flex-basis:0 이라도 border-box 는 좌우 border 에서 바닥이 잡혀 7장분 14px 이
        남는 자리에서 먼저 빠졌다) 사진판이 그만큼 넓어 오른쪽 끝이 잘려 있었다.
        ⚠️ 카드에 테두리·좌우 padding 을 다시 넣으면 그 차이가 되살아난다. */
  --card-share: calc(6 + var(--card-grow));
  --card-w-open: calc((100cqw - var(--card-gap) * 6) * var(--card-grow) / var(--card-share));
  /* cq 단위를 모르는 엔진용. 거터만큼(약 7px) 넓게 나오지만 남는 폭은 카드 밖이라
     overflow:hidden 이 잘라 낸다 — 레이아웃이 깨지지 않는다. */
  --card-w-open-fb: calc((min(100vw, var(--xc-area)) - 2 * var(--xc-pad) - var(--card-gap) * 6)
                         * var(--card-grow) / var(--card-share));

  /* 사진 판이 '펼친 카드 폭'을 알기 위한 질의 대상.
     ⚠️ inline-size 억제만 건다. 세로(height: clamp)와 카드의 contain:paint 는 건드리지 않는다.
        여기에 딸린 contain:layout 은 절대 배치의 기준을 이 <ul> 로 옮기지만, 카드 안의
        절대 요소는 전부 position:relative 인 .xc-card 를 기준으로 삼고 있어 영향이 없다.
        아웃라인은 paint 억제가 아니라서 그대로 카드 밖에 그려진다. */
  container-type: inline-size;

  margin-top: clamp(36px, 4vw, 60px);
  display: flex; gap: var(--card-gap);
  height: clamp(420px, 38vw, 520px);
}

.xc-card {
  /* ── 카드면은 사진이다 ──
     일곱 장 모두 어두운 사진이라(영역 평균 밝기 L 0.01~0.10) 글자는 흰색 계열로 고정한다.
     한때 물듦(html.is-stained)에 따라 글자를 네이비↔흰색으로 뒤집었는데 사진 위에서는
     성립하지 않는다(물듦 자체는 2026-08-28 에 걷어냈다). 네이비 글자를 4.5:1 로 띄우려면 흰 스크림을 0.71 이상 덮어야 해
     사진이 통째로 날아간다. 카드가 제 테마를 고정하는 것은 이 파일에 이미 있는 방식이다
     (아래 .xc-two__card--mate 는 반대로 라이트를 고정한다).
     ⚠️ --xc-text-weak 를 .52 에서 .78 로, --xc-text-sub 를 .72 에서 .84 로 올렸다.
        기존 값은 단색 카드면에서도 4.65:1 로 기준에 겨우 닿아 있었고, 사진이 깔리면
        그대로 미달이 된다. 스크림 세기와 함께 잰 값이라 둘 중 하나만 되돌리면 깨진다.
     ⚠️ --xc-focus 는 여기서 고정하지 않는다. 초점 테두리는 outline-offset 3px 이라
        카드 밖 페이지 바탕에 그려진다. 흰색으로 박으면 밝은 페이지에서 테두리가 통째로
        사라진다. 페이지를 따라가도록 상속에 맡긴다.

     🔴 **글자 토큰만 뒤집으면 안 된다(2026-08-28).** 테두리·바탕 토큰을 두고 갔더니
        카드 안 「자세히 보기」 알약이 사이트 표준과 다르게 보였다 —
        .xc-pill 의 테두리가 --xc-border-strong 이고, 그 라이트 값
        rgba(22,29,41,.38) 은 **어두운 사진 위에서 안 보인다.** 알약이 아니라 맨 글자로
        읽혔다(실측). 같은 이유로 호버하면 흰 원 위에 흰 글자가 됐다(--xc-bg 가 흰색이라).
        **카드는 제 테마를 고정하는 자리이므로 .xc-dark 와 같은 한 벌을 다 갖는다.**
        값은 .xc-dark(tokens.css §10)와 같게 유지할 것 — 갈라지면 카드 안팎이 어긋난다. */
  --xc-text:        var(--xc-white);
  --xc-text-sub:    rgba(255, 255, 255, .84);
  --xc-text-weak:   rgba(255, 255, 255, .78);
  --xc-border:        rgba(255, 255, 255, .16);
  --xc-border-weak:   rgba(255, 255, 255, .08);
  --xc-border-strong: rgba(255, 255, 255, .42);
  --xc-bg:            var(--xc-navy);
  color: var(--xc-text);

  flex: 1 1 0; min-width: 0;
  position: relative; overflow: hidden; contain: paint;
  /* 사진이 못 뜨는 경우(경로 오타·차단)에도 흰 글자가 남을 자리를 만든다.
     흰 바탕이면 글자가 통째로 사라진다. 사진이 뜨면 이 면은 전혀 보이지 않는다. */
  background: var(--xc-navy);
  /* 테두리 없음. 사진이 카드 전면을 덮으므로 테두리는 사진을 한 겹 가두는 선으로만
     남았다. 지우면 일곱 장이 gap 으로만 갈린다.
     ⚠️ 되살리면 폭 계산이 함께 틀어진다. box-sizing:border-box + flex-basis:0 조합에서
        카드 한 장의 flex base size 가 좌우 border 만큼 바닥이 잡혀, 일곱 장분이 나눠 가질
        남는 자리에서 먼저 빠진다(1px 시절 14px). 위 --card-w-open 검산 참조. */
  /* ⚠️ --xc-radius-lg(20px)를 쓰지 않는다. 접힌 카드는 폭이 113px 뿐이라 20px 이면
        좌우 모서리가 폭의 18% 씩을 먹어 알약처럼 보이고, 펼친 카드(637px)에서는
        같은 값이 3% 라 사각형으로 보인다. 한 값인데 두 상태가 다른 모양으로 읽힌다.
        12px 이면 접힘 11% · 펼침 2% 로 차이가 눈에 걸리지 않는다. */
  border-radius: var(--xc-radius);
  /* ⚠️ flex-grow 트랜지션은 리플로우를 일으킨다 — INTERACTION.md 가드레일 9 의 의도적 예외.
     이 섹션은 핀·스크럽이 없어 스크롤 계산과 겹치지 않고, 대상이 7개뿐이며
     contain:paint 로 페인트가 카드 밖으로 번지지 않는다. */
  transition: flex-grow var(--xc-dur-slow) var(--xc-ease-out),
              background-color var(--xc-dur-base) var(--xc-ease-standard);
}
/* 카드 전체를 클릭 영역으로 (stretched link) — 키보드로도 도달한다.
   ⚠️ 링크가 .xc-card__panel(position:absolute) 안에 있어 inset:0 은 패널 폭까지만 덮는다.
   오른쪽으로 넉넉히 늘리고 .xc-card 의 overflow:hidden 이 카드 경계에서 잘라 준다. */
.xc-card__link { display: inline-block; }
.xc-card__link::after { content: ""; position: absolute; inset: 0 -100vw 0 0; z-index: 4; }
.xc-card__link:focus-visible { outline: none; }


/* ── 카드 배경 사진 ──
   접힘 → 펼침에서 사진을 다시 스케일하지 않는다. 사진 판의 폭을 '펼친 카드 폭'에
   고정해 두고, 카드의 overflow:hidden 이 접혀 있는 동안 왼쪽 조각만 남긴다.
   폭이 변하는 것은 카드(창) 하나뿐이고 사진은 제자리에 가만히 있는다.
   ⚠️ background-size:cover 로 카드에 직접 붙이면 안 된다. 카드 폭이 바뀌는 매 프레임마다
      사진이 다시 리스케일되어 (가) 커튼이 아니라 줌아웃으로 읽히고 (나) 일곱 장 전부
      리페인트가 얹힌다. 창만 넓히면 합성 단계에서 끝난다.
   ⚠️ 왼쪽 기준(left:0)이다. 접힘은 왼쪽 조각, 펼치면 오른쪽이 드러난다.
   ⚠️ z-index 를 -1 로 둔다. 0 이면 안 된다. 1024 이하에서 .xc-card__panel 이
      position:static 으로 돌아가는데, 칠하는 차례가 「흐름 안 글자(5단계) →
      z-index:0 인 절대 요소(6단계)」라 사진이 본문 위로 올라와 글을 덮는다.
      음수는 2단계라 카드 자신의 배경(1단계) 위, 글자 아래에 정확히 놓인다.
      카드가 contain:paint 로 자기 쌓임 맥락을 갖고 있어 음수여도 카드 밖으로 빠지지 않는다. */
.xc-card__media {
  position: absolute; top: 0; bottom: 0; left: 0; z-index: -1;
  width: var(--card-w-open-fb);
  pointer-events: none;
}
@supports (width: 1cqw) {
  .xc-card__media { width: var(--card-w-open); }
}
/* <picture> 는 srcset 후보를 고르기 위한 래퍼일 뿐, 실제로 그려지는 것은 안의 <img> 다.
   기본값이 display:inline 이라 그대로 두면 아래 img 의 height:100% 가 기댈 상자가
   애매해지고(인라인 박스는 블록 컨테이너가 아니다) 브라우저에 따라 줄 높이가 끼어든다.
   블록으로 세워 판을 그대로 채우게 해서 사진 높이가 언제나 카드 높이가 되도록 못박는다. */
.xc-card__media picture { display: block; width: 100%; height: 100%; }
/* ⚠️ 자손 선택자여야 한다. `.xc-card__media > img` 로 조이면 사이에 낀 <picture> 때문에
      규칙이 끊기고 일곱 장이 전부 크기를 잃는다(원래 폭 1280px 로 삐져나온다). */
.xc-card__media img {
  display: block; width: 100%; height: 100%;
  object-fit: cover; object-position: 50% 50%;
}

/* ── 사진 위 글자를 위한 스크림 ──
   왼쪽(패널·접힘 이름 자리)은 짙게, 오른쪽으로 빠지며 걷힌다. 펼칠 때 새로 드러나는
   오른쪽이 그만큼 더 밝아서 커튼이 열리는 인상이 강해진다.
   ⚠️ 70% 는 임의값이 아니다. 패널 글자의 오른쪽 끝이 펼친 폭에서 차지하는 비율이
      제일 큰 곳이 0.694 다(vw 1025 · vw 1600 이상). 거기까지는 세기를 유지해야 한다.
   ⚠️ 세기(.74)는 일곱 장 전부에 대해 최저 픽셀 대비를 재서 정했다. 가장 불리한 장이
      solution_06 · 07 이고 --xc-text-weak 기준 5.15:1 이 나온다. 값을 내리면
      4.5:1 이 먼저 깨진다(0.70 이면 4.16:1). 글자 알파와 같이 잰 값이라 짝으로 움직인다.
   ⚠️ 오른쪽 끝값(.20)은 장식 도형을 걷어낸 뒤에도 그대로 둔다. 일곱 장 모두 어두운
      사진(영역 평균 밝기 L 0.01~0.10)이라 20% 네이비 막을 걷어 봐야 눈에 띄는 차이가
      없다 — .20 / .10 / 0 을 나란히 합성해 비교했고 구분이 안 됐다.
      대신 남겨 두면 색이 제각각인 일곱 장의 톤을 한 줄로 묶어 주고, 02 · 07 처럼
      흰색에 가까운 발광점이 있는 장에서 그 점이 카드 테두리에 바로 붙는 것을 눌러 준다. */
/* 사진 막 — 반투명이 아니라 곱하기. 접힘·펼침이 같은 막 하나를 쓴다.
   ⚠️ 반투명 네이비를 쓰면 안 된다. #161D29 는 사진의 가장 어두운 부분보다 밝아서
      덮는 순간 검정이 들려 올라간다. 밝은 곳은 눌리고 어두운 곳은 뜨니 사진이
      납작해지고 회색 막이 낀 것처럼 보인다(일곱 장 합성해서 확인했다).
      곱하기는 검정을 절대 들어 올리지 않는다. 어둡게만 가고 채도가 남는다.
      같은 세기에서 글자 대비도 곱하기 쪽이 높다.
   ⚠️ 접힘용 세로 막을 따로 두지 않는다. 예전에 세로(접힘)와 가로(펼침)를 섞어 봤는데
      접힌 카드 한 장 안에서 위쪽 모서리는 배경에 녹고 아래쪽만 또렷해져 윤곽이
      위아래로 다르게 읽혔고, 이웃한 카드끼리도 맞닿는 변의 밝기가 어긋나 이음매가
      들쭉날쭉했다. 방향을 하나로 두면 접힌 카드는 왼쪽 평탄 구간만 보이므로
      일곱 장이 균일해지고 펼친 카드의 왼쪽 변과도 밝기가 맞는다.

   세기는 opacity 가 아니라 색에 담는다. opacity 는 그라디언트가 될 수 없기 때문이다.
   곱하기 세기 m 에 대응하는 색은 C = 255 × (1 - m + m × 네이비채널 / 255) 이다.
     m = .75 → rgb(80, 86, 94)      (왼쪽, 글자 자리)
     m = .25 → rgb(197, 198, 202)   (오른쪽)
   두 색을 sRGB 로 선형 보간하면 m 도 선형으로 보간된다.
   ⚠️ 그래서 이 두 색은 --xc-navy 를 직접 읽지 않는다. 네이비 값이 바뀌면 위 식으로
      두 색을 손으로 다시 계산해야 한다. 1024 이하 되돌림도 같은 색을 쓴다.
   70% 정지점은 패널 글자 오른쪽 끝이 펼친 카드 폭에서 차지하는 최대 비율(0.694)이다.
   ⚠️ 세기 .75 는 일곱 장 최저 픽셀 대비로 정했다. 본문을 카드 아래쪽으로 붙인 뒤
      기준으로 펼침 본문 5.67:1, 접힘 이름·번호 8.24:1 이다. .68 이면 4.64:1,
      .62 면 3.93:1 로 기준이 깨진다. 글자 알파와 짝으로 잰 값이라 같이 움직인다. */
.xc-card__media::after {
  content: "";
  position: absolute; inset: 0; z-index: 1;
  background: linear-gradient(90deg,
    rgb(80, 86, 94) 0%,
    rgb(80, 86, 94) 70%,
    rgb(197, 198, 202) 100%);
  mix-blend-mode: multiply;
}


/* ── 접힘 : 세로로 눕힌 솔루션명 ──
   이름은 패널의 <h3> 가 갖는다. 이쪽은 시각 표현이라 aria-hidden 이다(중복 낭독 방지). */
.xc-card__spine {
  /* 카드 폭 전체를 차지해 이름은 좌측, 번호는 우측 끝에 붙는다 */
  position: absolute; top: 30px; left: 0; right: 0; z-index: 2;
  /* 접힌 카드 폭이 곧 이 padding + 이름 + 번호다. 카드를 좁히려고 24 에서 줄였다 */
  padding-inline: 20px;
  display: flex; align-items: flex-start; justify-content: space-between;
  color: var(--xc-text);
  transition: opacity var(--xc-dur-fast) var(--xc-ease-standard);
}
/* ⚠️ 눕힌 글자에서 line-height 는 '줄 간격'이 아니라 '글자가 차지하는 가로폭'이다.
   본문값 1.75 를 그대로 쓰면 한 줄짜리 이름이 글자 크기의 1.75배 폭을 먹어
   접힌 카드가 그만큼 넓어진다. 1.5 는 Pretendard 의 글자 영역(약 1.28em)보다
   넉넉해 잘리지 않으면서 이름·번호 합계에서 약 9px 을 돌려준다. */
.xc-card__label {
  writing-mode: vertical-rl; text-orientation: mixed;
  font-size: var(--xc-fs-card-label); font-weight: var(--xc-fw-extra);
  letter-spacing: -.01em; white-space: nowrap; line-height: 1.5;
}
/* 번호도 이름과 같은 방향으로 눕힌다 */
.xc-card__no {
  writing-mode: vertical-rl; text-orientation: mixed;
  margin-top: 2px; line-height: 1.5;
  font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-bold);
  letter-spacing: .08em; color: var(--xc-text-weak);
  font-variant-numeric: tabular-nums;
}

/* ⚠️ 카드 하단에 있던 장식 선화 7종은 사진을 넣으면서 걷어냈다.
      사진 위에서 선이 묻혀(펼침 상태 실측 대비 평균 2.96~3.57, 최저 1.06)
      제 역할을 못 했고, 사진 자체가 카드의 성격을 이미 말해 준다.
      공유하던 그라디언트 정의(<svg> defs)도 같이 지웠다 — 참조가 0 이다.
      SCREENS.md §H 의 "제품 아이콘 7종(통일 그리드)" 은 이 자리와 무관하게
      여전히 미제작 상태다. 카드 장식으로 되살릴 자리가 아니다. */

/* ── 펼침 패널 ──
   폭을 고정해 카드가 넓어지는 동안 본문이 리플로우되지 않게 한다.
   opacity 로만 감춘다 — display:none / visibility:hidden 은 스크린리더·검색엔진에서 사라진다. */
.xc-card__panel {
  position: absolute; inset: 0 auto 0 0; z-index: 2;
  width: clamp(258px, 30vw, 470px);
  padding: 34px 34px 32px;
  display: flex; flex-direction: column;
  /* 위아래로 갈라 놓는다. 분류·이름은 위, 태그라인·본문은 아래(.xc-card__tag 의
     margin-top:auto 가 민다). 가운데가 비어 사진이 가장 넓게 드러나는 띠가 살고,
     글자도 그 밝은 띠를 피하게 되어 대비가 좋아진다(세 배치 중 최고: 6.00:1.
     전부 위 5.87 · 전부 아래 5.67).
     ⚠️ 두 덩어리를 감싸는 요소를 새로 만들지 않는다. 마크업이 평평한 네 줄이라
        auto 마진 한 줄이면 되고, 태그를 새로 넣으면 일곱 장을 전부 고쳐야 한다. */
  opacity: 0;
  transition: opacity var(--xc-dur-base) var(--xc-ease-standard);
}
/* ⚠️ 패널 안 네 줄의 크기는 상태에 따라 갈라지지 않는다. 접힘에서 패널은 opacity 0 이라
   글이 보이는 순간은 사실상 펼쳤을 때뿐이고, .is-open / :hover / 폴백 :first-child
   세 경로에 크기를 복제하면 클래스가 붙는 순간 패널 하위 전체에 리플로우가 걸린다.
   기본값만 올려 둔다. font-size 는 transition 대상이 아니다.
   ⚠️ 공유 토큰(--xc-fs-h3 · --xc-fs-body · --xc-fs-sm) 자체를 키우지 않는다. 다른 페이지
      수십 곳이 같이 움직인다. 이 셀렉터가 가리키는 토큰만 바꾼다.
   ⚠️ 글자만 키우면 커 보이지 않는다. 상속된 본문 행간 1.75 를 같이 조여야 덩어리가 잡힌다. */
.xc-card__cat {
  font-size: var(--xc-fs-14); font-weight: var(--xc-fw-semibold);
  letter-spacing: .04em; color: var(--xc-text-weak);
  line-height: 1.5;
  /* 소제목과 아래 선을 한 줄에 놓는다 */
  display: flex; align-items: center; gap: 12px;
}
/* ── 소제목 옆 가로선 ──
   카드가 펼쳐지는 동안 소제목 오른쪽에서 카드 오른쪽 끝까지 그어진다.
   패널에서 마지막으로 멈추는 요소라 시선이 이 선을 따라 타이틀 덩어리에 얹힌다.
   (타이틀이 안 띄던 이유는 대비가 아니라 패널 네 줄이 전부 같은 무게였기 때문이다.)
   ⚠️ 폭이 아니라 scaleX 로 그린다. width 를 전환하면 매 프레임 레이아웃이 돈다.
      이 섹션은 이미 flex-grow 전환이라는 예외를 하나 쓰고 있어 더 얹지 않는다.
   ⚠️ 패널 폭(최대 470px)이 아니라 카드 폭(펼침 637px)까지 나가야 한다. 음수 마진으로
      넘기되 '넉넉히'가 아니라 정확히 계산해야 한다. -100vw 처럼 크게 넘기면 요소의 실제
      폭이 화면보다 커져서, scaleX 가 0.1 만 돼도 이미 카드 끝을 지나 버린다. 선이
      초반에 다 그어지고 남은 시간은 화면 밖에서 자라는 꼴이 된다.
      마진 식 (100% 는 이 flex 줄의 내용 폭 C = 패널폭 - 좌우 패딩):
        선의 오른쪽 끝 = 34 + C - margin  이고, 이것이 카드폭 - 34 여야 하므로
        margin = C - 카드폭 + 68
      vw1440 검산 : 402 - 637.24 + 68 = -167.24 → 오른쪽 끝 603.24 = 637.24 - 34 ✔
      즉 카드 안쪽 여백(34px)을 좌우 똑같이 두고 멈춘다.
   ⚠️ cq 미지원 엔진용 폴백을 아래 @supports 와 짝으로 둔다. --card-w-open 은 100cqw 를
      쓰므로 그 엔진에서는 계산이 통째로 무효가 된다.
   ⚠️ 지연을 패널과 맞춘다. 패널이 opacity 0 인 동안 그어 봐야 안 보인다. */
.xc-card__cat::after {
  content: "";
  flex: 1 0 auto; min-width: 0; height: 1px;
  margin-right: calc(100% - var(--card-w-open-fb) + 68px);
  background: rgba(255, 255, 255, .45);
  transform: scaleX(var(--card-line, 0));
  transform-origin: 0 50%;
  /* ⚠️ 폭 전환과 달리 --xc-ease-out 을 쓰지 않는다. 그 곡선은 전체 시간의 35% 에서
        90% 가 진행되는 등장용이라, 선이 앞에서 확 그어지고 끝에서 기어가는 모양이 된다.
        --xc-ease-in-out 은 대칭이라 처음부터 끝까지 고르게 그어진다. */
  transition: transform var(--xc-dur-draw) var(--xc-ease-in-out) var(--card-panel-delay);
}
@supports (width: 1cqw) {
  .xc-card__cat::after { margin-right: calc(100% - var(--card-w-open) + 68px); }
}
/* 이름은 메인 ② 두 갈래 카드와 같은 급으로 올린다(--xc-fs-two-name).
   같은 화면에서 카드 이름이 두 벌 있는데 한쪽만 작으면 위계가 아니라 실수로 읽힌다. */
.xc-card__name {
  margin-top: 12px; font-size: var(--xc-fs-two-name);
  font-weight: var(--xc-fw-extra); letter-spacing: -.02em;
  line-height: var(--xc-lh-tight);
}
/* 여백을 고정 px 에서 유동 토큰으로 옮긴다. 좁은 구간에서 스스로 줄어 넘침을 막는다
   (vw1025 에서 26 → 20.5, 12 → 12.3). */
/* 브랜드 동사. 이름 록업의 일부라 위 덩어리(분류·이름)에 붙어 있다.
   ⚠️ 태그라인 위가 아니라 이름 바로 아래다. .xc-card__tag 의 margin-top:auto 가
      아래 덩어리를 패널 바닥으로 미는 구조라, 여기 넣어야 auto 마진 계산이 그대로다.
      태그라인 쪽에 붙이면 아래 덩어리가 한 줄 늘어 사진이 드러나는 띠가 좁아진다.
   ⚠️ 태그라인과 경쟁하지 않게 작게 둔다. 카드마다 목적어만 바뀌는 틀의 반복이지
      읽히려고 있는 문장이 아니다(브랜드 담당 판정 2026-08-25).
   ⚠️ 그라디언트 글자다. 색이 아니라 배경을 글자 모양으로 자른 것이라
      color 로는 안 바뀐다. 되돌리려면 background 를 지워야 한다. */
.xc-card__wield {
  margin-top: 10px;
  font-size: var(--xc-fs-14); font-weight: var(--xc-fw-semibold);
  letter-spacing: .06em; line-height: 1.4;
  background: var(--xc-gradient);
  -webkit-background-clip: text; background-clip: text;
  color: transparent;
  /* 그라디언트가 글자 폭만큼만 걸리게 한다. 블록 전체 폭에 걸면 짧은 줄이 한 색으로 뭉갠다 */
  width: fit-content;
}

.xc-card__tag {
  /* 여기서부터 아래 덩어리다. auto 마진이 남는 세로 공간을 전부 먹어 태그라인과
     본문을 패널 바닥으로 민다.
     ⚠️ 간격을 padding 으로 따로 잡는 이유. margin 이 auto 라 최소 간격을 겸할 수 없고,
        내용이 길어져 남는 공간이 0 이 되면 auto 는 0 으로 접혀 이름과 태그라인이
        맞붙는다. padding 은 그때도 남는다. */
  margin-top: auto; padding-top: var(--xc-gap);
  font-size: var(--xc-fs-lead); font-weight: var(--xc-fw-semibold);
  color: var(--xc-text); line-height: 1.5;
}
.xc-card__desc {
  margin-top: var(--xc-gap-sm); font-size: var(--xc-fs-card-desc);
  color: var(--xc-text-sub); line-height: 1.65;
}

/* ── 펼친 상태 : 폴백(JS 가 없을 때) ──
   :focus-within 은 마우스 클릭에도 발동해 카드가 펼쳐진 채 고정된다 → focus-visible 만
   ⚠️ 앞의 :where() 는 명시도를 0 으로 계산한다. 여기에 붙는 조건은 '언제 쓰이는가' 일
      뿐이라 명시도를 올리면 안 된다. :not(.is-live) 로 명시도가 한 단계 오르면
      1024 이하 블록의 되돌림 규칙들을 이 규칙이 이겨 버린다(예전에 도형이 세로
      목록에서 다시 우측으로 빠지는 사고가 여기서 났다). :where() 를 쓰면
      이 규칙의 무게가 예전 그대로다. */
:where(.xc-lineup__acc:not(.is-live)) .xc-card:is(:hover, :has(.xc-card__link:focus-visible)) {
  flex-grow: var(--card-grow); --card-line: 1;
}
/* 초점 테두리는 폴백이 아니다. JS 유무와 무관하게 언제나 보여야 한다 */
.xc-card:has(.xc-card__link:focus-visible) {
  outline: 2px solid var(--xc-focus); outline-offset: 3px;
}
/* 펼칠 때는 즉시 사라진다 — 패널이 올라오는 동안 이름이 겹쳐 보이지 않게.
   접힐 때만 원래 속도로 되돌아온다(transition-duration 은 이 규칙에만 걸린다). */
:where(.xc-lineup__acc:not(.is-live)) .xc-card:is(:hover, :has(.xc-card__link:focus-visible)) .xc-card__spine {
  opacity: 0; transition-duration: 0s;
}
:where(.xc-lineup__acc:not(.is-live)) .xc-card:is(:hover, :has(.xc-card__link:focus-visible)) .xc-card__panel {
  opacity: 1; transition-delay: var(--card-panel-delay);
}


/* ── 열려 있는 카드 ──
   .is-open 은 main.js 가 붙인다(한 번에 한 장). 처음은 첫 장이고, 카드에 손이 닿으면
   그 장으로 옮겨 간다. 손이 목록을 벗어나도 그대로 남는 것이 이 방식의 목적이다.

   바로 아래 폴백은 스크립트가 막힌 화면을 위한 것이다. .is-live 가 붙기 전까지만
   유효하고, 그 사이에도 열리는 카드가 첫 장으로 같아 바뀌는 그림이 없다(깜빡임 없음).
   ⚠️ 폴백의 취소 조건을 .xc-card:hover 로 잡으면 안 된다. 카드 사이 gap(10px) 위를
      지날 때는 어떤 카드도 hover 가 아니라서 첫 카드가 다시 펼쳐지려 하고, 카드를
      옮겨 다닐 때마다 폭이 떨린다. gap 은 ul 안쪽이므로 ul:hover 는 그대로 유지된다.
   ⚠️ 폴백을 위 :hover 규칙에 콤마로 붙이지 않고 따로 쓴다. 위 규칙은 :has() 를 :is()
      안에 넣어 :has() 를 모르는 브라우저에서도 :hover 가 살아남게 해 두었는데, 여기
      선택자를 같은 목록에 넣으면 :not(:has()) 하나 때문에 규칙 전체가 버려져
      hover 까지 죽는다. 따로 두면 이 블록만 무시되고 아코디언은 그대로 동작한다.
   ⚠️ 통째로 min-width:1025 안에 둔다. 1024 이하는 아코디언이 아니라 세로 목록이라
      JS 가 .is-open 을 붙이든 말든 그림에 닿으면 안 된다. 아래 MD 블록이 덮어 주기를
      기대하지 않고 여기서 아예 걸지 않는다
      (1024.001px 로 쓰면 Chromium 이 1024 로 내려 1열 구간에서도 참이 된다). */
@media (min-width: 1025px) {
  /* 폴백 : 스크립트가 붙기 전 · 막힌 화면 */
  .xc-lineup__acc:not(.is-live):not(:hover, :has(.xc-card__link:focus-visible)) > .xc-card:first-child {
    flex-grow: var(--card-grow); --card-line: 1;
  }
  .xc-lineup__acc:not(.is-live):not(:hover, :has(.xc-card__link:focus-visible)) > .xc-card:first-child .xc-card__spine {
    opacity: 0; transition-duration: 0s;
  }
  .xc-lineup__acc:not(.is-live):not(:hover, :has(.xc-card__link:focus-visible)) > .xc-card:first-child .xc-card__panel {
    opacity: 1; transition-delay: var(--card-panel-delay);
  }

  /* 본 규칙 : JS 가 기억하고 있는 한 장 */
  .xc-card.is-open { flex-grow: var(--card-grow); --card-line: 1; }
  .xc-card.is-open .xc-card__spine { opacity: 0; transition-duration: 0s; }
  .xc-card.is-open .xc-card__panel { opacity: 1; transition-delay: var(--card-panel-delay); }
}

/* ⚠️ 물듦이 있던 시절 이 자리에 `html.is-stained .xc-card` 반투명 유리면이 있었다.
   2026-08-28 에 걷어냈다. 되살릴 이유가 있는지부터 보라 — 카드면은 사진(.xc-card__media)이
   전면을 덮어서 background 는 사진이 못 뜬 카드에서만 보인다. 그 자리는 위 .xc-card 의
   `background: var(--xc-navy)` 가 이미 맡고 있다. */

/* ══════════════════ ⑤ 사업분야 · MATE ══════════════════ */
/* ⚠️ 지금 어느 화면에도 걸려 있지 않다. 아래 .xc-biz 주석을 볼 것 */

/* ── 사업분야 : 가로 넉 장 + 사진 덮개 ────────────────────
   무대를 화면에 걸고(pin) 스크롤이 진행을 몬다(scrub).
     0 ~ 17%  붙어 있던 카드 사이가 벌어진다
    17 ~ 100% 덮개가 왼쪽부터 차례로 내려가며 글이 드러난다(칸마다 늦게 출발)

   ⚠️ 제목을 왼쪽에 두지 않는다. 왼쪽이 33% 를 가져가면 카드 한 장이 200px 로 줄어
      태그 목록이 접히다 못해 무너진다. 제목을 위로 올려야 카드가 전체 폭을 나눠 쓴다.
   ⚠️ 덮개는 62% 까지만 내린다. 다 걷으면 사진이 사라져 넣은 뜻이 없어지고,
      절반(andlab 값)에서 멈추면 태그 아홉 개가 남은 자리에 안 들어간다.
   ⚠️ 카드는 밝은 채로 둔다. 「네이비는 푸터에만」 — 사진은 아래 띠로만 남는다.
   ⚠️ 1024 아래에서는 걸지 않고 세로로 쌓으며 덮개를 아예 들어낸다.
      좁은 화면에서 덮개를 남기면 글을 가린 채로 굳는다 */
/* 덮개가 멈추는 자리. 여기서부터 아래가 사진 띠로 남는다.
   ⚠️ 백분율이 아니라 px 다. 글이 차지하는 높이(제목 두 줄 + 요약 두 줄 + 칩 네 줄 ≈ 270px)는
      카드가 커져도 그대로인데, 백분율로 두면 카드가 커질수록 덮개가 쓸데없이 더 내려가
      그림이 남지 않는다. 글에 필요한 만큼만 내리고 나머지는 그림으로 둔다.
        1280×720  카드 392 → 그림 띠 102px
        1440×900  카드 552 → 그림 띠 262px
        1920×1080 카드 709 → 그림 띠 419px */
/* ⚠️ 이 섹션은 지금 어느 화면에도 없다. 메인에서 사업분야를 뺐고(2026-08-11) 솔루션
   페이지가 쓰는 것은 이름이 비슷한 .xc-bizov 다. 되살릴 때 바탕색을 확인할 것 —
   물듦이 이 판을 투명하게 비워 주던 시절의 규칙이라 지금은 바탕색이 아예 없다. */
.xc-biz { --biz-open: 290px; }
/* ⚠️ 좁은 화면에서는 여기서 더 내려야 한다. 글 높이는 화면 높이가 아니라 「카드 폭」이
   정하고(폭이 좁으면 제목·요약·칩이 줄줄이 늘어난다), 카드 폭은 화면 폭이 정한다.
   그래서 px 를 쓴다는 원칙은 그대로 두고 구간별로 값만 갈아 끼운다.
   실측(2026-08-10, 스크럽이 끝난 gap 15px 상태 기준) — 카드 안 글이 끝나는 자리:
     vw1025  03 IT인프라 297.2 · 04 스마트팩토리 279.2 · 01 268.9
     vw1100  04 281.0 · 01 272.7
     vw1280  03 263.0 · 나머지 229.0
   290px 은 vw1025~1099 에서 이미 03 의 마지막 칩 줄을 5px 잘라먹고 있었다(글자 확대 전부터).
   310 이면 제일 빠듯한 03 이 12.8px 남는다.
   ⚠️ 사진 띠가 그만큼 줄어든다. 제일 불리한 1280×720 에서 카드 338.3 → 띠 28.3px 다.
      1281 이상은 카드가 넓어져 글이 짧아지므로 290 으로 되돌린다(띠 83px 회복).
   ⚠️ 1024 이하는 세로로 풀리고 덮개가 display:none 이라 이 값이 쓰이지 않는다. */
@media (min-width: 1025px) and (max-width: 1280px) {
  .xc-biz { --biz-open: 310px; }
}
.xc-biz__inner { display: flex; flex-direction: column; }
/* 걸린 무대는 한 화면에 딱 맞아야 한다. 넘치면 아랫부분이 잘린 채로 고정된다.
   높이를 정해 두지 않고 남는 세로를 카드가 받아 가게 한다 — 화면이 낮아도 안 넘친다 */
@media (min-width: 1025px) {
  .xc-biz {
    box-sizing: border-box; height: 100vh; display: flex;
    padding-block: clamp(56px, 7vh, 96px) clamp(28px, 4vh, 56px);
  }
  .xc-biz__inner { flex: 1; min-height: 0; container-type: inline-size; }
  /* ⚠️ 덮개 그림은 네 칸이 한 장을 나눠 쓰느라 폭이 400% 로 묶여 있다.
        폭이 묶이면 높이는 원본 비율(2752×1536)이 정한다.
        카드가 「카드폭 × 2.23」 보다 높아지면 그림이 덮개를 못 채우고 위아래가 빈다.
        2560×1440 에서 카드 973 · 그림 745 로 114px 씩 띠가 생겼다.
        카드 폭 = (판 폭 - 여백 45) / 4 이므로 그 2.23배에서 키우기를 멈춘다 */
  .xc-biz__list  { flex: 1; min-height: 0; max-height: calc((100cqw - 45px) / 4 * 2.23); }
  .xc-biz__card  { height: 100%; }
}
.xc-biz__head .xc-lead { margin-top: 18px; max-width: 52ch; }
.xc-biz__go { margin-top: 26px; }
/* ⚠️ 기본값은 「다 벌어지고 다 내려간 자리」다. 스크립트가 막혀도 글이 보인다.
   JS 가 잡을 때만 gap 0 · top 0 으로 되돌려 놓고 굴린다 */
.xc-biz__list {
  display: flex; gap: 15px;
  margin-top: clamp(28px, 3.4vw, 52px);
}
.xc-biz__item { flex: 1 1 0; min-width: 0; }
.xc-biz__card {
  position: relative; overflow: hidden;
  background: var(--xc-bg-soft);
  /* 카드가 붙어 있을 때는 한 판이라 모서리가 없고, 벌어지면서 둥글어진다.
     ⚠️ 값을 JS 가 --biz-r 로 넣는다. 여백이 벌어지는 것과 같은 진행도를 써야
        「떨어지면서 둥글어진다」로 보인다. 따로 돌리면 어긋난다.
     ⚠️ 기본값은 다 둥근 상태다. 스크립트가 막히면 원래 모습으로 보인다. */
  border-radius: var(--biz-r, var(--xc-radius));
}
/* 붙어 있을 때 줄 전체가 하나의 판으로 보이려면, 바깥으로 향한 모서리는
   처음부터 둥글어야 한다. 안쪽으로 맞닿는 모서리만 각졌다가 펴진다.
   ⚠️ 네 모서리를 한 값으로 묶으면 첫 카드 왼쪽까지 각져서 판이 잘린 것처럼 보인다. */
.xc-biz__item:first-child .xc-biz__card {
  border-radius: var(--xc-radius) var(--biz-r, var(--xc-radius))
                 var(--biz-r, var(--xc-radius)) var(--xc-radius);
}
.xc-biz__item:last-child .xc-biz__card {
  border-radius: var(--biz-r, var(--xc-radius)) var(--xc-radius)
                 var(--xc-radius) var(--biz-r, var(--xc-radius));
}
.xc-biz__cardin {
  position: relative; z-index: 1;
  padding: clamp(20px, 1.8vw, 28px);
}
.xc-biz__cardhead { display: flex; align-items: baseline; gap: 12px; }
/* 덮개 — 카드를 통째로 덮었다가 아래로 내려간다.
   ⚠️ 카드 글자보다 위(z 2)여야 한다. 아래로 두면 덮이지 않는다 */
.xc-biz__cover {
  position: absolute; z-index: 2; top: var(--biz-open); left: 0;
  width: 100%; height: 100%;
  /* 한 장을 넷이 나눠 쓴다. 폭을 네 배로 늘려 두고 칸마다 --biz-x 로 제 몫을 보인다 —
     칸이 붙어 있을 때(gap 0)는 네 칸이 이어져 한 장이 되고, 벌어지면 갈라진다.
     ⚠️ 400% auto 다. 400% 100% 로 두면 세로가 눌려 그림이 찌그러진다.
     ⚠️ 그림을 못 받으면 --biz-tone 회색 판이 자리를 지킨다 */
  /* ⚠️ 바탕색은 그림 위아래 가장자리 평균색이어야 한다. 그림이 못 채운 자리가
        그대로 띠로 보이기 때문이다.
        현재 그림은 밝은 계열이라 위 #eaf3f7 · 아래 #f4f7f6 의 중간을 쓴다.
        ⚠️ 그림을 바꾸면 이 값도 반드시 다시 재야 한다. 예전 어두운 그림 시절 값은
           #241b29(위 #271e2b · 아래 #221928)였고, 그대로 두면 검은 띠가 남는다. */
  background: var(--biz-tone, #eff5f6)
              url("../../img/main/biz-cover.jpg") var(--biz-x, 50%) 50% / 400% auto no-repeat;
}
.xc-biz__no {
  font-size: var(--xc-fs-20); font-weight: var(--xc-fw-bold);
  color: var(--xc-orange); font-variant-numeric: tabular-nums;
  line-height: 1; flex: none;
}
.xc-biz__cardhead h3 {
  font-size: var(--xc-fs-card-ttl); font-weight: var(--xc-fw-extra);
  letter-spacing: -.02em; line-height: 1.35;
}
/* 카드 요약문 — 이 섹션의 본문이다.
   ⚠️ --xc-fs-xs(13px)는 캡션·메타용 단이다. 본문 한 문장을 캡션 크기로 두면 제목과
      칩 사이에서 위계가 사라진다. 실제로 요약 13px 과 칩 12px 이 1px 차이로 붙어 있었다.
      라인업 패널 설명과 같은 단(--xc-fs-card-desc)으로 올려 「제목 > 본문 > 칩」을 되살린다.
        vw1025 19 / 15 / 12   vw1440 24 / 18 / 12
   ⚠️ 칩(.xc-biz__tags li)은 12px 그대로 둔다. 칩은 본문이 아니라 라벨이고, 여기서만
      키우면 줄이 늘어 카드마다 높이가 서로 다르게 불어난다. 아래 덮개 예산을 먼저 볼 것.
   ⚠️ 행간 1.6 → 1.5. 글자를 키운 만큼 조여야 덩어리로 읽힌다(줄당 +1.7px 로 억제).
   ⚠️ 여백은 고정 px 대신 유동 토큰으로. 좁은 구간(vw1025)에서 12.3px 로 거의 그대로 있고
      넓은 구간에서만 벌어져, 제일 빠듯한 곳에 부담을 주지 않는다. */
.xc-biz__sum {
  margin-top: var(--xc-gap-sm);
  font-size: var(--xc-fs-card-desc); color: var(--xc-text-sub); line-height: 1.5;
}
.xc-biz__tags { margin-top: var(--xc-gap-sm); display: flex; flex-wrap: wrap; gap: 6px; }
.xc-biz__tags li {
  padding: 5px 12px; border-radius: var(--xc-radius-full);
  border: 0;
  background: var(--xc-chip-bg); color: var(--xc-text-sub);
  font-size: var(--xc-fs-12); font-weight: var(--xc-fw-medium); line-height: 18px;
}

/* ══════════════════ ⑥ CLIENTS ══════════════════ */
.xc-clients { background: var(--xc-bg); overflow: hidden; }
.xc-clients__head { text-align: center; max-width: 62ch; margin-inline: auto; }
.xc-clients__head .xc-lead { margin-inline: auto; max-width: 46ch; }

/* 양 끝을 배경으로 녹인다 — 로고가 화면 가장자리에서 뚝 잘리지 않게 */
.xc-clients__viewport {
  margin-top: clamp(36px, 4vw, 60px);
  -webkit-mask-image: linear-gradient(to right, transparent, #000 7%, #000 93%, transparent);
          mask-image: linear-gradient(to right, transparent, #000 7%, #000 93%, transparent);
}
.xc-clients__track { display: flex; gap: var(--xc-gap); width: max-content; }
.xc-clients__row {
  display: flex; gap: var(--xc-gap);
  animation: marquee 42s linear infinite;
}
/* ⚠️ 물듦을 걷어내면서(2026-08-28) 한때 면을 --xc-gray-50, 테두리를 --xc-border 로 올렸다.
   흰 위 흰 칸이라 칸이 안 읽힌다는 이유였는데, **사용자가 원래대로 되돌리라고 했다.**
   다시 올리지 말 것 — 물으면 된다. */
.xc-clients__row li {
  width: 176px; height: 84px; flex: none;
  display: grid; place-items: center;
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius);
  background: var(--xc-white);
  padding: 0 18px;
}
/* 로고는 원본 비율을 유지하며 칸 안에 맞춘다. 가로가 긴 것과 세로가 긴 것이
   섞여 있어 width/height 를 고정하면 찌그러진다. */
.xc-clients__row li img {
  width: auto; height: auto;
  max-width: 100%; max-height: 52px;
  object-fit: contain; display: block;
}

@keyframes marquee {
  from { transform: translateX(0); }
  to   { transform: translateX(calc(-100% - var(--xc-gap))); }
}

/* ══════════════════ ⑦ 푸터 (Contact 통합) ══════════════════
   값 출처: i-bricks .footer 실측
   화면 가장자리에서 20px 띄운 라운드 블록 하나에 Contact + 회사정보를 담는다. */
:root {
  --ft-gap:       20px;    /* 화면 가장자리 여백 */
  --ft-r:         20px;    /* 블록 라운드 (1.25rem) */
  --ft-pad-t:    100px;    /* 6.25rem */
  --ft-pad-b:     44px;    /* 2.75rem */
  --ft-wrap-mt:  100px;    /* contact → 회사정보 */
  --ft-go:       120px;    /* 원형 버튼 지름 */
}

.xc-footer { padding: var(--ft-gap); overflow: hidden; }
.xc-footer__inner {
  background: var(--xc-navy-deep);
  border-radius: var(--ft-r);
  padding-block: var(--ft-pad-t) var(--ft-pad-b);
}
.xc-footer__area {
  max-width: var(--xc-area); margin-inline: auto;
  padding-inline: var(--xc-pad);
}

/* ── Contact ── */
.xc-footer__contact {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--xc-gap-lg);
}
.xc-footer__contact-txt { display: flex; flex-direction: column; gap: 24px; }
.xc-footer__title {
  color: #fff; font-size: var(--xc-fs-footer-title);
  font-weight: var(--xc-fw-bold); line-height: 1.2; letter-spacing: -.84px;
}
.xc-footer__desc {
  color: rgba(255, 255, 255, .7);
  font-size: var(--xc-fs-footer-desc); font-weight: var(--xc-fw-medium);
  line-height: 150%; letter-spacing: -.7px;
}
.xc-footer__go {
  flex: none; width: var(--ft-go); aspect-ratio: 1; border-radius: 50%;
  background: var(--xc-gradient); color: var(--xc-navy-deep);
  display: grid; place-items: center;
}
.xc-footer__go svg { width: 26%; }
/* 덮이는 원은 흰색 — 푸터가 --xc-navy-deep 이라 어두운 색으로 채우면 버튼이 사라진다.
   화살표는 네이비 그대로 둔다. 그라디언트 위에서도 흰 원 위에서도 대비가 충분하다. */
.xc-footer__go { --hc-fill: var(--xc-white); }

/* ── 회사정보 ── */
.xc-footer__wrap { margin-top: var(--ft-wrap-mt); }
.xc-footer__top {
  display: flex; align-items: center; justify-content: space-between;
  gap: 20px; flex-wrap: wrap;
}
/* 로고는 푸터에서 한 톤 낮춘다. 흰 로고가 그대로면 저작권·주소보다 세게 읽힌다 */
.xc-footer__logo img { width: 182px; height: auto; display: block; opacity: .62; }
.xc-footer__policy { display: flex; align-items: center; gap: 60px; }
.xc-footer__policy a {
  color: #999; font-size: var(--xc-fs-16); font-weight: var(--xc-fw-medium);
  letter-spacing: -.4px; transition: color var(--xc-dur-fast) var(--xc-ease-out);
}
.xc-footer__policy a:hover { color: #fff; }

.xc-footer__bot {
  margin-top: 40px;
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: var(--xc-gap-lg);
}
.xc-footer__info { display: flex; flex-wrap: wrap; gap: 12px 60px; }
.xc-footer__list { display: flex; flex-direction: column; gap: 12px; }
.xc-footer__list li { display: flex; align-items: flex-start; gap: 40px; }
.xc-footer__list span {
  color: #999; font-size: var(--xc-fs-16); font-weight: var(--xc-fw-medium);
  line-height: 140%; letter-spacing: -.4px;
}
.xc-footer__list .tit { color: #8a8a8a; font-weight: var(--xc-fw-semibold); flex: none; }
.xc-footer__list .tit1 { width: 100px; }
.xc-footer__list .tit2 { width: 60px; }
.xc-footer__list a:hover { color: #fff; }

.xc-footer__sns { display: flex; align-items: center; gap: 12px; flex: none; }
.xc-footer__sns a {
  width: 60px; height: 60px; border-radius: var(--xc-radius-full);
  background: rgba(255, 255, 255, .1); color: rgba(255, 255, 255, .7);
  display: grid; place-items: center;
  font-size: var(--xc-fs-18); font-weight: var(--xc-fw-bold);
  transition: var(--xc-trans-fast);
}
.xc-footer__sns a:hover { background: rgba(255, 255, 255, .18); color: #fff; }

.xc-footer__copy {
  margin-top: 40px; text-align: right;
  color: #999; font-size: var(--xc-fs-14); font-weight: var(--xc-fw-medium);
  line-height: 140%; text-transform: uppercase;
}

/* ── 커서 원 ──────────────────────────────────────────
   커서를 따라오는 작은 점. 원생 커서는 그대로 남긴다(숨기면 조작감이 떨어진다).

   ⚠️ 위치는 겉껍데기(.xc-cursor)의 transform 으로만 옮기고, 크기 변화는 안쪽
      요소가 scale 로 처리한다. 겉껍데기의 width/height 를 바꾸면 중심 보정값이
      함께 흔들려 점이 커질 때 커서에서 미끄러진다.
   ⚠️ mix-blend-mode 를 쓰면 안 된다. difference 가 채운 색을 반전시켜
      브랜드 색이 엉뚱한 색으로 나온다. 포인트 오렌지는 흰 배경 2.98:1,
      네이비 배경 5.67:1 로 양쪽 다 보이므로 고정 색으로 둔다. */
.xc-cursor {
  position: fixed; left: 0; top: 0; width: 0; height: 0;
  z-index: 2000; pointer-events: none;
  will-change: transform;
}
.xc-cursor i {
  position: absolute; left: 0; top: 0; display: block;
  width: 16px; height: 16px; margin: -8px 0 0 -8px;
  border-radius: 50%;
  background: var(--xc-orange);
  opacity: 0; transform: scale(.4);
  transition: opacity .3s var(--xc-ease-out),
              transform .3s var(--xc-ease-out),
              background-color .2s var(--xc-ease-out);
}
.xc-cursor.is-on i { opacity: 1; transform: none; }
/* 링크·버튼 위에서는 커진다.
   버튼 글자를 덮지 않는 선이 26px 정도다(그 위로 가면 라벨이 가려진다). */
.xc-cursor.is-active i { transform: scale(1.65); }
/* 누르는 동안 조인다 */
.xc-cursor.is-down i { transform: scale(.7); }
.xc-cursor.is-active.is-down i { transform: scale(1.25); }

/* ── 카드 위: VIEW 원 ──
   카드를 클릭하면 상세로 간다는 것을 커서가 직접 말한다.
   ⚠️ 라벨은 점(i)과 형제로 둔다. i 를 4.75배 키우는데 라벨이 그 안에 있으면
      글자까지 같이 늘어나 자모가 뭉갠다. 라벨은 제 크기를 유지하며 겹쳐 놓는다. */
.xc-cursor b {
  position: absolute; left: 0; top: 0;
  transform: translate(-50%, -50%) scale(.7);
  font-size: var(--xc-fs-16); font-weight: var(--xc-fw-extra);
  letter-spacing: .14em; white-space: nowrap;
  color: #fff;
  opacity: 0; pointer-events: none;
  transition: opacity .22s var(--xc-ease-out), transform .28s var(--xc-ease-out),
              color .2s var(--xc-ease-out);
}
.xc-cursor.is-more i { transform: scale(6.5); }         /* 16px → 104px */
.xc-cursor.is-more b { opacity: 1; transform: translate(-50%, -50%) scale(1); transition-delay: .1s; }
.xc-cursor.is-more.is-down i { transform: scale(5.8); }

/* ⚠️ 예전에는 수상·인증 카드(.xc-cert__open) 위에서 커서 원을 흰색으로 뒤집었다.
   카드가 포인트 오렌지로 채워져 같은 색 원이 그 위에서 사라졌기 때문이다.
   카드를 네이비로 바꾸면서 필요가 없어졌다 — 오렌지 원은 네이비 위에서 5.64:1 이다. */

/* 터치 기기에는 커서가 없다 */
@media (hover: none), (pointer: coarse) { .xc-cursor { display: none; } }
/* 강제 색상 모드에서는 장식 점을 감춘다 */
@media (forced-colors: active) { .xc-cursor { display: none; } }

/* ── 우측 고정 퀵버튼 ── */
.xc-quick { position: fixed; z-index: var(--xc-z-float); right: 40px; bottom: 70px; }
.xc-quick ul { display: flex; flex-direction: column; align-items: flex-end; gap: 12px; }
/* GNB 와 같은 반투명 블러. 이 버튼은 히어로 영상·흰 섹션·네이비 섹션 위를
   차례로 지나므로 뒤에 실제로 흐릴 대상이 있어 블러가 눈에 보인다.
   ⚠️ 어두운 틴트를 유지하는 이유: 흰 아이콘이 밝은 섹션 위에서도 읽혀야 한다.
      .55 면 흰 배경 위 합성값이 rgb(124,124,124) 로 흰 아이콘 대비 4.17:1 이다.
      더 투명하게 하면(.42) 2.78:1 로 떨어져 비텍스트 최소 3:1 을 못 넘긴다. */
.xc-quick a, .xc-quick button {
  display: flex; align-items: center; justify-content: center;
  width: 60px; height: 60px; padding: 0; border-radius: var(--xc-radius-full);
  border: 1px solid rgba(255, 255, 255, .22);
  background: rgba(17, 17, 17, .55);
  -webkit-backdrop-filter: blur(16px) saturate(140%);
          backdrop-filter: blur(16px) saturate(140%);
  color: #fff; cursor: pointer; overflow: hidden;
  transition: width var(--xc-dur-base) var(--xc-ease-out),
              gap var(--xc-dur-base) var(--xc-ease-out),
              background var(--xc-dur-fast) var(--xc-ease-out),
              border-color var(--xc-dur-fast) var(--xc-ease-out);
}
.xc-quick a.is-fill { background: rgba(17, 17, 17, .68); }
.xc-quick li:hover a, .xc-quick li:hover button,
.xc-quick a:focus-visible, .xc-quick button:focus-visible {
  background: rgba(17, 17, 17, .82);
  border-color: rgba(255, 255, 255, .38);
}
/* 블러 미지원 브라우저는 불투명하게 (투명한 채로 두면 아이콘이 안 읽힌다) */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .xc-quick a, .xc-quick button { background: rgba(17, 17, 17, .9); }
}
.xc-quick svg {
  width: 21px; height: 21px; flex: none;
  fill: none; stroke: currentColor; stroke-width: 1.6;
  stroke-linecap: round; stroke-linejoin: round;
}
.xc-quick span {
  opacity: 0; max-width: 0; white-space: nowrap;
  font-size: var(--xc-fs-15); font-weight: var(--xc-fw-semibold); letter-spacing: -.4px;
  transition: opacity var(--xc-dur-base) var(--xc-ease-out),
              max-width var(--xc-dur-base) var(--xc-ease-out);
}
.xc-quick li:hover a { width: 180px; gap: 14px; }
.xc-quick li:hover a span { opacity: 1; max-width: 100%; }

/* ══════════════════ 서브페이지 공통 틀 ══════════════════
   SCREENS.md A-2 확정안. 타이포 헤더 + 좌측 sticky LNB.
   배경 이미지 없이 성립하므로 미확보 자산과 무관하게 바로 쓸 수 있다. */

/* ── 페이지 헤더 ── */
.xc-ph {
  position: relative;
  background: var(--xc-navy);
  /* GNB(--gnb-top + --gnb-row = 120px)가 헤더 위에 떠 있으므로 그만큼은 반드시 비운다.
     SCREENS.md 의 280px 은 GNB 아래부터 재는 값이라, 실제 높이는 그보다 커진다. */
  padding-top: calc(var(--gnb-top) + var(--gnb-row) + clamp(24px, 3vw, 40px));
  /* 액자 만큼 아래 여백을 더 준다. 안 그러면 서브카피가 잘린 모서리에 붙는다 */
  padding-bottom: calc(clamp(64px, 7vw, 104px) + var(--hero-frame));
  min-height: calc(480px + var(--hero-frame) * 2);
  display: flex; align-items: flex-end;
  overflow: hidden;
  /* 메인 히어로와 같은 액자. 전체 폭 블록을 clip-path 로 잘라 바깥에 페이지 배경을 드러낸다.
     ⚠️ 히어로처럼 로드 후 트랜지션으로 들어가게 하지 않는다.
        서브페이지에서 2초간 액자가 좁혀지는 연출은 페이지 진입을 늦게 느끼게 한다. */
  clip-path: inset(var(--hero-frame) round var(--hero-frame-r));
}
/* 우상단 웜 광원. 이미지 대신 이것으로 헤더를 살린다 */
.xc-ph::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(ellipse 55% 80% at 88% 0%, rgba(249, 168, 92, .20), transparent 72%);
}
.xc-ph__area { position: relative; z-index: 1; width: 100%; }
/* 제목(좌) · 브레드크럼(우) 한 행. 브레드크럼은 영역 상단(제목 첫 줄 윗선)에 붙는다.
   ⚠️ flex-start 만으로는 '같은 선상'이 안 된다 — 정렬되는 건 줄상자(line box)이고
      눈에 보이는 건 글자 윗선(cap top)이다. 64px 제목은 반행간 + 글자 위 여백 때문에
      줄상자보다 한참 내려와 시작하는데 13px 브레드크럼은 그 여백이 훨씬 작아,
      그냥 맞추면 브레드크럼이 3px 정도 위로 떠 보인다. 아래 margin-top 이 그 차를 지운다.
   ⚠️ 계수는 눈짐작이 아니라 캔버스 글꼴 실측(actualBoundingBoxAscent)으로 잡았다.
      32~64px 전 구간에서 잉크 윗선 오차 ±0.7px 이내. 글꼴이나 line-height 를
      바꾸면 이 값도 다시 재야 한다.
   ⚠️ 제목 크기가 clamp 로 변하니 보정값도 --ph-fs 에 비례해야 한다. 고정 px 로 두면
      모바일(32px 제목)에서 반대로 브레드크럼이 내려앉는다. max(0px, …) 는 하한 가드. */
.xc-ph__row {
  /* 페이지 제목 크기. 값을 여기 적지 않고 h1 토큰을 가리킨다 —
     아래 브레드크럼 보정이 이 값을 계산에 쓰므로 한 곳에서만 읽혀야 한다. */
  --ph-fs: var(--xc-fs-h1);
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: clamp(16px, 3vw, 60px) clamp(20px, 3vw, 60px); flex-wrap: wrap;
}
.xc-ph__crumb {
  flex: none;
  margin-top: max(0px, calc(var(--ph-fs) * .09 - 2.9px));
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  font-size: var(--xc-fs-13); line-height: 1.5; color: rgba(255, 255, 255, .6);
}
.xc-ph__crumb a { color: inherit; }
.xc-ph__crumb a:hover { color: #fff; }
.xc-ph__crumb i { font-style: normal; opacity: .5; }
.xc-ph__title {
  font-size: var(--ph-fs, var(--xc-fs-h1)); font-weight: var(--xc-fw-extra);
  letter-spacing: var(--xc-ls-display); line-height: 1.1; color: #fff;
}
.xc-ph__sub {
  margin-top: 16px; max-width: 56ch;
  font-size: var(--xc-fs-ph-sub); line-height: 1.7;
  color: rgba(255, 255, 255, .72); text-wrap: pretty;
}
/* 브랜드 동사. 뜻풀이는 이 자리에서 한 번만 단다 —
   이후 화면에서는 Wield your ___ 와 Start wielding 만 쓴다(재정의안 적용 메모).
   ⚠️ 동사와 뜻풀이를 같은 무게로 두지 않는다. 뜻풀이는 괄호 주석 같은 것이라 한 단계 낮춘다. */
/* ⚠️ flex 로 두면 text-align: center 가 안 먹는다. 정렬하는 주체가 달라지기 때문이다.
   히어로는 가운데 정렬인데 이 줄만 왼쪽 끝에 붙어 혼자 떠 보였다.
   justify-content 로 따로 가운데를 잡아 준다. */
.xc-ph__wield {
  margin-top: 18px;
  display: flex; flex-wrap: wrap; justify-content: center;
  align-items: baseline; gap: 2px 10px;
}
.xc-ph__wield b {
  font-size: var(--xc-fs-md); font-weight: var(--xc-fw-extra);
  letter-spacing: .02em; color: #fff;
}
.xc-ph__wield span {
  font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-medium);
  color: rgba(255, 255, 255, .6);
}

/* ── 페이지 헤더 · 전체화면 라이트 변형 ────────────────────
   메인 히어로처럼 한 화면을 채우고, 배경을 움직이는 그라디언트로 깐다.
   배경이 네이비에서 밝은 색으로 뒤집히므로 글자색과 GNB 색이 함께 따라와야 한다
   (GNB 는 아래 .is-onlight 참조). 적용: company-general.html */

.xc-ph--full {
  height: 100dvh;
  min-height: 560px;                 /* 가로 화면 노트북에서 카피가 눌리지 않게 */
  align-items: center;               /* 기본값 flex-end 를 덮는다 */
  /* 세로 가운데 정렬이라 위아래를 같게 준다. GNB 높이만큼만 비우고 여분은 두지 않는다 —
     여분까지 양쪽에 주면 세로 560px 화면에서 카피가 잘린다(헤더는 overflow:hidden) */
  padding-top:    calc(var(--gnb-top) + var(--gnb-row));
  padding-bottom: calc(var(--gnb-top) + var(--gnb-row));
}
.xc-ph--light { background: var(--xc-white); }
/* 네이비 전용 웜 광원. 밝은 배경 위에서는 누렇게 뜬 얼룩으로 보인다 */
.xc-ph--light::before { display: none; }

.xc-ph__bg,
.xc-ph__dots { position: absolute; inset: 0; pointer-events: none; }
.xc-ph__bg   { z-index: 0; }
.xc-ph__dots { z-index: 1; }

/* 텍스트 뒤 흰 원 — 배경이 색을 띠는 자리에서도 글자가 뜨게 받쳐 준다.
   radial-gradient 가 아니라 실제 원에 blur 를 건다. 가장자리가 더 자연스럽고
   크기와 번짐을 따로 조절할 수 있다. 정지 요소라 blur 는 처음 한 번만 계산된다.
   값은 lab/subhead.html 에서 고른다 */
.xc-ph__glow {
  position: absolute; z-index: 2;        /* 점 격자(1) 위, 글자(3) 아래 */
  top: 50%; left: 50%;
  width: min(var(--ph-glow-size, 660px), 92vw);
  aspect-ratio: 1 / 1;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: rgba(255, 255, 255, var(--ph-glow-alpha, 1));
  filter: blur(var(--ph-glow-blur, 140px));
  pointer-events: none;
}
/* 넓게 퍼지는 두 번째 빛 — 알파만 올리면 가운데만 진해지고 밝은 면적은 그대로다.
   제목 폭(1380px)을 덮는 납작한 타원을 겹쳐 좌우로 넓힌다.
   크기는 원의 비율로 잡아 좁은 화면에서 원과 함께 줄어든다.
   부모의 blur 를 그대로 물려받으므로 여기서 filter 를 또 걸지 않는다 */
.xc-ph__glow::before {
  content: ""; position: absolute;
  top: 50%; left: 50%;
  width: var(--ph-halo-w, 195%);
  height: var(--ph-halo-h, 92%);
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: rgba(255, 255, 255, var(--ph-halo-alpha, .62));
}
/* CSS 크기를 안 주면 캔버스가 기본 300×150 으로 잡혀 헤더를 못 덮는다 */
.xc-ph__bg canvas,
.xc-ph__dots canvas {
  display: block; width: 100%; height: 100%;
  position: absolute; inset: 0;
}

/* 가운데 정렬 — 브레드크럼 · 제목 · 서브카피를 한 축에 세운다.
   이 변형에서는 마크업도 읽는 순서(크럼→제목→카피)로 바꿔 두었다.
   order 로 시각 순서만 뒤집으면 낭독·탭 순서가 화면과 어긋난다. */
.xc-ph--full .xc-ph__area  { z-index: 3; text-align: center; }
.xc-ph--full .xc-ph__crumb {
  justify-content: center;
  margin: 0 0 clamp(14px, 2vw, 22px);
}
.xc-ph--full .xc-ph__title { font-size: var(--xc-fs-display); }
.xc-ph--full .xc-ph__sub   { margin-inline: auto; }

/* 부제를 <br> 로 접은 줄 그대로 앉히는 변형.
   기본 56ch 는 문단용 읽기 폭이다. 여기 첫 문장은 35ch 짜리인데도
   글자가 커서 631px 이 되어 600px 캡에 31px 걸려 한 번 더 접힌다.
   ⚠️ .xc-ph__sub 는 21개 페이지가 함께 쓴다. 캡을 통째로 올리면 안 된다 —
      이 변형을 붙인 히어로에서만 올린다. */
.xc-ph--wide .xc-ph__sub { max-width: 62ch; }

.xc-ph--light .xc-ph__title { color: var(--xc-navy); }
.xc-ph--light .xc-ph__sub   { color: var(--xc-gray-700); }
.xc-ph--light .xc-ph__crumb { color: var(--xc-gray-600); }
.xc-ph--light .xc-ph__crumb a:hover { color: var(--xc-navy); }

/* ── GNB · 밝은 배경 위 ──────────────────────────────────
   GNB 는 기본이 흰 글자다(어두운 히어로 전제). 밝은 헤더에서는 그대로 사라진다.
   스크롤해서 is-solid 가 되면 원래 규칙이 이미 검정으로 바꾸므로,
   여기서는 '아직 안 내려간' 상태만 뒤집는다. */
.xc-gnb.is-onlight:not(.is-solid):not(.is-open) .xc-gnb__link,
.xc-gnb.is-onlight:not(.is-solid):not(.is-open) .xc-gnb__all { color: #111; }
.xc-gnb.is-onlight:not(.is-solid):not(.is-open) .xc-gnb__lang { color: #555; }
.xc-gnb.is-onlight:not(.is-solid):not(.is-open) .xc-gnb__lang .is-cur a { color: #111; }
.xc-gnb.is-onlight:not(.is-solid):not(.is-open) .xc-gnb__logo img { filter: brightness(0); }
/* 흰 배경에 흰 5% 틴트는 아무 역할을 못 한다. 살짝 올려 캡슐 경계를 남긴다 */
.xc-gnb.is-onlight:not(.is-solid):not(.is-open) .xc-gnb__bg {
  background: rgba(255, 255, 255, .38);
}
/* ── 본문 레이아웃 ── */
/* 좌측 LNB 없음. 본문이 콘텐츠 폭을 그대로 쓴다(1440 − 좌우 여백 = 1380px).
   흐르는 글은 아래에서 ch 단위로 따로 묶는다. 열이 넓어도 한 줄이 길어지지 않게. */
.xc-sub { padding-block: clamp(64px, 8vw, 128px) clamp(72px, 10vw, 160px); }

/* ── 좌측 LNB ── */
.xc-lnb { position: sticky; top: calc(var(--gnb-top) + var(--gnb-row) + 24px); align-self: start; }
.xc-lnb h2 {
  font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-bold);
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--xc-text-weak); padding-bottom: 14px;
  border-bottom: 1px solid var(--xc-border);
}
.xc-lnb ul { margin-top: 6px; }
.xc-lnb a {
  position: relative; display: block; padding: 12px 0 12px 16px;
  font-size: var(--xc-fs-sm); color: var(--xc-text-sub);
  transition: color var(--xc-dur-fast) var(--xc-ease-out);
}
.xc-lnb a:hover { color: var(--xc-text); }
/* 현재 항목. 좌측 3px 그라디언트 바 */
.xc-lnb a[aria-current="page"] {
  color: var(--xc-text); font-weight: var(--xc-fw-bold);
}
.xc-lnb a[aria-current="page"]::before {
  content: ""; position: absolute; left: 0; top: 10px; bottom: 10px;
  width: 3px; border-radius: 2px; background: var(--xc-gradient);
}

/* ── 본문 섹션 ──
   메인과 같은 헤더 체계를 쓴다: eyebrow(13px) + h2 + lead.
   메인은 가운데 정렬이지만 서브는 읽는 문서라 좌측 정렬을 유지한다.
   h2 는 메인(44px)보다 한 단계 낮춘 값으로 위계를 만든다.
   섹션 사이 간격도 메인의 리듬(160px)에 맞춘다 — 이전 104px 은 메인의 1/3 이었다. */
.xc-blk + .xc-blk { margin-top: clamp(72px, 10vw, 160px); }
.xc-blk__head { max-width: 62ch; }
.xc-blk__head .xc-h2 { font-size: var(--xc-fs-blk-h2); }
.xc-blk__head .xc-lead { max-width: 56ch; }
/* 문장마다 줄을 끊어 둔 리드는 그 문장이 한 줄에 들어가야 뜻이 산다.
   기본 폭(62ch·628px)에서는 한 줄에 약 37자뿐이라 긴 문장이 다시 감기며
   「설계했습니다.」 같은 조각만 남는다. 줄바꿈을 넣은 곳에서만 폭을 푼다.
   ⚠️ .xc-blk__head 를 통째로 넓히지 않는다. 이 부품은 24개 화면이 함께 쓴다.
   ⚠️ 리드만 넓혀 봐야 소용없다. 부모의 상한이 먼저 걸린다. 둘 다 풀어야 한다.
   ⚠️ 줄바꿈이 풀리는 폭(.xc-br-lg 는 1280px 이하에서 display:none)과 같은
      경계로 묶는다. :has() 는 br 이 숨어도 계속 맞으므로, 조건을 걸지 않으면
      줄바꿈은 사라졌는데 리드만 840px 로 남아 한 줄 55자가 된다. */
@media (min-width: 1281px) {
  .xc-blk__head:has(.xc-lead .xc-br-lg) { max-width: none; }
  .xc-blk__head:has(.xc-lead .xc-br-lg) .xc-h2 { max-width: 18em; }
  .xc-blk__head .xc-lead:has(.xc-br-lg) { max-width: 40em; }
}

/* ── 서브페이지 섹션 제목은 36px 하나로 ──────────────────
   .xc-h2 자체는 44px(--xc-fs-h2)이고, .xc-blk__head 안에서만 36px 로 낮아진다.
   그래서 제목을 .xc-blk__head 로 감싸지 않은 곳은 조용히 44px 가 된다.
   전 화면을 재 보니 서브페이지 안에서 그렇게 44px 가 된 곳이 12곳이었고,
   한 화면 안에 36 과 44 가 섞여 있었다(xcalibur · 사업분야 · 고객지원 등).

   ⚠️ 유지하는 것들 — 여기 넣지 말 것.
      · 메인(index.html)의 섹션 제목 44px. 메인과 서브는 눈금을 나눠 쓴다
      · .xc-solall__head 19곳 44px. MATE 제품 제목이다. 한 화면에 제품이 3~6개라
        제품 하나가 사실상 페이지 단위이고, 그 안의 소제목이 36px 이라 위계가 성립한다
      · .xc-adds__head · .xc-decl__head 55px 2곳. 페이지의 단언이라 역할이 다르다
      · .xc-xc__head(「왜 검과 검집인가」) 44px. 사용자가 그대로 두기로 정했다
   ⚠️ 마크업에 .xc-blk__head 를 붙이는 방법도 있으나 쓰지 않았다.
      그 클래스는 max-width: 62ch 를 함께 물고 있어 가운데 정렬인 CTA 상자가 틀어진다.
   ⚠️ .xc-inq__ttl 은 여기 없다. 자기 규칙이 파일 뒤쪽에 있고 명시도가 같아
      여기서 지정하면 진다. 그 규칙에서 직접 고쳤다. */
.xc-xc__cta-box .xc-h2,     /* xCalibur 상세 7 + 소개 1 의 ⑥ CTA (8곳) */
.xc-rec-lead > .xc-h2,      /* 사업분야 · 스마트팩토리 의 #intro (2곳) */
.xc-proc__side .xc-h2 {     /* 고객지원체계 #process (1곳) */
  font-size: var(--xc-fs-blk-h2);
}
/* 선언 섹션의 큰 제목은 메인 h2 크기를 그대로 쓴다 */
.xc-blk__body { margin-top: clamp(20px, 2.4vw, 32px); }
/* ⚠️ ch 를 쓰지 않는다. ch 는 숫자 '0' 의 폭이라 한글 한 자의 약 절반이다.
      72ch(729px)는 한글 본문으로 한 줄 60자가 되어 눈이 다음 줄 첫머리를
      놓친다. em 은 글자 크기를 따라가므로 글자 수와 맞는다. 34em ≈ 45자. */
.xc-blk__body p {
  max-width: 34em;
  font-size: var(--xc-fs-body); color: var(--xc-text-sub);
  line-height: 1.8; text-wrap: pretty;
}
/* ⚠️ 줄 간격(1.8 = 30.6px)보다 넓어야 한다. 좁으면 문단 사이가 줄 사이보다
      가까워서 여러 문단이 한 덩어리로 보인다. 이전 값 14px 이 그랬다. */
.xc-blk__body p + p { margin-top: clamp(22px, 2.2vw, 30px); }
/* 넓은 화면에서는 본문을 문장마다 한 줄로 끊는다(마크업의 .xc-br-lg).
   그러려면 가장 긴 문장이 안 감길 만큼 폭이 있어야 한다. 46em ≈ 57자로
   전체 문장 101개 중 89%가 한 줄에 들어간다. 나머지는 쉼표에서 한 번 더 끊었다.
   ⚠️ 줄바꿈이 든 문단에만 걸지 않는다. 그러면 같은 섹션 안에서 문단마다
      오른쪽 끝이 달라지고, 줄바꿈 없는 문단만 문장 중간에서 갈라진다.
   ⚠️ 폭 상한이 실제 줄 길이를 정하는 게 아니다. 문장마다 끊으므로 실제 줄은
      문장 길이(중앙값 37자)를 따른다. 상한은 「감기지 않게」 하는 장치일 뿐이다.
   ⚠️ .xc-br-lg 가 꺼지는 폭과 같은 경계로 묶는다. 안 묶으면 좁은 화면에서
      줄바꿈은 사라졌는데 폭만 넓게 남아 한 줄 57자가 된다. */
@media (min-width: 1281px) {
  .xc-blk__body p { max-width: 46em; }
}

/* ── 기업정보 숫자 ── */
/* ── 기업정보 ──
   사건(연도)과 규모(수치)를 형식으로 나눈다. 같은 크기의 숫자로 나열하면
   「1992년」과 「89명」이 동급으로 읽힌다. */
.xc-facts {
  margin-top: clamp(24px, 3vw, 40px);
  display: grid; gap: clamp(32px, 4vw, 56px);
}

/* 규모 지표. 한 상자를 선으로 나누지 않고 카드 두 장으로 떼어 놓는다.
   색·테두리·라운드는 메인의 라이트 카드(.xc-two__card--mate, .xc-biz__card)와 같은 값. */
/* 5장을 3 + 2 로 놓는다. 6칸 격자에서 위 줄은 2칸씩, 아래 줄은 3칸씩 차지해
   두 줄 모두 전체 폭을 채운다(빈칸이 남지 않는다). */
.xc-fact__nums {
  display: grid; grid-template-columns: repeat(6, 1fr);
  gap: clamp(12px, 1.4vw, 20px);
}
.xc-fact__nums > li { grid-column: span 2; }
.xc-fact__nums > li:nth-child(4),
.xc-fact__nums > li:nth-child(5) { grid-column: span 3; }
.xc-fact__nums li {
  background: var(--xc-gray-50);
  border: 1px solid var(--xc-border-weak);
  border-radius: var(--xc-radius-lg);
  padding: clamp(24px, 2.6vw, 36px);
  container-type: inline-size;
}
.xc-fact__nums dt {
  font-size: var(--xc-fs-sm); font-weight: var(--xc-fw-semibold);
  color: var(--xc-text-weak); letter-spacing: .02em;
}
.xc-fact__nums dd {
  margin-top: 12px;
  font-size: var(--xc-fs-facts-num); font-weight: var(--xc-fw-extra);
  letter-spacing: -.03em; color: var(--xc-text);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.xc-fact__nums dd .unit { font-size: .46em; margin-left: 3px; font-weight: var(--xc-fw-bold); }
.xc-fact__nums dd .as-of {
  display: block; margin-top: 8px; white-space: normal;
  font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-medium);
  letter-spacing: 0; color: var(--xc-text-weak);
}

/* ══════════════════ 채용안내 ══════════════════ */

/* ── 직군 카드 ── */
/* ── 모집 직무 : 아코디언 ── */
.xc-job {
  display: grid; gap: 10px;
  margin-top: clamp(24px, 3vw, 40px);
}
.xc-job > li {
  background: var(--xc-gray-50);
  border: 1px solid var(--xc-border-weak);
  border-radius: var(--xc-radius-lg);
  /* 펼침 애니메이션 중 패널 모서리가 상자 밖으로 비어져 나오지 않게 */
  overflow: hidden;
  transition: background var(--xc-dur-base) var(--xc-ease-out),
              border-color var(--xc-dur-base) var(--xc-ease-out);
}
.xc-job > li:has(.xc-job__sum[aria-expanded="true"]) {
  background: var(--xc-bg); border-color: var(--xc-border);
}
.xc-job__ttl { font-size: inherit; font-weight: inherit; }
/* ⚠️ background 를 비워 두면 브라우저 기본값 buttonface(#f0f0f0)가 남아 회색 띠가 된다.
   글꼴도 상속되지 않으므로 font: inherit 로 되돌린다. */
.xc-job__sum {
  width: 100%; display: flex; align-items: center; gap: clamp(12px, 1.4vw, 20px);
  padding: clamp(18px, 2vw, 26px) clamp(20px, 2.4vw, 32px);
  background: none; border: 0; font: inherit; color: var(--xc-text);
  text-align: left; cursor: pointer;
}
.xc-job__grp {
  flex: none;
  padding: 5px 11px; border-radius: var(--xc-radius-full);
  border: 1px solid var(--xc-border-strong); background: var(--xc-bg);
  font-size: var(--xc-fs-12); font-weight: var(--xc-fw-semibold); color: var(--xc-text-sub);
  white-space: nowrap;
}
.xc-job__name {
  font-size: var(--xc-fs-job-name); font-weight: var(--xc-fw-extra);
  letter-spacing: var(--xc-ls-heading); color: var(--xc-text);
}
/* 열림 표시 — 세로 막대를 눕히면 +가 −가 된다. 요소 하나로 끝난다 */
.xc-job__mark {
  position: relative; flex: none; width: 18px; height: 18px; margin-left: auto;
}
.xc-job__mark::before, .xc-job__mark::after {
  content: ""; position: absolute; left: 50%; top: 50%;
  width: 16px; height: 1.6px; border-radius: 2px; background: currentColor;
  transform: translate(-50%, -50%);
  transition: transform var(--xc-dur-base) var(--xc-ease-out);
}
.xc-job__mark::after { transform: translate(-50%, -50%) rotate(90deg); }
.xc-job__sum[aria-expanded="true"] .xc-job__mark::after { transform: translate(-50%, -50%) rotate(0); }

/* 높이는 JS 가 0 ↔ auto 로 움직인다. 넘치는 내용을 잘라 둬야 중간 프레임이 깨끗하다 */
.xc-job__panel { overflow: hidden; }
.xc-job__panel[hidden] { display: none; }

/* 행이 전체 폭이라 세 항목을 가로로 나눠야 한 줄이 지나치게 길어지지 않는다.
   ⚠️ dt·dd 를 그대로 그리드 아이템으로 두면 라벨과 설명이 서로 다른 칸에 흩어진다.
      각 쌍을 div 로 묶고 그 div 를 칸에 넣는다. */
.xc-job__spec {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  column-gap: clamp(20px, 2.4vw, 44px);
  padding: 0 clamp(20px, 2.4vw, 32px) clamp(22px, 2.4vw, 32px);
}
.xc-job__spec dt {
  /* ⚠️ 행간을 안 주면 본문 행간(1.8)이 상속돼 작은 라벨 아래위로 반행씩 붙는다 */
  font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-bold); line-height: 1.3;
  letter-spacing: .08em; color: var(--xc-text-weak);
}
.xc-job__spec dd {
  margin-top: 6px;
  font-size: var(--xc-fs-sm);
  color: var(--xc-text-sub); line-height: 1.65; text-wrap: pretty;
}

/* ── 지원 3단계 ── */
.xc-step {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: clamp(16px, 2vw, 28px);
  margin-top: clamp(24px, 3vw, 40px);
  counter-reset: none;
}
.xc-step > li {
  display: flex; flex-direction: column;
  padding-top: 26px; border-top: 2px solid var(--xc-text);
}
.xc-step__no {
  font-size: var(--xc-fs-sm); font-weight: var(--xc-fw-extra);
  letter-spacing: .06em; color: var(--xc-orange);
  font-variant-numeric: tabular-nums;
}
.xc-step__ttl {
  margin-top: 10px;
  font-size: var(--xc-fs-card-ttl); font-weight: var(--xc-fw-bold);
  letter-spacing: var(--xc-ls-heading); color: var(--xc-text);
}
.xc-step__body { margin-top: 18px; display: grid; gap: 10px; flex: 1; }
.xc-step__body li {
  font-size: var(--xc-fs-sm); color: var(--xc-text-sub);
  line-height: 1.7; text-wrap: pretty;
}
.xc-step__body b {
  display: block; font-weight: var(--xc-fw-bold); color: var(--xc-text);
}
.xc-step__body a { color: var(--xc-text); text-decoration: underline; text-underline-offset: 3px; }
.xc-step .xc-pill { align-self: flex-start; margin-top: 20px; }

/* ── 일하는 환경 ── */
.xc-wel {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: clamp(12px, 1.4vw, 20px);
  margin-top: clamp(24px, 3vw, 40px);
  align-items: start;
}
.xc-wel > li {
  padding: clamp(24px, 2.6vw, 36px);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius-lg);
  background: var(--xc-bg);
}
/* 구분선은 두지 않는다. 첫 항목의 border-top 이 바로 아래에 있어 선이 겹쳐 보였다 */
.xc-wel__head {
  display: flex; align-items: baseline; gap: 10px;
  padding-bottom: 12px;
}
.xc-wel__en {
  font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-bold);
  letter-spacing: .12em; text-transform: uppercase; color: var(--xc-text-weak);
}
.xc-wel__ko {
  font-size: var(--xc-fs-card-ttl); font-weight: var(--xc-fw-extra);
  letter-spacing: var(--xc-ls-heading); color: var(--xc-text);
}
.xc-wel__list { margin-top: 6px; }
/* 항목 이름 위, 한 줄 설명 아래. 이름과 설명이 가로로 갈리면
   설명이 좁은 열에 눌려 두세 줄로 접힌다. */
/* 이름·설명은 그대로 쌓아 두고, 아이콘만 오른쪽 여백에 띄운다.
   ⚠️ 2열 그리드로 짜면 안 된다 — dt 와 dd 가 각각 그리드 행이 되어, 두 행을 걸친
      아이콘이 자기 높이만큼 행을 벌린다. 아이콘을 키울 때마다 이름과 설명 사이가
      같이 벌어졌다(26px→4px, 34px→6px). 흐름에서 빼면 크기와 무관해진다. */
.xc-wel__list > div {
  position: relative; padding: 16px 44px 16px 0;
  border-top: 1px solid var(--xc-border-weak);
}
/* 뜻은 이름과 설명이 이미 다 말한다. 아이콘은 장식이라 낭독에서 뺀다(aria-hidden) */
.xc-wel__ico {
  position: absolute; right: 0; top: 50%; transform: translateY(-50%);
  width: 34px; height: 34px;
  /* 크기를 키우면 선이 같이 굵어 보인다. viewBox 는 24 그대로라 stroke-width 를
     낮춰 줘야 원래의 가는 선 느낌이 유지된다 */
  fill: none; stroke: currentColor; stroke-width: 1.35;
  stroke-linecap: round; stroke-linejoin: round;
  color: var(--xc-text-weak); opacity: .45;
  /* 손이 닿은 행의 아이콘만 포인트색으로 또렷해진다. 바뀌는 것은 색과 불투명도뿐이라
     글자 위치도 아이콘 자리도 움직이지 않는다.
     모션 최소화에서는 --xc-dur-base 가 .01ms 로 덮여 즉시 바뀐다(tokens.css §12).
     ⚠️ transform 은 이 전환에 넣지 않는다. main.js 의 진입 점등이 같은 속성을
        쓰기 때문에, 트윈이 끝나며 인라인 transform 을 지울 때 되돌아오는 것이
        transition 을 타고 한 번 더 미끄러진다.
     ⚠️ opacity 는 진입 점등(main.js)도 쓰는 속성이다. 점등이 clearProps 로 인라인
        스타일을 지운 뒤라야 이 규칙이 이긴다. 그 처리를 빼면 hover 가 영영 안 먹는다. */
  transition: color   var(--xc-dur-base) var(--xc-ease-out),
              opacity var(--xc-dur-base) var(--xc-ease-out);
}
/* hover 는 카드가 아니라 행(.xc-wel__list > div) 낱개에 건다.
   행은 이미 padding 16px 과 윗선으로 제 영역이 그려져 있어 반응 단위로 읽힌다.
   ⚠️ 포인터가 카드를 세로로 가로지르면 3~4개가 연달아 켜졌다 꺼진다. 전환이 길수록
      잔상이 남으므로 --xc-dur-base 보다 늘리지 말 것. 늘어지면 --xc-dur-fast 로 내린다.
   ⚠️ 아이콘은 행 안에 position:absolute 로 들어 있어 hover 판정에 함께 들어온다.
      행에 padding-right 44px 이 아이콘 자리를 비워 둔 덕분이다.
   불투명도·색 값에 토큰이 없다. 가장 가까운 선례인 .xc-ov__ico 도 리터럴을 쓰므로
   여기만 커스텀 프로퍼티를 새로 만들면 규칙이 갈린다.
   ⚠️ 오렌지는 흰 바탕에서 3.0:1 이라 글자에는 못 쓰는 색이다(tokens.css §1).
      여기 아이콘은 aria-hidden 장식이고 뜻은 dt·dd 가 전부 말하므로 대비 기준 대상이
      아니다. 같은 이유로 이 색을 dt·dd 로 옮기지 말 것.
   ⚠️ 카드 테두리는 건드리지 않는다. 가장 가까운 선례인 .xc-ov__group > li 가
      아이콘 하나만 바꾼다. 테두리를 바꾸는 .xc-awd__list · .xc-xc__sol 은
      hover 신호가 그것뿐인 카드들이고, 여기는 아이콘이 이미 그 역할을 한다. */
.xc-wel__list > div:hover .xc-wel__ico {
  color: var(--xc-accent); opacity: 1;
}
.xc-wel__list > div:first-child { border-top: 0; }
.xc-wel__list dt {
  font-size: var(--xc-fs-body); font-weight: var(--xc-fw-bold);
  letter-spacing: -.01em; color: var(--xc-text);
}
.xc-wel__list dd {
  margin-top: 4px;
  font-size: var(--xc-fs-sm); color: var(--xc-text-sub);
  line-height: 1.65; text-wrap: pretty;
}

/* ── 지원하기 ── */
.xc-rec-cta__box {
  margin-top: clamp(24px, 3vw, 40px);
  padding: clamp(28px, 3vw, 48px);
  /* 회색 박스. 흰 본문 위에서 한 단계만 내려앉게 gray-100 + 실선 테두리를 쓴다.
     ⚠️ 배경만 바꾸면 안 된다 — 아래 글자·버튼 색이 전부 네이비 배경 전제로 흰색이었다.
        pill 은 .xc-pill 기본값(테두리형·네이비 글자)에 맡기고 여기서 덮지 않는다. */
  background: var(--xc-bg-muted); border: 1px solid var(--xc-border);
  border-radius: var(--xc-radius-lg);
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(24px, 3vw, 48px); align-items: center;
}
.xc-rec-cta__acts { display: flex; flex-wrap: wrap; gap: 10px; }
.xc-rec-cta__info { display: grid; gap: 12px; }
.xc-rec-cta__info > div {
  display: grid; grid-template-columns: minmax(0, 96px) minmax(0, 1fr); gap: 16px;
}
.xc-rec-cta__info dt {
  font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-bold);
  letter-spacing: .08em; color: var(--xc-text-weak);
}
.xc-rec-cta__info dd { font-size: var(--xc-fs-sm); color: var(--xc-text); }
.xc-rec-cta__info a { color: inherit; text-decoration: underline; text-underline-offset: 3px; }

@media (max-width: 1024px) {
  /* 아코디언은 한 줄짜리 목록이라 열 수를 바꿀 게 없다.
     대신 펼친 내용의 3열을 푼다 — 좁은 칸에서는 설명이 대여섯 줄로 접힌다 */
  .xc-job__spec { grid-template-columns: 1fr; }
  .xc-job__spec > div + div { margin-top: 18px; }
  .xc-step { grid-template-columns: 1fr; gap: 28px; }
  .xc-wel { grid-template-columns: repeat(2, 1fr); }
  .xc-rec-cta__box { grid-template-columns: 1fr; align-items: start; }
}
@media (max-width: 640px) {
  /* 직군 뱃지와 직무명이 한 줄에 다 못 들어간다. 뱃지를 윗줄로 내린다 */
  .xc-job__sum { flex-wrap: wrap; }
  .xc-job__grp { width: 100%; margin-bottom: 4px; }
  .xc-wel { grid-template-columns: 1fr; }
  .xc-rec-cta__info > div { grid-template-columns: 1fr; gap: 2px; }
}

/* ── 강점 3블록 ── */
.xc-str { display: grid; gap: clamp(28px, 3.5vw, 52px); margin-top: clamp(24px, 3vw, 40px); }
.xc-str > li {
  display: grid; grid-template-columns: minmax(0, 420px) minmax(0, 1fr);
  gap: clamp(24px, 3.5vw, 56px); align-items: center;
}
.xc-str__img {
  margin: 0; border-radius: var(--xc-radius-lg); overflow: hidden;
  aspect-ratio: 5 / 3; background: var(--xc-bg-soft);
}
.xc-str__img img { width: 100%; height: 100%; object-fit: cover; display: block; }
.xc-str__name {
  font-size: var(--xc-fs-str-name); font-weight: var(--xc-fw-extra);
  letter-spacing: var(--xc-ls-heading); color: var(--xc-text);
}
.xc-str__keys { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 12px; }
/* 태그 칩 — 메인의 .xc-two__tags li 와 같은 규칙 (그 주석에 경위가 있다) */
.xc-str__keys li {
  padding: 5px 12px; border-radius: var(--xc-radius-full);
  border: 0; background: var(--xc-chip-bg);
  font-size: var(--xc-fs-12); font-weight: var(--xc-fw-medium); line-height: 18px;
  color: var(--xc-text-sub);
  white-space: nowrap;
}
.xc-str__txt {
  margin-top: 18px; max-width: 60ch; font-size: var(--xc-fs-sm);
  color: var(--xc-text-sub); line-height: 1.8; text-wrap: pretty;
}

/* ── 세 가지 기준 : 확대 무대 (넓은 화면 + 모션 허용에서만) ──
   작은 창 하나가 화면 아래쪽에 떠 있다가 스크롤에 따라 화면 전체로 커지고,
   그 뒤로 세 항목이 이미지째 교체된다. 마크업은 카드 목록과 같은 것을 쓴다.
   is-stage 는 JS 가 붙인다 — 없으면 위의 카드 목록 그대로다. */
/* 본문 열(1380px)을 뚫고 화면 폭을 다 쓴다.
   ⚠️ 100vw 는 스크롤바 폭을 포함해 가로 스크롤을 만든다.
      JS 가 documentElement.clientWidth 를 --str-vw 로 넣는다. */
.xc-str.is-stage {
  position: relative; height: var(--str-stage);
  width: var(--str-vw); margin-left: calc(50% - var(--str-vw) / 2);
  gap: 0; margin-top: clamp(24px, 3vw, 40px);
}
/* 세 항목이 같은 자리에 겹친다. 잘라내기(--str-clip)는 JS 가 매 프레임 넣는다.
   ⚠️ 앞 장을 빼면서 뒷 장을 넣으면 둘 다 반투명인 순간 흰 배경이 비친다.
      지나온 장은 불투명하게 남겨 두고 새 장이 그 위에 얹히게 한다(z-index 순서).
      뒤로 감을 때는 위의 장만 빠지고 아래 장이 그대로 드러난다. */
.xc-str.is-stage > li {
  position: absolute; inset: 0; display: block;
  clip-path: var(--str-clip, inset(0));
  background: var(--xc-navy);
  opacity: 0; transition: opacity .9s var(--xc-ease-out);
}
.xc-str.is-stage > li:nth-child(1) { z-index: 1; }
.xc-str.is-stage > li:nth-child(2) { z-index: 2; }
.xc-str.is-stage > li:nth-child(3) { z-index: 3; }
.xc-str.is-stage > li.is-shown { opacity: 1; }
.xc-str.is-stage .xc-str__img {
  position: absolute; inset: 0; margin: 0;
  border-radius: 0; aspect-ratio: auto;
}
/* 글자가 사진 위에 얹히므로 어둡게 깔아 준다 */
.xc-str.is-stage .xc-str__img::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(180deg,
    rgba(20, 26, 36, .10) 0%, rgba(20, 26, 36, .62) 62%, rgba(20, 26, 36, .88) 100%);
}
/* 글은 본문 열 왼쪽 선에 맞춘다(--str-pad = 열 시작 x) */
.xc-str.is-stage > li > div {
  position: absolute; left: var(--str-pad, 40px); right: var(--str-pad, 40px);
  bottom: clamp(40px, 7vh, 96px); max-width: 52ch;
  opacity: 0; transform: translateY(22px);
  transition: opacity .6s var(--xc-ease-out), transform .6s var(--xc-ease-out);
}
/* 창이 화면을 다 덮은 뒤에 글이 올라온다 */
.xc-str.is-stage.is-open > li.is-on > div { opacity: 1; transform: none; }
/* 무대 모드에서는 섹션 제목급으로 키운다.
   ⚠️ --xc-fs-h2 로 바꾸지 말 것. 양 끝(26·44)은 같지만 중간 기울기가 다르다
      (여기 3vw / 토큰 3.2vw). 1280px 에서 38.4px 대 40.96px 로 갈린다. */
.xc-str.is-stage .xc-str__name { color: var(--xc-white); font-size: var(--xc-fs-str-name-on); }
/* 무대 모드는 어두운 면 위다. 칩 규칙을 다시 쓰지 않고 면색 토큰만 갈아 끼운다
   (.xc-dark 가 --xc-chip-bg 에 넣는 값과 같다) */
.xc-str.is-stage .xc-str__keys li {
  --xc-chip-bg: rgba(255, 255, 255, .10);
  color: rgba(255, 255, 255, .92);
}
.xc-str.is-stage .xc-str__txt {
  color: rgba(255, 255, 255, .82); font-size: var(--xc-fs-body); max-width: 52ch;
}

@media (max-width: 1024px) {
  /* LNB 를 상단 가로 스크롤 탭으로 */
  .xc-sub { grid-template-columns: 1fr; gap: 28px; }
  .xc-lnb { position: static; }
  .xc-lnb h2 { border-bottom: 0; padding-bottom: 8px; }
  .xc-lnb ul {
    display: flex; gap: 4px; margin-top: 0;
    overflow-x: auto; overflow-y: hidden;
    border-bottom: 1px solid var(--xc-border);
    scrollbar-width: none;
  }
  .xc-lnb ul::-webkit-scrollbar { display: none; }
  .xc-lnb li { flex: none; }
  .xc-lnb a { padding: 12px 14px; white-space: nowrap; }
  .xc-lnb a[aria-current="page"]::before {
    left: 14px; right: 14px; top: auto; bottom: 0;
    width: auto; height: 3px;
  }
  .xc-str > li { grid-template-columns: 1fr; }
}
@media (max-width: 640px) {
  .xc-ph { min-height: 260px; }
  .xc-fact__nums { grid-template-columns: 1fr; }
  .xc-fact__nums > li,
  .xc-fact__nums > li:nth-child(4),
  .xc-fact__nums > li:nth-child(5) { grid-column: auto; }
}

/* ── 선언 ── */
.xc-decl { text-wrap: balance; }
/* 서브페이지 섹션 제목은 하나의 값만 쓴다.
   About 제목도 기업정보·연혁·수상인증과 같은 크기·굵기다. */
/* 이 페이지의 선언 문장이라 다른 섹션 제목(36px)은 물론
   메인 섹션 제목(44px)보다도 크게 잡는다.
   화면 가운데에서 한 줄씩 칠해지는 유일한 문장이라 이 페이지에서 가장 큰 활자다. */
/* ⚠️ 줄 나눔은 고정 모드와 무관하게 항상 유지돼야 한다.
   is-stage 안에만 display:block 을 두면 폴백에서 두 줄이 한 줄로 붙는다. */
.xc-decl__ln { display: block; }
/* 고정 모드가 아닐 때도 제목과 본문을 충분히 떼어 놓는다 */
.xc-decl__body { margin-top: clamp(40px, 5vw, 72px); }
.xc-decl__ttl {
  font-size: var(--xc-fs-decl-ttl); font-weight: var(--xc-fw-bold);
  letter-spacing: var(--xc-ls-heading); line-height: var(--xc-lh-heading);
  color: var(--xc-text); text-wrap: balance;
}
/* 72ch. 한글 한 줄 43자 정도로, 읽기 편한 범위(35~45자)의 상한에 맞췄다.
   구조 요소(표·카드)는 본문 열 1140px 을 그대로 쓰고, 흐르는 글만 여기서 묶는다. */
/* ⚠️ .xc-decl p 로 잡으면 eyebrow(<p class="xc-eyebrow">)까지 리드 크기가 된다.
   선택자 특정도가 (0,1,1) 대 (0,1,0) 이라 .xc-eyebrow 가 진다.
   본문 문단만 가리키도록 __body 안으로 좁힌다. */
/* 첫 문단은 리드. 크기만으로는 21 대 17 이라 위계가 흐릿해서
   굵기(500 대 400)와 색(본문색 대 보조색)까지 함께 벌린다. */
.xc-decl__body p {
  margin-top: clamp(18px, 2vw, 28px); max-width: 72ch;
  font-size: var(--xc-fs-sub-lead);
  font-weight: var(--xc-fw-medium);
  color: var(--xc-text);
  line-height: 1.6; letter-spacing: -.015em;
  text-wrap: pretty;
}
/* 이어지는 문단도 같은 단계로 둔다. 앞 문단만 크게 두면 뒤 문단이 각주처럼 읽혔다.
   두 문단은 '현장에서 배웠다'와 '그 위에 AI를 얹는다'로 무게가 같은 짝이다. */
.xc-decl__body p ~ p { margin-top: clamp(18px, 2vw, 26px); }

/* ── About 무대 (넓은 화면 + 모션 허용에서만) ──
   ⚠️ 100vh 짜리 무대를 만들고 제목을 그 안에서 가운데 두면, 첫 화면에 제목 위로
      화면 절반만큼의 빈 칸이 생긴다. 무대를 만들지 않고 글은 제 자리에 그대로 두되,
      제목이 화면 한가운데에 왔을 때 고정을 걸어(JS 가 시작점을 계산한다)
      그 상태로 칠하기와 설명 등장을 진행한다. 첫 로드에서 여백이 생기지 않는다.
   is-stage 는 JS 가 붙인다 — GSAP 이 없거나 좁은 화면에서는 평범한 글 블록으로 남는다. */
/* ⚠️ 고정되면 GSAP 이 이 섹션을 pin-spacer 로 감싼다. 그러면 다음 섹션이
   .xc-blk 의 형제가 아니게 되어 `.xc-blk + .xc-blk` 의 160px 간격이 끊긴다.
   섹션 자신의 padding 으로 같은 간격을 만든다. */
/* 고정 중에는 좌우 두 열이다. 왼쪽에 제목, 오른쪽에 문단.
   제목 줄이 접히면 줄 단위 채색이 깨지므로 왼쪽 열을 더 넓게 잡는다. */
.xc-decl.is-stage {
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  gap: clamp(40px, 5vw, 88px);
  align-items: start;
  text-align: left;
  /* 고정이 풀린 뒤 이 덩어리가 화면 밖으로 완전히 빠져나간 다음에
     다음 섹션이 아래에서 올라오게 한다. 화면 높이만큼 두면 둘이 정확히 교대한다
     (겹치지도, 빈 화면이 생기지도 않는다). --decl-tail 은 JS 가 넣는다. */
  padding-bottom: var(--decl-tail, clamp(72px, 10vw, 160px));
}
/* 제목 윗변을 우측 첫 문단 윗변과 맞춘다.
   eyebrow 를 흐름에 두면 그 높이만큼 제목이 내려가므로 위로 띄운다. */
.xc-decl.is-stage .xc-decl__head { max-width: 100%; position: relative; }
.xc-decl.is-stage .xc-eyebrow {
  position: absolute; bottom: calc(100% + 16px); left: 0;
  margin: 0; white-space: nowrap;
}
/* 줄마다 자기 --paint 를 갖는다. 상자를 글자 폭에 맞춰야
   그라디언트가 그 줄의 글자 시작~끝에 정확히 대응한다. */
.xc-decl.is-stage .xc-decl__ln {
  --paint: 0%;
  width: fit-content; margin-inline: 0;
  background-image: linear-gradient(90deg,
    var(--xc-text) 0 var(--paint),
    var(--xc-decl-ghost) var(--paint) 100%);
  background-clip: text; -webkit-background-clip: text;
  color: transparent; -webkit-text-fill-color: transparent;
}
/* 오른쪽 열. 문단이 하나씩 오른쪽에서 왼쪽으로 들어온다 */
.xc-decl.is-stage .xc-decl__body {
  max-width: none; margin: 0; text-align: left;
}
/* 글자 단위 등장.
   문단마다 --p(0~1)만 스크롤이 바꾸고, 글자는 자기 순번 --i 로 스스로 계산한다.
   --n = 그 문단의 글자 수, 6 = 동시에 흐릿한 글자 수(타자기처럼 끊기지 않게 하는 꼬리). */
.xc-decl.is-stage .xc-decl__ch {
  /* +6 을 더해야 --p 가 1일 때 마지막 글자까지 완전히 불투명해진다.
     (꼬리 길이만큼 진행을 앞당겨 주지 않으면 끝 6글자가 흐린 채로 끝난다) */
  /* --tail = 동시에 흐릿한 글자 수. 클수록 파도가 완만해진다.
     +tail 을 더해야 --p 가 1일 때 마지막 글자까지 완전히 불투명해진다. */
  --tail: 9;
  --o: clamp(0, calc((var(--p, 0) * (var(--n) + var(--tail)) - var(--i)) / var(--tail)), 1);
  /* 글자를 <i> 로 감싸므로 기울임을 꺼야 한다 */
  font-style: normal;
  display: inline-block;
  opacity: var(--o);
  transform: translateY(calc((1 - var(--o)) * 8px));
  will-change: opacity, transform;
}
/* 어절을 한 덩어리로 묶어 낱글자 사이에서 줄이 끊기지 않게 한다 */
.xc-decl.is-stage .xc-decl__w { display: inline-block; white-space: nowrap; }
/* 화면에는 안 보이지만 스크린리더가 읽을 원문 */
.xc-sr-only {
  position: absolute; width: 1px; height: 1px;
  margin: -1px; padding: 0; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap; border: 0;
}
.xc-decl.is-stage .xc-decl__body p:first-child { margin-top: 0; }
/* ⚠️ 강제 색상 모드에서는 background-clip:text + 투명 글자가 통째로 사라진다.
   칠하는 효과를 포기하고 글자를 되살린다. */
@media (forced-colors: active) {
  .xc-decl.is-stage .xc-decl__ln {
    background-image: none; color: CanvasText; -webkit-text-fill-color: CanvasText;
  }
  .xc-decl.is-stage .xc-decl__ch { opacity: 1; transform: none; }
}


/* ── 연혁 ──
   mondrian.ai se03 실측 구조를 옮긴 것.
     · 좌측 구간 목록 = sticky (원본은 ScrollTrigger pin + pin-spacer. 여기서는 같은 결과를
       내는 sticky 를 쓴다. pin-spacer 가 없어 리플로우도, refreshPriority 함정도 없다)
     · 우측 상세 = transform 없음. 일반 스크롤로 올라간다
     · 활성 구간 = 39px/불투명, 비활성 = 26px/0.2 (원본 실측값) */
.xc-hist {
  display: grid;
  grid-template-columns: minmax(0, 300px) minmax(0, 1fr);
  gap: clamp(24px, 4vw, 80px);
  margin-top: clamp(28px, 3.4vw, 48px);
}

/* ── 좌측: 화면에 고정되는 구간 목록 ── */
.xc-hist__navi {
  position: sticky;
  top: calc(var(--gnb-top) + var(--gnb-row) + clamp(48px, 8vh, 110px));
  align-self: start;
}
/* 구간 이미지. 네 장을 겹쳐 두고 활성 구간만 보인다 */
.xc-hist__pic {
  position: relative; width: min(360px, 100%); aspect-ratio: 16 / 10;
  margin-bottom: clamp(24px, 3vw, 40px);
  border-radius: var(--xc-radius-lg); overflow: hidden;
  background: var(--xc-bg-soft);
}
.xc-hist__pic figure {
  position: absolute; inset: 0; margin: 0;
  opacity: 0; transition: opacity .5s var(--xc-ease-out);
}
.xc-hist__pic figure.is-on { opacity: 1; }
.xc-hist__pic img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* 사진이 아니라 로고·마크를 넣는 칸. 잘라내지 않고 여백 안에 통째로 앉힌다.
   is-logo  가로로 긴 워드마크(641x70) — 폭이 병목이라 좌우 여백을 좁게
   is-mark  정사각에 가까운 인증마크(184x127) — 원본이 작아 확대하면 흐려진다.
            여백을 넉넉히 줘 원본 크기 그대로 앉히는 편이 선명하다. */
.xc-hist__pic figure:is(.is-logo, .is-mark) { background: var(--xc-bg-soft); }
/* ⚠️ padding 의 세로 퍼센트는 '가로 폭' 기준으로 풀린다.
   22% 를 주면 360px 기준 79px 이 되어 225px 높이가 67px 로 눌리고
   contain 이 그 높이에 맞춰 마크를 절반 크기로 줄여 버렸다. px 로 고정한다.
   상자는 항상 360x225 다(좌측 열은 1025px 이상에서만 보인다). */
.xc-hist__pic figure.is-logo img { object-fit: contain; padding: 40px 30px; }
/* 마크는 원본 크기가 제각각이다(946x454, 123x84).
   ⚠️ contain 은 작은 원본을 상자에 맞춰 '확대'까지 해 흐려진다.
      크기를 auto 로 두고 최대치만 막으면 큰 것은 줄고 작은 것은 원본 그대로 남는다. */
.xc-hist__pic figure.is-mark { display: grid; place-items: center; }
.xc-hist__pic figure.is-mark img {
  width: var(--mark-w, auto); height: auto;
  max-width: calc(100% - 80px); max-height: calc(100% - 60px);
}
/* 원본이 너무 작아 제자리 크기로는 빈약해 보이는 마크만 조금 키운다.
   1.2배 정도가 원본보다 크면서 가장자리가 버티는 선이다. */
.xc-hist__pic figure.is-mark.is-up img { --mark-w: 148px; }
/* 실사진이 오기 전 자리표시. img 가 들어오면 그 위를 덮는다 */
.xc-hist__pic figure span {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  border: 1px dashed var(--xc-border-strong); border-radius: inherit;
  font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-semibold);
  color: var(--xc-text-weak); font-variant-numeric: tabular-nums;
}
.xc-hist__pic figure:has(img) span { display: none; }

.xc-hist__navi ol { display: grid; gap: clamp(6px, 0.9vw, 14px); }
.xc-hist__navi button {
  display: block; width: 100%; padding: 2px 0;
  border: 0; background: none; cursor: pointer; text-align: left;
  color: var(--xc-text); opacity: .16;
  /* 활성 항목이 커지며 아래 항목을 밀어낸다. 목록이 3~4개뿐이라 리플로우 비용은 무시할 수 있다 */
  transition: opacity .42s var(--xc-ease-out), font-size .42s var(--xc-ease-out);
  font-size: var(--xc-fs-sub-lead);
}
.xc-hist__navi button em {
  display: block; font-style: normal;
  font-weight: var(--xc-fw-extra); letter-spacing: -.03em; line-height: 1.15;
  font-variant-numeric: tabular-nums;
}
.xc-hist__navi button em i { font-style: normal; margin: 0 1px; opacity: .55; }
/* 시기 이름은 현재 구간에만 보인다. 자리는 늘 비워 두어 목록이 들썩이지 않게 한다 */
/* 비활성 항목은 이름표가 차지하던 자리까지 접는다.
   자리를 남겨 두면 연도 사이가 21px + 여백만큼 벌어져 목록이 성기게 보인다.
   높이는 em 단위라 전환이 가능하다(auto 는 애니메이션되지 않는다). */
.xc-hist__navi button small {
  display: block; margin-top: 0; height: 0; overflow: hidden;
  font-size: var(--xc-fs-hist-sub); font-weight: var(--xc-fw-semibold);
  letter-spacing: -.01em; color: var(--xc-text-weak); opacity: 0;
  transition: opacity .32s var(--xc-ease-out),
              height .32s var(--xc-ease-out),
              margin-top .32s var(--xc-ease-out);
}
.xc-hist__navi button:hover { opacity: .38; }
.xc-hist__navi button[aria-current="true"] {
  opacity: 1; font-size: var(--xc-fs-hist-on);
}
.xc-hist__navi button[aria-current="true"] small { opacity: .72; height: 1.35em; margin-top: 5px; }
.xc-hist__navi button[aria-current="true"]:hover { opacity: 1; }

/* ── 우측: 세로선 + 상세 ── */
.xc-hist__view { position: relative; padding-left: clamp(26px, 2.6vw, 44px); }
.xc-hist__flow { position: relative; }
.xc-hist__line {
  position: absolute; left: 0; top: 10px; bottom: 10px; width: 2px;
  background: var(--xc-border);
}
/* 높이는 JS 가 넣는다. 흐름 모드에서는 점이 화면 55% 선에 머문다 */
.xc-hist__fill {
  position: absolute; left: 0; top: 0; width: 2px; height: 0;
  background: var(--xc-gradient);
  /* ⚠️ 여기에 transition 을 걸지 않는다. 스크롤을 뒤에서 쫓아오는 동작은 main.js 가
     속도를 들고 계산한다(HIST_K · HIST_D). CSS 전환은 매 프레임 새 목표로 다시
     시작하는 구조라 '시작도 느리고 끝도 느린' 곡선을 만들 수 없다 — 자세한 경위는
     main.js 의 '세로선 : 스크롤을 뒤에서 쫓아온다' 주석에 있다. */
}
.xc-hist__dot {
  position: absolute; left: 1px; bottom: 0;
  width: 11px; height: 11px; margin: 0 0 -5.5px -5.5px;
  border-radius: 50%; background: var(--xc-orange);
}
/* 구간 제목. 좌측 목록이 같은 정보를 크게 들고 있으므로 넓은 화면에서는 감춘다 */
.xc-hist__era + .xc-hist__era { margin-top: clamp(44px, 5vw, 88px); }
.xc-hist__era-ttl {
  padding-bottom: 14px; margin-bottom: 6px;
  border-bottom: 1px solid var(--xc-border-strong);
  font-size: var(--xc-fs-hist-era); font-weight: var(--xc-fw-extra);
  letter-spacing: -.02em; color: var(--xc-text);
  font-variant-numeric: tabular-nums;
}
.xc-hist__era-ttl i { font-style: normal; margin: 0 2px; opacity: .5; }
.xc-hist__era-ttl span {
  margin-left: 10px; font-size: var(--xc-fs-sm); font-weight: var(--xc-fw-semibold);
  color: var(--xc-text-weak); letter-spacing: 0;
}
/* 연.월 왼쪽, 항목 오른쪽. 구분선은 세로선이 대신하므로 행 사이 괘선을 두지 않는다 */
.xc-hist__row {
  display: grid; grid-template-columns: 104px minmax(0, 1fr);
  gap: clamp(14px, 1.8vw, 28px);
  padding: clamp(12px, 1.4vw, 18px) 0;
}
/* 연.월 라벨. 날짜가 없는 항목 묶음은 연도만 들어간다 */
.xc-hist__yr {
  font-size: var(--xc-fs-body); font-weight: var(--xc-fw-extra);
  letter-spacing: -.02em; color: var(--xc-text);
  font-variant-numeric: tabular-nums; line-height: 1.7;
  white-space: nowrap;
}
.xc-hist__yr i { font-style: normal; margin: 0 1px; opacity: .45; }
/* 유효기간이 있는 항목의 종료 시점 */
.xc-hist__per {
  margin-left: 7px; font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-medium);
  color: var(--xc-text-weak); font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
/* 🔴 칸을 minmax(0, 1fr) 로 못박는다. 안 적으면 암시 칸이 auto 가 되고 그 최소값은
   **min-content** 다 — 「(대구경북지방중소벤처기업청장)_(20260225)」처럼 띄어쓰기 없는
   긴 토막이 있으면 칸이 그만큼 부푼다. 390px 에서 목록이 277px 로 서서 오른쪽이
   통째로 잘려 나갔다(실측 2026-09-01).
   ⚠️ 페이지 가로 스크롤로는 안 잡힌다. html/body 가 overflow-x:clip 이라 잘릴 뿐이다. */
.xc-hist__items { display: grid; grid-template-columns: minmax(0, 1fr); gap: 8px; }
.xc-hist__items li {
  /* 긴 항목(MOU 체결문 등)이 열 끝까지 늘어지지 않게 본문과 같은 폭으로 묶는다 */
  max-width: 72ch;
  /* ⚠️ 칸을 좁혀도 토막 자체가 안 쪼개지면 여전히 삐져나온다. 여기서 쪼개 준다 */
  overflow-wrap: anywhere;
  font-size: var(--xc-fs-body); color: var(--xc-text-sub); line-height: 1.7;
  text-wrap: pretty;
}
.xc-hist__items .mo { color: var(--xc-text-weak); font-variant-numeric: tabular-nums; }

@media (min-width: 1025px) {
  .xc-hist__era-ttl { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
  .xc-hist__era:first-child { padding-top: 4px; }
}

/* ── 고정 모드 ──
   연혁이 화면에 오면 섹션을 고정(ScrollTrigger pin)하고, 그 안에서 우측 상세만
   translateY 로 올라간다. 다 지나가면 고정이 풀리고 페이지가 다시 흐른다.
   is-stage 는 JS 가 붙인다 — GSAP 이 없거나 좁은 화면에서는 sticky 흐름 모드로 남는다.
   --hist-win(보이는 창 높이)·--hist-min(구간 최소 높이)도 JS 가 넣는다. */
/* 무대 높이 = 화면 높이(--hist-stage, JS 가 innerHeight 를 넣는다).
   dvh 를 쓰면 pin 이 잡은 높이와 어긋날 수 있어 실측값을 쓴다.
   좌측 목록과 우측 창은 무대 안에서 세로 가운데. */
/* 두 열을 반씩 나눠 세로선이 화면 가로 중앙에 오게 한다.
   본문 컨테이너가 화면 가운데 정렬이므로 1fr 1fr 의 경계 = 화면 중앙이다.
   gap 을 두면 그만큼 선이 오른쪽으로 밀리므로 0 으로 두고,
   선과 글 사이 간격은 __view 의 padding-left 가 맡는다. */
.xc-hist.is-stage {
  height: var(--hist-stage); align-items: center;
  grid-template-columns: 1fr 1fr; gap: 0;
}
/* ⚠️ align-self 를 함께 되돌려야 한다 — 흐름 모드의 sticky 규칙이 start 로 박아 두는데
   그 값이 컨테이너의 align-items: center 를 이긴다. */
.xc-hist.is-stage .xc-hist__navi {
  position: static; top: auto; padding-top: 0; align-self: center;
}
.xc-hist.is-stage .xc-hist__view {
  align-self: stretch;
  display: flex; align-items: center;
}
/* 세로선이 무대 전체(=화면 전체)를 관통한다 */
.xc-hist.is-stage .xc-hist__line { top: 0; bottom: 0; }
/* 점은 늘 보인다. 내려가지 않는 구간에서는 채움의 끝(=선의 시작점)에 멈춰 있다.
   채움 높이가 0이면 점만 선의 위끝에 얹힌 모양이 된다. */
/* 창 = 화면 전체. 흐리게 마감하지 않고 화면 끝에서 그냥 잘린다 */
.xc-hist.is-stage .xc-hist__clip {
  width: 100%; height: var(--hist-win); overflow: hidden;
}
/* 실데이터(152개 항목)가 들어와 구간마다 충분한 높이가 나온다.
   빈 화면 방지용 min-height 장치는 두지 않는다. */
.xc-hist.is-stage .xc-hist__era + .xc-hist__era { margin-top: 0; }

/* 아래에서 한 줄씩 올라온다. 판정선을 넘은 줄에 JS 가 is-in 을 붙인다.
   흐름 모드(좁은 화면·모션 최소화·GSAP 실패)에서는 이 규칙이 걸리지 않아 항상 보인다. */
.xc-hist.is-stage .xc-hist__yr,
.xc-hist.is-stage .xc-hist__items li {
  opacity: 0; transform: translateY(18px);
  transition: opacity var(--xc-dur-reveal) var(--xc-ease-out), transform var(--xc-dur-reveal) var(--xc-ease-out);
}
.xc-hist.is-stage .xc-hist__yr.is-in,
.xc-hist.is-stage .xc-hist__items li.is-in {
  opacity: 1; transform: none;
}

/* ── 수상·인증 ──
   관리자에서 노출로 표시한 항목만 쌓인다. 개수가 1개든 10개든 같은 모양이 되도록
   가로로 긴 카드 하나를 반복한다(집계 숫자를 쓰지 않는다). */
/* 카드1은 좌측에서 두 행을 통째로 쓰고, 오른쪽 네 장은 좁게/넓게 번갈아 놓인다.
     [ 1 ][ 좁 ][  넓  ]
     [ 1 ][  넓  ][ 좁 ]
   행마다 폭이 뒤바뀌므로 3열로는 표현할 수 없다.
   오른쪽 영역을 5칸으로 쪼개 2+3 / 3+2 로 배분한다.
   ⚠️ 항목이 정확히 5개일 때 성립하는 배치다. 템플릿에서 5개로 잘라 넘길 것. */
.xc-awd__list {
  display: grid;
  grid-template-columns: 3fr repeat(5, 1fr);
  grid-auto-rows: minmax(168px, auto);
  gap: 12px;
  margin-top: clamp(20px, 2.4vw, 32px);
}
.xc-awd__list > li:nth-child(1) { grid-column: 1;         grid-row: 1 / span 2; }
.xc-awd__list > li:nth-child(2) { grid-column: 2 / span 2; grid-row: 1; }
.xc-awd__list > li:nth-child(3) { grid-column: 4 / span 3; grid-row: 1; }
.xc-awd__list > li:nth-child(4) { grid-column: 2 / span 3; grid-row: 2; }
.xc-awd__list > li:nth-child(5) { grid-column: 5 / span 2; grid-row: 2; }
.xc-awd__list > li {
  position: relative;
  display: flex; flex-direction: column; gap: 14px;
  min-height: 168px;
  padding: clamp(18px, 2vw, 26px);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius-lg);
  background: var(--xc-bg);
  transition: border-color var(--xc-dur-fast) var(--xc-ease-out),
              background-color var(--xc-dur-fast) var(--xc-ease-out);
}
.xc-awd__list > li:hover { border-color: var(--xc-border); background: var(--xc-bg-soft); }
/* 태그 칩 — 메인의 .xc-two__tags li / .xc-biz__tags li 와 같은 규칙을 쓴다.
   ⚠️ 이전에는 background 가 var(--xc-bg-soft) + 외곽선이라 라이트 카드 위에서
      칩면과 카드면이 거의 같은 값이 되어(대비 1.03:1) 채움이 사라지고 테두리만 남아
      알약 버튼처럼 읽혔다. 메인은 이미 반투명 면색 + 테두리 없음으로 고쳐져 있었는데
      이 칩만 옛 규칙에 남아 있었다. */
.xc-awd__type {
  align-self: flex-start;
  padding: 5px 12px; border-radius: var(--xc-radius-full);
  border: 0;
  background: var(--xc-chip-bg);
  color: var(--xc-text-sub);
  font-size: var(--xc-fs-12); font-weight: var(--xc-fw-medium); line-height: 18px;
  white-space: nowrap;
}
.xc-awd__body { flex: 1; }
.xc-awd__name {
  font-size: var(--xc-fs-awd-ttl); font-weight: var(--xc-fw-bold);
  color: var(--xc-text); letter-spacing: -.02em; line-height: 1.4;
  text-wrap: pretty;
}
.xc-awd__meta {
  margin-top: 5px; font-size: var(--xc-fs-xs); color: var(--xc-text-weak);
  font-variant-numeric: tabular-nums;
}
.xc-awd__yr {
  align-self: flex-end;
  font-size: var(--xc-fs-awd-yr); font-weight: var(--xc-fw-extra);
  letter-spacing: -.02em; color: var(--xc-text); font-variant-numeric: tabular-nums;
}
/* 실데이터가 들어오기 전 자리표시. DB 연결 시 이 표시가 붙은 항목을 지운다 */
.xc-awd__sample {
  position: absolute; top: 10px; right: 12px;
  font-size: var(--xc-fs-12); font-weight: var(--xc-fw-bold); letter-spacing: .08em;
  color: var(--xc-text-weak); opacity: .7;
}

/* ── 수상·인증 전체 목록 (company-awards.html) ──
   회사소개의 요약 카드(.xc-awd)와 달리 개수가 수십 건이다.
   분류 필터 + 3열 그리드 + 더보기. 이미지는 쓰지 않는다(원본 스캔을 싣지 않는다).

   ⚠️ .xc-cert__tabs / .xc-cert__tab / .xc-cert__more 는 **분류 필터 공용 부품**이다.
      레퍼런스(business-references.html)도 같은 것을 쓴다. 이름만 수상·인증에서 왔다.
      고칠 때 두 화면을 함께 볼 것. */
.xc-cert__tabs {
  display: flex; flex-wrap: wrap; gap: 8px;
  margin-top: clamp(20px, 2.4vw, 32px);
}
.xc-cert__tab {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 10px 18px; border-radius: var(--xc-radius-full);
  border: 1px solid var(--xc-border); background: var(--xc-bg);
  font-size: var(--xc-fs-sm); font-weight: var(--xc-fw-semibold);
  color: var(--xc-text-sub); white-space: nowrap; cursor: pointer;
  transition: color var(--xc-dur-fast) var(--xc-ease-out),
              border-color var(--xc-dur-fast) var(--xc-ease-out),
              background-color var(--xc-dur-fast) var(--xc-ease-out);
}
.xc-cert__tab i {
  font-style: normal; font-size: var(--xc-fs-12); font-weight: var(--xc-fw-bold);
  color: var(--xc-text-weak); font-variant-numeric: tabular-nums;
}
.xc-cert__tab:hover { color: var(--xc-text); border-color: var(--xc-border-strong); }
/* 선택 상태. ⚠️ 색만으로 구분하지 않는다 — 면을 채워 명도까지 바꾼다 */
.xc-cert__tab.is-on {
  background: var(--xc-text); border-color: var(--xc-text); color: var(--xc-bg);
}
.xc-cert__tab.is-on i { color: var(--xc-bg); opacity: .7; }

.xc-cert__list {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px;
  margin-top: clamp(18px, 2vw, 26px);
}
/* 더보기 전에는 숨는다. display:none 이라 탭 순서에서도 빠진다 */
.xc-cert__item[hidden] { display: none; }
/* 카드 전체가 버튼이다. li 는 껍데기만 맡는다 —
   ⚠️ 링크가 아니라 버튼이어야 한다. 이동이 아니라 같은 자리에서 대화상자를 연다. */
.xc-cert__open {
  width: 100%; height: 100%; text-align: left; cursor: pointer;
  display: flex; flex-direction: column; gap: 12px;
  min-height: 232px;
  padding: clamp(22px, 2.2vw, 30px);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius-lg);
  background: var(--xc-bg);
  transition: border-color var(--xc-dur-fast) var(--xc-ease-out),
              background-color var(--xc-dur-fast) var(--xc-ease-out),
              color var(--xc-dur-fast) var(--xc-ease-out);
}
/* 호버하면 카드가 네이비로 채워지고 글자 세 줄이 함께 흰색으로 뒤집힌다.

   ⚠️ 예전에는 포인트 오렌지로 채웠다. 흰색 대 #fc6500 이 2.98:1 이라 본문 기준
      4.5:1 에 못 미쳤고, 「변화가 보이는 쪽」을 택해 알고도 쓰던 값이었다.
      네이비로 바꾸면서 그 빚이 없어졌다 — 흰 글자 대 #161D29 는 16.9:1 이다.
   ⚠️ 분류 라벨(.xc-cert__type)은 기본 상태에서 오렌지다. 호버하면 흰색으로 뒤집혀
      네이비 위에서 읽힌다. 오렌지인 채로 두면 네이비 위 5.64:1 로 떨어진다. */
.xc-cert__open:is(:hover, :focus-visible) {
  background: var(--xc-navy); border-color: var(--xc-navy);
}
.xc-cert__open:is(:hover, :focus-visible)
  :is(.xc-cert__type, .xc-cert__name, .xc-cert__org) { color: var(--xc-white); }
/* 분류 라벨. 참고한 레퍼런스는 파란 글자만 썼는데, 우리 포인트색은 라이트 배경에서
   대비가 모자란다(#fc6500 = 2.9:1). 진한 쪽 토큰을 쓴다 */
.xc-cert__type {
  align-self: flex-start;
  font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-bold);
  letter-spacing: .02em; color: var(--xc-orange);
  transition: color var(--xc-dur-fast) var(--xc-ease-out);
}
/* ⚠️ 세 줄 모두 색 트랜지션이 있어야 한다. 배경만 0.18s 로 번지고 글자가 즉시 바뀌면
   따로 노는 것으로 보인다. 시간·이징을 배경과 같은 값으로 맞춘다. */
/* 카드 안에서 가장 먼저 읽혀야 하는 줄이다. 블록 제목 토큰(20~28)을 쓴다.
   ⚠️ 더 키우면 최장 제목이 3줄을 넘어 카드 높이(min 232px)를 밀어낸다.
      그리드 행은 가장 높은 카드에 맞춰 늘어나므로 한 장이 넘치면 그 줄 전체가 커진다. */
.xc-cert__name {
  flex: 1;
  font-size: var(--xc-fs-h3); font-weight: var(--xc-fw-bold);
  line-height: 1.5; letter-spacing: -.01em;
  color: var(--xc-text); text-wrap: pretty;
  transition: color var(--xc-dur-fast) var(--xc-ease-out);
}
.xc-cert__org {
  font-size: var(--xc-fs-xs); color: var(--xc-text-weak);
  overflow-wrap: anywhere; font-variant-numeric: tabular-nums;
  transition: color var(--xc-dur-fast) var(--xc-ease-out);
}
.xc-awd__more { display: flex; margin-top: clamp(20px, 2.4vw, 30px); }
.xc-cert__more { display: flex; justify-content: center; margin-top: clamp(24px, 3vw, 40px); }
.xc-cert__more[hidden] { display: none; }

/* ── 원본 보기 (라이트박스) ──
   인증서·상장 원본을 큰 화면으로 띄운다. 오버레이는 페이지에 하나만 두고 돌려 쓴다. */
.xc-lb {
  position: fixed; inset: 0; z-index: var(--xc-z-overlay);
  display: grid; place-items: center;
  padding: clamp(16px, 3vw, 48px);
  background: rgba(13, 17, 25, .82);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  opacity: 0;
  transition: opacity var(--xc-dur-base) var(--xc-ease-standard);
}
/* ⚠️ hidden 을 display:none 으로 두면 트랜지션이 안 걸린다.
      대신 열림 직후 클래스를 붙여 페이드한다(JS 가 다음 프레임에 붙인다). */
.xc-lb[hidden] { display: none; }
.xc-lb.is-open { opacity: 1; }

.xc-lb__panel {
  position: relative;
  width: min(100%, 1100px); max-height: 100%;
  display: flex; flex-direction: column;
}
.xc-lb__fig {
  display: flex; flex-direction: column; gap: 18px;
  min-height: 0;                       /* 자식 이미지가 줄어들 수 있게 */
  transform: translateY(10px) scale(.985);
  transition: transform var(--xc-dur-base) var(--xc-ease-out);
}
.xc-lb.is-open .xc-lb__fig { transform: none; }
/* 인증서는 세로가 길다. 화면 높이에 맞춰 줄이고, 남는 폭은 비워 둔다 */
.xc-lb__imgbox {
  display: grid; place-items: center; min-height: 0;
  border-radius: var(--xc-radius); overflow: hidden;
  background: #fff;
}
.xc-lb__imgbox img {
  display: block; max-width: 100%; max-height: min(66vh, 720px);
  width: auto; height: auto; object-fit: contain;
}
.xc-lb__cap { flex: none; text-align: center; color: #fff; }
.xc-lb__type {
  font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-bold);
  letter-spacing: .06em; color: var(--xc-orange);
}
.xc-lb__name {
  margin-top: 8px;
  font-size: var(--xc-fs-lb-name); font-weight: var(--xc-fw-extra);
  letter-spacing: -.02em; text-wrap: balance;
}
.xc-lb__org {
  margin-top: 6px; font-size: var(--xc-fs-sm);
  color: rgba(255, 255, 255, .72); font-variant-numeric: tabular-nums;
}
.xc-lb__idx {
  margin-top: 10px; font-size: var(--xc-fs-xs);
  color: rgba(255, 255, 255, .5); font-variant-numeric: tabular-nums;
}

/* 닫기 버튼은 전체메뉴(사이트맵)의 것과 같은 자리·같은 모양을 쓴다.
   ⚠️ 패널 기준(absolute)이 아니라 **화면 기준(fixed)** 이어야 위치가 같아진다 —
      사이트맵 버튼은 오버레이 안쪽 여백(--sm-pad-*)에 붙어 있고, 그 값은 :root 에 있다.
      패널에 매달면 인증서 크기에 따라 버튼이 위아래로 움직인다. */
.xc-lb__close {
  position: fixed; z-index: 3;
  top: var(--sm-pad-y); right: var(--sm-pad-x);
  width: 40px; height: 40px; padding: 0; border: 0; background: none;
  color: #fff; cursor: pointer;
  transition: transform var(--xc-dur-base) var(--gnb-ease),
              color var(--xc-dur-base) var(--gnb-ease);
}
.xc-lb__close:is(:hover, :focus-visible) { transform: rotate(90deg); color: var(--xc-orange); }
.xc-lb__close svg { width: 100%; height: 100%; display: block; fill: none; }

.xc-lb__nav {
  position: absolute; z-index: 2;
  display: grid; place-items: center;
  width: 46px; height: 46px; border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, .28);
  background: rgba(255, 255, 255, .08); color: #fff; cursor: pointer;
  transition: background-color var(--xc-dur-fast) var(--xc-ease-out),
              border-color var(--xc-dur-fast) var(--xc-ease-out);
}
.xc-lb__nav:is(:hover, :focus-visible) {
  background: var(--xc-orange); border-color: var(--xc-orange); color: var(--xc-navy);
}
.xc-lb__nav { top: calc(50% - 23px); }
.xc-lb__nav--prev { left: clamp(-64px, -4vw, -12px); }
.xc-lb__nav--next { right: clamp(-64px, -4vw, -12px); }
.xc-lb__nav[disabled] { opacity: .3; cursor: default; }

@media (max-width: 1024px) {
  /* 화살표를 패널 안으로 들인다. 밖에 둘 여백이 없다.
     ⚠️ 인증서 이미지 배경이 흰색이라 반투명 흰 버튼이 그 위에서 사라진다.
        겹치는 순간부터는 어두운 면으로 바꿔야 보인다. */
  .xc-lb__nav--prev { left: 8px; }
  .xc-lb__nav--next { right: 8px; }
  .xc-lb__nav {
    background: rgba(13, 17, 25, .74); border-color: rgba(255, 255, 255, .34);
    -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px);
  }
  /* 좁은 화면에서는 --sm-pad-x(80px)가 과하다. 사이트맵도 같은 폭에서 여백을 줄인다 */
  .xc-lb__close { right: clamp(16px, 4vw, 40px); }
}
@media (prefers-reduced-motion: reduce) {
  .xc-lb, .xc-lb__fig { transition: none; }
  .xc-lb__fig { transform: none; }
}

@media (max-width: 1024px) {
  /* 좌측을 고정해 둘 가로 여유가 없다. 목록을 접고 흐름 안의 구간 제목으로 읽힌다 */
  .xc-hist { grid-template-columns: 1fr; gap: 0; }
  .xc-hist__navi { display: none; }
  /* 좁은 화면에서는 좌우 지그재그를 풀고 첫 장만 전체 폭으로 둔다 */
  .xc-fact__nums { grid-template-columns: repeat(2, 1fr); }
  .xc-fact__nums > li,
  .xc-fact__nums > li:nth-child(4),
  .xc-fact__nums > li:nth-child(5) { grid-column: auto; }
  .xc-awd__list { grid-template-columns: repeat(2, 1fr); grid-auto-rows: auto; }
  .xc-awd__list > li:nth-child(1) { grid-column: 1 / -1; grid-row: auto; }
  .xc-awd__list > li:nth-child(2),
  .xc-awd__list > li:nth-child(3),
  .xc-awd__list > li:nth-child(4),
  .xc-awd__list > li:nth-child(5) { grid-column: auto; grid-row: auto; }
  .xc-cert__list { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 640px) {
  .xc-hist__flow { padding-left: 20px; }
  .xc-hist__row { grid-template-columns: 62px minmax(0, 1fr); gap: 12px; }
  .xc-awd__list { grid-template-columns: 1fr; }
  .xc-awd__list > li:nth-child(1) { grid-column: auto; }
  .xc-awd__list > li { min-height: 0; }
  .xc-cert__list { grid-template-columns: 1fr; }
  .xc-cert__item { min-height: 0; }
  /* 가로 스크롤 대신 줄바꿈. 탭이 6개라 한 줄에 안 들어간다 */
  .xc-cert__tab { padding: 9px 14px; }
}


/* ══════════════════ 찾아오시는 길 ══════════════════
   사업장 한 곳 = 지도(좌) + 정보(우) 한 행.
   지도는 기존 홈페이지가 쓰던 카카오맵 '지도 퍼가기'(roughmap)를 그대로 옮겼다.
   등록 key 가 같으므로 핀 위치도 기존과 같다.
   ────────────────────────────────────────── */
.xc-loc { margin-top: clamp(28px, 3.4vw, 48px); display: grid; gap: clamp(40px, 5vw, 72px); }
.xc-loc > li {
  display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
  gap: clamp(24px, 3vw, 48px);
  /* #office-hq 처럼 id 로 바로 들어올 때 GNB 아래에서 멈춘다 */
  scroll-margin-top: calc(var(--gnb-top) + var(--gnb-row) + 24px);
}

/* ── 지도 상자 ──
   ⚠️ roughmap 이 넣는 마크업은 자기 폭을 갖는다. 상자로 가두지 않으면 좁은 화면에서
      페이지가 좌우로 밀린다(가로 스크롤 금지). overflow 로 잘라 두고 폭은 100% 로 덮는다. */
.xc-loc__map {
  position: relative; overflow: hidden;
  min-height: 260px;
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius-lg);
  background: var(--xc-gray-100);
}
.xc-loc__map .root_daum_roughmap { position: relative; z-index: 1; width: 100% !important; }
/* 지도를 못 불러왔을 때만 읽힌다. 지도가 뜨면 그 아래에 깔려 가려진다 */
.xc-loc__fb {
  position: absolute; inset: 0; display: grid; place-content: center;
  padding: 24px; text-align: center;
  font-size: var(--xc-fs-sm); color: var(--xc-text-weak);
}

/* ── 정보 열 ── */
.xc-loc__info { display: flex; flex-direction: column; }
.xc-loc__name {
  margin-top: 6px;
  font-size: var(--xc-fs-loc-name); font-weight: var(--xc-fw-extra);
  letter-spacing: var(--xc-ls-heading); color: var(--xc-text);
}
/* 라벨·값 표. 채용안내의 .xc-wel__list 와 같은 리듬을 쓴다 */
.xc-loc__list { margin-top: clamp(18px, 2vw, 26px); }
.xc-loc__list > div {
  display: grid; grid-template-columns: minmax(0, 84px) minmax(0, 1fr);
  gap: clamp(10px, 1.2vw, 20px);
  padding: 14px 0; border-top: 1px solid var(--xc-border-weak);
}
.xc-loc__list > div:first-child { border-top: 0; padding-top: 0; }
.xc-loc__list dt {
  font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-bold);
  letter-spacing: .08em; color: var(--xc-text-weak);
}
.xc-loc__list dd {
  font-size: var(--xc-fs-sm); color: var(--xc-text-sub);
  line-height: 1.7; text-wrap: pretty;
}
.xc-loc__list dd a { color: inherit; text-decoration: underline; text-underline-offset: 3px; }
/* 우편번호는 주소보다 한 단계 내린다 */
.xc-loc__list .zip { color: var(--xc-text-weak); margin-right: 6px; }
/* 알약 버튼은 정보 열 바닥에 붙인다 — 지도 아래선과 눈높이가 맞는다 */
.xc-loc__acts { margin-top: auto; padding-top: clamp(20px, 2.4vw, 32px); }

/* ── 방문 전 문의 ── */
.xc-loc-help {
  margin-top: clamp(24px, 3vw, 40px);
  padding: clamp(24px, 2.6vw, 36px);
  background: var(--xc-gray-50);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius-lg);
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  gap: clamp(20px, 2.4vw, 40px); align-items: center;
}
.xc-loc-help__info { display: flex; flex-wrap: wrap; gap: 12px clamp(24px, 3vw, 48px); }
.xc-loc-help__info > div { display: flex; align-items: baseline; gap: 12px; }
.xc-loc-help__info dt {
  font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-bold);
  letter-spacing: .08em; color: var(--xc-text-weak); white-space: nowrap;
}
.xc-loc-help__info dd { font-size: var(--xc-fs-sm); color: var(--xc-text); }
.xc-loc-help__info dd a { color: inherit; text-decoration: underline; text-underline-offset: 3px; }
.xc-loc-help__acts { display: flex; flex-wrap: wrap; gap: 10px; }

@media (max-width: 1024px) {
  /* 지도와 정보를 세로로. 지도가 먼저 온다 */
  .xc-loc > li { grid-template-columns: 1fr; }
  .xc-loc-help { grid-template-columns: 1fr; align-items: start; }
}
@media (max-width: 640px) {
  .xc-loc__list > div { grid-template-columns: 1fr; gap: 4px; }
  .xc-loc-help__info > div { flex-direction: column; gap: 2px; }
}


/* ══════════════════ 고객지원체계 ══════════════════
   좌측 제목이 스크롤을 따라 붙어 있고(sticky), 우측 9단계가 세로로 지나간다.

   ⚠️ 고정(pin)·가로 이동을 쓰지 않는다. sticky 는 브라우저가 처리해 스크롤과 어긋나지
      않고, 좁은 화면에서는 저절로 풀린다. 세로 목록이라 9칸에 모두 닿는다.
   ⚠️ 주체(고객/컴퓨터메이트)는 카드가 어느 줄에 있느냐가 아니라 data-who 로 나타낸다.
      세로 배치에서는 줄로 구분할 수 없다.
   ────────────────────────────────────────── */
.xc-proc {
  /* ⚠️ 위쪽 여백을 두지 않는다. 이 섹션은 .xc-sub 안의 첫 요소라 .xc-sub 의 위 여백이
     이미 히어로와의 간격을 만든다. 여기 또 주면 다른 화면(자료실·문의·레퍼런스)의
     두 배가 된다 — 옛 구조에서는 .xc-sub 바깥이라 자기 여백이 필요했다.
     아래쪽은 다음 섹션(고객지원시스템 접속)과의 간격이라 남긴다 */
  /* ⚠️ 마지막 단계 아래로 세로선이 끝나는 지점이 시각적 바닥이라 여백이 실제보다
     좁아 보인다. 다음 섹션과 붙지 않도록 기본값보다 넉넉히 준다 */
  padding-bottom: clamp(104px, 13vw, 208px);
  /* 주체 색. 면(선·원 채움)과 글자를 따로 둔다.
     ⚠️ 포인트 오렌지 #fc6500 은 면으로는 쓰지만 글자로는 못 쓴다 —
        흰 배경 3.0:1, 흰 글자 3.0:1 로 어느 쪽도 4.5 를 못 넘긴다.
        면은 --proc-*, 글자는 --proc-*-ink 로 갈라 둔 이유다.
     ⚠️ 채운 오렌지 원 위 숫자는 흰색이 아니라 네이비다(5.64:1). 흰색이면 3.0:1 이다. */
  --proc-cust: var(--xc-navy);              /* 고객 · 면 */
  --proc-mate: var(--xc-accent);            /* 컴퓨터메이트 · 면 (#fc6500) */
  --proc-cust-ink: var(--xc-navy);          /* 흰 배경 위 글자 · 16.91:1 */
  --proc-mate-ink: var(--xc-orange);   /* 흰 배경 위 글자 · 4.98:1 */
  --proc-dot: clamp(44px, 4.4vw, 58px);   /* 번호 원 지름 */
  --proc-line: 2px;                       /* 세로선 굵기 */
}
/* ⚠️ 좌측 폭은 온라인문의(.xc-inq)와 같은 36% 다. 같은 구조(좌측 제목 + 우측 본문)를
   쓰는 화면끼리 비율이 다르면 화면을 옮길 때마다 기둥이 들쭉날쭉해 보인다.
   px 고정(340)으로 두면 넓은 화면에서 좌측만 좁아지고 우측이 붙어 보인다 */
/* 좌측 제목 기둥 + 우측 지그재그. 폭 비율은 온라인문의(.xc-inq)와 같은 36% 다 */
.xc-proc__grid {
  display: grid; grid-template-columns: minmax(0, 36%) minmax(0, 1fr);
  gap: clamp(32px, 5vw, 96px); align-items: start;
}
.xc-proc__side {
  position: sticky; top: calc(var(--gnb-top) + var(--gnb-row) + clamp(24px, 4vh, 56px));
}
.xc-proc__side .xc-lead { margin-top: clamp(16px, 1.8vw, 24px); }
/* 범례 — 좌측 기둥 본문 아래. 우측 지그재그의 좌우가 무엇인지 알려 준다 */
.xc-proc__legend {
  margin-top: clamp(24px, 2.8vw, 36px);
  padding-top: clamp(18px, 2vw, 26px);
  border-top: 1px solid var(--xc-border-weak);
  display: grid; gap: 10px; justify-items: start;
}
.xc-proc__legend li {
  display: flex; align-items: center; gap: 10px;
  font-size: var(--xc-fs-sm); font-weight: var(--xc-fw-semibold); color: var(--xc-text-sub);
}
.xc-proc__legend i { width: 10px; height: 10px; border-radius: 50%; background: var(--c); }
/* 고객지원시스템 바로가기 — 범례 바로 아래(2026-09-18 사용자 지시).
   ⚠️ 좌측 기둥이 sticky 라 오른쪽 아홉 단계를 읽는 내내 버튼이 따라온다.
      원래는 페이지 맨 아래 「접속」 구역에 있어 끝까지 내려야 보였다. */
.xc-proc__cta { margin-top: clamp(20px, 2.4vw, 28px); }

/* 지그재그 타임라인 — 가운데 세로선, 고객은 왼쪽 / 컴퓨터메이트는 오른쪽.
   ⚠️ 자리는 data-who 가 정한다. 마크업은 01~09 순서 그대로다 */
.xc-proc__list { position: relative; display: grid; }
.xc-proc__step {
  /* ⚠️ z-index 를 명시한다. 선(.xc-proc__list::after)은 목록의 마지막 자식이라
     같은 층에서는 칸보다 나중에 칠해져 번호 원 위로 지나간다. 칸을 한 층 올려
     원이 선을 가리게 한다 — 원의 배경이 불투명(--xc-bg)이라 그 자리에서 선이 끊긴다 */
  position: relative; z-index: 1;
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--proc-dot) minmax(0, 1fr);
  /* ⚠️ baseline 을 쓰면 안 된다. 번호 원은 안쪽을 가운데 정렬한 격자라 자체 기준선이
     없고, 그럴 때 브라우저는 상자 '아래변' 을 기준선으로 삼는다 — 글이 원 아래로 내려간다.
     윗변을 맞추고, 제목 줄의 한가운데가 원의 한가운데에 오도록 아래에서 계산해 내린다 */
  align-items: start; gap: clamp(16px, 2vw, 36px);
  padding-block: clamp(16px, 2vw, 26px);
  --c: var(--proc-cust); --c-ink: var(--proc-cust-ink);
}
.xc-proc__step[data-who="mate"] { --c: var(--proc-mate); --c-ink: var(--proc-mate-ink); }
/* 번호는 언제나 가운데 칸. 세로선이 그 한가운데를 지난다.
   ⚠️ grid-row 를 반드시 적는다. 마크업은 번호 → 본문 순인데 고객 단계의 본문은 1열이다.
      격자 자동 배치는 앞으로만 채우므로, 2열까지 간 뒤 1열로 돌아가지 못하고 본문을
      다음 줄로 밀어낸다 — 제목이 원보다 한 줄 아래에 놓인다.
      (컴퓨터메이트는 본문이 3열이라 앞으로 가는 방향이어서 멀쩡했다) */
.xc-proc__no {
  grid-column: 2; grid-row: 1; position: relative; z-index: 1;
  display: grid; place-items: center;
  width: var(--proc-dot); aspect-ratio: 1; border-radius: 50%;
  background: var(--xc-bg); border: 1px solid var(--c); color: var(--c-ink);
  font-size: var(--xc-fs-sm); font-weight: var(--xc-fw-extra);
  font-variant-numeric: tabular-nums;
  transition: background-color var(--xc-dur-base) var(--xc-ease-standard),
              color var(--xc-dur-base) var(--xc-ease-standard);
}
/* 지나온 단계는 원이 제 색으로 찬다 */
.xc-proc__step.is-on .xc-proc__no,
.no-gsap .xc-proc__step .xc-proc__no { background: var(--c); color: var(--xc-white); }

/* ── 채워지는 순간의 파문 ──
   원이 켜질 때 같은 색의 연한 원이 한 번 커지면서 사라진다. 선이 어디까지 내려왔는지가
   9칸 중 한 칸에서만 일어나는 사건이라, 그 순간을 눈이 따라가게 만드는 장치다.
   ⚠️ 자리는 absolute 로 잡는다. .xc-proc__no 가 grid + place-items:center 라 흐름에
      두면 파문이 grid 아이템이 되어 숫자를 밀어낸다.
   ⚠️ z-index:-1 이어야 한다. 위치 지정 요소는 흐름 속 글자보다 위에 그려지므로 그냥
      두면 파문이 번호를 덮는다. 음수면 원의 배경 위·숫자 아래에 정확히 놓인다
      (.xc-proc__no 가 position:relative + z-index:1 이라 이 음수는 원 밖으로 못 나간다).
   ⚠️ transition 이 아니라 animation 이다. 켜진 상태를 유지하는 게 아니라 한 번 치고
      끝나야 한다. is-on 은 스크롤을 되감으면 떨어졌다 다시 붙으므로 그때 다시 친다.
   ⚠️ 원 밖으로 나가야 하므로 .xc-proc__no 에 overflow 를 걸지 말 것. */
.xc-proc__no::after {
  content: ""; position: absolute; inset: 0; z-index: -1;
  border-radius: 50%; background: var(--c);
  opacity: 0; pointer-events: none;
}
.xc-proc__step.is-on .xc-proc__no::after {
  animation: xc-proc-pulse var(--xc-dur-pulse) var(--xc-ease-out) forwards;
}
/* 감속 곡선이 파문의 성격과 맞는다 — 처음에 확 번지고 가장자리에서 잦아든다 */
@keyframes xc-proc-pulse {
  from { opacity: .28; transform: scale(1); }
  to   { opacity: 0;   transform: scale(1.8); }
}
/* ⚠️ 채운 오렌지 원 위 흰 숫자는 3.0:1 이다(기준 4.5). 크고 굵은 두 글자라 읽히지만
   대비 기준에는 못 미친다 — 디자인 결정으로 흰색을 쓴다. 네이비로 되돌리면 5.64:1 이다 */
.xc-proc__step[data-who="cust"] .xc-proc__body { grid-column: 1; grid-row: 1; text-align: right; }
.xc-proc__step[data-who="mate"] .xc-proc__body { grid-column: 3; grid-row: 1; }
/* 세로선은 칸이 아니라 목록 하나에 그린다.
   ⚠️ 칸마다 그리면 안 된다. 칸이 페이드인업으로 26px 아래에서 투명하게 시작하는데
      선이 그 칸에 얹혀 있으면 아직 안 올라온 구간만 비어 끊겨 보인다.
      목록에 그리면 칸이 어떻게 움직이든 선은 온전하다.
   ⚠️ 대신 단계별 색을 CSS 만으로는 낼 수 없다. main.js 가 칸 경계를 재서
      하드 스톱 그라디언트(--proc-grad)를 만들어 넣는다. 파랑·보라 구간이 그대로 유지된다.
   ⚠️ 선의 시작·끝(--line-top/--line-h)도 JS 가 첫·마지막 번호 원의 한가운데로 잡는다 */
.xc-proc__list::before,
.xc-proc__list::after {
  content: ""; position: absolute; z-index: 0;
  left: 50%; translate: -50% 0;
  top: var(--line-top, 0px); height: var(--line-h, 0px);
  width: var(--proc-line, 3px); border-radius: 999px;
}
.xc-proc__list::before { background: var(--xc-border); }
.xc-proc__list::after {
  background: var(--proc-grad, var(--xc-border));
  /* ⚠️ scaleY 로 늘이면 안 된다. 변형은 '그려진 내용을 눌러 담는' 것이라 채움이 30% 일 때
     8구간 그라디언트 전체가 30% 높이 안으로 압축된다 — 파랑 구간에 보라가 끌려 들어온다.
     clip-path 는 자리를 그대로 두고 보이는 만큼만 잘라 낸다 */
  clip-path: inset(0 0 calc((1 - var(--fill, 0)) * 100%) 0);
}

/* ⚠️ :first-child 로는 못 지운다 — 주체 칩이 display:none 이어도 여전히 첫 자식이라
   제목은 둘째 자식으로 남는다. 제목의 윗여백은 아예 0 으로 두고,
   칩이 실제로 보이는 좁은 화면에서만 아래 미디어쿼리가 되살린다 */
/* 제목 줄의 한가운데를 번호 원의 한가운데에 맞춘다.
   내리는 값 = (원 지름 - 제목 줄 높이) / 2. 둘 다 clamp 라 화면 폭이 변해도 함께 따라간다.
   ⚠️ 제목의 line-height 를 여기 계수(1.35)와 반드시 같게 둘 것 */
.xc-proc__body { padding-top: calc((var(--proc-dot) - 1.35 * var(--xc-fs-awd-ttl)) / 2); }
/* ⚠️ 넓은 화면에서는 자리(왼쪽/오른쪽)가 곧 주체다. 칩까지 두면 같은 말을 두 번 한다.
   좁은 화면에서 지그재그가 풀리면 아래 미디어쿼리가 다시 보여 준다 */
.xc-proc__who {
  display: none; padding: 3px 10px; border-radius: var(--xc-radius-full);
  background: color-mix(in srgb, var(--c) 10%, transparent);
  font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-semibold); color: var(--c-ink);
}
.xc-proc__ttl {
  margin-top: 0;
  font-size: var(--xc-fs-awd-ttl); line-height: 1.35; font-weight: var(--xc-fw-bold);
  /* 원과 높이를 맞추는 계산이 .xc-proc__body 에 있다. 여기에 윗여백을 두면 그만큼 밀린다 */
  letter-spacing: var(--xc-ls-heading); color: var(--xc-text); text-wrap: pretty;
}
.xc-proc__desc {
  margin-top: 8px;
  font-size: var(--xc-fs-sm); color: var(--xc-text-sub); line-height: 1.7; text-wrap: pretty;
}
/* 자동 통보 — 시스템이 알아서 하는 일이라 한 단계 낮춰 보인다 */
.xc-proc__sms {
  margin-top: 12px; display: inline-flex; align-items: center; gap: 8px;
  padding: 6px 14px; border-radius: var(--xc-radius-full);
  background: var(--xc-gray-50); border: 1px solid var(--xc-border-weak);
  font-size: var(--xc-fs-xs); color: var(--xc-text-sub);
}
.xc-proc__sms::before {
  content: ""; width: 5px; height: 5px; border-radius: 50%; background: var(--xc-text-weak);
}

@media (max-width: 1024px) {
  /* 제목이 위로 올라가고 목록이 그 아래로 흐른다 */
}


/* ── 고객지원시스템 접속 ── */
.xc-proc-cs {
  margin-top: clamp(24px, 3vw, 40px);
  padding: clamp(24px, 2.6vw, 36px);
  background: var(--xc-gray-50);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius-lg);
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  gap: clamp(20px, 2.4vw, 40px); align-items: center;
}
.xc-proc-cs p { font-size: var(--xc-fs-sm); color: var(--xc-text-sub); line-height: 1.7; text-wrap: pretty; }
.xc-proc-cs b {
  display: block; font-size: var(--xc-fs-20); font-weight: var(--xc-fw-bold); color: var(--xc-text);
  /* 칸을 좁혀도 주소 자체가 안 쪼개지면 여전히 삐져나온다 */
  overflow-wrap: anywhere;
}

@media (max-width: 1024px) {
  /* 지그재그를 푼다. 번호가 왼쪽, 글이 오른쪽인 한 줄 목록이 된다.
     자리로 주체를 나타낼 수 없으므로 칩을 다시 보여 준다 */
  .xc-proc { padding-bottom: clamp(56px, 8vw, 96px); }
  .xc-proc__step { grid-template-columns: var(--proc-dot) minmax(0, 1fr); }
  .xc-proc__no { grid-column: 1; grid-row: 1; }
  .xc-proc__step[data-who="cust"] .xc-proc__body,
  .xc-proc__step[data-who="mate"] .xc-proc__body { grid-column: 2; grid-row: 1; text-align: left; }
  .xc-proc__list::before,
  .xc-proc__list::after { left: calc(var(--proc-dot) / 2); translate: none; }
  .xc-proc__who { display: inline-block; }
  /* 칩이 다시 보이므로 첫 줄이 제목이 아니다. 계산값 대신 작은 값으로 되돌리고
     칩과 제목 사이 여백도 되살린다 */
  .xc-proc__body { padding-top: 8px; }
  .xc-proc__who + .xc-proc__ttl { margin-top: 10px; }
  /* 제목이 위로 올라가고 목록이 그 아래로 흐른다 */
  .xc-proc__grid { grid-template-columns: 1fr; }
  .xc-proc__side { position: static; }
  .xc-proc__list { margin-top: clamp(28px, 4vw, 44px); }
  /* 🔴 맨 1fr 은 min-content 가 최소값이다. 「cs.computermate.co.kr」처럼 안 쪼개지는
     주소가 있으면 칸이 그만큼 부풀어 360 에서 21px 이 잘려 나갔다(실측) */
  .xc-proc-cs { grid-template-columns: minmax(0, 1fr); align-items: start; }
  /* 🔴 표준 알약은 white-space:nowrap 이라 좁아져도 안 줄어든다. 영문 라벨이 길어
     360 에서 336px 로 서서 잘려 나갔다(실측). 이 상자 안에서만 두 줄을 허용한다.
     ⚠️ .xc-pill 밑동을 고치지 않는다 — 전 화면 버튼이 같이 접힌다. */
  .xc-proc-cs .xc-pill { white-space: normal; text-align: center; padding-inline: 22px; }
}


/* ══════════════════ 게시판 (공용) ══════════════════
   게시판 4개(자료실 · 공지사항 · 홍보자료 · 보도자료)가 legacy 에서 스킨 하나를
   공유한다. 여기서도 껍데기(총건수·검색·페이지네이션·빈 상태)는 하나로 두고
   목록 모양만 세 가지로 가른다.

     .xc-btable   표형   자료실          첨부·링크가 제목만큼 중요하다
     .xc-brows    목록형 공지사항·보도자료 썸네일이 있을 수도, 없을 수도 있다
     .xc-bgrid    격자형 홍보자료         썸네일이 곧 콘텐츠다

   ⚠️ 썸네일을 필수로 두지 않는다. legacy 는 없으면 noimg.png 를 채워 넣는데,
      보도자료 40건이 회색 상자로 도배된다. 없으면 글이 그 폭을 쓴다.
   ⚠️ 썸네일을 오른쪽에 두는 이유 — 왼쪽에 두면 이미지 없는 행만 제목이 튀어나와
      목록의 시작선이 행마다 흔들린다.
   ────────────────────────────────────────── */

/* ── 총건수 + 검색 ── */
.xc-board__bar {
  margin-top: clamp(24px, 3vw, 40px);
  padding-bottom: clamp(14px, 1.6vw, 20px);
  border-bottom: 2px solid var(--xc-text);
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; flex-wrap: wrap;
}
.xc-board__total { font-size: var(--xc-fs-sm); color: var(--xc-text-sub); }
.xc-board__total b { font-weight: var(--xc-fw-bold); color: var(--xc-text); }
.xc-board__search {
  display: flex; align-items: center; gap: 8px;
  height: 46px; padding: 0 6px 0 18px;
  border: 1px solid var(--xc-border); border-radius: var(--xc-radius-full);
  width: min(320px, 100%);
}
.xc-board__search:focus-within { border-color: var(--xc-text); }
.xc-board__search input {
  flex: 1; min-width: 0; border: 0; background: none;
  font-size: var(--xc-fs-sm);
  /* ⚠️ align-items:center 라 입력은 글자 높이(28px)로만 선다. 알약은 46px 인데
     실제로 눌리는 자리가 28px 이라 손가락으로 맞추기 어렵다(실측). 높이를 채운다 */
  align-self: stretch;
}
.xc-board__search input:focus { outline: 0; }
.xc-board__search input::placeholder { color: var(--xc-text-weak); }
/* ⚠️ background 를 비워 두면 <button> 은 브라우저 기본 buttonface 가 남는다 */
.xc-board__search button {
  width: 34px; height: 34px; flex: none;
  border: 0; border-radius: 50%; cursor: pointer;
  background: var(--xc-text); color: var(--xc-bg);
  display: grid; place-items: center;
}
.xc-board__search button svg { width: 16px; height: 16px; }

/* 검색 결과가 없을 때도 같은 자리에 온다 */
.xc-board__empty {
  padding: clamp(56px, 10vw, 120px) 0;
  border-bottom: 1px solid var(--xc-border);
  text-align: center; font-size: var(--xc-fs-sm); color: var(--xc-text-weak);
}

/* ── ① 표형 · 자료실 ── */
.xc-btable { width: 100%; border-collapse: collapse; }
.xc-btable th {
  padding: 16px 12px;
  font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-bold); letter-spacing: .06em;
  color: var(--xc-text-weak); text-align: left;
  border-bottom: 1px solid var(--xc-border);
}
.xc-btable td { padding: 16px 12px; border-bottom: 1px solid var(--xc-border-weak); }
/* 행 전체가 클릭 영역이다 — 목록형·격자형과 같은 규칙.
   ⚠️ tr 에 position:relative 를 주는 건 표에서도 동작한다(요즘 브라우저 전부).
      이게 없으면 제목 링크의 ::after 가 행이 아니라 페이지 전체를 덮는다 */
.xc-btable tbody tr { position: relative; }
.xc-btable tbody tr:hover td { background: var(--xc-gray-50); }
.xc-btable__ttl {
  font-size: var(--xc-fs-md); font-weight: var(--xc-fw-semibold);
  color: var(--xc-text); letter-spacing: var(--xc-ls-heading);
}
.xc-btable__ttl::after { content: ""; position: absolute; inset: 0; }
.xc-btable tbody tr:hover .xc-btable__ttl { text-decoration: underline; text-underline-offset: 4px; }
.xc-btable__date {
  font-size: var(--xc-fs-sm); color: var(--xc-text-weak);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
/* 첨부·외부링크. 파일명은 노출하지 않는다 — 아이콘에 얹고 title·스크린리더로만 남긴다 */
.xc-bfile { display: flex; gap: 6px; flex-wrap: wrap; }
.xc-bfile a {
  /* 행 전체를 덮는 제목 링크 위로 올라와야 다운로드가 눌린다 */
  position: relative; z-index: 1;
  width: 34px; height: 34px; flex: none;
  border: 1px solid var(--xc-border); border-radius: 50%;
  display: grid; place-items: center; color: var(--xc-text-sub);
  transition: var(--xc-trans-fast);
}
.xc-bfile a:is(:hover, :focus-visible) { border-color: var(--xc-text); color: var(--xc-text); }
.xc-bfile svg { width: 16px; height: 16px; }
.xc-bnone { font-size: var(--xc-fs-sm); color: var(--xc-gray-300); }

/* ── ② 목록형 · 공지사항 · 보도자료 ──
   ⚠️ 링크로 항목 전체를 감싸지 않는다. 요약이 300자라 링크 이름이 통째로 300자가 되어
      스크린리더가 그걸 다 읽는다. 제목만 링크로 두고 ::after 로 항목 전체를 덮는다. */
.xc-brows > li {
  position: relative;
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  gap: clamp(20px, 3vw, 48px); align-items: center;
  padding: clamp(20px, 2.4vw, 32px) 12px;
  border-bottom: 1px solid var(--xc-border-weak);
  transition: background-color var(--xc-dur-fast) var(--xc-ease-out);
}
.xc-brows > li:hover { background: var(--xc-gray-50); }
.xc-brows__link::after { content: ""; position: absolute; inset: 0; }
.xc-brows > li:hover .xc-brows__ttl { text-decoration: underline; text-underline-offset: 4px; }
.xc-brows__badge {
  display: inline-block; margin-bottom: 10px;
  padding: 4px 10px; border-radius: var(--xc-radius-full);
  background: var(--xc-chip-bg);
  font-size: var(--xc-fs-12); font-weight: var(--xc-fw-bold); line-height: 18px;
  color: var(--xc-text);
}
.xc-brows__ttl {
  font-size: var(--xc-fs-lead); font-weight: var(--xc-fw-bold);
  letter-spacing: var(--xc-ls-heading); color: var(--xc-text); text-wrap: pretty;
}
.xc-brows__desc {
  margin-top: 8px; font-size: var(--xc-fs-sm); color: var(--xc-text-sub);
  line-height: 1.7;
  /* 요약은 두 줄까지. 원문이 300자라 안 자르면 행 높이가 제각각이 된다 */
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden;
}
.xc-brows__date {
  display: block; margin-top: 12px;
  font-size: var(--xc-fs-xs); color: var(--xc-text-weak);
  font-variant-numeric: tabular-nums;
}
.xc-brows__thumb {
  width: clamp(120px, 14vw, 200px); aspect-ratio: 16 / 11;
  border-radius: var(--xc-radius); overflow: hidden; background: var(--xc-gray-100);
}
.xc-brows__thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* ── ③ 격자형 · 홍보자료 ── */
.xc-bgrid { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(16px, 2vw, 28px); margin-top: clamp(20px, 2.4vw, 32px); }
.xc-bgrid__thumb {
  aspect-ratio: 16 / 11; border-radius: var(--xc-radius-lg);
  overflow: hidden; background: var(--xc-gray-100);
  /* 호버하면 모서리가 펴진다. 확대와 같은 시간으로 묶어 한 동작으로 읽히게 한다 */
  transition: border-radius var(--xc-dur-slow) var(--xc-ease-out);
}
.xc-bgrid > li:hover .xc-bgrid__thumb { border-radius: 0; }
.xc-bgrid > li { position: relative; }
.xc-bgrid__thumb img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform var(--xc-dur-slow) var(--xc-ease-out); }
.xc-bgrid > li:hover .xc-bgrid__thumb img { transform: scale(1.04); }
/* 목록형과 같은 이유로 제목만 링크다 (위 .xc-brows 주석 참조) */
.xc-bgrid__link::after { content: ""; position: absolute; inset: 0; }
.xc-bgrid > li:hover .xc-bgrid__ttl { text-decoration: underline; text-underline-offset: 4px; }
.xc-bgrid__ttl {
  margin-top: 16px;
  font-size: var(--xc-fs-h4); font-weight: var(--xc-fw-bold);
  letter-spacing: var(--xc-ls-heading); color: var(--xc-text); text-wrap: pretty;
}
.xc-bgrid__date { display: block; margin-top: 10px; font-size: var(--xc-fs-xs); color: var(--xc-text-weak); font-variant-numeric: tabular-nums; }

/* ── 페이지네이션 ── */
.xc-page { margin-top: clamp(32px, 4vw, 56px); display: flex; align-items: center; justify-content: center; gap: 6px; }
.xc-page a, .xc-page span {
  min-width: 40px; height: 40px; padding: 0 6px;
  display: grid; place-items: center; border-radius: var(--xc-radius-sm);
  font-size: var(--xc-fs-sm); color: var(--xc-text-sub);
  font-variant-numeric: tabular-nums;
  transition: var(--xc-trans-fast);
}
.xc-page a:hover { background: var(--xc-gray-100); color: var(--xc-text); }
/* ⚠️ 현재 쪽을 색만으로 구분하지 않는다 — 면을 채워 명도까지 바꾼다 */
.xc-page [aria-current="page"] { background: var(--xc-text); color: var(--xc-bg); font-weight: var(--xc-fw-bold); }
.xc-page .is-off { opacity: .3; pointer-events: none; }
.xc-page svg { width: 16px; height: 16px; }

/* ══════════════════ 게시글 상세 (공용) ══════════════════ */
.xc-post__head {
  padding-bottom: clamp(20px, 2.4vw, 32px);
  border-bottom: 2px solid var(--xc-text);
}
.xc-post__ttl {
  font-size: var(--xc-fs-blk-h2); font-weight: var(--xc-fw-extra);
  letter-spacing: var(--xc-ls-heading); color: var(--xc-text); text-wrap: pretty;
}
.xc-post__date { margin-top: 12px; font-size: var(--xc-fs-sm); color: var(--xc-text-weak); font-variant-numeric: tabular-nums; }

/* ── 본문 ──
   ⚠️ 여기 들어오는 HTML 은 관리자가 에디터로 쓴 것이다. 이 파일 맨 위의 리셋이
      ul 의 불릿과 p 의 여백을 지워 놨으므로, 이 스코프 안에서만 되살린다.
      안 그러면 기존 게시글 수백 건이 줄바꿈 없는 덩어리로 보인다. */
.xc-post__body {
  padding-block: clamp(32px, 4vw, 56px);
  font-size: var(--xc-fs-body); color: var(--xc-text-sub); line-height: 1.85;
}
.xc-post__body > :first-child { margin-top: 0; }
.xc-post__body p { margin-bottom: 1em; }
.xc-post__body h1, .xc-post__body h2, .xc-post__body h3,
.xc-post__body h4, .xc-post__body h5, .xc-post__body h6 {
  margin: 1.6em 0 .6em;
  font-weight: var(--xc-fw-bold); color: var(--xc-text);
  letter-spacing: var(--xc-ls-heading); line-height: var(--xc-lh-heading);
}
.xc-post__body h1 { font-size: var(--xc-fs-h3); }
.xc-post__body h2 { font-size: var(--xc-fs-h4); }
.xc-post__body h3, .xc-post__body h4, .xc-post__body h5, .xc-post__body h6 { font-size: var(--xc-fs-md); }
.xc-post__body ul { list-style: disc; padding-left: 1.4em; margin-bottom: 1em; }
.xc-post__body ol { list-style: decimal; padding-left: 1.6em; margin-bottom: 1em; }
.xc-post__body li { margin-bottom: .35em; }
.xc-post__body strong, .xc-post__body b { font-weight: var(--xc-fw-bold); color: var(--xc-text); }
.xc-post__body a { color: var(--xc-text); text-decoration: underline; text-underline-offset: 3px; }
.xc-post__body img { height: auto; border-radius: var(--xc-radius); }
.xc-post__body blockquote {
  margin: 1.4em 0; padding: 4px 0 4px 20px;
  border-left: 3px solid var(--xc-border-strong); color: var(--xc-text);
}
.xc-post__body hr { margin: 2em 0; border: 0; border-top: 1px solid var(--xc-border); }
/* 넓은 표는 페이지를 밀지 않고 자기 안에서만 가로 스크롤한다(가로 스크롤 금지 규칙).
   ⚠️ display:block 이 아니면 table 이 컨테이너를 뚫고 나간다 */
.xc-post__body table {
  display: block; width: max-content; max-width: 100%;
  overflow-x: auto; overflow-y: hidden;
  border-collapse: collapse; margin-bottom: 1em;
}
.xc-post__body th, .xc-post__body td {
  padding: 10px 14px; border: 1px solid var(--xc-border); font-size: var(--xc-fs-sm);
}
.xc-post__body th { background: var(--xc-gray-50); font-weight: var(--xc-fw-semibold); color: var(--xc-text); }

/* ── 링크 · 첨부 ── */
.xc-post__files { border-top: 1px solid var(--xc-border); }
.xc-post__files > div {
  display: grid; grid-template-columns: minmax(0, 96px) minmax(0, 1fr);
  gap: clamp(12px, 1.6vw, 24px);
  padding: 16px 0; border-bottom: 1px solid var(--xc-border-weak);
}
.xc-post__files dt {
  font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-bold);
  letter-spacing: .08em; color: var(--xc-text-weak);
}
.xc-post__files dd { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.xc-post__files a {
  font-size: var(--xc-fs-sm); color: var(--xc-text);
  text-decoration: underline; text-underline-offset: 3px;
  overflow-wrap: anywhere;
}

/* ── 이전글 · 다음글 ── */
.xc-post__nav { margin-top: clamp(32px, 4vw, 56px); border-top: 1px solid var(--xc-border); }
.xc-post__nav > li {
  display: grid; grid-template-columns: minmax(0, 96px) minmax(0, 1fr);
  gap: clamp(12px, 1.6vw, 24px);
  padding: 18px 0; border-bottom: 1px solid var(--xc-border-weak);
  align-items: baseline;
}
.xc-post__nav dt, .xc-post__nav .tit {
  font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-bold);
  letter-spacing: .08em; color: var(--xc-text-weak);
}
.xc-post__nav a { font-size: var(--xc-fs-sm); color: var(--xc-text); }
.xc-post__nav a:hover { text-decoration: underline; text-underline-offset: 3px; }
.xc-post__nav .is-none { font-size: var(--xc-fs-sm); color: var(--xc-gray-400); }
.xc-post__back { margin-top: clamp(28px, 3.4vw, 48px); display: flex; justify-content: center; }

@media (max-width: 1024px) {
  .xc-bgrid { grid-template-columns: repeat(2, 1fr); }
  /* 표를 행 단위 블록으로 바꾼다. 가로 스크롤을 만들지 않는다.
     제목이 한 줄을 다 쓰고, 링크·첨부·등록일이 그 아래 한 줄로 모인다.
     ⚠️ 같은 내용을 모바일용으로 한 벌 더 적지 않는다 — 순서만 바꿔 흘린다 */
  .xc-btable, .xc-btable tbody { display: block; width: auto; }
  .xc-btable thead, .xc-btable colgroup { display: none; }
  .xc-btable tr {
    display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px;
    padding: 18px 0; border-bottom: 1px solid var(--xc-border-weak);
  }
  .xc-btable td { display: block; padding: 0; border: 0; }
  .xc-btable td:first-child { flex: 1 0 100%; }
  .xc-btable tbody tr:hover td { background: none; }
  /* 목록형은 좁아져도 두 열을 유지한다. 세로로 쌓으면 한 항목이 화면을 다 먹어
     목록을 훑을 수가 없다. 썸네일만 줄인다 */
  .xc-brows__thumb { width: clamp(110px, 18vw, 160px); }
  .xc-post__files > div,
  .xc-post__nav > li { grid-template-columns: 1fr; gap: 6px; }
}
@media (max-width: 640px) {
  .xc-bgrid { grid-template-columns: 1fr; }
  .xc-brows > li { gap: 14px; padding-inline: 0; }
  .xc-brows__thumb { width: 96px; }
  .xc-board__search { width: 100%; }
  .xc-page a, .xc-page span { min-width: 34px; height: 34px; }
}


/* ══════════════════ 온라인문의 폼 ══════════════════
   xCalibur 데모·상담 문의도 같은 폼을 쓴다(IA §3.2 에서 Inquire 모듈로 통일 확정).
   그래서 이 컴포넌트는 이 화면 전용이 아니다.

   ⚠️ 필드 목록은 관리자(DB inquire_configs)가 정한다. 프로토타입은 값을 박아 두지만
      Blade 이식 때 반드시 $fields 루프로 되돌린다. 안 그러면 관리자에서 문의 항목을
      바꾸는 기능이 죽는다.
   ⚠️ 선택지는 <button aria-pressed> 가 아니라 진짜 라디오다. JS 없이 값이 전송되고
      화살표 키·스크린리더가 그대로 동작해야 한다.
   ────────────────────────────────────────── */
/* ── 2열 : 좌측 제목·안내 / 우측 폼 ──
   좌측은 화면에 붙어 있고 우측 폼만 흐른다. 폼이 길어서 아래로 내려가면
   무엇을 쓰는 화면인지가 사라진다.
   ⚠️ sticky 는 격자 항목이 늘어나 있으면 안 먹는다. align-items:start 가 필요하다 */
.xc-inq {
  display: grid; grid-template-columns: minmax(0, 36%) minmax(0, 1fr);
  gap: clamp(32px, 5vw, 96px); align-items: start;
}
.xc-inq__aside { position: sticky; top: calc(var(--gnb-top) + var(--gnb-row) + 32px); }
/* 서브페이지 섹션 제목이므로 36px 이다. 위쪽 '서브페이지 섹션 제목' 구역 참고 */
.xc-inq__ttl {
  margin-top: 14px;
  font-size: var(--xc-fs-blk-h2); font-weight: var(--xc-fw-extra);
  letter-spacing: var(--xc-ls-heading); line-height: var(--xc-lh-heading);
  color: var(--xc-text); text-wrap: pretty;
}
/* 리드는 전 화면이 --xc-fs-lead 하나로 간다 (.xc-lead · .xc-sol__lead 와 같은 값) */
.xc-inq__lead {
  margin-top: clamp(16px, 2vw, 24px);
  font-size: var(--xc-fs-lead); color: var(--xc-text-sub);
  line-height: 1.8; text-wrap: pretty;
}
/* 폼을 쓰기 전에 바로 연결할 방법. 좌측 아래 빈 자리를 이게 채운다 */
.xc-inq__info { margin-top: clamp(28px, 3.4vw, 48px); border-top: 1px solid var(--xc-border); }
.xc-inq__info > div {
  display: grid; grid-template-columns: minmax(0, 88px) minmax(0, 1fr); gap: 16px;
  padding: 14px 0; border-bottom: 1px solid var(--xc-border-weak);
}
.xc-inq__info dt {
  font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-bold);
  letter-spacing: .08em; color: var(--xc-text-weak);
}
.xc-inq__info dd { font-size: var(--xc-fs-sm); color: var(--xc-text); }
.xc-inq__info dd a { color: inherit; text-decoration: underline; text-underline-offset: 3px; }

@media (max-width: 1024px) {
  .xc-inq { grid-template-columns: 1fr; gap: clamp(28px, 4vw, 44px); }
  .xc-inq__aside { position: static; }
}

.xc-form fieldset { margin: 0; padding: 0; border: 0; min-width: 0; }
.xc-form legend { padding: 0; }
.xc-form__sect + .xc-form__sect { margin-top: clamp(40px, 5vw, 72px); }
.xc-form__head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 16px; flex-wrap: wrap;
  padding-bottom: clamp(12px, 1.4vw, 18px); border-bottom: 2px solid var(--xc-text);
}
.xc-form__ttl {
  font-size: var(--xc-fs-card-ttl); font-weight: var(--xc-fw-extra);
  letter-spacing: var(--xc-ls-heading); color: var(--xc-text);
}
.xc-form__note-req { font-size: var(--xc-fs-xs); color: var(--xc-text-weak); }
/* 필수 표시. 별표만으로 두지 않고 라벨에 스크린리더용 '필수'를 함께 넣는다 */
.xc-req { color: var(--xc-orange); margin-left: 3px; }

/* ── 선택지 : 알약 라디오 ── */
.xc-choice { display: flex; flex-wrap: wrap; gap: 10px; margin-top: clamp(18px, 2.2vw, 28px); }
.xc-choice__item { position: relative; display: inline-flex; }
/* 진짜 라디오를 알약 위에 투명하게 덮는다 */
.xc-choice__item input {
  position: absolute; inset: 0; width: 100%; height: 100%;
  margin: 0; opacity: 0; cursor: pointer;
}
.xc-choice__item span {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 52px; padding: 0 26px;
  border: 1px solid var(--xc-border-strong); border-radius: var(--xc-radius-full);
  background: var(--xc-bg);
  font-size: var(--xc-fs-sm); font-weight: var(--xc-fw-semibold); color: var(--xc-text);
  white-space: nowrap;
  transition: background-color var(--xc-dur-base) var(--xc-ease-standard),
              border-color var(--xc-dur-base) var(--xc-ease-standard),
              color var(--xc-dur-base) var(--xc-ease-standard);
}
.xc-choice__item:hover span { border-color: var(--xc-text); }
/* ⚠️ 선택을 색으로만 구분하지 않는다 — 면을 채워 명도까지 바꾼다 */
.xc-choice__item input:checked + span {
  background: var(--xc-text); border-color: var(--xc-text); color: var(--xc-bg);
}
.xc-choice__item input:focus-visible + span { outline: 2px solid var(--xc-focus); outline-offset: 3px; }

/* 유지보수를 고르면 펼쳐지는 안내. 막지 않고 더 빠른 창구만 알려 준다 */
.xc-form__cs {
  margin-top: 16px; padding: clamp(18px, 2vw, 26px);
  background: var(--xc-gray-50);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius-lg);
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  gap: clamp(16px, 2vw, 28px); align-items: center;
}
.xc-form__cs[hidden] { display: none; }   /* display:grid 가 hidden 을 이긴다 */
.xc-form__cs p { font-size: var(--xc-fs-sm); color: var(--xc-text-sub); line-height: 1.7; text-wrap: pretty; }

/* ── 입력 칸 ── */
.xc-form__grid {
  margin-top: clamp(18px, 2.2vw, 28px);
  display: grid; grid-template-columns: repeat(2, 1fr); gap: clamp(16px, 2vw, 28px);
}
.xc-field--full { grid-column: 1 / -1; }
.xc-field__label {
  display: block; margin-bottom: 10px;
  font-size: var(--xc-fs-sm); font-weight: var(--xc-fw-semibold); color: var(--xc-text);
}
/* 입력 칸은 테두리가 아니라 면으로 구분한다 — 회색 바탕에 선 없음.
   ⚠️ border 를 0 으로 지우지 않고 투명하게 남긴다. 포커스에서 선을 켤 때
      높이가 2px 튀지 않게 하려면 자리를 미리 잡아 둬야 한다. */
.xc-field__input, .xc-field__area {
  width: 100%; padding: 0 18px;
  border: 1px solid transparent; border-radius: var(--xc-radius);
  background: var(--xc-gray-100);
  font-size: var(--xc-fs-sm); color: var(--xc-text);
  transition: background-color var(--xc-dur-fast) var(--xc-ease-out),
              border-color var(--xc-dur-fast) var(--xc-ease-out);
}
.xc-field__input { height: 54px; }
.xc-field__area { min-height: clamp(160px, 22vh, 220px); padding: 16px 18px; line-height: 1.7; resize: vertical; }
.xc-field__input::placeholder, .xc-field__area::placeholder { color: var(--xc-text-weak); }
.xc-field__input:hover, .xc-field__area:hover { background: var(--xc-gray-200); }
.xc-field__input:focus, .xc-field__area:focus {
  outline: 0; background: var(--xc-bg); border-color: var(--xc-text);
}
/* ⚠️ 자동완성이 들어오면 브라우저가 연노랑 배경을 강제로 칠한다. 회색 면이 통째로 깨진다.
   background 로는 못 막는다 — 안쪽 그림자로 덮어야 한다 */
.xc-field__input:-webkit-autofill,
.xc-field__input:-webkit-autofill:hover,
.xc-field__input:-webkit-autofill:focus {
  -webkit-box-shadow: 0 0 0 1000px var(--xc-gray-100) inset;
  -webkit-text-fill-color: var(--xc-text);
}
.xc-field__help { margin-top: 8px; font-size: var(--xc-fs-xs); color: var(--xc-text-weak); line-height: 1.6; }

/* ── 첨부 ──
   파일 고르기는 글을 쓰는 일이 아니라 행동이다. 회색 입력 면을 입히면 빈 칸처럼 보이는데
   실제로는 칠 수가 없어서 어색하다. 사이트 표준인 원통형 버튼으로 둔다.
   ⚠️ 네이티브 파일 입력의 기본 모양은 브라우저마다 다르고 '선택된 파일 없음' 문구를
      숨길 수 없다. 그래서 입력을 눈에서 빼고 라벨을 버튼으로 세운다.
   ⚠️ display:none 으로 지우면 안 된다 — 키보드 포커스를 못 받아 탭으로 도달할 수 없다. */
.xc-file__input {
  position: absolute; width: 1px; height: 1px;
  opacity: 0; pointer-events: none;
}
.xc-file__btn {
  display: inline-flex; align-items: center; gap: 10px;
  min-height: 46px; padding: 0 22px; cursor: pointer;
  border: 1px solid var(--xc-border-strong); border-radius: var(--xc-radius-full);
  background: var(--xc-bg); color: var(--xc-text);
  font-size: var(--xc-fs-sm); font-weight: var(--xc-fw-semibold);
  transition: var(--xc-trans-fast);
}
.xc-file__btn:hover { border-color: var(--xc-text); }
.xc-file__btn svg { width: 16px; height: 16px; flex: none; }
/* 포커스 링·에러 테두리는 보이지 않는 입력 대신 버튼이 받는다 */
.xc-file__input:focus-visible ~ .xc-file__btn { outline: 2px solid var(--xc-focus); outline-offset: 3px; }
.xc-file__input[aria-invalid] ~ .xc-file__btn { border-color: var(--xc-error); }

/* ── 동의 ──
   ⚠️ 여기에 개인정보처리방침 전문을 붙이지 않는다. 처리방침은 '공개' 대상이고
      동의받을 때 고지할 것은 수집항목·목적·보유기간·거부권 네 가지다.
      기존 화면은 399줄짜리 처리방침을 폼 안에 펼쳐 두고 있었다. */
.xc-form__agree {
  margin-top: clamp(28px, 3vw, 44px); padding: clamp(20px, 2.2vw, 28px);
  border: 1px solid var(--xc-border); border-radius: var(--xc-radius-lg);
}
.xc-check { display: flex; align-items: flex-start; gap: 12px; cursor: pointer; }
.xc-check input {
  width: 20px; height: 20px; flex: none; margin: 2px 0 0;
  accent-color: var(--xc-navy); cursor: pointer;
}
.xc-check span { font-size: var(--xc-fs-sm); color: var(--xc-text); }
.xc-check em { font-style: normal; font-weight: var(--xc-fw-bold); color: var(--xc-orange); margin-right: 4px; }
/* 팝업 대신 그 자리에서 펼친다 — 새 창은 키보드·모바일에서 더 불편하다 */
.xc-terms { margin-top: 14px; }
.xc-terms summary {
  display: inline-block; cursor: pointer;
  font-size: var(--xc-fs-xs); color: var(--xc-text-sub);
  text-decoration: underline; text-underline-offset: 3px;
}
/* 구분선은 항목 사이에만. 위아래 끝선은 두지 않는다 —
   이미 .xc-form__agree 상자가 테두리를 갖고 있어 선이 겹쳐 보인다 */
.xc-terms__body { margin-top: 14px; }
.xc-terms__body > div {
  display: grid; grid-template-columns: minmax(0, 110px) minmax(0, 1fr); gap: 16px;
  padding: 12px 0; border-bottom: 1px solid var(--xc-border-weak);
}
.xc-terms__body > div:last-child { border-bottom: 0; padding-bottom: 0; }
.xc-terms__body dt {
  font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-bold);
  letter-spacing: .06em; color: var(--xc-text-weak);
}
.xc-terms__body dd { font-size: var(--xc-fs-sm); color: var(--xc-text-sub); line-height: 1.7; }

/* ── 에러 ──
   ⚠️ 브라우저 기본 말풍선을 쓰지 않는다. 한 번에 하나만 뜨고, 클릭하면 사라지고,
      스타일을 못 입힌다. 무엇보다 서버 검증으로 되돌아왔을 때 쓸 자리가 없다.
   ⚠️ 색만으로 알리지 않는다 — 문구가 함께 나오고 aria-invalid 로 보조기술에도 전달된다. */
.xc-field__error {
  margin-top: 8px;
  font-size: var(--xc-fs-xs); color: var(--xc-error-text); line-height: 1.6;
}
.xc-field__error[hidden] { display: none; }
.xc-field__input[aria-invalid], .xc-field__area[aria-invalid] {
  border-color: var(--xc-error); background: var(--xc-bg);
}
/* 선택 항목 표시. 필수가 대부분이라 별표를 다 다는 대신 선택인 것만 알린다 */
.xc-field__opt { font-weight: var(--xc-fw-medium); color: var(--xc-text-weak); }

/* ── 고른 파일 ──
   용량 초과를 서버에서 반려하면 다 쓴 폼이 날아간다. 고르는 즉시 그 자리에서 잡는다 */
.xc-file__info {
  margin-top: 10px; display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 10px 14px; border-radius: var(--xc-radius); background: var(--xc-gray-100);
}
.xc-file__info[hidden] { display: none; }
.xc-file__name { font-size: var(--xc-fs-sm); color: var(--xc-text); overflow-wrap: anywhere; }
.xc-file__del {
  margin-left: auto; padding: 5px 14px; cursor: pointer;
  border: 1px solid var(--xc-border-strong); border-radius: var(--xc-radius-full);
  background: var(--xc-bg); color: var(--xc-text-sub);
  font-size: var(--xc-fs-12); font-weight: var(--xc-fw-semibold);
  transition: var(--xc-trans-fast);
}
.xc-file__del:is(:hover, :focus-visible) { border-color: var(--xc-text); color: var(--xc-text); }

.xc-form__submit { margin-top: clamp(28px, 3.4vw, 48px); display: flex; justify-content: center; }
.xc-form__submit .xc-pill[disabled] { opacity: .5; pointer-events: none; }

/* ── 접수 완료 ──
   모달로 띄우지 않는다. 닫는 순간 방금 무엇을 했는지가 사라지고,
   뒤로가기로 돌아오면 재제출 경고가 뜬다. 폼 자리를 대체한다. */
.xc-form__done {
  margin-top: clamp(20px, 2.4vw, 32px);
  padding: clamp(40px, 6vw, 80px) clamp(24px, 3vw, 48px);
  border: 1px solid var(--xc-border); border-radius: var(--xc-radius-lg);
  background: var(--xc-gray-50); text-align: center;
}
.xc-form__done[hidden] { display: none; }
.xc-form__done-ttl {
  margin-top: 12px;
  font-size: var(--xc-fs-blk-h2); font-weight: var(--xc-fw-extra);
  letter-spacing: var(--xc-ls-heading); color: var(--xc-text);
}
/* ⚠️ eyebrow 도 <p> 다. :not 으로 빼지 않으면 이 규칙(0,1,1)이 .xc-eyebrow(0,1,0)를 덮어
   13px 라벨이 15px 로 커진다. 전 화면 eyebrow 154개 중 여기 하나만 어긋나 있었다. */
.xc-form__done p:not(.xc-eyebrow) { margin-top: 14px; font-size: var(--xc-fs-sm); color: var(--xc-text-sub); line-height: 1.8; }
.xc-form__done dl {
  margin-top: clamp(20px, 2.4vw, 32px); display: flex; justify-content: center;
  gap: 10px clamp(20px, 3vw, 40px); flex-wrap: wrap;
}
.xc-form__done dl > div { display: flex; align-items: baseline; gap: 10px; }
.xc-form__done dt { font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-bold); color: var(--xc-text-weak); letter-spacing: .06em; }
.xc-form__done dd { font-size: var(--xc-fs-sm); color: var(--xc-text); }
.xc-form__done dd a { color: inherit; text-decoration: underline; text-underline-offset: 3px; }
.xc-form__done .xc-pill { margin-top: clamp(24px, 3vw, 40px); }

@media (max-width: 1024px) {
  .xc-form__grid { grid-template-columns: 1fr; }
  .xc-form__cs { grid-template-columns: 1fr; align-items: start; }
  .xc-terms__body > div { grid-template-columns: 1fr; gap: 4px; }
}
@media (max-width: 640px) {
  .xc-choice { gap: 8px; }
  .xc-choice__item span { min-height: 46px; padding: 0 18px; }
  .xc-form__submit .xc-pill { width: 100%; }
}


/* ══════════════════ 레퍼런스 ══════════════════
   187건. 이 사이트에서 가장 큰 실증 자산이다.
   ⚠️ 상세 화면이 없다(라우트 자체가 목록뿐). 카드를 링크로 만들지 않는다 —
      클릭할 데가 없는데 커서가 바뀌면 거짓말이다.
   ⚠️ 분류 필터는 수상·인증의 .xc-cert__tab 을 그대로 쓴다(공용 부품).
   ────────────────────────────────────────── */

/* 분류 + 검색 한 줄 */
.xc-ref__bar {
  margin-top: clamp(24px, 3vw, 40px);
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px clamp(20px, 2.4vw, 40px); flex-wrap: wrap;
}
.xc-ref__bar .xc-cert__tabs { margin-top: 0; flex: 1 1 auto; }
.xc-ref__bar .xc-board__search { flex: 0 0 auto; }

.xc-ref__list {
  margin-top: clamp(20px, 2.4vw, 32px);
  display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(16px, 1.6vw, 24px);
}
.xc-ref__card {
  position: relative;
  display: flex; flex-direction: column;
  padding: clamp(24px, 2.4vw, 34px);
  background: var(--xc-bg);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius-lg);
  transition: border-color var(--xc-dur-fast) var(--xc-ease-out);
}
.xc-ref__card[hidden] { display: none; }
/* 클릭 대상이 아니므로 뜨거나 그림자를 깔지 않는다. 테두리만 반응한다 */
.xc-ref__card:hover { border-color: var(--xc-border); }

/* ── 스크롤 등장 ──
   ⚠️ is-rv 는 JS 가 붙인다. 초기 상태(투명)를 CSS 에 그냥 두면 스크립트가 막혔을 때
      187건이 영영 안 보인다.
   ⚠️ transition 을 .is-in 쪽에만 둔다. 처음 상태에 걸어 두면 목록이 그려지는 순간
      한 번 깜빡인다.
   시간은 --xc-dur-reveal 을 쓴다 — 사이트의 모든 페이드인업이 같은 값을 읽는다.
   모션 최소화에서는 이 토큰이 0 에 가까워져 즉시 표시된다. */
.xc-ref__list.is-rv .xc-ref__card { opacity: 0; transform: translateY(22px); }
.xc-ref__list.is-rv .xc-ref__card.is-in {
  opacity: 1; transform: none;
  transition: opacity var(--xc-dur-reveal) var(--xc-ease-out),
              transform var(--xc-dur-reveal) var(--xc-ease-out);
}

/* ── 빠른 페이드인업 (조작 버튼용) ──
   움직임과 거리(22px)는 위 카드와 똑같고 **시간만 짧다**.
   ⚠️ 페이드인업 시간은 원래 --xc-dur-reveal 하나로 통일한다. 여기만 예외를 두는 이유는
      대상이 '읽는 콘텐츠'가 아니라 '누르는 버튼'이기 때문이다. 0.95초에 걸쳐 떠오르면
      그 사이 시선이 카드에 있어 버튼을 지나친다. 값은 새로 만들지 않고
      기존 토큰 --xc-dur-base(.28s)를 쓴다.
   ⚠️ 초기 상태는 is-rv 가 켠다. JS 가 붙인다 — 스크립트가 막히면 버튼이 사라진다. */
.xc-rv-fast.is-rv { opacity: 0; transform: translateY(22px); }
.xc-rv-fast.is-rv.is-in {
  opacity: 1; transform: none;
  transition: opacity var(--xc-dur-base) var(--xc-ease-out),
              transform var(--xc-dur-base) var(--xc-ease-out);
}


/* 로고 칸.
   ⚠️ 칸을 꽉 채우게 두면(max-width·max-height 100%) 187개가 제각각으로 보인다.
      가로가 긴 로고는 칸 끝까지 뻗어 거대해지고, 정사각 로고는 높이에만 걸려 작아진다.
      **높이로 먼저 묶고 폭으로 한 번 더 자른다.** 칸보다 작은 상한을 둬야
      비율이 다른 로고들이 비슷한 무게로 읽힌다. */
/* 창. 두 겹이 이 높이 안에서만 움직이고 밖은 잘린다 */
.xc-ref__logo {
  height: clamp(52px, 4.6vw, 66px); display: grid; place-items: center;
  position: relative; overflow: hidden;
}
/* GNB 메뉴와 같은 동작 — 로고가 위로 빠지고 같은 로고가 아래에서 올라온다.
   ⚠️ 겹을 span 으로 감싸는 이유. <img> 에 직접 translateY(100%) 를 걸면 이미지
      자기 높이(최대 40px)만큼만 움직여 창(66px)을 벗어나지 못한다.
      창을 꽉 채우는 겹을 만들어야 100% 가 창 높이가 된다.
   ⚠️ 겹은 JS 가 만든다. 187장 마크업을 고치지 않는다(main.js). */
.xc-ref__lyr {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  /* 값을 직접 쓰지 않고 토큰을 쓴다. 모션 최소화에서 토큰이 .01ms 로 바뀌어 자동으로 멈춘다 */
  transition: transform var(--xc-dur-slow) var(--xc-ease-out);
}
.xc-ref__lyr + .xc-ref__lyr { transform: translateY(100%); }
.xc-ref__card:hover .xc-ref__lyr { transform: translateY(-100%); }
.xc-ref__card:hover .xc-ref__lyr + .xc-ref__lyr { transform: translateY(0); }
@media (prefers-reduced-motion: reduce) {
  .xc-ref__card:hover .xc-ref__lyr { transform: none; }
  .xc-ref__card:hover .xc-ref__lyr + .xc-ref__lyr { transform: translateY(100%); }
}
.xc-ref__logo img {
  /* ⚠️ 카드가 커졌다고 로고를 같은 비율로 키우지 않는다. 3열이 되며 카드 폭이 1.5배가
     됐지만 로고는 한 단계만 올린다 — 그대로 따라 키우면 다시 제각각으로 커 보인다 */
  max-height: clamp(30px, 2.8vw, 40px);
  max-width: min(100%, 180px);
  width: auto; height: auto;
}
/* 로고가 등록되지 않았거나 파일을 못 불러온 경우. 상호명이 그 자리를 대신한다.
   ⚠️ 빈 칸으로 두지 않는다 — 격자에서 그 카드만 위가 비어 무너져 보인다 */
.xc-ref__logo--none { text-align: center; padding-inline: 4px; }
.xc-ref__logo--none span {
  font-size: var(--xc-fs-sm); font-weight: var(--xc-fw-bold);
  color: var(--xc-text-weak); letter-spacing: var(--xc-ls-heading); line-height: 1.35;
}
.xc-ref__co {
  margin-top: clamp(18px, 2vw, 26px);
  font-size: var(--xc-fs-h4); font-weight: var(--xc-fw-bold);
  letter-spacing: var(--xc-ls-heading); color: var(--xc-text); text-wrap: pretty;
}
.xc-ref__task {
  margin-top: 10px; font-size: var(--xc-fs-sm); color: var(--xc-text-sub);
  line-height: 1.6; text-wrap: pretty;
  /* 과제명이 한 줄짜리부터 두 줄 넘는 것까지 섞여 있다. 두 줄로 잘라 카드 높이를 맞춘다 */
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden;
}
.xc-ref__term {
  margin-top: auto; padding-top: 14px;
  font-size: var(--xc-fs-xs); color: var(--xc-text-weak);
  font-variant-numeric: tabular-nums;
}

@media (max-width: 1024px) {
  .xc-ref__list { grid-template-columns: repeat(2, 1fr); }
  .xc-ref__bar .xc-board__search { width: 100%; }
}
@media (max-width: 640px) { .xc-ref__list { grid-template-columns: 1fr; } }


/* ══════════════════ 사업분야 개요 ══════════════════
   사업 축 4개(솔루션·서비스·인프라·스마트팩토리)를 먼저 보여 주고 각 축으로 내려보낸다.
   기존 화면은 그냥 나열이었다 — 이 화면이 할 일은 다음 화면으로 보내는 것이다.
   ────────────────────────────────────────── */

/* 축 4개. 누르면 해당 섹션으로 내려간다 */

/* ── 사업분야 개요 : 좌측 고정 목차 + 우측 흐름 ──────────────
   좌우 비대칭이 의도다. 목차는 짧고 늘 같은 자리, 내용은 분야마다 분량이 크게 다르다
   (항목 수 20 / 6 / 2 / 9). 같은 크기 카드로 맞추려던 게 빈 카드를 만들던 원인이었다. */
.xc-bizov {
  display: grid;
  /* ⚠️ 목차는 이름만 읽는 자리다. 폭·글자를 줄여 본문에 자리를 넘긴다.
     사업분야 개요와 AI 솔루션이 같은 부품을 쓰므로 두 화면이 함께 바뀐다 */
  grid-template-columns: minmax(0, 208px) minmax(0, 1fr);
  gap: clamp(28px, 4vw, 72px);
  margin-top: clamp(72px, 10vw, 160px);   /* .xc-blk + .xc-blk 의 리듬을 이어받는다 */
}
/* 목차 바깥으로 빠진 섹션(도입 문의)도 같은 리듬을 잇는다.
   ⚠️ .xc-blk + .xc-blk 는 앞 형제가 .xc-bizov 라 걸리지 않는다 */
.xc-bizov + .xc-blk { margin-top: clamp(72px, 10vw, 160px); }
.xc-bizov__navi {
  position: sticky;
  top: calc(var(--gnb-top) + var(--gnb-row) + clamp(40px, 7vh, 96px));
  align-self: start;
}
.xc-bizov__navi ol { display: grid; gap: clamp(14px, 1.5vw, 20px); }
.xc-bizov__navi a {
  display: block; color: var(--xc-text);
  opacity: .3;
  transition: opacity .38s var(--xc-ease-out);
}
.xc-bizov__navi a:hover { opacity: .62; }
.xc-bizov__navi li.is-on a { opacity: 1; }
.xc-bizov__en {
  display: block; margin-bottom: 5px;
  font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-bold);
  letter-spacing: .12em; text-transform: uppercase; color: var(--xc-text-weak);
}
.xc-bizov__navi em {
  display: block; font-style: normal;
  font-size: var(--xc-fs-navi-sub); font-weight: var(--xc-fw-bold);
  letter-spacing: var(--xc-ls-heading); line-height: 1.35; text-wrap: pretty;
}
/* 현재 항목 왼쪽의 짧은 막대. 세로 위치는 글줄을 따라간다 */
.xc-bizov__navi li { position: relative; padding-left: 14px; }
.xc-bizov__navi li::before {
  content: ""; position: absolute; left: 0; top: 4px; bottom: 4px; width: 2px;
  border-radius: 2px; background: var(--xc-orange);
  transform: scaleY(0); transform-origin: 50% 0;
  transition: transform .38s var(--xc-ease-out);
}
.xc-bizov__navi li.is-on::before { transform: scaleY(1); }

/* ── 솔루션 묶음 목차 (2026-08-31 사용자 지시) ──
   **짧은 이름 + 설명 두 줄** + 왼쪽 레일이다. 라인업 차례표(.xc-fx-rail)와 같은 어휘로,
   가는 세로 줄 하나에 지금 자리를 그라디언트 막대로 얹는다. 목록이 하나의 축으로 묶인다.

   ⚠️ 라벨은 lang/{ko,en}/solnav.php 에서 온다. GNB 메뉴 이름(「MATE-…」)을 쓰면
      접두사가 폭을 다 먹어 설명이 들어갈 자리가 없다 — 한 줄짜리가 답답했던 이유다.
   ⚠️ 수식어(--sol)로 묶는다. 밑동 .xc-bizov__navi 는 **사업분야 개요와 프로토타입
      묶음 화면**이 제 꼴로 쓰고 있어 밑동을 고치면 그쪽이 같이 바뀐다.
   ⚠️ 비활성을 opacity 로 흐리지 않고 **색을 직접** 정한다. 투명도는 글자와 배경을
      섞어 버려 실제 대비를 예측할 수 없다.

   🔴🔴 **비활성 대비가 접근성 기준 아래다. 알고 그렇게 뒀다(2026-08-31 사용자 결정).**
      흰 바탕 대비 — 비활성 이름 gray-400 **2.19:1** · 비활성 설명 gray-300 **1.43:1**.
      WCAG AA 는 본문 4.5:1 이다. 활성은 navy 16.91:1 · gray-600 5.98:1 로 문제없다.

      경위 : 한 줄이던 시절 opacity .3(2.4:1)이 너무 옅다고 보고 gray-600(5.98)까지
      올렸다가, 두 줄로 바꾸며 gray-500/400 으로 내렸고, 사용자가 「더 연하게」를
      두 번 확인해 지금 값이 됐다. 「그때 올렸다」는 앞선 주석은 지금 값과 안 맞아 지웠다.

      ⚠️ 되돌릴 때는 **사용자에게 먼저 묻는다.** 접근성만 보고 조용히 올리지 말 것 —
         디자인 의도이지 실수가 아니다. 올린다면 이름 gray-500(3.77) 이 현실적인 절충선이고,
         gray-600(5.98) 이라야 AA 를 넘는다.
      ⚠️ 대신 활성 쪽을 세게 하는 길이 있다(이름 굵게 · 설명 gray-700). 같은 요구를
         목록을 지우지 않고 푼다. 한 번 제안했고 사용자가 고르지 않았다. */
.xc-bizov__navi--sol ol {
  position: relative;
  padding-left: 18px;
  /* 2026-08-31 : 20~28 → 13~18 로 줄였다(사용자 지시).
     ⚠️ 칸 사이가 두 줄의 줄간(설명 margin-top 2px)보다 넉넉히 커야 한다.
        비슷해지면 이름과 설명이 어느 칸의 짝인지 안 읽힌다. */
  gap: clamp(13px, 1.4vw, 18px);
}
/* 남은 차례 — 목록 전체를 잇는 가는 줄.
   ⚠️ top/bottom 4px 은 첫·끝 글줄의 위아래 여백만큼 줄을 안으로 들인 것이다.
      0 으로 두면 줄이 글보다 길어 목록 밖으로 삐져나온 것처럼 보인다. */
.xc-bizov__navi--sol ol::before {
  content: ""; position: absolute; left: 0; top: 4px; bottom: 4px;
  width: 2px; border-radius: 2px; background: var(--xc-border-weak);
}
.xc-bizov__navi--sol li { padding-left: 0; }
/* 지금 자리 — 줄 위에 얹히는 그라디언트 막대. 두 줄짜리 항목이라 칸 높이를 그대로 짚는다.
   ⚠️ left 는 ol 의 padding-left(18px)를 되돌린 값이라 **둘이 한 묶음**이다.
      한쪽만 바꾸면 막대가 줄에서 어긋난다.
   ⚠️ transform-origin 을 밑동(50% 0)에서 50% 50% 로 바꾼다. 가운데서 자라야 줄을
      짚는 것으로 읽힌다. 위에서 자라면 흘러내리는 것처럼 보인다. */
.xc-bizov__navi--sol li::before {
  left: -18px; top: 0; bottom: 0; width: 2px; border-radius: 2px;
  background: var(--xc-gradient);
  transform: scaleY(0); transform-origin: 50% 50%;
}
.xc-bizov__navi--sol li.is-on::before { transform: scaleY(1); }
.xc-bizov__navi--sol a { opacity: 1; }
/* 2026-08-31 : 이름 15 → 14, 설명 13 → 12 로 한 단계씩 줄였다(사용자 지시).
   ⚠️ 12 는 토큰 눈금의 **하한**이다(--xc-fs-12). 설명을 더 줄이면 눈금 밖으로 나간다 —
      더 조용하게 하려면 크기가 아니라 색(--xc-gray-400)을 만진다. */
.xc-solnav__nm {
  display: block;
  font-size: var(--xc-fs-14); font-weight: var(--xc-fw-semibold); letter-spacing: .01em;
  color: var(--xc-gray-400);          /* 2.19:1 — 위 🔴🔴 참고 */
  transition: color .3s var(--xc-ease-standard);
}
.xc-solnav__desc {
  display: block; margin-top: 2px; font-style: normal;
  font-size: var(--xc-fs-12); line-height: 1.45;
  color: var(--xc-gray-300);          /* 1.43:1 — 위 🔴🔴 참고 */
  text-wrap: pretty;
  transition: color .3s var(--xc-ease-standard);
}
.xc-bizov__navi--sol a:hover .xc-solnav__nm { color: var(--xc-navy); }
.xc-bizov__navi--sol li.is-on .xc-solnav__nm { color: var(--xc-navy); }
.xc-bizov__navi--sol li.is-on .xc-solnav__desc { color: var(--xc-gray-600); }
/* 흐름 안에서는 첫 섹션이 목차와 같은 줄에서 시작해야 한다 */
.xc-bizov__flow > .xc-blk:first-child { margin-top: 0; }
/* 좌측이 이름을 이미 말한다. 오른쪽 제목은 한 단계 낮춰 반복이 덜 들리게 한다 */
.xc-bizov__flow .xc-blk__head .xc-h2 { font-size: var(--xc-fs-blk-h3); }

@media (max-width: 1024px) {
  /* 고정할 가로 여유가 없다. 목차를 접고 각 섹션 제목이 그 역할을 대신한다.
     🔴 `1fr` 이 아니라 **minmax(0, 1fr)** 이라야 한다(2026-08-31 고침).
        `1fr` 은 자동 최소값이 min-content 라, 안에 min-width 가 박힌 것이 하나라도 있으면
        칸이 그 폭까지 부풀어 오른다. 배합관리시스템의 뱀 도해(.xc-serp, min-width:960px)가
        그것이라 **스마트 제조 묶음이 390·768 에서 칸 960px 로 터져 오른쪽이 잘렸다**(실측).
        도해는 제 상자(.xc-serp__wrap)에서 가로로 굴게 되어 있는데, 칸이 부풀면 그 장치가
        아무 몫도 못 한다. 위(데스크톱) 규칙은 처음부터 minmax(0,1fr) 이었다 — 여기만 빠졌다.
     ⚠️ 페이지에 가로 스크롤이 안 잡혀서 오래 안 드러났다. 조상 어딘가가 잘라 내고 있어
        **넘친 만큼이 그냥 안 보인다.** 가로 스크롤 검사만으로는 이 부류를 못 잡는다. */
  .xc-bizov { grid-template-columns: minmax(0, 1fr); gap: 0; }
  .xc-bizov__navi { display: none; }
}

/* 축 안의 묶음 카드. 아이콘 + 제목 + 항목 목록 */
.xc-ov__group {
  margin-top: clamp(20px, 2.4vw, 32px);
  display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(12px, 1.4vw, 20px);
}
.xc-ov__group--5 { grid-template-columns: repeat(5, 1fr); }
.xc-ov__group--1 { grid-template-columns: 1fr; }
/* 5장을 3 + 2 로 나눈다. 앞 4장은 1/3 폭으로 같고 마지막 한 장이 남는 2/3 를 채운다.
   ⚠️ 3열 그리드 + 마지막만 span 2 로 만든다. 행을 나눠 두 개의 ul 로 쪼개면
      항목이 두 목록으로 갈려 낭독·마크업 의미가 흐려진다. */
.xc-ov__group--3-2 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.xc-ov__group--3-2 > li:last-child { grid-column: span 2; }
.xc-ov__group > li {
  display: flex; flex-direction: column;
  padding: clamp(22px, 2.4vw, 32px);
  background: var(--xc-bg);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius-lg);
}
/* 머리 : 제목(좌) · 아이콘(우). 제목이 카드의 첫 줄이라 훑기가 빠르다 */
.xc-ov__top {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 14px;
}
/* 인라인 라인 아이콘. 12개 모두 viewBox 24×24 로 통일했다 —
   기존 브랜드 SVG 는 41×62 · 54×40 처럼 제각각이라 높이만 맞춰도 가로폭이 26~54px 로 벌어졌다.
   색은 currentColor 라 여기 한 줄로 정한다(<img> 로는 안 되는 이유이기도 하다). */
.xc-ov__ico {
  flex: none; width: 34px; height: 34px; margin-top: -2px;
  fill: none; stroke: currentColor; stroke-width: 1.4;
  stroke-linecap: round; stroke-linejoin: round;
  color: var(--xc-navy); opacity: .4;
  transition: opacity var(--xc-dur-base) var(--xc-ease-out);
}
.xc-ov__group > li:hover .xc-ov__ico { opacity: .72; }
/* 안전망 — 마크업이 옛 형태(<p class="xc-ov__ico"><img>)로 돌아가도 화면이 깨지지 않게 한다.
   위 규칙은 인라인 <svg> 를 전제로 34×34 를 못박기 때문에, <p> 가 그걸 받으면
   그 안의 이미지가 상자를 뚫고 나온다. 실제로 파일이 원본으로 되돌아갔을 때 그렇게 됐다. */
p.xc-ov__ico { width: auto; height: 40px; }
p.xc-ov__ico img { max-width: 100%; max-height: 100%; width: auto; }
.xc-ov__name {
  font-size: var(--xc-fs-ov-name); font-weight: var(--xc-fw-bold);
  letter-spacing: var(--xc-ls-heading); line-height: 1.4;
  color: var(--xc-text); text-wrap: pretty;
}
/* 항목은 태그로. 카드마다 개수가 11 / 6 / 3 / 1 / 0 으로 제각각인데
   흘려 담으면 개수 차이가 어색하지 않고, 항목이 없는 카드도 제목만으로 완결돼 보인다.
   ⚠️ 격자(grid-template-columns)로 묶지 않는다. 홀수 개면 마지막 줄에 빈칸이 남는다. */
.xc-ov__items {
  margin-top: clamp(22px, 2.2vw, 32px);
  display: flex; flex-wrap: wrap; gap: 7px;
}
.xc-ov__items li {
  /* 글자를 키운 만큼 좌우 여백도 같이 키운다. 패딩을 그대로 두면 알약이 글자에 끼인다 */
  padding: 7px 15px; border-radius: var(--xc-radius-full);
  background: var(--xc-gray-100); color: var(--xc-text-sub);
  font-size: var(--xc-fs-sm); line-height: 1.5;
}

/* 축 섹션 끝의 다음 화면 링크 */
.xc-ov__cta { margin-top: clamp(24px, 3vw, 40px); }


/* ══════════════════ 가로 슬라이더 (공용) ══════════════════
   이 사이트의 첫 슬라이더다. xCalibur 솔루션·MATE 화면에서도 쓸 수 있게 공용으로 둔다.

   ⚠️ Swiper 를 쓰지 않는다. legacy 에는 있지만 이 프로토타입은 GSAP + Lenis 만 부른다.
      브라우저 기본 가로 스크롤 + scroll-snap 이면 스와이프·트랙패드·드래그가 공짜다.
      JS 는 화살표·자동재생·진행 막대만 맡는다 — **JS 가 막혀도 스와이프는 살아 있다.**
   ⚠️ data-lenis-prevent 를 붙이지 말 것. Lenis 는 세로만 가로채므로 가로는 그냥 통과한다.
      붙이면 슬라이더 위에 마우스를 올린 채로 페이지 세로 스크롤이 죽는다.
   ────────────────────────────────────────── */
.xc-slide {
  /* 한 장이 넘어가기까지의 시간. JS 가 이 값을 읽어 타이머와 진행 막대에 함께 쓴다 */
  --xc-slide-dur: 4.5s;
  --slide-gap: clamp(12px, 1.4vw, 20px);
  margin-top: clamp(20px, 2.4vw, 32px);
}
/* 제목 줄 우측에 화살표 */
.xc-slide__head {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 20px; flex-wrap: wrap;
}
.xc-slide__nav { display: flex; gap: 8px; flex: none; }
.xc-slide__arw {
  width: 48px; height: 48px; cursor: pointer;
  border: 1px solid var(--xc-border-strong); border-radius: 50%;
  background: var(--xc-bg); color: var(--xc-text);
  display: grid; place-items: center;
  transition: var(--xc-trans-fast);
}
.xc-slide__arw:is(:hover, :focus-visible) { background: var(--xc-navy); border-color: var(--xc-navy); color: var(--xc-white); }
.xc-slide__arw[disabled] { opacity: .3; pointer-events: none; }
.xc-slide__arw svg { width: 18px; height: 18px; }

/* ⚠️ overflow-y 를 명시해 닫는다. 한쪽만 auto 로 두면 반대쪽이 auto 로 계산돼
   세로로도 스크롤되는 상자가 된다(가로 스크롤 금지 규칙과 별개로 모양이 깨진다) */
.xc-slide__track {
  display: flex; gap: var(--slide-gap);
  overflow-x: auto; overflow-y: hidden;
  scroll-snap-type: x mandatory;
  /* 스크롤바를 감춘다. 아래 진행 막대가 그 역할을 대신한다 */
  scrollbar-width: none;
}
.xc-slide__track::-webkit-scrollbar { display: none; }
.xc-slide__track:focus-visible { outline: 2px solid var(--xc-focus); outline-offset: 4px; }
/* 마우스로 끌 수 있다는 신호. 터치·트랙패드는 원래 되던 것이라 표시가 필요 없다 */
.xc-slide__track { cursor: grab; }
/* ⚠️ 끄는 동안 snap 을 꺼야 한다. 켜 둔 채로 scrollLeft 를 만지면 매 프레임
   가까운 카드로 되돌아가서 끌리지 않는다. 손을 떼면 다시 켜지며 붙는다 */
.xc-slide__track.is-drag {
  cursor: grabbing; scroll-snap-type: none;
  user-select: none; -webkit-user-select: none;
}
/* 한 화면에 3.4장. ⚠️ 딱 3장으로 끊으면 오른쪽에 더 있다는 걸 알 수 없어 화살표를 안 누른다.
   네 번째가 잘려 보이는 게 이 값의 목적이다 */
.xc-slide__item {
  flex: 0 0 clamp(240px, 28%, 340px);
  scroll-snap-align: start;
}

/* 진행 막대 = 다음 장까지 남은 시간. 위치 표시가 아니다 */
.xc-slide__bar {
  margin-top: clamp(18px, 2vw, 26px);
  height: 2px; background: var(--xc-border); border-radius: 2px; overflow: hidden;
}
.xc-slide__bar i {
  display: block; height: 100%; width: 100%;
  background: var(--xc-gradient);
  transform: scaleX(0); transform-origin: left;
}

@media (max-width: 1024px) { .xc-slide__item { flex-basis: 46%; } }
@media (max-width: 640px)  { .xc-slide__item { flex-basis: 82%; } }


/* ══════════════════ 스마트팩토리 ══════════════════ */
/* 특징 카드. 슬라이더 안에서 높이를 맞추려면 항목이 늘어난 만큼 카드가 채워야 한다 */
.xc-slide__item .xc-sf__card { height: 100%; }
.xc-sf__card {
  display: flex; flex-direction: column;
  padding: clamp(22px, 2.4vw, 30px);
  background: var(--xc-gray-50);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius-lg);
}
/* 8장 중 몇 번째인지. 슬라이더는 전체가 안 보여서 번호가 없으면 답답하다 */
.xc-sf__no {
  font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-extra); letter-spacing: .06em;
  color: var(--xc-accent); font-variant-numeric: tabular-nums;
}
.xc-sf__card b {
  display: block; margin-top: 16px;
  /* 최소값 18 은 허용 목록에서 고른 값이다(16 → 18 로 한 단계 올림) */
  font-size: var(--xc-fs-card-ttl-sm); font-weight: var(--xc-fw-bold);
  letter-spacing: var(--xc-ls-heading); color: var(--xc-text);
}
.xc-sf__card p {
  margin-top: 12px;
  font-size: var(--xc-fs-body); color: var(--xc-text-sub);
  line-height: 1.75; text-wrap: pretty;
}

/* ── 운영시스템 프레임워크 ──
   원래 1600×840 JPG(407KB) 한 장이었다. 코드로 바꾼 이유:
     · 좁은 화면에서 통째로 축소돼 글자가 2px 이 됐다(사실상 PC 전용 화면이었다)
     · 글자를 검색·복사·번역할 수 없고 스크린리더가 못 읽는다
     · 영문판 이미지를 따로 관리해야 했다(457KB)
   국문·영문 문구는 docs/SMARTFACTORY-FRAMEWORK.md 에 옮겨 두었다.
   ⚠️ 표(table)로 만들지 않는다. 행·열이 교차하는 데이터가 아니라
      '계층 라벨 + 그 계층의 구성요소'다. 정의 목록이 의미에 맞고 재배치도 자유롭다. */
.xc-fw {
  margin-top: clamp(20px, 2.4vw, 32px);
  /* 계층 표가 위, 핵심기능·기반기술이 아래. 옆에 세우면 표가 눌려서
     제조운영 3열이 읽히지 않는다 */
  display: grid; gap: clamp(20px, 2.4vw, 36px);
}
.xc-fw__layers { display: grid; gap: clamp(10px, 1.2vw, 16px); }
/* ⚠️ 아래 dt·dd 규칙은 반드시 직계 자식(>)으로 건다. 제조운영·기계&제어 계층은
   dd 안에 또 dl 을 품고 있어서, 자손 선택자로 두면 안쪽 라벨까지 네이비로 칠해진다 */
.xc-fw__row {
  display: grid; grid-template-columns: minmax(0, 180px) minmax(0, 1fr);
  gap: clamp(10px, 1.2vw, 16px); align-items: stretch;
}
.xc-fw__row > dt {
  display: grid; place-content: center; text-align: center;
  padding: clamp(12px, 1.4vw, 18px);
  background: var(--xc-navy); color: var(--xc-white);
  border-radius: var(--xc-radius);
  font-size: var(--xc-fs-h4); font-weight: var(--xc-fw-bold);
  letter-spacing: var(--xc-ls-heading);
}
.xc-fw__row > dt span {
  display: block; margin-top: 4px;
  font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-medium);
  color: rgba(255, 255, 255, .62); letter-spacing: 0;
}
.xc-fw__row > dd { margin: 0; min-width: 0; }

/* 한 줄짜리 띠 (비전·목표) */
.xc-fw__band {
  height: 100%; display: grid; place-content: center; text-align: center;
  padding: clamp(14px, 1.6vw, 20px);
  background: var(--xc-gray-100); border-radius: var(--xc-radius);
  font-size: var(--xc-fs-body); color: var(--xc-text); text-wrap: balance;
}
/* 나란한 상자 (PLM·ERP·SCM·FEMS) */
.xc-fw__cells {
  height: 100%; display: grid; grid-template-columns: repeat(4, 1fr);
  gap: clamp(8px, 1vw, 12px);
}
.xc-fw__cells li {
  display: grid; place-content: center; padding: clamp(14px, 1.6vw, 20px);
  background: var(--xc-gray-100); border-radius: var(--xc-radius);
  font-size: var(--xc-fs-md); font-weight: var(--xc-fw-semibold); color: var(--xc-text);
}

/* ── 제조운영 흐름 ──
   ⚠️ 원본 이미지의 배치가 흐름을 잘못 보이게 했다. 실제 순서는
      제품개발 → 생산계획 → 물류운영(조달) → 제조실행 → 물류운영(배송) 이다.
   화살표는 장식이라 aria-hidden 이다. 순서는 목록 순서가 이미 말한다 */
.xc-fw__ops {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.25fr) minmax(0, 1fr);
  gap: clamp(26px, 2.6vw, 38px); align-items: end;
}
.xc-fw__chain { display: grid; gap: clamp(22px, 2.2vw, 30px); }
.xc-fw__chain li {
  position: relative;
  padding: clamp(14px, 1.6vw, 18px); text-align: center;
  background: var(--xc-gray-100); border-radius: var(--xc-radius);
  font-size: var(--xc-fs-body); color: var(--xc-text); text-wrap: balance;
}
/* 세로 화살표 — 항목 사이에만 */
.xc-fw__chain li + li::before {
  content: "↓"; position: absolute; left: 50%; top: -1.55em;
  transform: translateX(-50%);
  font-size: var(--xc-fs-md); color: var(--xc-accent); line-height: 1;
}
/* 가로 화살표 — 조달 → 제조실행 → 배송 */
.xc-fw__exec, .xc-fw__ship { position: relative; }
.xc-fw__exec::before, .xc-fw__ship::before {
  content: "→"; position: absolute; top: 50%; left: calc(-1 * clamp(26px, 2.6vw, 38px));
  width: clamp(26px, 2.6vw, 38px); transform: translateY(-50%);
  text-align: center; font-size: var(--xc-fs-md); color: var(--xc-accent); line-height: 1;
}
.xc-fw__exec {
  padding: clamp(14px, 1.6vw, 18px);
  background: var(--xc-gray-50);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius);
}
.xc-fw__exec > p:first-child {
  text-align: center; padding-bottom: 12px;
  font-size: var(--xc-fs-md); font-weight: var(--xc-fw-bold); color: var(--xc-text);
}
.xc-fw__exec ul { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; }
.xc-fw__exec li, .xc-fw__exec > p:last-child {
  display: grid; place-content: center; text-align: center;
  padding: 10px 6px; background: var(--xc-bg);
  border: 1px solid var(--xc-border); border-radius: var(--xc-radius-full);
  font-size: var(--xc-fs-14); font-weight: var(--xc-fw-semibold); color: var(--xc-text);
}
.xc-fw__exec > p:last-child { margin-top: 6px; }
.xc-fw__ship {
  padding: clamp(14px, 1.6vw, 18px); text-align: center;
  background: var(--xc-gray-100); border-radius: var(--xc-radius);
  font-size: var(--xc-fs-body); color: var(--xc-text); text-wrap: balance;
}

/* ── 기계&제어 ── */
.xc-fw__mc { display: grid; gap: clamp(10px, 1.2vw, 14px); }
.xc-fw__mc > div {
  display: grid; grid-template-columns: minmax(0, 150px) minmax(0, 1fr);
  gap: clamp(12px, 1.4vw, 20px); align-items: center;
  padding-bottom: clamp(10px, 1.2vw, 14px);
  border-bottom: 1px dashed var(--xc-border);
}
.xc-fw__mc > div:last-child { border-bottom: 0; padding-bottom: 0; }
/* ⚠️ 배경을 반드시 스스로 정한다. 예전에 바깥 .xc-fw__row dt 의 네이비 배경이
   여기까지 새어 들어와 네이비 글자 + 네이비 배경으로 안 보였다 */
.xc-fw__mc dt {
  background: var(--xc-bg);
  padding: 10px 14px; text-align: center;
  border: 1px solid var(--xc-border-strong); border-radius: var(--xc-radius-full);
  font-size: var(--xc-fs-sm); font-weight: var(--xc-fw-semibold); color: var(--xc-text);
}
.xc-fw__mc dd { margin: 0; font-size: var(--xc-fs-body); color: var(--xc-text-sub); line-height: 1.7; }

/* ── 우측 : 핵심기능 · 기반기술 ── */
/* 아래로 내려온 만큼 폭이 넓어졌다. 둘을 나란히 두고 각자 안에서 열을 늘린다 */
/* ⚠️ align-items 를 start 로 두면 짧은 쪽(기반기술)이 위에 붙고 아래가 빈다.
   stretch 로 두 열의 높이를 맞추고, 안쪽 목록이 남은 높이를 채우게 한다 */
.xc-fw__side {
  display: grid; grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
  gap: clamp(16px, 2vw, 28px); align-items: stretch;
}
.xc-fw__side > section { display: flex; flex-direction: column; }
.xc-fw__side h4 {
  padding: 12px; text-align: center; border-radius: var(--xc-radius);
  background: var(--xc-navy); color: var(--xc-white);
  font-size: var(--xc-fs-h4); font-weight: var(--xc-fw-bold);
}
/* ⚠️ align-items 를 start 로 두면 같은 행에서 항목이 적은 쪽(지능화&에너지 3개)이
   위에 붙고 아래가 빈다. 지우면(기본값 stretch) 짝인 이상대응(5개) 높이에 맞춰 늘어난다 */
.xc-fw__fn {
  flex: 1;
  margin-top: clamp(10px, 1.2vw, 14px);
  display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px clamp(16px, 2vw, 28px);
}
/* ⚠️ align-items 를 start 로 두면 키워드 상자가 한 줄 높이로 붙어 버린다.
   이상대응처럼 항목이 5개인 묶음에서 라벨만 위에 동동 뜬다.
   stretch(기본값)로 두면 라벨이 자기 항목 높이만큼 늘어난다 —
   글자는 dt 의 place-content:center 가 가운데로 잡아 준다 */
.xc-fw__fn > div {
  display: grid; grid-template-columns: minmax(0, 108px) minmax(0, 1fr);
  gap: 12px;
}
.xc-fw__fn dt {
  display: grid; place-content: center; text-align: center;
  padding: 12px 8px; background: var(--xc-gray-100); border-radius: var(--xc-radius-sm);
  font-size: var(--xc-fs-md); font-weight: var(--xc-fw-semibold); color: var(--xc-text);
}
/* 라벨(dt)이 세로 가운데 정렬이므로 본문도 맞춘다.
   항목이 1개인 묶음(통합/연계·유연성)은 라벨 상자가 더 높아 글이 위에 붙어 보였다 */
.xc-fw__fn dd { margin: 0; display: grid; align-content: center; }
.xc-fw__fn dd li {
  position: relative; padding-left: 11px;
  font-size: var(--xc-fs-sm); color: var(--xc-text-sub); line-height: 1.7;
}
.xc-fw__fn dd li + li { margin-top: 6px; }
.xc-fw__fn dd li::before {
  content: ""; position: absolute; left: 0; top: .55em;
  width: 3px; height: 3px; background: var(--xc-text-weak);
}
/* 8칸이 남은 높이를 고르게 나눠 가진다 — 옆 핵심기능과 아래 끝이 맞는다 */
.xc-fw__tech {
  flex: 1;
  margin-top: clamp(10px, 1.2vw, 14px);
  display: grid; grid-template-columns: repeat(2, 1fr); grid-auto-rows: 1fr; gap: 8px;
}
.xc-fw__tech li {
  display: grid; place-content: center; text-align: center; padding: 12px 8px;
  background: var(--xc-gray-50); border: 1px solid var(--xc-border-weak);
  border-radius: var(--xc-radius-sm);
  font-size: var(--xc-fs-md); font-weight: var(--xc-fw-semibold); color: var(--xc-text);
}

@media (max-width: 1024px) {
  .xc-eff__list, .xc-eff__list--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .xc-fw__side { grid-template-columns: 1fr; }
  .xc-fw__fn { grid-template-columns: 1fr; }
  .xc-fw__row { grid-template-columns: minmax(0, 150px) minmax(0, 1fr); }
}
@media (max-width: 640px) {
  .xc-eff__list, .xc-eff__list--3 { grid-template-columns: minmax(0, 1fr); }
  /* 라벨을 내용 위로. 좁은 화면에서 라벨 열을 유지하면 내용이 못 읽을 만큼 눌린다 */
  .xc-fw__row { grid-template-columns: 1fr; gap: 8px; }
  .xc-fw__row > dt { padding: 10px; }
  .xc-fw__row > dt span { display: inline; margin-left: 6px; }
  .xc-fw__cells { grid-template-columns: repeat(2, 1fr); }
  /* 흐름을 세로 한 줄로. 가로 화살표도 아래 방향으로 바꾼다 */
  .xc-fw__ops { grid-template-columns: 1fr; gap: clamp(22px, 6vw, 30px); }
  .xc-fw__exec::before, .xc-fw__ship::before {
    content: "↓"; left: 50%; top: calc(-1 * clamp(22px, 6vw, 30px));
    width: auto; transform: translate(-50%, 0);
  }
  .xc-fw__mc > div { grid-template-columns: 1fr; gap: 8px; }
  .xc-fw__mc dt { justify-self: start; padding-inline: 18px; }
  .xc-fw__fn > div { grid-template-columns: 1fr; gap: 6px; }
  .xc-fw__fn dt { justify-self: start; padding-inline: 14px; }
}

/* 수준기준 표.
   ⚠️ 좁은 화면에서 페이지를 밀지 않는다. 표는 자기 상자 안에서만 가로로 움직인다.
      overflow-y 를 명시해 닫지 않으면 x 만 auto 로 둬도 y 가 auto 로 계산된다. */
.xc-sf__tablebox {
  margin-top: clamp(20px, 2.4vw, 32px);
  overflow-x: auto; overflow-y: hidden;
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius-lg);
}
.xc-sf__table { width: 100%; min-width: 900px; border-collapse: collapse; }
/* 칸 글자를 키우면 표가 그만큼 넓어진다. min-width 도 같이 올려야
   좁은 화면에서 글자가 칸에 눌려 세 줄로 접히지 않는다 */
.xc-sf__table th, .xc-sf__table td {
  padding: 16px 18px; border: 1px solid var(--xc-border-weak);
  font-size: var(--xc-fs-body); color: var(--xc-text-sub);
  line-height: 1.6; text-align: center; vertical-align: middle;
}
.xc-sf__table thead th {
  background: var(--xc-navy); color: var(--xc-white);
  font-weight: var(--xc-fw-semibold); border-color: var(--xc-navy-2);
}
.xc-sf__table tbody th {
  background: var(--xc-gray-100); color: var(--xc-text);
  font-weight: var(--xc-fw-bold); white-space: nowrap;
}
/* 바깥 가장자리의 칸 테두리를 지운다.
   ⚠️ 상자 테두리와 칸 테두리가 가장자리에서 두 겹으로 겹친다. 직선 구간은 그만큼 진해지는데
      둥근 모서리 구간은 칸 테두리가 radius 에 잘려 한 겹만 남는다. 그래서 모서리만 흐려 보였다.
      가장자리는 상자 테두리 한 겹으로 통일한다. */
.xc-sf__table tr > *:first-child { border-left: 0; }
.xc-sf__table tr > *:last-child { border-right: 0; }
.xc-sf__table thead tr:first-child > * { border-top: 0; }
.xc-sf__table tbody tr:last-child > * { border-bottom: 0; }
.xc-sf__table sub { font-size: var(--xc-fs-12); vertical-align: baseline; }
.xc-sf__table td:empty { background: var(--xc-gray-50); }

/* ── 공정·경영 개선 성과 ──
   ⚠️ 일곱 개가 전부 '개선치'다. 증가·감소를 서로 다른 색으로 칠하면
      한쪽이 나쁜 값처럼 읽힌다(원가 절감·산업재해 감소는 좋은 것이다).
      색은 하나로 두고 **방향은 화살표와 낱말이 말한다.**
   ⚠️ 숫자만 두면 29.0% 가 '생산성이 29%' 인지 '29% 올랐다' 인지 알 수 없다.
      값 아래 향상·절감·감소를 반드시 붙인다. */
.xc-eff { margin-top: clamp(20px, 2.4vw, 32px); display: grid; gap: clamp(24px, 3vw, 40px); }
.xc-eff__grp h3 {
  font-size: var(--xc-fs-md); font-weight: var(--xc-fw-bold);
  letter-spacing: var(--xc-ls-heading); color: var(--xc-text);
}
/* 🔴 칸은 minmax(0, 1fr) 이라야 한다. 맨 1fr 의 최소값은 **min-content** 라
   카드 안에 안 쪼개지는 긴 토막이 있으면 칸이 그만큼 부푼다 — 430·360 에서
   목록이 421px 로 서서 오른쪽이 잘려 나갔다(실측 2026-09-01).
   ⚠️ 페이지 가로 스크롤로는 안 잡힌다. html/body 가 overflow-x:clip 이라 잘릴 뿐이다. */
.xc-eff__list {
  margin-top: clamp(14px, 1.6vw, 20px);
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: clamp(12px, 1.4vw, 20px);
}
.xc-eff__list--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
/* 2×2 배치 — 윗줄 지표명 · 아이콘 / 아랫줄 값 · 방향어.
   세로로 쌓으면 카드가 길어지고 아이콘이 숫자보다 먼저 읽힌다. 주인공은 숫자다 */
.xc-eff__list li {
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  align-items: center; gap: clamp(4px, 0.6vw, 8px) 12px;
  padding: clamp(16px, 1.8vw, 22px) clamp(18px, 2vw, 24px);
  background: var(--xc-gray-50);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius-lg);
}
/* 사이트 표준 선 아이콘. 색은 CSS 가 잡는다(파일에 색을 박지 않는다) */
.xc-eff__ico {
  width: 34px; height: 34px; justify-self: end;
  /* ⚠️ 사업분야 개요의 .xc-ov__ico 와 같은 값을 쓴다. 두 화면이 나란한 메뉴라
     아이콘 톤이 갈리면 바로 티가 난다. 색·불투명도·선 굵기 셋 다 맞춰야 한다
     (예전에는 --xc-text-sub + 1.6 이라 개요보다 진하고 굵었다).
     ⚠️ 이 카드의 주인공은 숫자다. 아이콘은 물러나 있어야 한다 */
  color: var(--xc-navy); opacity: .4;
  fill: none; stroke: currentColor; stroke-width: 1.4;
  stroke-linecap: round; stroke-linejoin: round;
}
.xc-eff__name { font-size: var(--xc-fs-sm); color: var(--xc-text-sub); }
.xc-eff__val {
  text-align: left;
  /* 이 화면의 주인공. 최소값 32 는 허용 목록에서 골랐다(26 → 32) */
  font-size: var(--xc-fs-eff-val); font-weight: var(--xc-fw-extra);
  letter-spacing: -.03em; color: var(--xc-text);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
/* ⚠️ .unit 으로 좁힌다. 숫자 자체가 [data-count] span 이라 span 전체를 잡으면
   카운트업 하는 숫자까지 절반 크기가 된다 */
.xc-eff__val .unit { font-size: .5em; margin-left: 1px; font-weight: var(--xc-fw-bold); }
/* 방향은 태그로. 낱말 하나만 둔다.
   ⚠️ ▲▼ 화살표를 쓰지 않는다. 원가 '절감'과 산업재해 '감소'는 좋은 결과인데
      아래 화살표가 하락으로 읽혀 성과가 부정적으로 보였다. 낱말이 이미 방향을 말한다.
   ⚠️ 증가·감소를 다른 색으로 칠하지 않는다. 일곱 개 모두 같은 면색이다 */
.xc-eff__dir {
  justify-self: end; white-space: nowrap;
  display: inline-flex; align-items: center;
  padding: 6px 12px; border-radius: var(--xc-radius-full);
  background: var(--xc-chip-accent-bg);
  font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-semibold);
  /* ⚠️ 브랜드 오렌지(#fc6500)를 그대로 쓰면 이 면 위에서 2.7:1 이라 안 읽힌다.
     글자용 오렌지 토큰을 쓴다(5.0:1) */
  color: var(--xc-orange);
}
/* 고용율만 퍼센트가 아니다. 무엇의 2.1명인지 지표명 옆에서 밝힌다.
   ⚠️ 아래로 내리면 일곱 장 중 이 카드만 한 줄 길어져 격자가 어긋난다 */
.xc-eff__note {
  margin-left: 6px; font-weight: var(--xc-fw-regular);
  font-size: var(--xc-fs-xs); color: var(--xc-text-weak);
}


/* 출처. 인용한 숫자에는 반드시 따라붙는다 */
.xc-src {
  margin-top: 14px;
  font-size: var(--xc-fs-xs); color: var(--xc-text-weak); line-height: 1.7;
}

@media (max-width: 1280px) {
  .xc-ov__group--5 { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 1024px) {
  .xc-ov__group, .xc-ov__group--5 { grid-template-columns: repeat(2, 1fr); }
  /* 2열이 되면 5장이 2·2·1 로 떨어진다. 마지막 한 장이 반쪽으로 남지 않게 두 칸을 채운다 */
  .xc-ov__group--3-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 640px) {
  .xc-ov__group, .xc-ov__group--5, .xc-ov__group--3-2 { grid-template-columns: 1fr; }
  .xc-ov__group--3-2 > li:last-child { grid-column: auto; }
}


/* ══════════════════ xCalibur 소개 ══════════════════
   설계 : docs/SCREENS.md §C
   ⚠️ 상태 라벨·정량 성과는 화면에 없다. 스타일도 만들지 않는다. */

/* ── ② 검과 검집 : 이미지 배경 위 두 화면 ──
   섹션은 스크롤 길이를 만드는 통이고, 보이는 것은 배경 한 겹 + 글 화면 두 겹이다.
   ⚠️ 본문 열(.xc-sub) 밖에 둔다. 안에 두면 좌우 여백만큼 잘려 화면을 못 채운다.
      100vw 로 늘리는 방법은 쓰지 않는다 — 스크롤바 자리(scrollbar-gutter)만큼 넘쳐
      가로 스크롤이 생긴다. */
/* 스크롤 길이. 줄 하나가 한가운데를 지나는 데 충분한 거리를 준다 —
   짧으면 여러 줄이 한꺼번에 스쳐 지나가 한 문장씩 읽히지 않는다 */
/* ⚠️ 문단 수가 곧 슬롯 수다. main.js 가 문단을 세어 이 높이를 균등하게 나눈다.
   문단을 늘리면 여기도 같이 늘려야 한 문단이 머무는 거리가 유지된다.
   2026-08-11 재정의 개정판에서 본문이 다시 다듬어져 8문단으로 돌아왔다(문단당 약 112vh). */
.xc-xc-story { position: relative; height: var(--xc-story-h, 900vh); }

/* 배경은 화면에 고정한다.
   ⚠️ 섹션 안에 absolute 로 두면 섹션이 화면 위로 올라온 다음에야 보인다. 그러면
      '화면이 통째로 내려간 뒤 페이드인' 이 된다. fixed 로 두면 지금 보고 있는 화면
      위에 그대로 스며든다.
   ⚠️ z-index 는 퀵버튼(900)·GNB(1000) 아래여야 한다. */
.xc-xc__bg {
  position: fixed; inset: 0;
  /* 액자로 들어가는 동안 모서리가 계단지지 않게. 값 자체는 JS 가 스크롤에 맞춰 준다 */
  transition: clip-path .12s linear;
  /* ⚠️ 이 값은 무대 안에서의 순서다. 무대(z 3)가 통째로 위에 있으므로 화면은 덮는다.
     여기서 글보다 큰 값을 주면 무대 안에서 글을 가린다 — 실제로 그래서 글이 안 보였다. */
  z-index: 0;
  opacity: 0; pointer-events: none;
}
.xc-xc__bg img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* 사진만 두면 가운데 광선이 밝아 흰 글자가 묻힌다 */
.xc-xc__bg::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(180deg,
    rgba(9, 13, 20, .62) 0%, rgba(9, 13, 20, .48) 45%, rgba(9, 13, 20, .70) 100%);
}
/* 글은 무대에 담아 고정한다. 무대 자체는 투명하다 */
.xc-xc__stage {
  position: sticky; top: 0; z-index: 3;
  height: 100svh;
}
/* 글은 화면 가운데를 지나 위로 흘러간다. 창 밖은 잘라 낸다 */
.xc-xc__page {
  position: absolute; inset: 0; z-index: 1;   /* 배경(0) 위 */
  overflow: hidden; text-align: center; opacity: 0;
}
.xc-xc__page > .xc-area { position: static; }
/* 문단 하나가 화면 한가운데에 한 번에 하나씩 선다. 전부 같은 자리에 겹쳐 두고
   JS 가 차례로 켠다.
   ⚠️ .xc-xc__page 를 기준으로 잡는다(inset:0). .xc-area 는 static 이라 기준이 되지 않는다. */
.xc-xc__page .xc-xc__story-body p,
.xc-xc__page .xc-xc__quote p {
  position: absolute; left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  width: min(calc(100% - 2 * clamp(24px, 5vw, 80px)), 1180px);
  margin: 0;
}
/* 제목은 좌측 상단 고정. 화면이 바뀌어도 자리를 지킨다.
   ⚠️ GNB(고정 헤더) 아래로 내려 준다. 안 그러면 로고·메뉴와 겹친다 */
.xc-xc__head {
  position: absolute; z-index: 2;
  /* GNB(--gnb-top + --gnb-row = 120px) 바로 아래. 더 올리면 스크롤을 되감아 GNB 가
     다시 나타날 때 로고·메뉴와 겹친다 */
  top: calc(var(--gnb-top) + var(--gnb-row) + 8px);
  left: clamp(24px, 5vw, 80px);
  text-align: left;
}
.xc-xc__head .xc-eyebrow { color: rgba(255, 255, 255, .62); }
.xc-xc__head .xc-h2 { color: var(--xc-white); }
/* ⚠️ 폭을 좁게 두면 <br> 로 고정한 줄이 그 안에서 또 접힌다.
   가장 긴 줄(좋은 기능을 가진 검은 ~)이 한 줄에 들어갈 만큼 연다 */
.xc-xc__story-body {
  max-width: min(100%, 900px); margin-inline: auto;
  margin-top: clamp(28px, 3.4vw, 48px);
}
/* 본문만 키운다. 인용문(.xc-xc__quote)은 이미 크므로 손대지 않는다.
   ⚠️ 글자를 키우면 <br> 로 고정한 줄이 상자 안에서 또 접힌다. 문단 폭도 같이 넓힌다. */
.xc-xc__story-body p {
  font-size: var(--xc-fs-story-body); color: rgba(255, 255, 255, .84);
  line-height: 1.85; text-wrap: pretty;
}
.xc-xc__story-body p + p { margin-top: clamp(14px, 1.6vw, 22px); }
/* JS 가 문단을 눈에 보이는 줄 단위로 쪼개 이 요소로 감싼다 */
.xc-xc__ln { display: block; }
/* ⚠️ ch 를 쓰면 안 된다 — blockquote 자신의 글자 크기(16px)로 계산된다. 큰 글자는 안쪽 p 에 있다 */
.xc-xc__quote { margin: 0 auto; max-width: min(100%, 860px); }
.xc-xc__quote p {
  font-size: var(--xc-fs-xc-quote); font-weight: var(--xc-fw-extra);
  letter-spacing: var(--xc-ls-heading); line-height: 1.45;
  color: var(--xc-white); text-wrap: balance;
}

/* 좁은 화면 : 무대 고정은 풀되 **배경은 화면에 붙여 둔다.** 글 두 판이 그 위를 지나간다
   (2026-09-17 사용자 지시 · A안). 데스크톱의 「이미지 배경 위에서 두 화면이 차례로
   지나간다」를 스크럽 없이 재현한 것이다.

   🔴 그전에는 문단 넷이 position:absolute 인 채로 남아 **한 자리에 포개져** 있었다.
      데스크톱은 스크롤 진행도가 하나씩 띄우지만 모바일엔 그게 없다. 글자가 뒤엉켜
      읽을 수 없는 상태였다(실측 2026-09-17). 흐름으로 되돌린다.
   ⚠️ 배경은 sticky + margin-bottom: -100svh 다. 음수 여백이 없으면 배경이 흐름에서
      한 화면을 차지해 글이 그만큼 아래로 밀린다.
   ⚠️ 제목도 absolute 를 푼다. 무대가 static 이 되면 기준 상자가 바뀌어 글 위에 겹친다.
   ⚠️ 글 색은 손대지 않는다. 본문·인용문 모두 원래 흰 계열이다(배경 위에 얹는 설계).
   ⚠️ 판마다 100svh 를 준다. 실측 높이는 ①326 ②399 라 화면에 넉넉히 들어간다. */
@media (max-width: 640px) {
  .xc-xc-story { height: auto; }
  .xc-xc__stage { position: relative; height: auto; }
  /* 🔴 .xc-xc__bg 자체에 sticky 를 걸면 **안 붙는다**(실측: 스크롤을 따라 그냥 올라간다).
     대신 바깥은 absolute 로 이야기 전체를 덮고, **안의 <img> 와 스크림을 sticky** 로 세운다.
     ⚠️ 스크림(::after)도 함께 붙여야 한다. 안 붙이면 그라디언트가 이야기 전체 높이로
        늘어나 화면마다 농도가 달라진다.
     ⚠️ ::after 는 <img> 다음에 흐르므로 margin-top 으로 한 화면만큼 끌어올려 겹친다. */
  .xc-xc__bg {
    position: absolute; inset: 0; height: auto; margin: 0;
    opacity: 1; z-index: 0;
  }
  .xc-xc__bg img { position: sticky; top: 0; height: 100svh; }
  .xc-xc__bg::after {
    position: sticky; inset: auto; top: 0;
    display: block; height: 100svh; margin-top: -100svh;
  }
  .xc-xc__head {
    position: relative; z-index: 2; top: auto; left: auto;
    padding: calc(var(--gnb-top) + var(--gnb-row) + 20px) var(--xc-pad) 0;
  }
  .xc-xc__page {
    position: relative; inset: auto; opacity: 1; z-index: 1;
    overflow: visible;
    min-height: 100svh;
    display: flex; align-items: center;
    padding-block: clamp(36px, 8vw, 64px);
  }
  /* 겹쳐 두었던 문단을 흐름으로 되돌린다 */
  .xc-xc__page .xc-xc__story-body p,
  .xc-xc__page .xc-xc__quote p {
    position: static; transform: none !important; width: auto;
  }
  .xc-xc__page .xc-area { width: 100%; }
}

/* ── ③ 세 가지 축 ── */
.xc-xc__axis {
  margin-top: clamp(24px, 3vw, 40px);
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(12px, 1.4vw, 20px);
  /* ⚠️ 여기에 overflow:hidden 을 걸지 않는다. 걸면 카드가 화면 밖이 아니라
     본문 열(1380px) 가장자리에서 튀어나오는 것처럼 보인다.
     밀어낸 카드는 위 22행의 `html, body { overflow-x: clip }` 이 받아 준다.
     고정 중에는 GSAP 이 position:fixed 로 붙이므로 화면 밖 부분은 문서 폭에도 안 들어간다. */
}
/* 고정 구간에서만 붙는다(JS). 화면 높이를 채우고 내용을 세로 가운데에 둔다.
   ⚠️ 평상시에 걸면 안 된다. 1열로 떨어지는 폭에서 섹션만 화면 높이로 늘어나 빈 곳이 생긴다. */
[data-axis].is-axis-pin {
  min-height: 100dvh;
  display: flex; flex-direction: column; justify-content: center;
}
/* 배경은 아래 배경막이 맡는다. 섹션 자신은 비워 둔다.
   ⚠️ .xc-dark 가 background 를 칠하므로 명시도를 한 단계 올려 덮는다.
      섹션이 스스로 칠하면 배경막이 걷혀도 그 자리만 네이비로 남아 경계가 다시 생긴다. */
[data-axis].is-axis-pin.xc-dark,
[data-axis-follow].xc-dark,
[data-stain].xc-dark,
[data-stain-edge].xc-dark { background: transparent; }
/* 물드는 중간(막 0.5 언저리)에는 배경이 애매한 회색이 된다. 그 지점에서는
   밝은 글자도 어두운 글자도 대비가 떨어진다 — 두 색이 같은 회색으로 수렴하기 때문이다.
   gray-600(#5a6474)은 흰 배경 기준 값이라 이 구간에서 1.6:1 까지 떨어졌다.
   아직 라이트인 동안만 한 단계 낮춰 쓴다.
   ⚠️ .xc-dark 로 넘어간 뒤에는 걸면 안 된다. 네이비 위에서 오히려 어두워진다. */
html.is-staining :is([data-stain], [data-stain-edge]):not(.xc-dark) {
  /* 본문색까지 끌어올린다. #3A4353 으로는 막 0.5 지점에서 2.88:1 까지 떨어졌다.
     이 구간에서만 위계를 한 단계 잃는 대신 읽히게 한다(막 0.49 에서 4.6:1). */
  --xc-text-sub:  var(--xc-navy);
  --xc-text-weak: var(--xc-navy);
}
/* 물듦 구간 위아래에 걸치는 섹션. 막이 화면 전체를 덮으므로 이 둘도 같이 넘어가야
   글자가 읽힌다. 구간의 시작·끝을 정하는 기준(anchor)은 아니고 색만 따라간다.
   ⚠️ 두 섹션이 화면에서 겹치지 않는 순간이 없어서 생기는 문제다. 메인도 같은 방식이다. */
/* 막이 걷히는 구간에서 라인업이 화면에 들어온다. 두 섹션은 붙어 있어서
   '둘 다 화면 밖' 인 순간이 없다 — 그래서 색을 함께 넘긴다.
   ⚠️ 카드 바탕과 글자가 전부 역할색을 쓰고 있어 .xc-dark 하나로 같이 뒤집힌다.
      섹션 자신의 배경만 비워 막이 비치게 한다. */
[data-axis-follow],
[data-axis-follow] .xc-xc__sol > li,
[data-axis-follow] :is(.xc-eyebrow, .xc-h2, .xc-lead,
  .xc-xc__sol-kind, .xc-xc__sol-name, .xc-xc__sol-tag, .xc-xc__sol-desc,
  .xc-xc__sol-wield),
[data-stain], [data-stain-edge],
[data-stain] :is(.xc-eyebrow, .xc-h2, .xc-lead, .xc-sol__keeps, .xc-sol__keeps b,
  .xc-mth__cell, .xc-mth__head, .xc-mth__ico, .xc-mth__area-name, .xc-mth__area-desc) {
  transition: background-color .25s ease, border-color .25s ease, color .25s ease;
}
@media (prefers-reduced-motion: reduce) {
  [data-axis-follow],
  [data-axis-follow] .xc-xc__sol > li,
  [data-axis-follow] :is(.xc-eyebrow, .xc-h2, .xc-lead,
    .xc-xc__sol-kind, .xc-xc__sol-name, .xc-xc__sol-tag, .xc-xc__sol-desc,
    .xc-xc__sol-wield) { transition: none; }
}

/* 무대 배경막. 고정 판 하나의 불투명도만 움직인다 —
   문서에 깔린 상자가 아니라 화면에 고정된 막 하나의 불투명도를 스크롤로 움직인다.
   그래야 경계가 위아래로 쓸려 지나가지 않고 화면 전체가 서서히 물들고 걷힌다.
   ⚠️ inset:0 은 스크롤바를 뺀 영역이라 scrollbar-gutter 로 예약된 약 15px 띠에
      흰 캔버스가 드러난다. 100vw 는 그 띠를 포함한다.
      고정 요소는 스크롤 영역에 기여하지 않으므로 가로 스크롤을 만들지 않는다.
   ⚠️ z-index -1 이라 검 구간 무대(.xc-xc__stage, z 3)보다 뒤에 있다.
      그래서 검 이미지가 걷히면 덮이는 것이 아니라 이 막이 드러난다. */
.xc-stain-veil {
  position: fixed; top: 0; left: 0; width: 100vw; height: 100dvh; z-index: -1;
  background: var(--xc-gradient-glow), var(--xc-navy-deep);
  opacity: var(--axis-stain, 0);
  pointer-events: none;
}

/* 불씨. 브랜드 이미지의 '검 주위로 떠오르는 금빛 알갱이'를 옮긴 것이다.
   ⚠️ 장식이라 JS 가 만든다. 스크립트가 막히면 그냥 안 보인다(내용 손실 없음).
   ⚠️ transform 과 opacity 만 움직인다. left/top 을 애니메이션하면 매 프레임 레이아웃이 다시 계산된다.
   ⚠️ 배경막 안에 둔다. 막이 걷힐 때 불씨도 같이 걷혀야 한다. */
.xc-axis-fx { position: absolute; inset: 0; overflow: hidden; pointer-events: none; }
.xc-axis-fx i {
  position: absolute; bottom: -10px; left: var(--x);
  width: var(--s); height: var(--s); border-radius: 50%;
  background: var(--c); box-shadow: 0 0 var(--g) var(--c);
  opacity: 0;
  animation: xcEmber var(--t) linear var(--d) infinite;
}
@keyframes xcEmber {
  0%   { transform: translate3d(0, 0, 0) scale(.5); opacity: 0; }
  14%  { opacity: var(--o); }
  72%  { opacity: var(--o); }
  100% { transform: translate3d(var(--dx), calc(var(--rise) * -1), 0) scale(1); opacity: 0; }
}
/* 움직임 최소화에서는 무대 자체를 만들지 않는다(JS 가 고정을 걸지 않는다).
   혹시 남아 있어도 여기서 멈춘다 */
@media (prefers-reduced-motion: reduce) {
  .xc-axis-fx { display: none; }
}
.xc-xc__axis > li {
  padding: clamp(30px, 3.1vw, 46px);
  background: var(--xc-gray-50);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius-lg);
}
/* 3열로 나란히 설 때만 바닥 높이를 준다. 무대가 화면 높이를 쓰므로 위아래 여백이 남는데,
   그만큼 카드를 키워 채운다.
   ⚠️ 1열 구간에는 걸지 않는다. 글이 짧은 카드가 빈 상자처럼 늘어난다. */
@media (min-width: 1025px) {
  .xc-xc__axis > li { min-height: clamp(280px, 20vw, 320px); }
}
.xc-xc__ico {
  width: 34px; height: 34px;
  fill: none; stroke: currentColor; stroke-width: 1.4;
  stroke-linecap: round; stroke-linejoin: round;
  color: var(--xc-navy); opacity: .4;
}
.xc-xc__en {
  margin-top: 20px;
  font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-bold);
  letter-spacing: .12em; text-transform: uppercase; color: var(--xc-text-weak);
}
.xc-xc__name {
  margin-top: 6px;
  font-size: var(--xc-fs-card-ttl-sm); font-weight: var(--xc-fw-extra);
  letter-spacing: var(--xc-ls-heading); line-height: 1.35;
  color: var(--xc-text); text-wrap: pretty;
}
.xc-xc__desc {
  margin-top: 12px;
  font-size: var(--xc-fs-sm); color: var(--xc-text-sub);
  line-height: 1.7; text-wrap: pretty;
}
/* 네이비 카드. JS 가 .xc-dark 를 붙인다.
   ⚠️ 날아오는 도중에 색을 바꾸지 않는다. 전에는 회색으로 들어와 중간에 넘어갔는데
      흰 판이 지나가는 것처럼 보였다. 색은 처음부터 완성 상태고 움직임과 투명도만 변한다.
   ⚠️ 배경만 바꾸면 안 된다. 이 카드의 글자·아이콘은 밝은 바탕을 전제로 한 색이라
      네이비 위에서 그대로 사라진다. 역할색 스코프(.xc-dark)를 통째로 걸어
      글자·테두리를 함께 뒤집고, 고정값을 쓰는 둘만 아래에서 되돌린다.
        · 카드 바탕  --xc-gray-50  (역할색이 아니라 회색 램프값)
        · 아이콘     --xc-navy     (네이비 위에서 안 보인다)
   ⚠️ 본문 안 네이비 바탕은 원래 쓰지 않는 것이 이 프로젝트의 규칙이다.
      2026-08-04 사용자 지시로 이 카드에만 예외를 둔다. */
.xc-xc__axis > li,
.xc-xc__ico, .xc-xc__en, .xc-xc__name, .xc-xc__desc {
  transition: background-color .45s ease, border-color .45s ease, color .45s ease;
}
.xc-xc__axis > li.xc-dark { background: var(--xc-bg); }
/* 네이비로 넘어간 뒤에만 xCalibur 그라디언트를 얹는다.
   ⚠️ 밝은 바탕에서는 쓸 수 없다. #FBE38A 가 회색 카드(#F8F9FB) 위에서 1.2:1 이라 사라진다.
      tokens.css 에도 '다크 섹션 위에서만 그라디언트 텍스트를 쓴다' 고 적혀 있다.
   ⚠️ 아이콘은 CSS 그라디언트를 stroke 로 못 받는다. HTML 의 defs 를 참조한다. */
.xc-xc__axis > li.xc-dark .xc-xc__ico {
  stroke: url(#xcAxisGrad); color: var(--xc-white); opacity: 1;
}
.xc-xc__axis > li.xc-dark .xc-xc__en {
  background: var(--xc-gradient);
  -webkit-background-clip: text; background-clip: text;
  color: transparent;
}
@media (prefers-reduced-motion: reduce) {
  .xc-xc__axis > li,
  .xc-xc__ico, .xc-xc__en, .xc-xc__name, .xc-xc__desc { transition: none; }
}

/* ── ⑤ 솔루션 7 ──
   ⚠️ 하나의 목록. 그룹 분리·순서 위계를 만들지 않는다. 7장이 모두 같은 무게다.
   ⚠️ 3열이면 3·3·1 이 되어 마지막 줄에 두 칸이 빈다. 4열로 두면 4·3 이 되고
      한 칸만 남으므로 마지막 장이 두 칸을 차지해 빈 곳이 없다.
      좌측 목차가 없는 화면이라 4열이어도 카드가 좁지 않다 */
.xc-xc__sol {
  margin-top: clamp(16px, 1.8vw, 24px);
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(12px, 1.4vw, 20px);
}
/* 마지막 줄 메우기는 파일 아래쪽 '카드 격자' 규칙이 맡는다 — 구간마다 열 수가 달라
   여기(구간 없는 자리)에 두면 1열이 되는 모바일에서도 두 칸을 만들어 가로로 넘친다 */
.xc-xc__sol > li {
  /* 카드 전체가 클릭 영역이다. 제목 링크의 ::after 가 이 상자를 덮는다 (파일 아래 .xc-xc__sol-name a) */
  position: relative;
  display: flex; flex-direction: column;
  padding: clamp(24px, 2.4vw, 34px);
  background: var(--xc-bg);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius-lg);
  transition: border-color var(--xc-dur-fast) var(--xc-ease-out);
}
.xc-xc__sol > li:hover { border-color: var(--xc-border); }
/* 키보드로 왔을 때. 링크는 제목 글자만 차지하므로 테두리는 카드가 그린다 */
.xc-xc__sol > li:has(.xc-xc__sol-name a:focus-visible) {
  outline: 2px solid var(--xc-focus); outline-offset: 3px;
}

/* 커서 주변 카드가 그쪽으로 기운다. add.html 'AI 가 맡는 영역'(.xc-mth__area) 과 같은 장치다.
   기울기는 main.js 가 transform 으로 직접 쓰고, 여기서는 빛번짐과 되돌아오는 곡선만 맡는다.

   ⚠️ 상시 transition 에 transform 을 넣지 않는다. 이 목록은 data-reveal="stagger" 라
      GSAP 이 같은 transform 을 쓴다. 되돌아올 때만 JS 가 is-tilt-back 을 붙인다.
   ⚠️ 이 섹션은 [data-axis-follow] 다. 물듦 구간에서 배경·테두리·글자색이 함께 넘어가므로
      transition 을 다시 쓸 때 그 셋을 빠뜨리면 크로스페이드가 끊긴다.
      선택자에 [data-axis-follow] 를 함께 적어야 한다 — 위쪽 규칙이 명시도가 더 높아
      한쪽만 적으면 파일 뒤에 있어도 진다.
   ⚠️ 빛번짐은 MATE 오렌지(#fc6500)가 아니라 xCalibur 그라디언트 끝단(#F18757)이다.
      두 브랜드는 색으로 나눈다.
   ⚠️ 마우스가 있을 때만 건다. 터치에서 :hover 는 한 번 누르면 붙어 있는 상태가 된다. */
@media (hover: hover) and (pointer: fine) {
  .xc-xc__sol > li,
  [data-axis-follow] .xc-xc__sol > li {
    transition: background-color .25s ease, border-color .25s ease, color .25s ease,
                box-shadow .28s var(--xc-ease-out);
  }
  .xc-xc__sol.is-tilt-back > li,
  [data-axis-follow] .xc-xc__sol.is-tilt-back > li {
    transition: background-color .25s ease, border-color .25s ease, color .25s ease,
                box-shadow .28s var(--xc-ease-out),
                transform .35s var(--xc-ease-out);
  }
  .xc-xc__sol > li:hover {
    box-shadow: 0 16px 38px rgba(241, 135, 87, .32);
    border-color: rgba(241, 135, 87, .5);
  }
}
@media (prefers-reduced-motion: reduce) {
  .xc-xc__sol > li,
  [data-axis-follow] .xc-xc__sol > li { transition: none; }
}
.xc-xc__sol-kind {
  font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-bold);
  letter-spacing: .06em; color: var(--xc-text-weak);
}
/* ⚠️ 위 여백은 묶음(.xc-xc__sol-head)이 갖는다. 여기 두면 두 번 더해진다 */
.xc-xc__sol-name {
  font-size: var(--xc-fs-xc-sol-name); font-weight: var(--xc-fw-extra);
  letter-spacing: -.02em; color: var(--xc-text);
}
.xc-xc__sol-tag {
  margin-top: 12px;
  font-size: var(--xc-fs-md); font-weight: var(--xc-fw-bold);
  color: var(--xc-text); line-height: 1.5; text-wrap: pretty;
}
/* 이름과 브랜드 동사를 한 줄에 묶는다.
   ⚠️ 층을 하나 줄이려는 것이다. 분류(kind)와 동사(wield)가 둘 다 13px 회색이라
      28px 이름을 사이에 두고 똑같은 라벨이 위아래로 붙어 있었다.
      분류는 지울 수 없다 — xMES 의 「MES」, xVerse 의 「디지털트윈」처럼
      카드 어디에도 다시 안 나오는 말이 6장에 있다.
   ⚠️ 동사는 h3 밖에 둔다. 안에 넣으면 제목 글에 섞여 문서 구조가 흐려진다.
   ⚠️ baseline 정렬. 28px 과 13px 을 가운데로 맞추면 작은 쪽이 떠 보인다. */
.xc-xc__sol-head {
  margin-top: 8px;
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 10px;
}
/* 브랜드 동사. 히어로에서 뜻을 한 번 달고, 카드에서는 Wield your ___ 만 반복한다.
   ⚠️ 크게 키우지 않는다. 제품 이름(28px)보다 커지면 동사가 이름을 눌러 버린다. */
.xc-xc__sol-wield {
  font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-bold);
  letter-spacing: .04em; color: var(--xc-text-weak);
}
.xc-xc__sol-desc {
  margin-top: 10px;
  font-size: var(--xc-fs-sm); color: var(--xc-text-sub);
  line-height: 1.7; text-wrap: pretty;
}

/* ── ⑥ CTA ── */
/* ⚠️ 네이비 바탕은 푸터에만 쓴다. 본문 안의 배너·상자는 회색으로 둔다.
   배경만 바꾸면 안 된다 — 글자·버튼이 네이비 전제로 흰색이었다. 함께 되돌린다.
   채용안내의 '지원하기' 상자와 같은 값을 쓴다. */
/* 글은 왼쪽, 버튼은 오른쪽. 한 줄에 마주 놓는다.
   ⚠️ 글을 .xc-xc__cta-txt 로 묶어 둔다. xCalibur 소개 화면만 제목 아래 리드가
      하나 더 있어서, 감싸지 않으면 그 리드가 버튼 자리(2열)로 들어간다.
   ⚠️ 버튼은 글 덩어리의 세로 한가운데다. 제목 줄 수가 화면마다 달라(한 줄·두 줄)
      버튼이 앉는 절대 높이는 화면마다 다르다. 기준은 「글 덩어리의 가운데」다.
   ⚠️ 좁아지면(720px 이하) 한 칸으로 접고 버튼도 왼쪽에 붙인다.
      한 칸에서 버튼만 오른쪽에 두면 글과 따로 노는 조각이 된다. */
.xc-xc__cta-box {
  padding: clamp(36px, 4vw, 64px);
  background: var(--xc-bg-muted); border: 1px solid var(--xc-border);
  border-radius: var(--xc-radius-lg);
  text-align: left;
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  align-items: center; gap: clamp(20px, 3vw, 48px);
}
.xc-xc__cta-box .xc-h2 { color: var(--xc-text); }
.xc-xc__cta-box .xc-lead {
  margin-top: 16px; max-width: 46em;
  color: var(--xc-text-sub);
}
.xc-xc__cta-acts {
  display: flex; flex-wrap: wrap; gap: 10px; justify-content: flex-end;
}
@media (max-width: 720px) {
  .xc-xc__cta-box { grid-template-columns: minmax(0, 1fr); }
  .xc-xc__cta-acts { justify-content: flex-start; }
}

@media (max-width: 1024px) {
  .xc-xc__axis { grid-template-columns: 1fr; }
  .xc-xc__sol { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 640px) {
  .xc-xc__sol { grid-template-columns: 1fr; }
  /* 좁은 화면에서는 <br> 로 고정한 줄이 상자 안에서 또 접힌다.
     글자를 한 단계 낮춰 지정한 줄을 지킨다 */
  .xc-xc__story-body p { font-size: var(--xc-fs-16); }
}


/* ══════════════════ MATE 솔루션 ══════════════════
   19개가 같은 틀을 쓴다. 섹션 구성은 페이지마다 다르다(3~5개) —
   틀은 '있는 섹션만 그린다'. 없는 섹션을 빈 채로 두지 않는다.
   ⚠️ 콘텐츠는 legacy 를 그대로 옮긴다. 카피를 새로 쓰지 않는다(PROJECT.md 작업 범위).
   ────────────────────────────────────────── */

/* ── 그룹 목록 (AI 솔루션 6 등) ── */
.xc-solist {
  margin-top: clamp(24px, 3vw, 40px);
  display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(12px, 1.4vw, 20px);
}
.xc-solist > li { position: relative; }
.xc-solist__card {
  height: 100%; display: flex; flex-direction: column;
  padding: clamp(24px, 2.6vw, 36px);
  background: var(--xc-bg);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius-lg);
  /* ⚠️ 카드는 움직이지 않는다. 색만 바뀐다.
     ⚠️ 이징은 --xc-ease-standard 를 쓴다. --xc-ease-out 은 등장용 곡선이라
        앞이 너무 빨라(초반 60ms 에 90% 진행) 색 전환이 안 보인다. */
  transition: background-color var(--xc-dur-slow) var(--xc-ease-standard),
              border-color var(--xc-dur-slow) var(--xc-ease-standard);
}
/* 배경이 바뀌는 동안 글자도 같은 속도로 따라오게 한다 */
.xc-solist__name, .xc-solist__en, .xc-solist__ko,
.xc-solist__desc, .xc-solist__more {
  transition: color var(--xc-dur-slow) var(--xc-ease-standard);
}
/* 호버 반응은 실제로 갈 수 있는 카드에만. 준비 중 카드는 조용히 둔다.
   ⚠️ 글자색을 하나하나 뒤집지 않는다. 역할 토큰만 갈아 끼우면 카드 안 모든 글자가
      따라온다(사이트의 .xc-dark 가 쓰는 방식과 같다).
      한글 정의는 --xc-accent 라 오렌지로 남는데, 네이비 위 5.64:1 로 기준을 넘는다. */
.xc-solist > li.is-linked:hover .xc-solist__card {
  background: var(--xc-navy); border-color: var(--xc-navy);
  --xc-text:        var(--xc-white);
  --xc-text-sub:    rgba(255, 255, 255, .72);
  --xc-text-weak:   rgba(255, 255, 255, .52);
  --xc-border-weak: rgba(255, 255, 255, .12);
}
.xc-solist__name {
  font-size: var(--xc-fs-awd-yr); font-weight: var(--xc-fw-extra);
  letter-spacing: var(--xc-ls-heading); color: var(--xc-text); text-wrap: pretty;
}
/* 카드 전체가 클릭 영역이다. 이름만 링크로 두고 ::after 로 카드를 덮는다
   (게시판 목록과 같은 이유 — 요약까지 링크 이름이 되면 스크린리더가 다 읽는다) */
.xc-solist__name a::after { content: ""; position: absolute; inset: 0; }
/* 아직 화면이 없는 것 — 눌러도 갈 데가 없다는 걸 글자와 색이 함께 말한다 */
.xc-solist__more--soon { color: var(--xc-text-weak); font-weight: var(--xc-fw-medium); }
.xc-solist__more--soon::after { content: ""; }
.xc-solist__en {
  margin-top: 6px;
  font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-semibold);
  letter-spacing: .02em; color: var(--xc-text-weak);
}
.xc-solist__ko {
  margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--xc-border-weak);
  font-size: var(--xc-fs-md); font-weight: var(--xc-fw-bold); color: var(--xc-orange);
}
.xc-solist__desc {
  margin-top: 10px; font-size: var(--xc-fs-sm); color: var(--xc-text-sub);
  line-height: 1.7; text-wrap: pretty;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden;
}
.xc-solist__more {
  margin-top: auto; padding-top: clamp(18px, 2vw, 26px);
  display: flex; align-items: center; gap: 6px;
  font-size: var(--xc-fs-sm); font-weight: var(--xc-fw-semibold); color: var(--xc-text);
}
/* 화살표만 따로 민다. ::after 의 content 로는 못 움직여서 요소로 뺐다 */
.xc-solist__more i {
  font-style: normal;
  transition: transform var(--xc-dur-base) var(--xc-ease-out);
}
.xc-solist > li.is-linked:hover .xc-solist__more i { transform: translateX(5px); }

/* ── 상세 : 형제 솔루션 이동 ──
   히어로 바로 아래. 좌우 끝에 붙되 본문과 같은 세로선(.xc-area)에 맞춘다.
   화면 맨 끝까지 밀면 GNB·본문과 어긋나 보이고 좁은 화면에서 여백이 사라진다. */
/* 구분은 선이 아니라 면이 한다. 옅은 띠를 깔면 경계가 스스로 생기므로
   여백을 줄여도 다음 섹션과 섞이지 않는다 */
.xc-solnav { background: var(--xc-gray-50); }
.xc-solnav__area {
  display: flex; align-items: stretch; justify-content: space-between;
  gap: 12px; padding-block: clamp(14px, 1.4vw, 20px);
}
/* ⚠️ .xc-sub 의 상단 여백은 '히어로 바로 아래에 본문' 을 전제한 값이다.
      사이에 이동 바가 끼면 여백이 두 번 쌓인다. 이 조합에서만 끌어올린다 */
.xc-solnav + .xc-sub { padding-top: clamp(44px, 4.5vw, 72px); }
.xc-solnav__btn {
  display: flex; align-items: center; gap: clamp(10px, 1vw, 16px);
  min-width: 0;                       /* ⚠️ 없으면 긴 이름이 flex 를 밀어 가로 스크롤이 생긴다 */
  max-width: calc(50% - 6px);
  padding: clamp(10px, 1vw, 14px) clamp(14px, 1.4vw, 20px);
  border-radius: var(--xc-radius);
  text-decoration: none; color: var(--xc-text);
}
.xc-solnav__btn--next { margin-left: auto; text-align: right; }
.xc-solnav__txt { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.xc-solnav__dir {
  font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-semibold);
  color: var(--xc-text-weak);
}
.xc-solnav__name {
  font-size: var(--xc-fs-sm); font-weight: var(--xc-fw-semibold); color: var(--xc-text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.xc-solnav__arw {
  flex: none; display: grid; place-items: center;
  width: clamp(44px, 3.6vw, 56px); aspect-ratio: 1; border-radius: 50%;
  border: 1px solid var(--xc-border-strong); color: var(--xc-text);
  --hc-fill: var(--xc-navy);                   /* CTA 버튼과 같은 원형 확장 호버 */
  /* ⚠️ 버튼은 제자리에 있는다. 움직이는 것은 안에서 퍼지는 원뿐이다 */
  transition: border-color var(--xc-dur-slow) var(--xc-ease-standard),
              color var(--xc-dur-slow) var(--xc-ease-standard);
}
.xc-solnav__arw svg { width: 21px; height: 21px; }

/* 갈 수 있는 쪽만 반응한다.
   ⚠️ 글자 줄에는 색을 칠하지 않는다 — 화살표 단추 하나만 색이 찬다.
      글자까지 뒤집으면 이동 바가 본문보다 세게 읽힌다.
   ⚠️ 원을 퍼뜨리는 방아쇠는 원 자신이 아니라 바깥 버튼이다. 글자 위에 있어도 반응해야 한다.
      (.xc-hover-circle 기본 규칙은 자기 :hover 라 여기서 덮어쓴다) */
a.xc-solnav__btn:is(:hover, :focus-visible) .xc-solnav__arw {
  border-color: var(--xc-navy); color: var(--xc-white);
}
a.xc-solnav__btn:is(:hover, :focus-visible) .xc-solnav__arw::after {
  transform: translate(-50%, -50%) scale(1);
}
.xc-solnav__btn:focus-visible { outline: 2px solid var(--xc-focus); outline-offset: 3px; }

/* 아직 없는 페이지. 이름은 그대로 보여 주되 누를 수 없다는 것만 흐린 글자로 알린다
   (배지·테두리 없음. 이름은 지우지 않는다 — 어디로 이어지는지가 이 줄의 목적이다) */
.xc-solnav__btn.is-soon { cursor: default; }
.xc-solnav__btn.is-soon .xc-solnav__name { color: var(--xc-text-weak); }
.xc-solnav__btn.is-soon .xc-solnav__arw  { opacity: .45; }

@media (max-width: 640px) {
  .xc-solnav__btn { gap: 8px; padding-inline: 12px; }
}

/* ── 상세 : 제품개요 ── */
.xc-sol__lead { margin-top: clamp(20px, 2.4vw, 32px); }
/* ⚠️ 크기·줄 길이·행간을 .xc-lead 와 같은 값으로 둔다. 제품개요는 다른 화면(사업분야·회사소개
   ·고객지원)의 섹션 리드문과 같은 자리다. 여기만 본문 크기(17px)를 쓰면 화면을 넘나들 때
   솔루션만 작아 보인다. 셋은 한 벌이라 크기만 따로 바꾸면 안 된다 */
.xc-sol__lead p {
  /* ⚠️ ch 를 쓰지 않는다. ch 는 숫자 '0' 의 폭(약 0.55em)이라 한글에서는 절반만 들어간다
     — 62ch 는 한글 34자밖에 안 되고, 그러면 어느 절도 한 줄에 못 들어가 통째로 접힌다.
     한글은 한 글자가 1em 이므로 em 으로 잡는다. 54em = 한글 약 54자.
     이 값은 아래 span(절 단위 줄바꿈)이 실제로 동작하는 하한이다. 더 줄이면 무력해진다 */
  /* ⚠️ 예전에 '한 페이지에 솔루션이 여섯이라 리드 크기면 페이지가 큰 글씨로 읽힌다'는
     이유로 본문 크기까지 낮췄던 적이 있다. 2026-08-11 전 화면 실측으로 되돌렸다.
     리드는 전 화면 30곳이 21px 인데 여기 19곳만 15.8px 라 71% 크기였다.
     제품 제목이 44px(다른 화면 섹션 제목 36px보다 크다)인데 그 아래 리드가 본문 크기면
     낙차가 너무 크다. 제목 44 : 리드 21 이 다른 화면의 36 : 21 과 같은 결이다. */
  max-width: 62em; font-size: var(--xc-fs-lead); color: var(--xc-text-sub);
  line-height: 1.8; text-wrap: pretty;
}
/* 문장을 통째로 옮긴다 — 한 문장이 줄 중간에서 시작해 다음 줄로 넘어가지 않는다.
   inline-block 은 남은 폭에 안 들어가면 통째로 다음 줄로 내려가고,
   한 줄보다 긴 문장은 그 안에서만 접힌다(길면 줄바꿈 허용).
   ⚠️ 어절이 갈라지는 문제는 전역 word-break: keep-all 이 이미 막고 있다. 여긴 문장 단위다 */
.xc-sol__lead p > span { display: inline-block; }
.xc-sol__lead p + p { margin-top: 16px; }
/* 틀은 본문 폭을 그대로 채우고, 줄어드는 것은 안쪽 그림뿐이다.
   ⚠️ 폭 제한을 figure 에 걸면 안 된다 — 틀까지 같이 줄어든다 */
.xc-sol__fig {
  margin: clamp(24px, 3vw, 40px) 0 0;
  padding: clamp(24px, 3vw, 48px);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius-lg);
  background: var(--xc-bg);
}
.xc-sol__fig img {
  display: block; margin-inline: auto;
  width: 100%; max-width: 820px; height: auto;   /* 원본 1820px. 다 펴면 설명글보다 커진다 */
}

/* ── AI 솔루션 한 페이지 ──────────────────────────────
   6개를 화면으로 나누지 않고 좌측 고정 목차 + 우측 흐름으로 이어 본다.
   틀은 사업분야 개요(.xc-bizov)를 그대로 쓰고, 여기서는 솔루션 사이 간격만 정한다.
   ⚠️ 솔루션 이름이 h2, 그 안 섹션(제품개요·주요 기능…)이 h3 다. 한 페이지에 여섯 벌이
      들어가므로 위계를 한 단계씩 내려야 목차와 본문이 어긋나지 않는다. */
.xc-solall__one + .xc-solall__one { margin-top: clamp(88px, 11vw, 176px); }
.xc-solall__head { padding-bottom: clamp(20px, 2.4vw, 32px); border-bottom: 2px solid var(--xc-text); }
.xc-solall__sub {
  margin-top: 10px;
  font-size: var(--xc-fs-sm); font-weight: var(--xc-fw-semibold); color: var(--xc-text-sub);
}
/* 아티클 안 첫 섹션은 이름 바로 아래다 — 섹션 사이 리듬을 그대로 두면 너무 벌어진다 */
.xc-solall__one .xc-blk:first-of-type { margin-top: clamp(28px, 3.4vw, 48px); }
/* ⚠️ 사업분야 개요의 섹션 제목과 같은 크기다(.xc-bizov__flow .xc-blk__head .xc-h2).
   같은 틀을 쓰는 두 화면이라 오갈 때 제목 크기가 달라지면 안 된다 */
.xc-h3 {
  font-size: var(--xc-fs-blk-h3); font-weight: var(--xc-fw-extra);
  letter-spacing: var(--xc-ls-heading); color: var(--xc-text); text-wrap: pretty;
}

/* ── 상세 : 도입의 필요성 ───────────────────────────────
   짧은 문장이 5~12개 늘어선다. 문단으로 두면 벽처럼 보이고, 카드로 두면 12장이 된다.
   알약으로 흘려 놓으면 개수가 달라도 덩어리로 읽힌다 */
.xc-need {
  margin-top: clamp(20px, 2.4vw, 32px);
  display: flex; flex-wrap: wrap; gap: 10px;
}
.xc-need > li {
  padding: 10px 18px; border-radius: var(--xc-radius-full);
  background: var(--xc-gray-50); border: 1px solid var(--xc-border-weak);
  font-size: var(--xc-fs-sm); color: var(--xc-text-sub); line-height: 1.5;
}

/* 순서가 있는 알약(업무흐름도처럼 차례가 뜻을 갖는 목록).
   ⚠️ <ol> 로 두는 것만으로는 번호가 화면에 안 나온다. flex 로 펴는 순간
      브라우저 기본 마커가 사라지기 때문이다. 카운터로 직접 그린다 */
.xc-need--num { counter-reset: xc-need; }
.xc-need--num > li {
  counter-increment: xc-need;
  display: flex; align-items: baseline; gap: 9px; padding-left: 12px;
}
.xc-need--num > li::before {
  content: counter(xc-need, decimal-leading-zero);
  flex: none;
  font-size: var(--xc-fs-12); font-weight: var(--xc-fw-bold);
  letter-spacing: .04em; color: var(--xc-orange);
}

/* ── 상세 : 적용 예시 소제목 ───────────────────────────
   한 섹션 안에 사례가 여러 건이고, 사례마다 딸린 형태가 다르다(표 · 설명 · 대조).
   소제목만 같은 모양으로 두어 어디서 사례가 갈리는지 보이게 한다 */
.xc-solcase {
  margin-top: clamp(30px, 3.2vw, 46px);
  padding-left: 14px; border-left: 3px solid var(--xc-orange);
}
/* 섹션 제목 바로 아래 오는 첫 사례는 제목과의 간격을 다른 섹션과 맞춘다 */
.xc-blk__head + .xc-solcase { margin-top: clamp(20px, 2.4vw, 32px); }
.xc-solcase__title {
  font-size: var(--xc-fs-h4); font-weight: var(--xc-fw-bold);
  letter-spacing: var(--xc-ls-heading); color: var(--xc-text); text-wrap: pretty;
}
.xc-solcase__desc {
  margin-top: 8px;
  font-size: var(--xc-fs-sm); color: var(--xc-text-sub); line-height: 1.75; text-wrap: pretty;
}

/* ── 상세 : 도입 전 · 도입 후 대조 ─────────────────────
   legacy 는 이 대조를 그림 한 장으로 두었다. 글자가 그림 안에 박혀 있어 코드로 옮긴다.
   ⚠️ 두 열의 높이를 맞추지 않는다. 단계 수가 다른 것이 이 도해가 말하려는 바다 */
.xc-ba {
  margin-top: clamp(20px, 2.4vw, 32px);
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(12px, 1.4vw, 20px);
}
.xc-ba__col {
  padding: clamp(20px, 2vw, 28px);
  background: var(--xc-gray-50);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius-lg);
}
.xc-ba__head {
  display: inline-block; padding: 6px 14px; border-radius: var(--xc-radius-full);
  background: var(--xc-navy); color: #fff;
  font-size: var(--xc-fs-12); font-weight: var(--xc-fw-bold); letter-spacing: .04em;
}
.xc-ba__col--new .xc-ba__head { background: var(--xc-orange); }
.xc-ba__desc {
  margin-top: 14px;
  font-size: var(--xc-fs-sm); color: var(--xc-text-sub); line-height: 1.7; text-wrap: pretty;
}
.xc-ba__flow { margin-top: clamp(16px, 1.6vw, 22px); display: grid; gap: 0; }
.xc-ba__flow > li {
  padding: 13px 16px; background: var(--xc-bg);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius);
  font-size: var(--xc-fs-sm); font-weight: var(--xc-fw-medium);
  color: var(--xc-text); line-height: 1.5; text-align: center; text-wrap: pretty;
}
.xc-ba__flow > li em {
  display: block; margin-top: 3px;
  font-style: normal; font-size: var(--xc-fs-12); font-weight: var(--xc-fw-regular);
  color: var(--xc-text-weak);
}
/* 화살표는 칸 사이에만 둔다 — 마지막 칸 아래에 꼬리가 남지 않게 */
.xc-ba__flow > li + li { margin-top: 30px; position: relative; }
.xc-ba__flow > li + li::before {
  content: ""; position: absolute; left: 50%; top: -30px;
  width: 1.5px; height: 30px; background: var(--xc-text-weak);
}
.xc-ba__flow > li + li::after {
  content: ""; position: absolute; left: 50%; top: -9px;
  width: 9px; height: 9px; translate: -50% 0; rotate: 45deg;
  border-right: 2px solid var(--xc-text-weak); border-bottom: 2px solid var(--xc-text-weak);
}
.xc-ba__col--new .xc-ba__flow > li + li::before,
.xc-ba__col--new .xc-ba__flow > li + li::after { border-color: var(--xc-orange); background: var(--xc-orange); }
.xc-ba__col--new .xc-ba__flow > li + li::after { background: none; border-color: var(--xc-orange); }
.xc-ba__col--new .xc-ba__flow > li.is-key {
  border-color: var(--xc-orange); border-width: 2px;
  color: var(--xc-orange);
}
@media (max-width: 720px) {
  .xc-ba { grid-template-columns: minmax(0, 1fr); }
}

/* ── 상세 : 메뉴 묶음 ──────────────────────────────────
   '묶음 이름 + 메뉴 여러 개' 인 기능 목록(Cloud·QMS)용.
   ⚠️ 주요 기능 카드(.xc-sol__feat)와 다르다. 저건 기능마다 설명 한 줄이고
      이건 메뉴 이름 나열이라, 같은 카드에 담으면 글자만 빽빽해진다 */
.xc-menu { margin-top: clamp(20px, 2.4vw, 32px); }
.xc-menu > li {
  padding: clamp(20px, 2vw, 26px);
  background: var(--xc-gray-50);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius-lg);
}
.xc-menu > li > b {
  display: block; padding-bottom: 12px; margin-bottom: 12px;
  border-bottom: 1px solid var(--xc-border-weak);
  font-size: var(--xc-fs-h4); font-weight: var(--xc-fw-bold);
  letter-spacing: var(--xc-ls-heading); color: var(--xc-text); text-wrap: pretty;
}
.xc-menu ul { display: flex; flex-direction: column; gap: 7px; }
.xc-menu ul > li {
  position: relative; padding-left: 11px;
  font-size: var(--xc-fs-sm); color: var(--xc-text-sub); line-height: 1.6; text-wrap: pretty;
}
.xc-menu ul > li::before {
  content: ""; position: absolute; left: 0; top: .62em;
  width: 4px; height: 4px; border-radius: 50%; background: var(--xc-text-weak);
}

/* 용어 풀이 한 줄 */
.xc-sol__note {
  margin-top: clamp(20px, 2.4vw, 32px);
  padding: clamp(18px, 2vw, 26px);
  background: var(--xc-gray-50);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius-lg);
  font-size: var(--xc-fs-sm); color: var(--xc-text-sub); line-height: 1.75; text-wrap: pretty;
}
/* ⚠️ --xc-gray-50 은 .xc-dark 에서 뒤집히지 않는다. 글자만 흰색으로 바뀌어
      흰 상자 위에 흰 글자가 남는다(xVerse #scabbard 에서 실제로 그랬다).
      어두운 구간에서는 배경도 같이 뒤집는다.
   ⚠️ 값을 새로 적지 않고 같은 구간의 카드(.xc-xm__trust > li)가 쓰는
      --gnb-tint 를 그대로 쓴다. 두 상자가 따로 놀면 안 된다. */
.xc-dark .xc-sol__note {
  background: var(--gnb-tint);
  border-color: rgba(255, 255, 255, .14);
}

/* ── 상세 : 도해를 담는 회색 상자 ──────────────────────
   여러 조각으로 이루어진 도해(ADUP 가지 · OPC 알고리즘 · QP 원)를 한 상자에 묶는다.
   ⚠️ 사진 한 장(AD)이나 절차 카드(TMS)에는 쓰지 않는다 — 이미 자기 테두리가 있어
      상자가 두 겹이 된다.
   ⚠️ 상자가 회색이 되면 그 안 조각은 흰색이어야 한다. 회색 위 회색은 경계가 사라진다 */
.xc-figbox {
  margin-top: var(--xc-sol-figgap);
  padding: clamp(28px, 3.4vw, 52px);
  background: var(--xc-gray-50);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius-lg);
}
/* 상자 안에서는 바깥 여백을 상자가 대신한다 */
.xc-figbox > * { margin-top: 0; }
/* 조각을 흰색으로 뒤집는다 */
.xc-figbox .xc-hub__cell,
.xc-figbox .xc-opc > .xc-opc__step { background: var(--xc-bg); }
/* ⚠️ .xc-pipe__chips 는 여기 없다. 저건 흰 몸통(.xc-pipe__body) 위에 앉아 있어
   회색이라야 구분된다. 회색 상자에 직접 놓인 조각만 흰색으로 뒤집는다 */
/* 아이콘 원은 카드와 같은 흰색이라 테두리로만 구분된다 — 한 톤 낮춰 되살린다 */
.xc-figbox .xc-hub__ico { background: var(--xc-gray-50); }

/* ── 상세 : 하나에서 갈라지는 가지 ─────────────────────
   원본은 방사형 그림 한 장이었다(ADUP). 글자가 그림 안에 박혀 있어 코드로 옮겼다.
                  ADUP
        ┌────┬────┼────┬────┐
       이미지 데이터 전이 모델 시각화

   ⚠️ 가지선을 카드에 그리지 않는다. 카드가 등장 애니메이션으로 움직이면 선도 함께
      흔들린다 — 선은 따로 두고 자리만 맞춘다.
   ⚠️ 가로선의 양 끝은 첫 칸과 끝 칸의 '한가운데' 다. 5칸이면 각각 10% · 90% 다.
      칸 수가 바뀌면 이 값도 바뀐다(--hub-n 으로 계산한다).
   ⚠️ 초기 상태를 CSS 에 두지 않는다. 스크립트가 막혀도 다 보인다.
   ────────────────────────────────────────── */
/* --hub-mid : 줄기가 설 가운데 칸. 칸이 홀수여야 가운데가 생긴다 */
.xc-hub { --hub-n: 5; --hub-mid: 3; --hub-gap: clamp(10px, 1.2vw, 18px); }
.xc-hub__core {
  width: fit-content; margin-inline: auto; text-align: center;
  padding: clamp(20px, 2.2vw, 30px) clamp(28px, 3vw, 44px);
  background: var(--xc-navy); color: var(--xc-white);
  border-radius: var(--xc-radius-lg);
}
.xc-hub__core b {
  display: block;
  font-size: var(--xc-fs-hub-core-em); font-weight: var(--xc-fw-extra);
  letter-spacing: var(--xc-ls-heading);
}
.xc-hub__core span { font-size: var(--xc-fs-sm); color: rgba(255, 255, 255, .72); }

/* 가지선 — 세로 줄기 → 가로 버스 → 칸마다 내려꽂는 선 */
.xc-hub__wire {
  position: relative; height: clamp(40px, 5vh, 64px);
  display: grid;
  grid-template-columns: repeat(var(--hub-n), minmax(0, 1fr));
  /* 위 줄 = 줄기, 아래 줄 = 칸으로 내려가는 선 */
  grid-template-rows: 1fr 1fr;
  /* ⚠️ 칸 사이 여백을 아래 카드 격자와 똑같이 준다. 빠뜨리면 다섯 칸이 여백 없이
     폭을 나눠 가져 세로선이 카드 한가운데에서 벗어나고(가운데 칸만 맞는다),
     가로선은 여백을 셈에 넣은 자리에서 끝나 양 끝이 세로선 밖으로 삐져나온다. */
  gap: 0 var(--hub-gap);
}
.xc-hub__stem, .xc-hub__bus, .xc-hub__wire > span {
  background: var(--xc-border-strong);
}
/* ⚠️ 줄기도 세로선과 같은 격자에 올린다. 예전에는 줄기만 left:50% 로 따로 잡았는데,
   그러면 자리를 정하는 길이 둘이라 무엇이든 어긋나면 그대로 드러난다.
   같은 칸(--hub-mid)에 같은 방식(justify-self: center)으로 세우면 둘이 어긋날 수 없다. */
.xc-hub__stem {
  grid-row: 1; grid-column: var(--hub-mid);
  justify-self: center; align-self: stretch;
  width: 2px; transform-origin: 50% 0;
}
.xc-hub__bus {
  position: absolute; top: calc(50% - 1px); height: 2px;
  /* ⚠️ 타임라인과 같은 계산이다 — 간격을 빼야 선 끝이 칸의 한가운데에 온다 */
  left:  calc((100% - (var(--hub-n) - 1) * var(--hub-gap)) / (var(--hub-n) * 2));
  right: calc((100% - (var(--hub-n) - 1) * var(--hub-gap)) / (var(--hub-n) * 2));
  transform-origin: 50% 50%;
}
/* 칸마다 한 줄씩. 격자 칸의 한가운데에서 아래로 내려간다.
   ⚠️ 아래 줄에만 놓는다. 줄을 지정하지 않으면 위 줄의 줄기 옆으로 밀려 들어간다 */
.xc-hub__wire > span {
  grid-row: 2; align-self: stretch; width: 2px;
  justify-self: center; transform-origin: 50% 0;
}

.xc-hub__cells {
  display: grid; grid-template-columns: repeat(var(--hub-n), minmax(0, 1fr));
  gap: var(--hub-gap);
}
.xc-hub__cell {
  padding: clamp(18px, 1.8vw, 24px);
  background: var(--xc-gray-50);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius-lg);
}
.xc-hub__ico {
  display: grid; place-items: center;
  width: clamp(34px, 3vw, 42px); aspect-ratio: 1; border-radius: 50%;
  background: var(--xc-bg); border: 1px solid var(--xc-border-weak); color: var(--xc-navy);
}
.xc-hub__ico svg { width: 58%; height: 58%; }
.xc-hub__cell > b {
  display: block; margin-top: 12px;
  font-size: var(--xc-fs-h4); font-weight: var(--xc-fw-bold);
  letter-spacing: var(--xc-ls-heading); color: var(--xc-text); text-wrap: pretty;
}
.xc-hub__cell ul { margin-top: 10px; display: flex; flex-direction: column; gap: 7px; }
.xc-hub__cell li {
  position: relative; padding-left: 11px;
  font-size: var(--xc-fs-sm); color: var(--xc-text-sub); line-height: 1.7; text-wrap: pretty;
}
/* ⚠️ 점은 기본색이다. 오렌지는 이 화면에서 '바뀐 것·강조' 에만 쓴다 —
   불릿마다 포인트 컬러를 두면 정작 강조할 곳이 묻힌다.
   다른 설명 목록(.xc-sol__flist)도 같은 회색이라 한 페이지 안에서 점이 하나로 읽힌다 */
.xc-hub__cell li::before {
  content: ""; position: absolute; left: 0; top: .68em;
  width: 4px; height: 4px; border-radius: 50%; background: var(--xc-text-weak);
}

@media (max-width: 1024px) {
  /* 다섯 칸이 좁아 글이 답답해진다. 세 칸으로 접고 가지선은 뜻이 없어지므로 감춘다 */
  .xc-hub { --hub-n: 3; }
  .xc-hub__wire { display: none; }
  .xc-hub__cells { margin-top: clamp(20px, 3vw, 32px); }
}
@media (max-width: 640px) {
  .xc-hub { --hub-n: 1; }
}

/* ── 상세 : QP 제품개요 도해 ──
   원본은 그림 한 장이었다(mate-ai-for-qp-img-01.jpg). 글자가 그림 안에 박혀 있어 옮겼다.
   왼쪽은 중심(Cloud·Local)과 네 갈래, 오른쪽은 데이터에서 예측까지의 흐름이다 */
/* ⚠️ 좌우는 별개의 그림이다. 한 상자에 담지 않고 카드 두 장으로 나눈다.
   담는 그릇은 자리만 잡고, 면·테두리는 각 카드가 가진다 */
/* ⚠️ 카드 한 장이다. 오른쪽 흐름 그림은 뺐다 — 두 칸 격자를 그대로 두면
   카드가 왼쪽 절반만 차지하고 오른쪽이 빈다 */
.xc-qp { display: grid; }
/* ⚠️ 카드 껍데기를 두지 않는다. 바깥 .xc-figbox 가 이미 면과 테두리를 갖는다 */
.xc-qp > * { width: 100%; }
/* 중심을 네 갈래가 둘러싼다 — 원본 그림의 자리 그대로 */
.xc-qp__ring {
  /* 중심 원 지름을 변수로 둔다 — 파문의 링 반지름이 이 값을 기준으로 계산된다 */
  --qp-core: clamp(180px, 18.5vw, 256px);
  position: relative; overflow: hidden;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  grid-template-areas: ".    top    ."
                       "left core   right"
                       ".    bottom .";
  gap: clamp(14px, 1.6vw, 22px); align-items: center; justify-items: center;
  align-content: center;   /* 카드가 세로로 늘어나도 내용은 가운데 */
}
/* 층 순서 — 파문(0) < 갈래(1) < 중심 원(2).
   ⚠️ 갈래가 중심보다 아래여야 원 뒤에서 밀려 나오는 것으로 보인다.
      중심 원의 배경이 불투명(--xc-bg)이라 시작 순간에는 완전히 가려진다 */
.xc-qp__leaf { grid-area: var(--a); z-index: 1; }
.xc-qp__core { grid-area: core; z-index: 2; }

/* 중심에서 번져 나가는 동심원. 자리를 차지하면 격자가 밀리므로 절대 위치로 띄운다.
   ⚠️ 링 전체의 한가운데가 곧 중심 원의 한가운데다(위·아래 갈래 높이가 같은 격자다) */
.xc-qp__wave {
  position: absolute; left: 50%; top: 50%; translate: -50% -50%;
  z-index: 0; pointer-events: none;
  /* ⚠️ 링 간격을 고정값으로 반복(repeating-radial-gradient)하면 안 된다.
     중심 원 크기가 화면 폭에 따라 변하는데 링 자리는 그대로라, 어떤 폭에서는
     링 하나가 원 가장자리에 8px 까지 붙는다. 링마다 '원 가장자리 + 거리' 로 잡는다. */
  width: calc(var(--qp-core) + 232px); aspect-ratio: 1; border-radius: 50%;
  background:
    radial-gradient(circle at 50% 50%, transparent 0 calc(var(--qp-core) / 2 + 26px),
      rgba(22, 29, 41, .10) calc(var(--qp-core) / 2 + 26px) calc(var(--qp-core) / 2 + 27px),
      transparent calc(var(--qp-core) / 2 + 27px)),
    radial-gradient(circle at 50% 50%, transparent 0 calc(var(--qp-core) / 2 + 64px),
      rgba(22, 29, 41, .075) calc(var(--qp-core) / 2 + 64px) calc(var(--qp-core) / 2 + 65px),
      transparent calc(var(--qp-core) / 2 + 65px)),
    radial-gradient(circle at 50% 50%, transparent 0 calc(var(--qp-core) / 2 + 102px),
      rgba(22, 29, 41, .05) calc(var(--qp-core) / 2 + 102px) calc(var(--qp-core) / 2 + 103px),
      transparent calc(var(--qp-core) / 2 + 103px));
}

.xc-qp__core {
  display: grid; place-content: center; justify-items: center; gap: 2px;
  width: var(--qp-core); aspect-ratio: 1;
  border: 6px solid var(--xc-navy); border-radius: 50%;
  /* ⚠️ 면은 흰색을 지킨다. 갈래가 이 원 뒤에서 나오므로 불투명이어야 한다 */
  background: var(--xc-bg);
  /* 그림자로 띄운다. 파문(옅은 링) 위에 놓이므로 세 겹으로 나눈다 —
     가까이는 또렷하게 윤곽을, 멀리는 넓게 퍼져 원이 떠 있게. 한 겹만 쓰면 파문에 묻힌다.
     ⚠️ 색은 포인트 오렌지 #fc6500 이다. .xc-glow 유틸의 오렌지(249,168,92)는
        xCalibur 그라디언트 색이라 MATE 화면에 쓰지 않는다 */
  /* ⚠️ 세로 오프셋 0 이다. 값을 주면 그림자가 아래로 처져 후광의 중심이 원 밖으로
     내려간다 — 여기서는 원을 중심으로 사방에 고르게 퍼져야 파문과 방향이 맞는다
     (.xc-glow 의 --gl-y 주석과 같은 이유) */
  box-shadow: 0 0 24px rgba(252, 101, 0, .16),
              0 0 60px rgba(252, 101, 0, .20),
              0 0 120px rgba(252, 101, 0, .14);
  text-align: center;
}
.xc-qp__core b {
  font-size: var(--xc-fs-qp-core); font-weight: var(--xc-fw-bold);
  letter-spacing: var(--xc-ls-heading); color: var(--xc-text);
}
/* Cloud 와 Local 사이의 점.
   ⚠️ 가운뎃점 글자(·)를 그대로 두면 본문 크기(15~17px)를 물려받아 글자보다 작아 보인다.
      글자를 감추고 실제 원으로 그린다 — 크기를 정확히 정할 수 있다 */
.xc-qp__core i {
  font-style: normal; font-size: 0; line-height: 0;
  width: clamp(4px, 0.42vw, 6px); aspect-ratio: 1;
  border-radius: 50%; background: var(--xc-text-weak);
  margin-block: 4px;
}
.xc-qp__leaf {
  padding: 12px 24px; border-radius: var(--xc-radius-full);
  background: var(--xc-bg); border: 1px solid var(--xc-border-weak);
  font-size: var(--xc-fs-leaf); color: var(--xc-text-sub); text-align: center;
}
/* 흐름 — 데이터 → 신경망 → 예측. 셋이 한 줄에 선다 */
/* ⚠️ 이름표를 흐름에서 빼낸 만큼 아래 여백으로 자리를 마련한다 */
.xc-flow {
  display: flex; align-items: center; justify-content: center;
  gap: clamp(8px, 1.2vw, 18px);
  /* ⚠️ 카드 여백(.xc-qp > *)을 덮어쓴다. 이름표가 흐름 밖으로 나가 있으므로
     그 자리까지 더해야 카드 아래 끝에 글자가 붙지 않는다 */
  padding-bottom: calc(clamp(28px, 3.4vw, 48px) + clamp(34px, 3.2vw, 44px));
}
/* 양 끝은 아이콘 위, 이름 아래 — 원본 그림과 같은 배치.
   ⚠️ 이름표를 흐름 안에 두면 묶음 높이가 '아이콘 + 글자' 가 되어, 가운데 맞춤 기준이
      아이콘이 아니라 그 합의 중간이 된다. 신경망 가운데 선이 아이콘보다 19px 아래를
      지나 어긋나 보인다. 이름표를 띄워 두면 묶음 높이가 아이콘 높이와 같아진다. */
.xc-flow__end {
  position: relative; flex: none;
  font-size: var(--xc-fs-leaf); font-weight: var(--xc-fw-semibold);
  color: var(--xc-text); text-align: center;
}
.xc-flow__end b {
  position: absolute; top: calc(100% + 12px); left: 50%; translate: -50% 0;
  font-weight: inherit; white-space: nowrap;
}
/* ⚠️ 양 끝은 같은 위계다. 색을 나누지 않는다 — 원본 그림은 데이터베이스가 회색이었지만
   그건 그 그림 안의 사정이고, 여기서는 한쪽만 흐려 보일 이유가 없다 */
.xc-flow__ico {
  display: grid; place-items: center;
  width: clamp(46px, 4.6vw, 64px); aspect-ratio: 1; color: var(--xc-navy);
}
.xc-flow__ico svg { width: 100%; height: 100%; }
/* ⚠️ 화살표는 글자다. 그냥 두면 글자상자 안에서 baseline 쪽으로 내려앉아
   아이콘·신경망 가운데 선과 어긋난다. 격자 가운데 맞춤 + line-height 1 로 고정한다 */
.xc-flow__arw {
  flex: none; display: grid; place-items: center; line-height: 1;
  color: var(--xc-text-weak); font-size: var(--xc-fs-h3);
}
/* ⚠️ 혼자 커지면 양 끝 아이콘이 초라해지고 세로로도 넘친다. 폭을 눌러 둔다 */
.xc-flow__net { flex: 1 1 auto; min-width: 0; max-width: 280px; height: auto; }

/* ── 상세 : OPC 제품개요 도해 ──
   원본은 그림 한 장이었다(mate-ai-for-opc-img-01.jpg). 위는 쓰는 알고리즘 두 가지,
   아래는 데이터에서 최적값까지의 흐름이다. 원본 그림의 트리·신경망은 흐릿한 스캔이라 다시 그렸다 */
.xc-alg {
  /* XGBoost 도해가 MLP 보다 넓다. 같은 폭을 주면 트리 상자가 뭉개진다.
     다만 MLP 를 너무 좁히면 층 이름과 노드가 같이 작아진다 — 1.5 : 1 이 절충점이다 */
  display: grid; grid-template-columns: minmax(0, 1.5fr) auto minmax(0, 1fr);
  gap: clamp(12px, 1.6vw, 24px);
  align-items: stretch;   /* 한 행의 카드는 높이를 맞춘다. 속은 각자 가운데에 선다 */
}
.xc-alg__card {
  position: relative;
  display: grid; align-content: center;   /* 높이가 늘어나도 속은 가운데 */
  padding: clamp(30px, 3vw, 42px) clamp(20px, 2.2vw, 30px) clamp(20px, 2.2vw, 30px);
  background: var(--xc-bg);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius-lg);
  text-align: center;
}
/* 이름표가 윗변 위에 앉는다. 아래 흐름의 묶음 이름표(.xc-opc__label)와 같은 규칙이다
   — 한 화면에서 '묶음 이름은 상자 윗변에 앉는다' 를 하나로 지킨다 */
.xc-alg__name {
  position: absolute; top: 0; left: 50%; transform: translate(-50%, -50%);
  padding: 7px 22px; border-radius: var(--xc-radius-full);
  background: var(--xc-navy); border: 0; color: var(--xc-white);
  font-size: var(--xc-fs-md); font-weight: var(--xc-fw-bold);
  letter-spacing: var(--xc-ls-heading); white-space: nowrap;
}
/* 원본 그림을 그대로 옮긴 SVG. 글자가 그림 안에 박히지 않도록 text 로 두었고,
   색은 currentColor 가 아니라 토큰을 직접 읽는다(다크 섹션에 놓일 일이 없다) */
.xc-alg__xgb { display: block; width: 100%; height: auto; margin-top: 14px; }
/* ⚠️ 층 이름(Input·Hidden·Output)은 SVG 안에 있다. 바깥에서 3등분 격자로 얹으면
   노드 기둥(26% · 50% · 74%)과 어긋난다 */
.xc-alg__net { display: block; width: 100%; height: auto; }
/* 두 알고리즘을 잇는 화살표. 글자가 선 위에 얹힌다 */
.xc-alg__link {
  display: grid; justify-items: center; align-content: center; gap: 6px;
  color: var(--xc-text-weak);
}
.xc-alg__link span {
  font-size: var(--xc-fs-md); font-weight: var(--xc-fw-bold);
  color: var(--xc-text); white-space: nowrap;
}
.xc-alg__link::after {
  content: "→"; font-size: var(--xc-fs-alg-arrow); line-height: 1; color: var(--xc-accent);
}

/* 아래 흐름 — 데이터 → [품질예측: 예측모델 → 불량판정] → [최적조건제시: 최적조건 모델 → 설비 최적값 도출]
   ⚠️ 묶음(.xc-opc__group)이 핵심이다. 다섯 칸을 평평하게 늘어놓으면 '무엇이 무엇을 한다' 가
      사라진다. 묶음 이름표가 상자 윗변에 걸터앉아 그 안 두 단계의 결과임을 보여 준다 */
.xc-opc {
  margin-top: clamp(20px, 2.4vw, 32px);
  display: grid;
  grid-template-columns: minmax(0, .8fr) auto minmax(0, 1.4fr) auto minmax(0, 1.4fr);
  gap: clamp(8px, 1.2vw, 18px);
  align-items: stretch;   /* 한 행의 카드는 높이를 맞춘다. 속은 각자 가운데에 선다 */
}
.xc-opc__group {
  position: relative;
  display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  gap: clamp(8px, 1vw, 14px); align-items: stretch;
  padding: clamp(24px, 2.4vw, 34px) clamp(12px, 1.4vw, 20px) clamp(18px, 2vw, 26px);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius-lg);
  background: var(--xc-bg);
}
/* 이름표가 윗변 위에 앉는다. 위 알고리즘 카드(.xc-alg__name)와 같은 모양으로 둔다
   — 한 화면에서 '묶음 이름은 상자 윗변에 앉는 네이비 알약' 하나로 지킨다 */
.xc-opc__label {
  position: absolute; top: 0; left: 50%; transform: translate(-50%, -50%);
  padding: 7px 22px; border-radius: var(--xc-radius-full);
  background: var(--xc-navy); border: 0; color: var(--xc-white);
  font-size: var(--xc-fs-md); font-weight: var(--xc-fw-bold);
  letter-spacing: var(--xc-ls-heading); white-space: nowrap;
}
.xc-opc__step {
  display: grid; justify-items: center; align-content: center; gap: 10px; text-align: center;
  padding: clamp(14px, 1.6vw, 20px) clamp(10px, 1.2vw, 16px);
}
/* 묶음 밖에 홀로 선 단계(실시간 설비 데이터)만 카드로 둔다 */
.xc-opc > .xc-opc__step {
  padding: clamp(18px, 2vw, 26px);
  background: var(--xc-gray-50);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius-lg);
}
.xc-opc__ico { display: grid; place-items: center; width: 40px; height: 40px; color: var(--xc-navy); }
.xc-opc__ico svg { width: 100%; height: 100%; }
.xc-opc__step b {
  font-size: var(--xc-fs-ph-sub); font-weight: var(--xc-fw-bold);
  letter-spacing: var(--xc-ls-heading); color: var(--xc-text);
}
.xc-opc__chips { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px; }
.xc-opc__chips > li {
  padding: 4px 12px; border-radius: var(--xc-radius-full);
  background: var(--xc-bg); border: 1px solid var(--xc-border-weak);
  font-size: var(--xc-fs-xs); color: var(--xc-text-sub);
}
/* 크기는 위 알고리즘 화살표(.xc-alg__link::after)와 같은 척도로 둔다 */
.xc-opc__arw { display: grid; place-items: center; color: var(--xc-accent); }
.xc-opc__arw svg { width: clamp(30px, 3vw, 42px); height: auto; }
/* 묶음 안 화살표는 한 단계 약하게. 묶음과 묶음 사이가 더 큰 이동이다 */
.xc-opc__arw--in { color: var(--xc-text-weak); }
.xc-opc__arw--in svg { width: clamp(24px, 2.3vw, 32px); }

/* ── 상세 : 프로세스 지도(ERP 업무흐름도 · SCM 시스템흐름도) ──
   여러 프로세스가 나란히 서고, 좌우에 바깥 상대(공급업체 · 고객)가 기둥으로 붙는다.
   ⚠️ 원본의 점선 화살표를 전부 옮기지 않는다. 열 사이를 오가는 선이 스무 가닥 넘어
      웹 폭에서는 그물처럼 뭉개진다. 한 프로세스 '안'의 차례만 화살표로 남기고,
      프로세스끼리의 관계는 나란히 세우는 것으로 대신한다.
   ⚠️ 열 수는 도해마다 다르다. 마크업에서 --cols 로 준다 */
.xc-map {
  --map-gap: clamp(10px, 1.2vw, 18px);
  --map-pad: clamp(12px, 1.4vw, 18px);
  margin-top: clamp(24px, 3vw, 40px);
  display: grid; gap: var(--map-gap);
}
.xc-map__row {
  display: grid; grid-template-columns: var(--cols, repeat(3, minmax(0, 1fr)));
  gap: var(--map-gap); align-items: stretch;
}
/* 바깥 상대 기둥 */
.xc-map__rail {
  display: grid; place-content: center;
  width: clamp(66px, 6vw, 92px); padding: 14px 8px;
  background: var(--xc-navy); border-radius: var(--xc-radius-lg);
  color: var(--xc-white);
  font-size: var(--xc-fs-12); font-weight: var(--xc-fw-bold);
  line-height: 1.5; text-align: center; text-wrap: pretty;
}
/* 프로세스 한 열.
   ⚠️ 몸통이 둘 이상일 수 있다(원본에서 한 열 안이 두 갈래로 갈리는 경우).
      줄 수를 못박지 않고 위에서부터 쌓는다 */
.xc-map__col {
  display: grid; align-content: start;
  background: var(--xc-gray-50);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius-lg);
}
/* ⚠️ overflow: hidden 을 쓰지 않는다. 단계에서 기둥으로 뻗는 화살표가 잘린다.
   대신 머리 자체에 위쪽 모서리를 준다 */
.xc-map__head {
  border-radius: calc(var(--xc-radius-lg) - 1px) calc(var(--xc-radius-lg) - 1px) 0 0;
  padding: 11px 12px; background: var(--xc-navy); color: var(--xc-white);
  font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-bold);
  letter-spacing: .02em; text-align: center;
}
.xc-map__body {
  display: grid; gap: 8px; align-content: start;
  padding: var(--map-pad);
}
/* 한 열이 두 갈래로 갈리는 경우(구매자재 프로세스) */
.xc-map__pair {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(8px, 1vw, 14px); align-items: start;
  padding: var(--map-pad);
}
.xc-map__chain { display: grid; gap: 20px; align-content: start; }
.xc-map__body > li,
.xc-map__chain > li {
  position: relative;
  padding: 9px 11px; background: var(--xc-bg);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius-sm);
  font-size: var(--xc-fs-12); color: var(--xc-text);
  line-height: 1.5; text-align: center; text-wrap: pretty;
}
.xc-map__body > li.is-key { border-color: var(--xc-orange); color: var(--xc-orange); font-weight: var(--xc-fw-bold); }
/* 차례가 있는 열 — 항목 사이에 아래 화살표를 둔다 */
.xc-map__body--flow { gap: 20px; }
.xc-map__body--flow > li + li::before,
.xc-map__chain > li + li::before {
  content: ""; position: absolute; left: 50%; top: -20px; height: 20px; width: 0;
  border-left: 1.5px dashed var(--xc-text-weak);
}
.xc-map__body--flow > li + li::after,
.xc-map__chain > li + li::after {
  content: ""; position: absolute; left: 50%; top: 0;
  width: 8px; height: 8px; translate: -50% calc(-100% - 2px); rotate: 45deg;
  border: 0 solid var(--xc-accent); border-bottom-width: 2px; border-right-width: 2px;
}
/* 가로로 늘어놓는 하위 묶음(품질 관리 · 물류 관리 · 입고작업) */
.xc-map__body--row { grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); }
/* 두 칸씩 채우는 묶음(OPTION 카드 안) */
.xc-map__body--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
/* 다른 열의 단계와 이어지는 표시.
   ⚠️ 원본은 이 관계를 열 사이를 직교로 꺾여 도는 점선으로 그린다. 그 배선은 상자 위치가
      픽셀로 고정돼야 성립한다 — 폭이 바뀌면 선이 상자를 뚫고 지나간다.
      '어디서 어디로' 라는 알맹이만 단계에 붙여 남긴다 */
.xc-map__link {
  display: block; margin-top: 5px;
  font-style: normal; font-size: var(--xc-fs-12); font-weight: var(--xc-fw-bold);
  color: var(--xc-orange); line-height: 1.4; text-wrap: pretty;
}

/* 바깥 기둥과 주고받는 단계 — 열 밖으로 선을 뻗는다.
   ⚠️ 세로 잇는 선이 가상요소 두 자리를 이미 쓰므로 가로선은 <i> 로 따로 둔다.
   ⚠️ 길이는 '몸통 안쪽 여백 + 열 사이 여백' 이다. 그래야 끝이 기둥 변에 닿는다 */
.xc-map__chain > li > i,
.xc-map__body > li > i {
  position: absolute; top: 50%; height: 0; z-index: 1;
  width: calc(var(--map-pad) + var(--erp-gap, var(--map-gap)));
  border-top: 1.5px dashed var(--xc-text-weak);
}
.xc-map__chain > li > i::after,
.xc-map__body > li > i::after {
  content: ""; position: absolute; top: 50%;
  width: 8px; height: 8px; rotate: 45deg; border: 0 solid var(--xc-accent);
}
/* ⚠️ 방향 규칙의 선택자를 위 기본 규칙과 같은 깊이로 쓴다.
   `.to-l > i::after` 처럼 짧게 쓰면 명시도가 기본 규칙(.xc-map__chain > li > i::after)보다
   낮아, 기본 규칙의 `border: 0 solid` 가 이겨 촉의 굵기가 0 이 된다 — 화살표 머리가 사라진다.
   나중에 쓴 규칙이라고 이기지 않는다. */
.xc-map__chain > li.to-l > i,   .xc-map__body > li.to-l > i,
.xc-map__chain > li.from-l > i, .xc-map__body > li.from-l > i {
  left: calc(-1 * (var(--map-pad) + var(--erp-gap, var(--map-gap))));
}
.xc-map__chain > li.to-r > i,   .xc-map__body > li.to-r > i,
.xc-map__chain > li.from-r > i, .xc-map__body > li.from-r > i {
  right: calc(-1 * (var(--map-pad) + var(--erp-gap, var(--map-gap))));
}
/* 나가는 쪽은 촉이 바깥 끝에, 들어오는 쪽은 촉이 칸 옆에 */
.xc-map__chain > li.to-l > i::after,
.xc-map__body > li.to-l > i::after {
  left: 0; translate: 2px -50%; border-bottom-width: 2px; border-left-width: 2px;
}
.xc-map__chain > li.from-l > i::after,
.xc-map__body > li.from-l > i::after {
  right: 0; translate: -2px -50%; border-top-width: 2px; border-right-width: 2px;
}
.xc-map__chain > li.to-r > i::after,
.xc-map__body > li.to-r > i::after {
  right: 0; translate: -2px -50%; border-top-width: 2px; border-right-width: 2px;
}
.xc-map__chain > li.from-r > i::after,
.xc-map__body > li.from-r > i::after {
  left: 0; translate: 2px -50%; border-bottom-width: 2px; border-left-width: 2px;
}

/* 한 열 안에서 갈래가 바뀔 때 긋는 금 */
.xc-map__body + .xc-map__body { border-top: 1px dashed var(--xc-border); padding-top: clamp(12px, 1.4vw, 18px); }
/* 여러 열을 한 이름으로 묶을 때(OPTION) */
.xc-map__group {
  display: block; margin-bottom: calc(var(--map-gap) * -.4);
  font-size: var(--xc-fs-12); font-weight: var(--xc-fw-bold);
  letter-spacing: .1em; color: var(--xc-text-weak); text-align: center;
}
/* 도해 아래 붙는 이름표 */
.xc-map__cap {
  font-size: var(--xc-fs-12); font-weight: var(--xc-fw-bold);
  color: var(--xc-text-weak); letter-spacing: .04em;
}

/* ── 상세 : 세 갈래 성과(SCM 기대효과) ──────────────────
   ⚠️ 생김새는 이 화면의 다른 기대효과 카드(.xc-sol__pts--cards)와 같아야 한다.
      원본은 알약 테두리에 칸막이를 친 띠였지만, 한 화면 안에서 같은 이름의 구간이
      둘로 보이면 안 된다. 여백·바탕·테두리·모서리를 카드 규칙 그대로 쓰고
      아이콘과 이름만 담는다. 열 수는 .xc-fitrow 가 맡는다 */
.xc-eff3 { margin-top: clamp(20px, 2.4vw, 32px); }
.xc-eff3 > li {
  display: grid; justify-items: center; gap: 14px;
  padding: clamp(22px, 2.4vw, 30px);
  background: var(--xc-gray-50);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius-lg);
}
.xc-eff3 svg { display: block; width: clamp(34px, 3.2vw, 44px); height: auto; color: var(--xc-navy); }
.xc-eff3 b {
  font-size: var(--xc-fs-h4); font-weight: var(--xc-fw-bold);
  letter-spacing: var(--xc-ls-heading); color: var(--xc-text);
}

/* ── 상세 : ERP 업무흐름도 ─────────────────────────────
   원본 배치를 그대로 따른다. 도해 전체가 격자 하나다.
     열 : 공급업체 │ 구매자재(두 갈래) │ 잇는 길A │ 생산 │ 잇는 길B │ 영업 │ 고객 │ OPTION
     줄 : 세 프로세스의 칸이 같은 줄에 서도록 12줄로 나눈다
   ⚠️ 칸끼리 잇는 화살표가 이 그림의 뼈대다. 그러려면 세 프로세스가 같은 줄 격자를 써야 한다.
      프로세스마다 따로 목록을 두면 칸의 높이가 제각각이라 이을 수가 없다.
   ⚠️ 열을 건너뛰는 선은 '잇는 길' 열에서 꺾는다. 원본도 프로세스 상자 사이 빈 띠에서 꺾는다.
   ⚠️ 겹치는 격자다. 상자·선·바탕판 모두 --a 로 자리를 못박는다.
      마크업 차례는 바탕판 → 선 → 칸. 뒤에 오는 것이 위에 그려진다 */
.xc-erp {
  --erp-gap: clamp(8px, 1vw, 14px);
  --erp-row: 20px;      /* 줄 사이 */
  /* 칸 높이의 절반. 꺾이는 선이 칸 한가운데에서 나가고 들어온다.
     ⚠️ 눈대중으로 잡지 않는다. 칸 높이 = 안쪽 여백 9+9 + 글자 12×1.5 + 테두리 1+1 = 38px 다 */
  --erp-half: 19px;
  --erp-lap: 3px;       /* 바닥 배선에서 세로 도막이 가로 버스를 지나치는 양 */
  --q-size: clamp(46px, 4.2vw, 58px);  /* 품질 · 물류 원 지름 */
  --erp-cor: clamp(34px, 3.4vw, 52px); /* 잇는 길 열 폭 */
  /* 품질 · 물류 머리띠와 원 사이. 줄 사이 여백(20px)만으로는 원으로 들어오는
     화살표를 놓을 자리가 없다. 원 무리를 통째로 내려 그만큼 벌린다.
     ⚠️ 아래(--erp-half-q 등)를 기준으로 재는 값들은 그대로다. 위로만 늘어난다 */
  /* 기둥 상자가 한 줄일 때의 높이 — 위아래 여백 14 + 12px 글자 한 줄(1.5) */
  --erp-railh: calc(28px + 1.5 * var(--xc-fs-12));
  --q-drop: 16px;
  --q-gap: 8px;                        /* 원 사이 여백 */
  --q-clear: 7px;                      /* 원과 촉 사이 틈 */
  /* 모서리. 도해는 상자가 스무 개 넘어 모서리가 크면 둥근 것만 눈에 띈다.
     ⚠️ 사이트 토큰(--xc-radius-lg 20px)을 그대로 쓰지 않는다. 도해 안에서만 줄인다 */
  --erp-r: 10px;
  --erp-r-sm: 4px;
  --q-up: 16px;                        /* 위 줄 깊이 */
  --q-dn: 32px;                        /* 아래 줄 깊이 */
  --erp-wire: 42px;                    /* 그 아래에 비워 두는 배선 자리(두 층) */
  /* ⚠️ 줄 높이를 따로 정하지 않는다. 원 + 배선 자리로 정해야 원이 줄보다 커져
     줄이 늘어나는 일이 없다. 늘어나면 아래 --erp-half-q 계산이 어긋난다 */
  --erp-qh: calc(var(--q-size) + var(--erp-wire));
  /* 품질 · 물류 칸의 한가운데는 줄 바닥에서 이만큼 위다.
     ⚠️ 이 줄은 다른 줄보다 훨씬 높다. --erp-half(22px)를 그대로 쓰면 꺾이는 선이
        칸 한참 아래를 지나 연결이 끊겨 보인다 */
  --erp-half-q: calc(var(--erp-wire) + var(--q-size) / 2);
  /* 기둥과 프로세스 바탕판 사이 틈.
     ⚠️ 바탕판은 --map-pad 만큼 열 밖으로 번진다. 열 사이 여백(--erp-gap)이 그보다 좁으면
        바탕판이 기둥에 닿는다. 기둥을 이만큼 물려 틈을 만든다 */
  --erp-railgap: clamp(14px, 1.4vw, 22px);
  --map-pad: clamp(10px, 1.2vw, 16px);
  margin-top: clamp(24px, 3vw, 40px);
  display: grid;
  /* ⚠️ 생산도 구매자재처럼 두 열을 차지한다. 한 열(1.15fr)로 두면 열 사이 여백만큼
     구매자재보다 좁아 두 프로세스의 폭이 안 맞는다. 칸은 두 열을 함께 덮는다 */
  grid-template-columns:
    auto minmax(0, 1fr) minmax(0, 1fr) clamp(34px, 3.4vw, 52px)
    minmax(0, 1fr) minmax(0, 1fr) clamp(34px, 3.4vw, 52px)
    minmax(0, 1fr) auto minmax(0, 1.75fr);
  column-gap: var(--erp-gap); row-gap: var(--erp-row);
  align-items: stretch;
  /* 품질 ↔ 물류 배선이 이 상자를 기준으로 자리를 잡는다 */
  position: relative;
}
.xc-erp > * { grid-area: var(--a); }
/* 프로세스 바탕판 — 맨 아래 */
.xc-erp__panel {
  z-index: 0; margin: calc(var(--map-pad) * -1);
  background: var(--xc-gray-50);
  border: 1px solid var(--xc-border-weak); border-radius: var(--erp-r);
}
/* 프로세스 머리 */
.xc-erp__head {
  z-index: 2; margin: calc(var(--map-pad) * -1) calc(var(--map-pad) * -1) 0;
  padding: 11px 12px;
  background: var(--xc-navy); color: var(--xc-white);
  border-radius: calc(var(--erp-r) - 1px) calc(var(--erp-r) - 1px) 0 0;
  font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-bold);
  letter-spacing: .02em; text-align: center;
}
/* 칸 */
.xc-erp__step {
  z-index: 2; position: relative;
  display: grid; place-content: center;
  padding: 9px 11px; background: var(--xc-bg);
  border: 1px solid var(--xc-border-weak); border-radius: var(--erp-r-sm);
  font-size: var(--xc-fs-12); color: var(--xc-text);
  line-height: 1.5; text-align: center; text-wrap: pretty;
}
.xc-erp__step.is-key { border-color: var(--xc-orange); color: var(--xc-orange); font-weight: var(--xc-fw-bold); }
/* 동그란 칸(자재출고) */
.xc-erp__node {
  z-index: 2; align-self: center; justify-self: center;
  display: grid; place-content: center;
  /* ⚠️ 잇는 길 열(clamp 34~52px)보다 넓으면 원이 옆 열을 침범한다. 그 안에 들어오게 잡는다.
     이름은 두 줄로 접힌다(자재 / 출고) */
  width: clamp(34px, 3.3vw, 48px); height: clamp(34px, 3.3vw, 48px); border-radius: 50%;
  padding: 2px; line-height: 1.35;
  background: var(--xc-bg); border: 1.5px solid var(--xc-orange);
  font-size: var(--xc-fs-12); font-weight: var(--xc-fw-bold); color: var(--xc-orange);
  text-align: center;
}
/* 기둥 */
.xc-erp__rail {
  z-index: 2; display: grid; place-content: center;
  width: clamp(62px, 5.4vw, 86px); padding: 14px 8px;
  background: var(--xc-navy); border-radius: var(--erp-r);
  color: var(--xc-white);
  font-size: var(--xc-fs-12); font-weight: var(--xc-fw-bold);
  line-height: 1.5; text-align: center; text-wrap: pretty;
}
/* 아래 두 기둥(Data 송 · 수신 · 기준정보)은 높이가 같아야 한다.
   'Data 송 · 수신' 은 1열 폭(62~86px)에 안 들어가 두 줄로 앉고 '기준정보' 는 한 줄이라,
   여백을 그대로 두면 18px 차이가 난다. 두 줄이 한 줄짜리 높이(--erp-railh) 안에
   들어오도록 위아래 여백을 줄인다. 좁아져서 둘 다 두 줄이 되어도 높이는 그대로다 */
.xc-erp__rail--wide { width: auto; padding-block: 5px; min-height: var(--erp-railh); }
/* 왼쪽 기둥은 오른쪽으로, 오른쪽 기둥은 왼쪽으로 물린다.
   ⚠️ :nth-of-type 으로 고르지 않는다. 같은 <p> 형제가 스무 개 넘어 세는 기준이 흔들린다 */
.xc-erp__rail { margin-right: var(--erp-railgap); }
.xc-erp__rail--r { margin-right: 0; margin-left: var(--erp-railgap); }
/* ⚠️ 프로세스 바탕판은 --map-pad 만큼 위아래로 번진다. 기둥에 같은 번짐을 주지 않으면
   윗변이 그만큼 아래에서 시작해 어긋나 보인다. 기준정보 기둥(--wide)은 바탕판이 없어 제외 */
.xc-erp__rail:not(.xc-erp__rail--wide),
.xc-erp__opt { margin-top: calc(var(--map-pad) * -1); }
.xc-erp__rail:not(.xc-erp__rail--wide) { margin-bottom: calc(var(--map-pad) * -1); }

/* ── 잇는 선 ────────────────────────────────────────── */
.xc-erp__v, .xc-erp__h, .xc-erp__l { z-index: 1; position: relative; }
/* 같은 열에서 위아래로 — 줄 사이 여백을 채운다(칸이 이웃한 줄에 선다) */
.xc-erp__v {
  justify-self: center; align-self: start; width: 0;
  height: var(--erp-row); translate: 0 -100%;
  border-left: 1.5px dashed var(--xc-text-weak);
}
.xc-erp__v::after {
  content: ""; position: absolute; left: 50%; bottom: 0;
  width: 8px; height: 8px; translate: -50% -2px; rotate: 45deg;
  border: 0 solid var(--xc-accent); border-bottom-width: 2px; border-right-width: 2px;
}
/* 기둥과 주고받기 — 열 사이 여백 + 기둥이 물러난 폭까지 채운다.
   ⚠️ 기둥을 물린 만큼 선도 길어져야 한다. 안 그러면 화살촉이 허공에서 끝난다 */
.xc-erp__h {
  align-self: center; height: 0;
  width: calc(var(--erp-gap) + var(--erp-railgap));
  border-top: 1.5px dashed var(--xc-text-weak);
}
.xc-erp__h--l { justify-self: start; translate: -100% 0; }
.xc-erp__h--r { justify-self: end;   translate: 100% 0; }
.xc-erp__h::after {
  content: ""; position: absolute; top: 50%;
  width: 8px; height: 8px; rotate: 45deg; border: 0 solid var(--xc-accent);
}
.xc-erp__h.to-l::after   { left: 0;  translate: 2px -50%;  border-bottom-width: 2px; border-left-width: 2px; }
.xc-erp__h.from-l::after { right: 0; translate: -2px -50%; border-top-width: 2px; border-right-width: 2px; }
.xc-erp__h.to-r::after   { right: 0; translate: -2px -50%; border-top-width: 2px; border-right-width: 2px; }
.xc-erp__h.from-r::after { left: 0;  translate: 2px -50%;  border-bottom-width: 2px; border-left-width: 2px; }
/* 열을 건너뛰며 꺾이는 선 — 아래 가로 · 세로 · 위 가로 세 도막.
   ⚠️ --x(세로 도막 자리)를 백분율로 주지 않는다. 꺾임마다 걸치는 열 수가 달라
      같은 백분율이 서로 다른 자리를 가리킨다. 오른쪽 끝(= 다음 열의 변)에서 몇 px 인지로 잰다.
   ⚠️ 두 꺾임이 같은 줄을 지날 때는 세로 도막을 서로 다른 자리에 두되,
      '아래 도막이 왼쪽에서 오는 쪽' 의 세로를 더 왼쪽에 둔다. 그래야 두 가로 도막이
      한 줄에서 겹치지 않는다 */
.xc-erp__l { margin-inline: calc(var(--erp-gap) * -1); }
.xc-erp__l > i {
  position: absolute; border: 0 dashed var(--xc-text-weak);
}
/* ⚠️ 세 도막이 같은 기준을 써야 만난다. 위 끝은 --half-t, 아래 끝은 --half-b 다.
   위 끝은 --half-t, 아래 끝은 --half-b 로 함께 움직인다 */
.xc-erp__l > .v {
  left: var(--x);
  top: var(--half-t, var(--erp-half));
  bottom: var(--half-b, var(--erp-half));
  border-left-width: 1.5px;
}
.xc-erp__l > .b { bottom: var(--half-b, var(--erp-half)); border-top-width: 1.5px; }
.xc-erp__l > .t { top: var(--half-t, var(--erp-half)); border-top-width: 1.5px; }
/* 오른쪽 위로 빠지는 꺾임(구매발주 → 자재소요량 계획) */
.xc-erp__l--ur > .b { left: 0; right: calc(100% - var(--x)); }
.xc-erp__l--ur > .t { left: var(--x); right: 0; }
.xc-erp__l--ur > .t::after {
  content: ""; position: absolute; top: 50%; right: 0;
  width: 8px; height: 8px; translate: -2px -50%; rotate: 45deg;
  border: 0 solid var(--xc-accent); border-top-width: 2px; border-right-width: 2px;
}
/* 왼쪽 위로 빠지는 꺾임(계획 오더 → 구매의뢰) */
.xc-erp__l--ul > .b { left: var(--x); right: 0; }
.xc-erp__l--ul > .t { left: 0; right: calc(100% - var(--x)); }
.xc-erp__l--ul > .t::after {
  content: ""; position: absolute; top: 50%; left: 0;
  width: 8px; height: 8px; translate: 2px -50%; rotate: 225deg;
  border: 0 solid var(--xc-accent); border-top-width: 2px; border-right-width: 2px;
}
/* 원으로 내려가 꽂히는 꺾임 두 종류(생산실적 → 공정검사 · 생산품 입고 → 입고).
   위 가로 · 세로 · 아래 가로 세 도막에, 아래 가로 끝에서 원까지 내려꽂는 도막을 하나 더 단다.
   ⚠️ 가로 도막을 원 바로 위에 붙이면 머리띠와의 사이가 답답하다. 가로는 --drop 만큼 높이 두고
      거기서 세로로 내려 촉이 원에 닿게 한다. --drop 과 --half-b 는 같은 값을 함께 쓴다.
   ⚠️ 촉이 원(z 2) 에 닿으므로 원보다 위(z 3)에 둔다. 아니면 머리가 원 밑으로 먹힌다 */
.xc-erp__l--dl, .xc-erp__l--dr { z-index: 3; }
.xc-erp__l--dl > .t { left: var(--x); right: 0; }
.xc-erp__l--dl > .b { left: var(--bx, 0); right: calc(100% - var(--x)); }
.xc-erp__l--dr > .t { left: var(--x); right: var(--tr, 0); }
.xc-erp__l--dr > .b { left: var(--x); right: var(--br, 0); }
/* 내려꽂는 도막 — 왼쪽 끝(dl) · 오른쪽 끝(dr)에서 --drop 만큼 내려간다 */
.xc-erp__l--dl > .b::before,
.xc-erp__l--dr > .b::before {
  content: ""; position: absolute; top: 50%;
  width: 0; height: var(--drop);
  border-left: 1.5px dashed var(--xc-text-weak);
}
/* 촉 — 45° 돌린 사각형이라 꼭짓점이 아래로 온다. 아래 변을 원 위에 맞추고 2px 만 물린다 */
.xc-erp__l--dl > .b::after,
.xc-erp__l--dr > .b::after {
  content: ""; position: absolute; top: calc(50% + var(--drop));
  width: 8px; height: 8px; rotate: 45deg;
  border: 0 solid var(--xc-accent); border-bottom-width: 2px; border-right-width: 2px;
}
.xc-erp__l--dl > .b::before { left: 0; }
.xc-erp__l--dl > .b::after  { left: 0;  translate: -50% calc(-100% - 2px); }
.xc-erp__l--dr > .b::before { right: 0; }
.xc-erp__l--dr > .b::after  { right: 0; translate: 50% calc(-100% - 2px); }
/* 아래 가로 + 세로만 있고 위 끝에 촉이 붙는 꺾임(출고 → 자재출고) */
.xc-erp__l--u > .b { left: 0; right: calc(100% - var(--x)); }
.xc-erp__l--u > .v::after {
  content: ""; position: absolute; left: 50%; top: 0;
  width: 8px; height: 8px; translate: -50% 2px; rotate: 45deg;
  border: 0 solid var(--xc-accent); border-top-width: 2px; border-left-width: 2px;
}

/* ⚠️ 송수신 줄은 위 여백이 좁다. 바로 위 품질 · 물류 바탕판이 아래로 --map-pad 만큼
   번져 나오기 때문이다(실제 여백 = 줄사이 - 번짐). 그만큼 줄을 내려 위아래를 같게 한다 */
.xc-erp__io,
.xc-erp__rail--io { margin-top: var(--map-pad); }

/* 기준정보와 주고받는 줄 — 한 방향 화살표 두 개가 나란히 선다(Data 송 · 수신).
   ⚠️ 줄 하나에 촉을 양쪽으로 달지 않는다. 보내는 선과 받는 선이 따로다.
   ⚠️ 이 줄이 곧 기준정보 위 여백이다. 여백만 주면 화살표를 놓을 자리가 없다 */
.xc-erp__io {
  z-index: 1; display: flex; justify-content: center; gap: 20px;
  /* ⚠️ 이 줄 높이가 곧 기둥 높이다. 기둥보다 높게 두면 기둥만 늘어나 기준정보와 어긋난다 */
  min-height: var(--erp-railh);
}
.xc-erp__io > i {
  position: relative; width: 0; height: 100%;
  border-left: 1.5px dashed var(--xc-text-weak);
}
.xc-erp__io > i::after {
  content: ""; position: absolute; left: 50%;
  width: 8px; height: 8px; rotate: 45deg; border: 0 solid var(--xc-accent);
}
/* 가로로 오가는 자리 — 열 사이 여백에 선 두 가닥을 위아래로 나란히 */
.xc-erp__io--h {
  flex-direction: column; justify-self: end; align-self: center;
  width: calc(var(--erp-gap) + 4px); min-height: 0; gap: 12px;
  translate: 100% 0;
}
.xc-erp__io--h > i {
  width: 100%; height: 0; border-left: 0;
  border-top: 1.5px dashed var(--xc-text-weak);
}
.xc-erp__io--h > i::after { top: 50%; }
.xc-erp__io--h > .is-r::after { left: auto; right: 0; translate: -2px -50%; border-top-width: 2px; border-right-width: 2px; }
.xc-erp__io--h > .is-l::after { left: 0; right: auto; translate: 2px -50%; border-bottom-width: 2px; border-left-width: 2px; }
.xc-erp__io > .is-up::after { top: 0; translate: -50% 2px; border-top-width: 2px; border-left-width: 2px; }
.xc-erp__io > .is-dn::after { bottom: 0; translate: -50% -2px; border-bottom-width: 2px; border-right-width: 2px; }

/* 항목을 담는 띠(품질 · 물류 · 기준정보 · OPTION 카드 안) */
.xc-erp__list {
  z-index: 2; display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr);
  gap: 8px;
  /* ⚠️ align-content: center 로 두면 줄이 글자 높이에 딱 맞게 줄어 카드가 얇아진다.
     칸을 채우도록 늘려 위 프로세스 카드와 두께가 맞게 한다 */
  align-content: stretch; grid-auto-rows: minmax(0, 1fr);
}
/* 두 칸씩 채우는 묶음(OPTION 카드 안) */
.xc-erp__list--wrap { grid-auto-flow: row; grid-template-columns: repeat(2, minmax(0, 1fr)); }
.xc-erp__list > li {
  display: grid; place-content: center;
  padding: 9px 11px; background: var(--xc-bg);
  border: 1px solid var(--xc-border-weak); border-radius: var(--erp-r-sm);
  font-size: var(--xc-fs-12); color: var(--xc-text);
  line-height: 1.5; text-align: center; text-wrap: pretty;
}
/* SCM 시스템흐름도 — 같은 부품에 열 수만 넷으로 바꿔 쓴다.
   ⚠️ 상자를 --scm-in 만큼 안으로 물린다. 여기에는 기둥이 없어 가로 화살표가
      기둥 물림(--erp-railgap)만큼 길게 잡히는데, 상자가 열을 꽉 채우면 그 길이가
      상자 배경을 파고든다. 상자를 물리고 화살표를 그만큼만 늘린다 */
.xc-erp--scm {
  --scm-in: clamp(8px, 1vw, 14px);
  --scm-head: calc(22px + 1.5 * var(--xc-fs-xs));   /* 머리 높이 = 위아래 여백 11+11 + 글줄 */
  grid-template-columns: repeat(4, minmax(0, 1fr));
  /* 세로로 큰 덩어리 셋(메일 · 네 갈래 작업 · 아래 작업) 사이를 좁힌다.
     사이 = 줄사이 + 잇는 줄 높이 + 줄사이 */
  row-gap: 8px;
}
/* ⚠️ 잇는 줄이 따로 있는 도해다. 세로 화살표를 위 여백으로 밀어 올리면(translate)
   그 줄이 빈 띠로 남는다. 줄을 그대로 채우게 한다 */
.xc-erp--scm .xc-erp__v {
  align-self: stretch; height: auto; min-height: 26px; translate: none;
}
.xc-erp--scm .xc-erp__io { min-height: 26px; margin-top: 0; }
.xc-erp--scm .xc-map__col { margin-inline: var(--scm-in); }
/* 가로 화살표는 상자와 상자 '사이' 에만 있어야 한다.
   상자가 열 안에서 --scm-in 만큼 물러나 있으므로 사이 폭 = 열사이 + 물림 2 다.
   ⚠️ 길이만 늘리면 안 된다. 시작점이 열 변에 잡혀 있어 끝이 다음 상자를 파고든다.
      물림만큼 되밀어 시작점을 이쪽 상자의 변에 맞춘다 */
.xc-erp--scm .xc-erp__h,
.xc-erp--scm .xc-erp__io--h { width: calc(var(--erp-gap) + 2 * var(--scm-in)); }
.xc-erp--scm .xc-erp__h--r,
.xc-erp--scm .xc-erp__io--h { translate: calc(var(--erp-gap) + var(--scm-in)) 0; }
.xc-erp--scm .xc-erp__h--l { translate: calc(-1 * (var(--erp-gap) + var(--scm-in))) 0; }
/* 머리(네이비 띠)를 뺀 회색 몸통 기준으로 세로 한가운데에 둔다.
   ⚠️ align-self: center 는 상자 전체(머리 + 몸통) 한가운데다. 머리가 있는 만큼 위로 치우친다.
   ⚠️ margin-top 은 가운데 정렬에서 절반만 먹는다(위아래로 나눠 밀리므로).
      머리 높이만큼 주면 정확히 머리의 절반만큼 내려간다.
   ⚠️ 머리 높이를 재려면 줄 간격이 정해져 있어야 한다. 상속에 맡기지 않고 못박는다 */
.xc-erp--scm .xc-map__head { line-height: 1.5; }
.xc-erp--scm .xc-erp__h--body { margin-top: var(--scm-head); }
/* 아래 줄(ERP · 입고작업 · 배송) — 세 상자의 칸 높이를 맞추고 몸통 한가운데에 세운다.
   ⚠️ 칸마다 글줄 수가 달라(한 줄 ~ 두 줄) 그대로 두면 높이가 들쭉날쭉하다.
      두 줄 높이를 바닥으로 잡아 한 줄짜리도 같이 커지게 한다.
   ⚠️ align-content 를 start 로 두면 상자가 늘어난 만큼 칸이 위로 붙는다. 가운데로 */
.xc-erp--scm .xc-map__col--btm > .xc-map__body { align-content: center; }
.xc-erp--scm .xc-map__col--btm > .xc-map__body > li {
  min-height: calc(2 * 1.5 * var(--xc-fs-12) + 20px);
}
/* 메일 쪽 상자 — 흐름 바깥에 있는 장치라 색을 달리한다.
   ⚠️ 몸통 없이 머리만 있는 상자다. 머리는 윗모서리만 둥글게 잡혀 있으므로 네 귀를 다시 준다 */
.xc-erp--scm .xc-map__col--mail { background: var(--xc-bg); border-color: var(--xc-navy); }
.xc-erp--scm .xc-map__col--mail > .xc-map__head {
  background: var(--xc-bg); color: var(--xc-navy);
  border-radius: calc(var(--erp-r) - 1px);
}
/* ⚠️ 머리의 모서리는 바깥 상자보다 딱 테두리 굵기(1px)만큼만 작아야 한다.
   더 작으면 그 차이만큼 머리 배경이 상자의 둥근 테두리 바깥으로 삐져나와 모퉁이를 덮는다.
   자식 배경은 부모 모서리에 잘리지 않는다(overflow: hidden 을 쓰지 않으므로).
   SCM 도해는 상자 모서리도 도해 값(--erp-r)으로 맞춘다 */
.xc-erp--scm .xc-map__col { border-radius: var(--erp-r); }
.xc-erp--scm .xc-map__head {
  border-radius: calc(var(--erp-r) - 1px) calc(var(--erp-r) - 1px) 0 0;
}
.xc-erp--scm .xc-map__col--mail > .xc-map__head { border-radius: calc(var(--erp-r) - 1px); }
/* 위를 향하는 세로 화살표 */
.xc-erp__v--up::after {
  top: 0; bottom: auto; translate: -50% 2px;
  border-bottom-width: 0; border-right-width: 0;
  border-top-width: 2px; border-left-width: 2px;
}

/* SCM 발주작업 안 — 카드가 반폭 · 전폭으로 나뉘고 아래쪽은 위로 흐른다(원본이 그렇다).
   ⚠️ 두 카드가 하나로 합쳐지는 자리(BOM전개결과 · 마감관리 → 자름발주)는 ∪ 자 한 요소로
      그린다. 세로 두 가닥과 가로를 따로 두면 모서리가 대시 위상 탓에 뚫린다.
   ⚠️ 두 열 한가운데 : 열 폭 W, 열 사이 g 일 때 W/2 이고 W = (100% - g)/2 이므로 (100% - g)/4 다 */
.xc-scmb {
  --b-gap: 10px;
  --b-c: calc((100% - var(--b-gap)) / 4);
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: var(--b-gap);
  padding: var(--map-pad);
}
.xc-scmb > p {
  grid-area: var(--a);
  display: grid; place-content: center;
  padding: 9px 11px; background: var(--xc-bg);
  border: 1px solid var(--xc-border-weak); border-radius: var(--erp-r-sm);
  font-size: var(--xc-fs-12); color: var(--xc-text);
  line-height: 1.5; text-align: center; text-wrap: pretty;
}
.xc-scmb > i {
  grid-area: var(--a); position: relative; height: 22px;
  border: 0 dashed var(--xc-text-weak);
}
.xc-scmb > i::after {
  content: ""; position: absolute; left: 50%;
  width: 8px; height: 8px; rotate: 45deg; border: 0 solid var(--xc-accent);
}
/* 세로 한 가닥 */
.xc-scmb > .v { justify-self: center; width: 0; border-left-width: 1.5px; }
.xc-scmb > .v--dn::after { bottom: 0; translate: -50% -2px; border-bottom-width: 2px; border-right-width: 2px; }
.xc-scmb > .v--up::after { top: 0; translate: -50% 2px; border-top-width: 2px; border-left-width: 2px; }
/* ∪ 자 : 두 카드에서 내려와 가운데로 모인다 */
.xc-scmb > .y {
  margin-inline: var(--b-c); height: 12px;
  border-left-width: 1.5px; border-right-width: 1.5px; border-bottom-width: 1.5px;
  border-radius: 0 0 var(--erp-r-sm) var(--erp-r-sm);
}
.xc-scmb > .y::after { display: none; }
/* 모인 뒤 아래로 */
.xc-scmb > .y2 {
  justify-self: center; width: 0; height: 10px; border-left-width: 1.5px;
}
.xc-scmb > .y2::after { bottom: 0; translate: -50% -2px; border-bottom-width: 2px; border-right-width: 2px; }
/* 마지막 칸은 흐름에서 떨어져 있다 */
.xc-scmb > .gapped { margin-top: 14px; }
/* 한 줄짜리 안(발주정보) — 칸 사이 여백을 다른 열(.xc-map__body)과 같은 8px 로 맞춘다.
   ⚠️ 여백을 주면 잇는 선이 칸에서 떨어진다. 선만 음수 margin 으로 양쪽 여백을 도로 덮어
      끊김 없이 잇는다.
   ⚠️ 이 여백을 .xc-scmb 전체에 주면 안 된다. 발주작업의 ∪ 자와 그 아래 세로 도막이
      갈라져 모이는 자리가 끊긴다 */
.xc-scmb--1 { grid-template-columns: minmax(0, 1fr); }
.xc-scmb--gap { row-gap: 8px; }
.xc-scmb--gap > i { height: 30px; margin-block: -8px; }
/* 내용이 열 한가운데에 서는 안(협력업체) */
.xc-scmb--mid { align-content: center; }
/* 촉 없는 세로 — 무엇이 무엇으로 간다기보다 '이 칸을 거친다' 는 표시다 */
.xc-scmb > .v--plain::after { display: none; }
/* 알약 칸(Backup) — 원본에서 이 칸만 모양이 다르다 */
.xc-scmb > .pill {
  padding: 13px 16px; border-radius: var(--xc-radius-full);
  border-color: var(--xc-orange); color: var(--xc-orange);
  font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-bold);
}

/* ── 품질 관리 · 물류 관리 ────────────────────────────
   원 셋이 나란히 서고 그 아래에 배선이 흐른다.
   ⚠️ 원을 <ul> 한 칸에 몰아넣지 않는다. 세 열짜리 자체 격자에 하나씩 올린다.
      그래야 배선이 '몇째 원의 한가운데' 를 좌표로 가리킬 수 있다.
      한 칸에 몰아 두면 배선이 원의 위치를 알 수 없어 눈대중이 된다.
   ⚠️ 꺾이는 배선은 한 상자의 두세 변으로 그린다(border-left · bottom · right).
      도막을 따로 두고 맞대면 점선의 대시 위상이 어긋나 모서리가 뚫린다.
   ⚠️ 열 한가운데 좌표 : 세 열 폭이 W, 열 사이가 g 이면 첫 열 한가운데는 W/2 이고
      W = (100% - 2g)/3 이므로 (100% - 2g)/6 이다. 셋째 열은 오른쪽에서 같은 값이다. */
.xc-erp__q {
  /* ⚠️ position: relative 를 빼면 안 된다. 갈매기표가 절대 위치라, 기준이 없으면
     위로 거슬러 올라가 도해 전체(.xc-erp)를 기준으로 잡고 한복판에 가서 붙는다 */
  z-index: 2; position: relative;
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  grid-template-rows: minmax(0, 1fr) var(--erp-wire);
  column-gap: var(--q-gap);
  min-height: var(--erp-qh); margin-top: var(--q-drop);
}
.xc-erp__q > p {
  grid-row: 1; grid-column: var(--c);
  justify-self: center; align-self: center;
  display: grid; place-content: center;
  width: var(--q-size); height: var(--q-size);
  padding: 4px; border-radius: 50%;
  background: var(--xc-bg); border: 1px solid var(--xc-border-weak);
  font-size: var(--xc-fs-12); color: var(--xc-text);
  line-height: 1.35; text-align: center; text-wrap: pretty;
}
/* 차례가 있는 묶음(물류) — 원 사이 갈매기표 */
/* 차례가 있는 묶음(물류) — 원 사이 갈매기표 둘.
   ⚠️ 원에 붙이지 않는다. 원은 넓은 열 한가운데에 서 있어, 원을 기준으로 잡으면
      표가 원 바로 옆에 붙고 반대쪽이 휑해진다. 열 경계에 맞춰 상자 기준으로 잡는다.
   ⚠️ 세 열 폭 W, 열 사이 g 일 때 첫·둘째 열 한가운데의 중간은 W + g/2 다 */
.xc-erp__q--seq::before,
.xc-erp__q--seq::after {
  content: "›";
  /* ⚠️ 원의 세로 한가운데다. 상자 높이의 절반에서 배선 자리의 절반을 뺀다.
     정해 둔 값(--erp-qh)으로 재면 상자가 늘어났을 때 표만 위로 뜬다 */
  position: absolute; top: calc(50% - var(--erp-wire) / 2);
  font-size: var(--xc-fs-erp-seq); font-weight: var(--xc-fw-bold); color: var(--xc-text-weak);
}
.xc-erp__q--seq::before {
  left: calc((100% - 2 * var(--q-gap)) / 3 + var(--q-gap) / 2); translate: -50% -50%;
}
.xc-erp__q--seq::after {
  right: calc((100% - 2 * var(--q-gap)) / 3 + var(--q-gap) / 2); translate: 50% -50%;
}
/* ── 품질 ↔ 물류 배선 ─────────────────────────────────
   원본은 두 줄이다. 위 줄이 수입검사 ↔ 입고, 아래 줄이 고객반품 ↔ 출고 를 잇는다.
   두 줄 모두 통로를 건너므로 상자 안이 아니라 도해 격자 위에 놓는다.
   ⚠️ 한 요소의 세 변(왼 · 아래 · 오른)으로 ㄷ 자를 그린다. 도막을 따로 두고 맞대면
      점선의 대시 위상이 어긋나 모서리가 뚫린다.
   ⚠️ 원의 가로 자리는 격자에서 계산한다.
        상자 폭 W3 = (전체 - 열사이 2 - 통로) / 2
        양 끝 원의 한가운데 Q = (W3 - 원사이여백 2) / 6
      위 줄은 왼쪽에서 Q · 오른쪽에서 W3-Q, 아래 줄은 그 반대다 */
.xc-erp__qw {
  --w3: calc((100% - 2 * var(--erp-gap) - var(--erp-cor)) / 2);
  --q1: calc((var(--w3) - 2 * var(--q-gap)) / 6);
  /* ⚠️ 원 아래로 --q-clear 만큼 띄운다. 원에 딱 붙이면 45° 돌린 촉의 꼭짓점이
     원 안으로 몇 픽셀 들어가고, 원이 위층(z-index 2)이라 그 부분이 먹혀 머리가 사라진다.
     ⚠️ z-index 는 원보다 위로 둔다. 띄워도 반올림으로 1px 씩 겹칠 수 있다.
     ㄷ 자 자체는 원 아래 빈 띠에만 있으므로 위로 올려도 글자를 덮지 않는다 */
  grid-area: var(--a); z-index: 3; position: relative;
  margin-top: calc(var(--q-drop) + var(--q-size) + var(--q-clear));
  border: 0 dashed var(--xc-text-weak);
  border-left-width: 1.5px; border-bottom-width: 1.5px; border-right-width: 1.5px;
}
/* 위 줄 : 수입검사 ↔ 입고 */
.xc-erp__qw--a {
  margin-left: var(--q1); margin-right: calc(var(--w3) - var(--q1));
  margin-bottom: calc(var(--erp-wire) - var(--q-up));
}
/* 아래 줄 : 고객반품 ↔ 출고 */
.xc-erp__qw--b {
  margin-left: calc(var(--w3) - var(--q1)); margin-right: var(--q1);
  margin-bottom: calc(var(--erp-wire) - var(--q-dn));
}
/* 원으로 올라가는 촉 */
.xc-erp__qw::before,
.xc-erp__qw::after {
  content: ""; position: absolute; top: 0; z-index: 1;
  width: 9px; height: 9px; rotate: 45deg;
  border: 0 solid var(--xc-accent); border-top-width: 2px; border-left-width: 2px;
}
/* ⚠️ 세로 도막은 테두리다. 테두리는 상자의 '바깥' 에 그려지므로 왼쪽 도막의 한가운데는
   left: 0 이 아니라 -0.75px(굵기의 절반) 다. 촉을 left: 0 에 두면 반 픽셀 어긋난다 */
.xc-erp__qw::before { left: 0; translate: calc(-50% - .75px) 2px; }
.xc-erp__qw::after  { right: 0; translate: calc(50% + .75px) 2px; }
/* 출고 쪽은 보내는 자리라 촉이 없다 */
.xc-erp__qw--b::after { display: none; }

/* 오른쪽 OPTION 열 — 카드 세 장이 자리를 끝까지 나눠 채운다(기둥과 아랫변을 맞춘다) */
.xc-erp__opt {
  z-index: 2; display: grid; gap: var(--erp-gap);
  grid-template-rows: auto repeat(3, minmax(0, 1fr));
  margin-bottom: calc(var(--map-pad) * -1);
}
.xc-erp__opt > b {
  padding: 10px 12px; border-radius: var(--erp-r);
  border: 1.5px solid var(--xc-navy); color: var(--xc-navy);
  font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-bold);
  letter-spacing: .1em; text-align: center;
}
.xc-erp__card {
  display: grid; grid-template-rows: auto minmax(0, 1fr);
  background: var(--xc-gray-50);
  border: 1px solid var(--xc-border-weak); border-radius: var(--erp-r);
}
.xc-erp__card > p {
  padding: 11px 12px; background: var(--xc-navy); color: var(--xc-white);
  border-radius: calc(var(--erp-r) - 1px) calc(var(--erp-r) - 1px) 0 0;
  font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-bold); text-align: center;
}
.xc-erp__card > ul { padding: var(--map-pad); }

@media (max-width: 1024px) {
  /* 세로로 쌓는다. 자리 지정과 잇는 선을 모두 푼다 */
  .xc-erp { grid-template-columns: minmax(0, 1fr); }
  .xc-erp > * { grid-area: auto; margin: 0; }
  .xc-erp__panel, .xc-erp__v, .xc-erp__h, .xc-erp__l, .xc-erp__io,
  .xc-erp__qw { display: none; }
  .xc-erp__q { grid-template-rows: auto; min-height: 0; }
  .xc-erp__opt { grid-template-rows: none; }
  .xc-erp__rail { width: auto; }
  .xc-erp__list { grid-auto-flow: row; grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .xc-erp__head { border-radius: var(--erp-r); }
}

/* ── 상세 : 반원 아크 세 겹(그룹웨어 제품개요) ──────────
   원본은 두 겹의 원이다 — 가운데가 기본제품, 그 둘레가 확장제품이고,
   둘레는 다시 '확장제품(Package 제품 · Option)' 과 'Customizing 확장영역' 두 호로 나뉜다.
   반원 셋을 같은 바닥선에 겹쳐 세워 그 안팎 관계를 그대로 살린다.
   칩은 자기 층의 호를 따라 앉는다. 위치는 --l(가로) · --b(바닥선에서의 높이) 로 주는데,
   둘 다 도형 상자에 대한 백분율이라 도형이 커지든 작아지든 원 위에 그대로 남는다.
   ⚠️ 반원(.xc-core__ring)은 배경, 칩은 그 위를 덮는 판(.xc-core__arc)에 둔다.
      칩을 각 반원 안에 넣으면 뒤에 오는 반원이 앞 반원의 칩을 덮는다. 층이 셋이라 반드시 겹친다.
   ⚠️ 칩에는 이름만 담고 확장제품 설명은 아래 범례로 뺀다. 띠 두께가 100px 남짓이다.
   ⚠️ 칩 위치는 눈대중으로 잡지 않는다. scratchpad/solve_gw.py 가 제약(띠 안에 들 것 ·
      서로 안 겹칠 것)을 걸고 푼 값이다. 칩 크기를 바꾸면 그 풀이를 다시 돌려 값을 갈아 끼운다.
   ⚠️ 도형 폭이 960px 아래로 내려가면 아크를 풀어 세 층을 그냥 쌓는다.
      좁은 띠는 글자를 못 담는다. 화면이 아니라 도형 폭으로 재야 해서 컨테이너 질의를 쓴다.
   ⚠️ 겹마다 바탕을 번갈아 둔다. 같은 색이 이어지면 몇 겹인지 보이지 않는다 */
.xc-core { margin-top: clamp(24px, 3vw, 40px); container-type: inline-size; }
.xc-core__fig { display: grid; }
.xc-core__ring { display: none; }
.xc-core__title {
  display: block; margin-bottom: 12px; text-align: center;
  font-size: var(--xc-fs-h4); font-weight: var(--xc-fw-bold);
  letter-spacing: var(--xc-ls-heading); color: var(--xc-navy);
}
.xc-core__arc {
  padding: clamp(14px, 1.8vw, 22px);
  background: var(--xc-chip-accent-bg);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius-lg);
  text-align: center;
}
.xc-core__arc + .xc-core__arc { margin-top: 10px; }
.xc-core__arc--mid { background: var(--xc-bg); }
.xc-core__arc--core { background: var(--xc-gray-50); }
.xc-core__label {
  display: block;
  font-size: var(--xc-fs-12); font-weight: var(--xc-fw-bold);
  letter-spacing: .06em; color: var(--xc-text); line-height: 1.4;
}
.xc-core__list {
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: 8px; margin-top: 10px;
}
.xc-core__list > li {
  padding: 7px 15px; border-radius: var(--xc-radius-full);
  background: var(--xc-bg); border: 1px solid var(--xc-border-weak);
  font-size: var(--xc-fs-sm); color: var(--xc-text-sub); line-height: 1.4;
}
/* 층마다 색을 나눈다 — 안쪽 둘은 제품(네이비 계열), 맨 바깥은 고객 맞춤(오렌지).
   ⚠️ 층 이름표는 셋 다 네이비다. 오렌지는 칩에만 쓴다 — 이름표까지 물들이면
      어느 층이 강조인지 흐려지고, 작은 글자라 대비도 모자란다 */
.xc-core__arc--out .xc-core__list > li {
  border-color: var(--xc-orange); color: var(--xc-orange);
  font-weight: var(--xc-fw-semibold);
}
.xc-core__arc--mid .xc-core__list > li {
  border-color: var(--xc-navy); color: var(--xc-text);
  font-weight: var(--xc-fw-semibold);
}
/* 한가운데 = 핵심. 가장 진하게 둔다 */
.xc-core__arc--core .xc-core__list > li {
  background: var(--xc-navy); border-color: var(--xc-navy);
  color: var(--xc-white); font-weight: var(--xc-fw-bold);
}
/* 확장제품 설명 — 아크 안에 넣으면 띠를 넘긴다. 그림 아래 범례로 둔다 */
.xc-core__note {
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: 6px clamp(14px, 1.8vw, 24px);
  margin-top: clamp(14px, 1.6vw, 20px);
  font-size: var(--xc-fs-12); color: var(--xc-text-weak); line-height: 1.5;
}
.xc-core__note > li > b {
  margin-right: 6px;
  font-weight: var(--xc-fw-bold); color: var(--xc-text-sub);
}
/* ─ 아크 모드 : 반원 셋을 바닥선에 겹쳐 세우고 칩을 호 위에 앉힌다 ─ */
@container (min-width: 960px) {
  .xc-core__fig {
    display: block; position: relative;
    width: min(100%, 1080px); margin-inline: auto;
    aspect-ratio: 2 / 1;
  }
  .xc-core__ring {
    display: block; position: absolute; left: 50%; bottom: 0; translate: -50% 0;
    width: var(--w); aspect-ratio: 2 / 1;
    background: var(--xc-chip-accent-bg); border: 1px solid var(--xc-border-weak);
    /* 가로 반지름 = 폭의 절반, 세로 반지름 = 높이 전부 → 정확한 반원 */
    border-radius: 50% 50% 0 0 / 100% 100% 0 0;
  }
  .xc-core__ring--mid { background: var(--xc-bg); }
  .xc-core__ring--core { background: var(--xc-gray-50); }
  /* 맨 안쪽 = 제품 자리. 테두리만 진하게 둔다(바탕을 네이비로 채우면 본문에서 홀로 튄다) */
  .xc-core__ring--in { background: var(--xc-bg); border-color: var(--xc-navy); }
  .xc-core__title {
    position: absolute; left: var(--l); bottom: var(--b); translate: -50% 50%;
    margin: 0; white-space: nowrap; font-size: var(--xc-fs-20);
  }
  /* 칩을 얹는 판 — 바탕도 테두리도 없다. 반원 셋을 통째로 덮는다 */
  .xc-core__arc {
    position: absolute; inset: 0;
    padding: 0; background: none; border: 0; margin: 0;
  }
  .xc-core__arc + .xc-core__arc { margin-top: 0; }
  .xc-core__list { display: block; margin: 0; }
  /* --l · --b 가 가리키는 점에 제 가운데를 맞춘다 */
  .xc-core__label,
  .xc-core__list > li {
    position: absolute; left: var(--l); bottom: var(--b);
    translate: -50% 50%; white-space: nowrap;
  }
  .xc-core__label { font-size: var(--xc-fs-xs); }
  .xc-core__list > li { padding: 7px 15px; font-size: var(--xc-fs-sm); }
}

/* ── 상세 : 3단 흐름 도해(BI 제품개요) ──────────────────
   '어디서 모아 → 어디서 처리해 → 어디서 본다' 를 세 칸으로 늘어놓는다.
   ⚠️ 칸 이름은 몸통과 떨어진 별도 상자다. legacy 그림이 그렇게 그려져 있고,
      떨어져 있어야 '이름 - 내용' 이 한 덩어리로 읽힌다.
   ⚠️ 회색 상자(.xc-figbox) 안에 들어가므로 조각은 흰색이다. 회색 위 회색은 경계가 사라진다 */
.xc-pipe {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr) auto minmax(0, 1fr);
  gap: clamp(8px, 1.2vw, 18px); align-items: stretch;
}
.xc-pipe__stage { display: grid; grid-template-rows: auto minmax(0, 1fr); gap: clamp(10px, 1.2vw, 16px); }
.xc-pipe__head,
.xc-pipe__body {
  background: var(--xc-bg);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius-lg);
}
.xc-pipe__head {
  padding: clamp(14px, 1.6vw, 20px) clamp(12px, 1.4vw, 18px);
  font-size: var(--xc-fs-ph-sub); font-weight: var(--xc-fw-bold);
  letter-spacing: var(--xc-ls-heading); color: var(--xc-text);
  text-align: center; text-wrap: balance;
}
.xc-pipe__body {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: clamp(14px, 1.6vw, 22px);
  padding: clamp(22px, 2.4vw, 34px) clamp(14px, 1.6vw, 22px);
}
/* 칸 안의 주인공(Power BI) */
.xc-pipe__lead { display: grid; justify-items: center; gap: 8px; }
.xc-pipe__lead b {
  font-size: var(--xc-fs-h4); font-weight: var(--xc-fw-bold);
  letter-spacing: var(--xc-ls-heading); color: var(--xc-text);
}
/* 아이콘 크기는 CSS 가 정한다. svg 에 width·height 를 박아 두면 화면이 좁아져도
   그대로 남아 칸을 밀어낸다 */
.xc-pipe__ico { display: block; color: var(--xc-navy); }
.xc-pipe__ico svg { display: block; width: auto; height: clamp(52px, 5vw, 72px); }
.xc-pipe__ico--accent { color: var(--xc-accent); }
/* 갈래 도해(Data Relation) — DB 하나가 둘로 갈라진다. 가로로 넓어 따로 잰다 */
.xc-pipe__rel { display: block; color: var(--xc-navy); }
.xc-pipe__rel svg { display: block; width: clamp(116px, 11vw, 158px); height: auto; }
/* 항목 알약. 아이콘이 있는 것과 없는 것이 섞인다 */
.xc-pipe__chips { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; }
.xc-pipe__chips > li {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 7px 14px; border-radius: var(--xc-radius-full);
  background: var(--xc-gray-50); border: 1px solid var(--xc-border-weak);
  font-size: var(--xc-fs-xs); color: var(--xc-text-sub); line-height: 1.4;
}
.xc-pipe__chips svg { flex: none; color: var(--xc-navy); }
/* 갈래(Data Relation) — 원본은 DB 하나가 둘로 갈라지는 그림이다.
   구름·Power BI 와 한 덩어리로 읽혀야 하므로 사이를 좁혀 위로 붙인다.
   ⚠️ 몸통의 gap(최대 22px)을 음수 margin 으로 되무는 방식이다. gap 을 통째로 줄이면
      아래 캡션·다른 칸의 알약 간격까지 함께 좁아진다 */
.xc-pipe__lead + .xc-pipe__rel { margin-top: clamp(-13px, -1.1vw, -4px); }
.xc-pipe__rel + .xc-pipe__cap { margin-top: clamp(-15px, -1.3vw, -6px); }
.xc-pipe__cap { font-size: var(--xc-fs-xs); color: var(--xc-text-weak); text-align: center; }
.xc-pipe__arw { display: grid; place-items: center; color: var(--xc-accent); }
.xc-pipe__arw svg { width: clamp(36px, 3.6vw, 52px); height: auto; stroke-width: 2.2; }

/* ── 상세 : 레인 흐름(RPA 적용 예시 1) ─────────────────
   누가 무엇을 하는지가 요점이다. 열 = 주체(담당자 · Bot · 사원), 행 = 차례.
   원본처럼 번호가 붙은 영역 넷으로 묶고, 잇는 선도 원본을 따른다.

   ⚠️ 원본은 '붙어 있는 상자' 와 '떨어져서 화살표로 이어진 상자' 를 구분한다.
      붙은 곳에는 선을 두지 않는다. 줄 사이 여백은 모든 줄에서 같다 — 한 줄 안에서
      칸마다 세로 중심이 달라지면 가로선이 어느 칸과도 맞지 않는다(음수 margin 으로
      칸을 끌어올리면 그 줄의 높이가 줄어 나머지 칸의 중심이 함께 내려간다).
   ⚠️ 잇는 선은 칸이 아니라 칸 사이 여백에 놓는 별도 항목이다(.xc-swim__v · __h).
      칸의 가상요소로 그리면 세로선·가로선·꼬리표 세 가지를 두 자리(::before·::after)에
      욱여넣게 되어 한 칸이 둘 이상을 쓰는 순간 하나가 사라진다.
   ⚠️ 겹치는 격자다. 칸·선·영역 모두 행과 열을 명시한다(--r · --c · --a).
      하나라도 자동 배치에 맡기면 없는 열이 생겨 판이 통째로 어긋난다.
   ⚠️ 그리는 차례 = 영역 → 선 → 칸. 칸이 맨 위라야 선의 끝이 칸에 가려 깔끔하다. */
.xc-swim {
  --swim-gap: clamp(14px, 1.8vw, 26px);
  --swim-pad: clamp(12px, 1.4vw, 18px);
  /* 칸이 영역 안쪽으로 물러나는 폭. 레인 머리줄 = 영역 테두리 > 칸 순으로 좁아진다 */
  --swim-in: clamp(16px, 1.8vw, 22px);
  --swim-no: 26px;   /* 순번 알약 높이 */
  --swim-row: 44px;    /* 줄 사이 = 세로 잇는 선의 길이. 순번 알약이 들어앉을 자리이기도 하다 */
  --swim-half: 23px;   /* 한 줄 높이의 절반. 되돌아가는 선이 칸 한가운데에서 나가고 들어온다 */
  margin-top: clamp(20px, 2.4vw, 32px);
}
.xc-swim__heads,
.xc-swim__board {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  column-gap: var(--swim-gap); padding-inline: var(--swim-pad);
}
.xc-swim__heads > li {
  padding: 10px 12px; border-radius: var(--xc-radius);
  background: var(--xc-navy); color: var(--xc-white);
  font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-bold); letter-spacing: .04em;
  text-align: center;
}
/* 첫 영역의 순번 알약이 레인 머리줄에 닿지 않도록 띄운다.
   위 번짐(23) + 알약 절반(13) + 흰 테두리(6) = 42 보다 커야 한다 */
.xc-swim__board { row-gap: var(--swim-row); margin-top: 50px; }

/* ① 번호 영역 — 맨 아래에 깔린다 */
.xc-swim__grp {
  grid-area: var(--a); position: relative; z-index: 0;
  /* 위쪽은 순번 알약이 앉을 자리라 알약 절반보다 넉넉히, 아래쪽은 짧게.
     ⚠️ 위 번짐 + 아래 번짐 < 줄 사이 여백(--swim-row) 이어야 한다.
        넘으면 위아래로 이웃한 영역의 테두리끼리 겹친다 */
  margin: calc(var(--swim-no) / -2 - 10px) 0 -11px;
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius-lg);
}
.xc-swim__grp > b {
  position: absolute; top: 0; left: 50%; translate: -50% -50%;
  display: grid; place-items: center;
  height: var(--swim-no); padding-inline: 15px; border-radius: var(--xc-radius-full);
  background: var(--xc-navy); color: var(--xc-white);
  /* 알약 둘레를 바탕색으로 한 겹 두른다. 지나가던 테두리가 알약 앞에서 끊겨 보인다 */
  box-shadow: 0 0 0 6px var(--xc-bg);
  font-size: var(--xc-fs-12); font-weight: var(--xc-fw-bold); letter-spacing: .1em;
}
/* ⚠️ 순번은 영역 윗변 한가운데에 앉는다. 세로 변(왼쪽)에 두면 가로로 긴 알약이
   칸 쪽으로 절반이나 들어가 글자를 덮는다. 윗변이면 부딪히는 것이 위쪽 여백뿐이다.
   ⚠️ 두 열을 걸치는 영역(03 · 04)은 한가운데가 열과 열 사이 여백이라 알약 아래에
      칸이 없다. 한 열짜리(01 · 02)는 그 열의 윗줄이 비어 있다 */

/* ② 잇는 선 — 칸보다 위다.
   ⚠️ 화살촉은 선 끝에서 절반쯤 튀어나와 칸에 닿는다. 선을 칸 아래에 두면 그 절반이
      칸 배경에 가려 머리가 사라진다. 선 자체는 칸과 칸 사이 여백만 차지하므로
      위로 올려도 글자를 덮지 않는다.
   ⚠️ 되돌이(.xc-swim__ret)는 아래에 둔다. 칸 옆을 스쳐 지나므로 위로 올릴 필요가 없다 */
.xc-swim__v,
.xc-swim__h { grid-row: var(--r); grid-column: var(--c); position: relative; z-index: 3; }
/* ⚠️ 화살촉은 45° 돌린 정사각형이다. 한 변이 9px 이면 중심에서 꼭짓점까지 6.36px 이라,
   상자를 선 끝에 딱 붙여 두면 꼭짓점이 1.9px 더 나가 카드 안으로 파고든다.
   그만큼(2px) 되물려 꼭짓점이 카드 테두리에 닿게 한다 */
/* 세로 : 윗줄에서 내려온다. 줄 사이 여백을 그대로 채운다 */
.xc-swim__v {
  justify-self: center; align-self: start;
  width: 0; height: var(--swim-row); translate: 0 -100%;
  border-left: 1.5px dashed var(--xc-text-weak);
}
.xc-swim__v::after {
  content: ""; position: absolute; bottom: 0; left: 50%;
  width: 9px; height: 9px; translate: -50% -2px; rotate: 45deg;
  border: 0 solid var(--xc-accent); border-bottom-width: 2px; border-right-width: 2px;
}
/* 가로 : 오른쪽 여백을 채운다. --l 이면 화살촉이 왼쪽 끝에 붙어 되돌아온다 */
.xc-swim__h {
  align-self: center; justify-self: end;
  /* 칸과 칸 사이 = 열 사이 여백 + 양쪽 칸이 물러난 폭 */
  width: calc(var(--swim-gap) + 2 * var(--swim-in)); height: 0;
  translate: calc(var(--swim-gap) + var(--swim-in)) 0;
  border-top: 1.5px dashed var(--xc-text-weak);
}
.xc-swim__h::after {
  content: ""; position: absolute; top: 50%; right: 0;
  width: 9px; height: 9px; translate: -2px -50%; rotate: 45deg;
  border: 0 solid var(--xc-accent); border-top-width: 2px; border-right-width: 2px;
}
.xc-swim__h--l::after { right: auto; left: 0; translate: 2px -50%; rotate: 225deg; }
/* 도착점이 아니라 이어지는 도막이면 화살촉을 두지 않는다.
   ⚠️ 04 의 '메일 발송' 이 그렇다. 선은 여기서 끝나지 않고 오른쪽 바깥을 돌아
      사원에게 간다. 여기에 화살촉을 두면 뒤로 이어지는 선이 촉을 뚫고 나간다 */
.xc-swim__h--go::after { display: none; }
/* ㄱ 자로 꺾이는 선(문서확인 및 서명 → 서명내용 DB저장).
   원본은 사원 칸 '아래'로 빠져나와 왼쪽으로 꺾여 Bot 칸의 오른쪽 변으로 들어간다.
   곧은 가로선 하나로는 어느 칸에서 나왔는지 알 수 없어 두 도막으로 그린다.
   ⚠️ 두 열(--a 로 2~3열)에 걸치는 상자다. 열 폭을 W, 열 사이를 G 라 하면
      상자 폭은 2W+G 다. 3열 한가운데는 상자 왼쪽에서 1.5W+G = 75% + G/4,
      2열 칸의 오른쪽 변은 W - in = 50% - G/2 - in 이다. 폭이 변해도 이 식은 성립한다 */
.xc-swim__hook { grid-area: var(--a); position: relative; z-index: 3; }
.xc-swim__hook::before,
.xc-swim__hook::after { content: ""; position: absolute; }
/* 세로 : 윗줄 칸 아래에서 이 줄 한가운데까지 */
.xc-swim__hook::before {
  top: calc(var(--swim-row) * -1); bottom: 50%;
  left: calc(75% + var(--swim-gap) / 4);
  border-left: 1.5px dashed var(--xc-text-weak);
}
/* 가로 : 거기서 왼쪽 칸의 오른쪽 변까지 */
.xc-swim__hook::after {
  bottom: 50%;
  left: calc(50% - var(--swim-gap) / 2 - var(--swim-in));
  right: calc(25% - var(--swim-gap) / 4);
  border-top: 1.5px dashed var(--xc-text-weak);
}
.xc-swim__hook > i {
  position: absolute; bottom: 50%;
  left: calc(50% - var(--swim-gap) / 2 - var(--swim-in));
  width: 9px; height: 9px; translate: 2px 50%; rotate: 225deg;
  border: 0 solid var(--xc-accent); border-top-width: 2px; border-right-width: 2px;
}
/* 갈래 이름표(Yes · No).
   ⚠️ 화살촉을 피해서 앉힌다. 세로선은 화살촉이 아래 끝에 있으므로 위쪽에,
      가로선은 화살촉이 한쪽 끝에 있고 선 자체가 짧으므로 선 위(바깥)에 둔다.
   ⚠️ 둘레를 바탕색으로 둘러 지나가는 점선이 이름표 앞에서 끊겨 보이게 한다 */
.xc-swim__v > em,
.xc-swim__h > em {
  position: absolute; z-index: 1;
  padding: 2px 9px; border-radius: var(--xc-radius-full);
  background: var(--xc-navy); color: var(--xc-white);
  font-style: normal; font-size: var(--xc-fs-12); font-weight: var(--xc-fw-bold);
  white-space: nowrap; box-shadow: 0 0 0 4px var(--xc-bg);
}
.xc-swim__v > em { top: 30%; left: 50%; translate: -50% -50%; }
/* 가로선(Yes)은 선 한가운데에 앉는다. 전에는 선 위로 5px 띄워 두었는데,
   선과 떨어져 있어 어느 갈래의 이름인지가 약했다.
   ⚠️ 이 선은 짧다(70px). 라벨(38px)에 바탕 테두리 4px 이 둘러 있어 선이 거의 덮이는데,
      그게 의도다 — 점선이 이름표 앞에서 끊겨 보인다. 화살촉은 왼쪽 끝에 남는다. */
.xc-swim__h > em { top: 0; left: 50%; translate: -50% -50%; }
/* 미회신자에게 다시 보내는 되돌이 — 오른쪽 바깥을 돌아 사원에게 간다.
   ⚠️ 한 상자의 세 변으로 그리지 않는다. 그러면 윗변이 사원 칸 밑을 가로지르는데,
      칸 높이가 글자 줄 수에 따라 달라지면 칸 오른쪽으로 삐져나오는 지점의 높이가
      들어오는 화살표와 어긋나 계단처럼 보인다.
      보이는 세 도막만 따로 그린다 — 칸 밑을 지나는 선은 아예 없다.
   ⚠️ 세 도막은 모두 줄 위에서 --swim-half 만큼 내려온 자리에 둔다. 줄 한가운데(center)로
      맞추면 줄마다 높이가 달라 도막끼리 어긋난다. 같은 값을 쓰면 반드시 만난다. */
.xc-swim__ret {
  grid-area: var(--a); position: relative; z-index: 1;
  border: 0 dashed var(--xc-text-weak);
}
/* 위 : 사원 칸의 오른쪽 변에서 오른쪽 바깥까지 */
.xc-swim__ret--top {
  align-self: start; height: 0; margin-top: var(--swim-half);
  margin-left: calc(100% - var(--swim-in));
  margin-right: calc(var(--swim-pad) * -1);
  border-top-width: 1.5px;
}
/* 아래 : 앞 도막이 끝난 자리에서 오른쪽 바깥까지 */
.xc-swim__ret--btm {
  align-self: start; height: 0; margin-top: var(--swim-half);
  margin-left: var(--swim-in);
  margin-right: calc(var(--swim-pad) * -1);
  border-top-width: 1.5px;
}
/* 옆 : 두 도막의 오른쪽 끝을 잇는다 */
.xc-swim__ret--side {
  justify-self: end; width: 0;
  margin: var(--swim-half) calc(var(--swim-pad) * -1) var(--swim-half) 0;
  border-left-width: 1.5px;
}
/* 되돌이의 끝 — 사원 칸의 오른쪽 변으로 들어간다 */
.xc-swim__ret--top > i {
  position: absolute; top: 0; left: 0;
  width: 9px; height: 9px; translate: 2px -50%; rotate: 225deg;
  border: 0 solid var(--xc-accent); border-top-width: 2px; border-right-width: 2px;
}

/* ③ 칸 — 맨 위 */
.xc-swim__cell {
  grid-row: var(--r); grid-column: var(--c); position: relative; z-index: 2;
  display: grid; place-content: center; gap: 4px;
  margin-inline: var(--swim-in);
  padding: 12px 14px; border-radius: var(--xc-radius);
  background: var(--xc-gray-50);
  border: 1px solid var(--xc-border-weak);
  font-size: var(--xc-fs-xs); color: var(--xc-text); line-height: 1.5;
  text-align: center; text-wrap: pretty;
}
.xc-swim__cell.is-key {
  background: var(--xc-bg); border-color: var(--xc-orange);
  color: var(--xc-orange); font-weight: var(--xc-fw-bold);
}
/* 분기는 마름모다 */
.xc-swim__cell.is-fork {
  padding: 26px 34px; border: 0; background: var(--xc-gray-50);
  clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);
  font-weight: var(--xc-fw-bold);
}
/* 순번·주체 이름표는 세로로 설 때만 쓴다 */
.xc-swim__cell > i { display: none; }

/* 구성도 카드 안 쌓임(RPA 적용 예시 2) */
.xc-rpa__stack { display: grid; gap: 6px; margin-top: 4px; }
.xc-rpa__stack > li {
  padding: 8px 12px; border-radius: var(--xc-radius-sm);
  background: var(--xc-bg); border: 1px solid var(--xc-border-weak);
  font-size: var(--xc-fs-12); color: var(--xc-text-sub); line-height: 1.5; text-wrap: pretty;
}
.xc-rpa__stack > li i {
  display: block; font-style: normal; color: var(--xc-text-weak);
}

/* ── 상세 : 계층 구조 도해(RPA 제품개요 · 시스템 구성도) ──
   위에서 아래로 세 겹이다 — 인터페이스 · 자동화 수단 · 이를 엮는 제어센터.

   ⚠️ 도해 전체가 격자 하나다. 줄을 나눠 <ul> 로 감싸지 않는다. 원본에는 두 묶음이 있고
      (3열 세로 띠 · 아래 줄+Power Automate 가로 묶음) 서로 겹친다. 묶음을 감싸개로 만들면
      한쪽이 다른 쪽을 자른다. 같은 격자에 놓고 칸을 걸치게 해야 겹칠 수 있다.
   ⚠️ 줄 번호를 못박는다 — 1 상자 · 2 세로선 · 3 갈래 · 4 위 카드 · 5 잇는 줄 ·
      6 아래 카드 · 7 버스 · 8 세로선 · 9 상자. 자동 배치에 맡기면 칸이 없는 도해
      (시스템 구성도)에서 줄이 당겨져 띠 좌표가 어긋난다.
   ⚠️ 띠는 마크업에서 카드보다 앞에 둔다. 자리 잡힌 요소가 아니라 그리는 차례가 앞뒤를 정한다.
   ⚠️ 띠가 카드 밖으로 번지는 만큼 도해 자체에 안쪽 여백(--rpa-pad)을 준다. 여백 없이
      음수 margin 으로 번지게 하면 오른쪽으로 넘쳐 가로 스크롤이 생긴다. */
.xc-rpa {
  --rpa-gap: clamp(10px, 1.4vw, 20px);
  --rpa-pad: clamp(10px, 1.2vw, 16px);
  --rpa-link: clamp(26px, 3vw, 40px);
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  column-gap: var(--rpa-gap);
  padding: var(--rpa-pad);
  margin-top: clamp(24px, 3vw, 40px);
}
/* 묶음 띠 — 카드 뒤에 깔린다 */
.xc-rpa__grp,
.xc-rpa__band { border-radius: var(--xc-radius-lg); }
/* 아래 줄 + Power Automate : 이 셋이 한 몸으로 움직인다 */
.xc-rpa__grp {
  grid-area: 6 / 1 / 10 / -1;
  margin: calc(var(--rpa-pad) * -1);
  background: rgba(22, 29, 41, .05);
}
/* 3열 세로 띠 : 인터페이스와 그 자동화 수단이 한 줄기다 */
.xc-rpa__band {
  grid-area: 4 / 3 / 7 / 4;
  margin: -9px calc(var(--rpa-pad) * -1) -9px calc(var(--rpa-gap) / -2);
  background: rgba(252, 101, 0, .08);
}
.xc-rpa__box {
  grid-column: 1 / -1;
  max-width: min(100%, 520px); margin-inline: auto;
  padding: clamp(16px, 1.8vw, 22px) clamp(18px, 2vw, 28px);
  background: var(--xc-navy); border-radius: var(--xc-radius-lg);
  color: var(--xc-white); text-align: center;
}
.xc-rpa__box--top { grid-row: 1; }
.xc-rpa__box--btm { grid-row: 9; }
.xc-rpa__box b {
  display: block;
  font-size: var(--xc-fs-h4); font-weight: var(--xc-fw-bold);
  letter-spacing: var(--xc-ls-heading);
}
.xc-rpa__box span {
  display: block; margin-top: 9px; padding-top: 9px;
  border-top: 1px solid rgba(255, 255, 255, .24);
  font-size: var(--xc-fs-xs); color: rgba(255, 255, 255, .8);
  line-height: 1.55; text-wrap: pretty;
}
/* 잇는 줄 — 세로선이 카드와 같은 격자에 서서 저절로 칸 한가운데에 온다 */
.xc-rpa__fan,
.xc-rpa__bus,
.xc-rpa__links {
  position: relative; grid-column: 1 / -1;
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--rpa-gap);
  height: var(--rpa-link);
}
.xc-rpa__fan { grid-row: 3; }
.xc-rpa__links { grid-row: 5; }
.xc-rpa__bus { grid-row: 7; }
.xc-rpa__fan::before,
.xc-rpa__bus::before {
  content: ""; position: absolute; height: 0;
  left: calc((100% - 2 * var(--rpa-gap)) / 6);
  right: calc((100% - 2 * var(--rpa-gap)) / 6);
  border-top: 1.5px dashed var(--xc-text-weak);
}
.xc-rpa__fan::before { top: 0; }
.xc-rpa__bus::before { bottom: 0; }
.xc-rpa__v {
  position: relative; justify-self: center;
  width: 0; height: 100%; border-left: 1.5px dashed var(--xc-text-weak);
}
/* 격자 밖 줄에 홀로 서는 세로선(상자 ↔ 버스) */
.xc-rpa__v--solo {
  grid-column: 1 / -1; display: block;
  height: clamp(14px, 1.6vw, 22px); margin-inline: auto;
}
.xc-rpa__v--top { grid-row: 2; }
.xc-rpa__v--btm { grid-row: 8; }
/* 화살촉 — 필요한 쪽만 켠다 */
.xc-rpa__v::before,
.xc-rpa__v::after {
  content: ""; position: absolute; left: 50%; display: none;
  width: 9px; height: 9px; translate: -50% 0; rotate: 45deg;
  border: 0 solid var(--xc-accent);
}
.xc-rpa__v::before { top: 2px; border-top-width: 2px; border-left-width: 2px; }
.xc-rpa__v::after { bottom: 2px; border-bottom-width: 2px; border-right-width: 2px; }
.xc-rpa__v--up::before,
.xc-rpa__v--both::before { display: block; }
.xc-rpa__v--dn::after,
.xc-rpa__v--both::after { display: block; }
/* 카드 */
/* ⚠️ 열을 반드시 명시한다(--c). 띠가 먼저 3열을 차지하고 있어 자동 배치에 맡기면
   카드가 들어갈 자리를 못 찾고 없는 4열을 새로 만든다 — 격자가 통째로 어긋난다 */
.xc-rpa__cell {
  grid-row: 4; grid-column: var(--c);
  display: grid; align-content: center; gap: 8px;
  padding: clamp(18px, 2vw, 26px) clamp(12px, 1.4vw, 18px);
  background: var(--xc-gray-50);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius-lg);
  text-align: center;
}
.xc-rpa__cell--btm { grid-row: 6; }
.xc-rpa__cell b {
  font-size: var(--xc-fs-sm); font-weight: var(--xc-fw-bold);
  color: var(--xc-text); line-height: 1.5; text-wrap: pretty;
}
.xc-rpa__cell p {
  font-size: var(--xc-fs-xs); color: var(--xc-text-sub); line-height: 1.6; text-wrap: pretty;
}
.xc-rpa__cell--on { background: var(--xc-bg); border-color: var(--xc-orange); }
/* 구성도 카드 안 쌓임(RPA 적용 예시 2) */
.xc-rpa__stack { display: grid; gap: 6px; margin-top: 4px; }
.xc-rpa__stack > li {
  padding: 8px 12px; border-radius: var(--xc-radius-sm);
  background: var(--xc-bg); border: 1px solid var(--xc-border-weak);
  font-size: var(--xc-fs-12); color: var(--xc-text-sub); line-height: 1.5; text-wrap: pretty;
}
.xc-rpa__stack > li i { display: block; font-style: normal; color: var(--xc-text-weak); }

/* ── 상세 : 가로 단계 흐름(BI 업무 프로세스) ────────────
   차례가 있는 여러 단계를 왼쪽에서 오른쪽으로 늘어놓는다. 아이콘 원을 선 하나가 꿰고,
   원과 원 사이에 화살촉이 하나씩 앉아 방향을 알려 준다.
   ⚠️ 선의 양 끝은 첫 원과 끝 원의 '한가운데' 다. 칸 수가 바뀌면 이 값도 따라가야 하므로
      --fl-n 으로 계산한다(가지 도해 .xc-hub__bus 와 같은 셈이다).
   ⚠️ 화살촉은 칸과 칸 사이(gap 한가운데)에 둔다. 원 안에 넣으면 아이콘과 겹친다.
   ⚠️ 좁아지면 가로로 못 읽는다. 1024 아래에서는 세로로 세우고 선·화살촉도 아래를 향한다 */
.xc-fl {
  --fl-n: 5;
  --fl-dot: clamp(54px, 5.2vw, 76px);
  --fl-gap: clamp(12px, 1.6vw, 28px);
  position: relative;
  margin-top: clamp(24px, 3vw, 40px);
}
.xc-fl__rail {
  position: absolute; top: calc(var(--fl-dot) / 2); height: 1px;
  left: calc((100% - (var(--fl-n) - 1) * var(--fl-gap)) / (var(--fl-n) * 2));
  right: calc((100% - (var(--fl-n) - 1) * var(--fl-gap)) / (var(--fl-n) * 2));
  background: var(--xc-border);
}
.xc-fl__steps {
  display: grid; grid-template-columns: repeat(var(--fl-n), minmax(0, 1fr));
  gap: var(--fl-gap);
}
.xc-fl__step {
  position: relative;
  display: grid; justify-items: center; align-content: start; gap: 12px;
  text-align: center;
}
/* 칸과 칸 사이 화살촉 */
.xc-fl__step + .xc-fl__step::before {
  content: ""; position: absolute;
  top: calc(var(--fl-dot) / 2); left: calc(var(--fl-gap) / -2);
  width: 10px; height: 10px; translate: -50% -50%; rotate: 45deg;
  border-top: 2px solid var(--xc-accent); border-right: 2px solid var(--xc-accent);
}
.xc-fl__dot {
  position: relative; z-index: 1;
  display: grid; place-items: center;
  width: var(--fl-dot); height: var(--fl-dot); border-radius: 50%;
  background: var(--xc-gray-50); border: 1px solid var(--xc-border-weak);
  color: var(--xc-navy);
}
.xc-fl__dot svg { width: 50%; height: 50%; }
.xc-fl__name {
  display: block;
  font-size: var(--xc-fs-h4); font-weight: var(--xc-fw-bold);
  letter-spacing: var(--xc-ls-heading); color: var(--xc-text);
  line-height: 1.5; text-wrap: pretty;
}
.xc-fl__name i {
  display: block; margin-bottom: 4px;
  font-style: normal; font-size: var(--xc-fs-12); font-weight: var(--xc-fw-bold);
  letter-spacing: .06em; color: var(--xc-orange);
}
/* 단계 이름이 두 줄인 경우(legacy 원문이 두 줄로 적혀 있다). 크기·색은 이름 그대로다 —
   작게 두면 부제처럼 읽혀 뜻이 달라진다. 줄만 나눈다 */
.xc-fl__name em { display: block; font-style: normal; }
.xc-fl__list { display: grid; gap: 6px; }
.xc-fl__list > li {
  padding: 7px 14px; border-radius: var(--xc-radius-full);
  background: var(--xc-gray-50); border: 1px solid var(--xc-border-weak);
  font-size: var(--xc-fs-xs); color: var(--xc-text-sub); line-height: 1.5; text-wrap: pretty;
}

/* ── 상세 : 뱀 모양 공정 흐름(배합관리 생산공정 프로세스) ────
   원본(mate-mixture-system-img-01.jpg)은 열한 단계가 위에서 오른쪽으로 갔다가
   오른쪽 끝에서 꺾여 내려와 아래에서 왼쪽으로 돌아오는 뱀 모양이다.
   아이콘 · 레일 · 이름을 각각 제 줄에 두고 격자에 올린다.

   줄 : 1 위 아이콘 · 2 위 레일 · 3 위 이름 · 4 되돌림 · 5 아래 아이콘 · 6 아래 레일 · 7 아래 이름
   ⚠️ 레일의 양 끝은 첫 칸과 끝 칸의 '한가운데' 다. 여섯 칸이므로 반 칸 = (100% - 5g)/12 이고,
      아래 레일은 2열부터 시작하므로 왼쪽만 반 칸 셋 + 여백 하나를 더 민다.
   ⚠️ 오른쪽 꺾임은 한 요소의 세 변(위 · 오른쪽 · 아래)으로 그린다. 도막을 따로 두고 맞대면
      모서리가 뚫린다(ERP 도해에서 겪은 것과 같다).
   ⚠️ 좁아지면 열한 칸이 안 들어간다. 세로로 풀면 뱀 모양이라는 뜻 자체가 사라지므로
      제 상자 안에서만 가로로 굴린다. 페이지가 좌우로 밀리면 안 되므로 overflow-x 를 명시한다 */
.xc-serp__wrap {
  margin-top: clamp(24px, 3vw, 40px);
  overflow-x: auto; overflow-y: hidden;
  scrollbar-width: thin;
}
.xc-serp {
  --serp-n: 6;
  --serp-gap: clamp(14px, 1.8vw, 30px);
  --serp-dot: clamp(68px, 6.2vw, 96px);
  --serp-railh: 18px;
  --serp-ring: 11px;
  --serp-bulge: clamp(36px, 3.6vw, 66px);
  --serp-half: calc((100% - (var(--serp-n) - 1) * var(--serp-gap)) / (var(--serp-n) * 2));
  min-width: 960px;
  display: grid;
  grid-template-columns: repeat(var(--serp-n), minmax(0, 1fr));
  grid-template-rows:
    var(--serp-dot) var(--serp-railh) auto
    clamp(80px, 8.4vw, 130px)
    var(--serp-dot) var(--serp-railh) auto;
  column-gap: var(--serp-gap); row-gap: 14px;
}
.xc-serp > * { grid-area: var(--a); }
/* 레일 — 칸 전체를 덮고 반 칸씩 물러나 첫 원과 끝 원의 한가운데에서 끝난다 */
.xc-serp__rail {
  align-self: center; height: 1px;
  margin-inline: var(--serp-half);
  background: var(--xc-border);
}
.xc-serp__rail--btm { margin-left: calc(3 * var(--serp-half) + var(--serp-gap)); }
/* 레일 위의 작은 고리 */
.xc-serp__ring {
  justify-self: center; align-self: center; z-index: 1;
  width: var(--serp-ring); height: var(--serp-ring); border-radius: 50%;
  background: var(--xc-bg); border: 2px solid var(--xc-border-strong);
}
/* 오른쪽 꺾임 — 위 레일 끝에서 아래 레일 끝까지 감아 내린다 */
.xc-serp__turn {
  width: var(--serp-bulge);
  margin-left: auto; margin-right: calc(var(--serp-half) - var(--serp-bulge));
  margin-block: calc(var(--serp-railh) / 2);
  border: 0 solid var(--xc-border);
  border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px;
  border-radius: 0 var(--xc-radius-lg) var(--xc-radius-lg) 0;
}
.xc-serp__turn::after {
  content: ""; position: relative; display: block; top: 50%; left: 100%;
  width: 11px; height: 11px; translate: -50% -50%; rotate: 45deg;
  border: 0 solid var(--xc-accent); border-bottom-width: 2px; border-right-width: 2px;
}
/* 흐르는 방향을 알리는 촉 — 첫 고리 바로 옆에 하나씩만 둔다 */
.xc-serp__go {
  justify-self: center; align-self: center; z-index: 1;
  width: 11px; height: 11px; translate: 18px 0; rotate: 45deg;
  border: 0 solid var(--xc-accent); border-top-width: 2px; border-right-width: 2px;
}
.xc-serp__go--back { rotate: 225deg; }
.xc-serp__ico {
  justify-self: center;
  display: grid; place-items: center;
  width: var(--serp-dot); height: var(--serp-dot); border-radius: 50%;
  background: var(--xc-gray-50); border: 1px solid var(--xc-border-weak);
  /* 아이콘은 회색. 원 안이 이미 회색 면이라 네이비로 두면 아이콘만 도드라져
     단계 이름보다 먼저 읽힌다. 읽는 차례는 이름 → 아이콘이다 */
  color: var(--xc-text-sub);
}
.xc-serp__ico svg { width: 50%; height: 50%; }
.xc-serp__name {
  align-self: start; text-align: center;
  font-size: var(--xc-fs-h4); font-weight: var(--xc-fw-bold);
  letter-spacing: var(--xc-ls-heading); color: var(--xc-text);
  line-height: 1.5; text-wrap: pretty;
}
/* 되돌림 — BOM(냉각) 에서 고무Checker 로 A련 고무가 올라간다.
   ⚠️ 점선과 촉은 칸 한가운데, 글자는 그 오른쪽이다. 글자를 가운데 두면 선이 글자를 뚫는다 */
.xc-serp__back {
  position: relative;
  display: grid; align-content: center; justify-items: center;
  padding-left: 88px;
  font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-bold);
  color: var(--xc-text-sub); white-space: nowrap;
}
.xc-serp__back::before {
  content: ""; position: absolute; left: 50%; top: 6px; bottom: 6px;
  border-left: 1.5px dashed var(--xc-accent);
}
.xc-serp__back::after {
  content: ""; position: absolute; left: 50%; top: 6px;
  width: 11px; height: 11px; translate: -50% 2px; rotate: 45deg;
  border: 0 solid var(--xc-accent); border-top-width: 2px; border-left-width: 2px;
}

/* ── 상세 : 주요 기능 ──
   열 수와 마지막 줄 메우기는 .xc-fitrow 가 맡는다(파일 아래쪽 '카드 격자' 참고).
   ⚠️ 예전에는 auto-fit(minmax 240px)이었다. 폭에 따라 열이 저절로 바뀌어 편했지만,
      바로 그래서 마지막 줄에 빈 칸이 몇 개 남을지 알 수 없었다. 열 수를 못박고
      개수에 맞춰 고르는 쪽으로 바꿨다 */
.xc-sol__feat { margin-top: clamp(20px, 2.4vw, 32px); }
/* 2열은 카드가 넓다. 긴 목록을 여러 갈래로 흘려 높이를 반으로 줄인다.
   ⚠️ 짧은 목록은 그대로 한 갈래다 — 두 줄짜리를 둘로 쪼개면 오히려 어수선하다 */
@media (min-width: 1025px) {
  .xc-fitrow--2 .xc-sol__flist {
    display: block; columns: 2; column-gap: clamp(16px, 2vw, 32px);
  }
  .xc-fitrow--2 .xc-sol__flist > li { break-inside: avoid; margin-bottom: 7px; }
}
.xc-sol__feat > li {
  display: flex; flex-direction: column;
  padding: clamp(22px, 2.4vw, 30px);
  background: var(--xc-gray-50);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius-lg);
}
/* 번호가 이 섹션의 리듬을 만든다. 솔루션 페이지마다 똑같이 있는 구간이라
   멀리서도 01 02 03 04 가 먼저 읽혀야 한다.
   ⚠️ 선택자를 .xc-sol__no 하나로 두면 안 된다. 번호가 <p> 라서 아래의
      `.xc-sol__feat p`(0-1-1)가 이 규칙(0-1-0)을 이겨 color 가 회색으로 덮인다.
      실제로 모든 솔루션 페이지에서 브랜드 색이 죽어 있었다. 클래스를 하나 더 얹는다.
   ⚠️ line-height 를 1 로 눌러 둔다. 글자가 커진 만큼 기본 행간이 카드 위에 빈 띠를 만든다. */
.xc-sol__feat .xc-sol__no {
  /* ⚠️ 토큰(--xc-fs-feat-no)을 그대로 쓰지 않는다. 한 페이지에 카드 24장이 이어지므로
     숫자가 크면 그것만 눈에 밟힌다. 이 화면 전용 값으로 한 단계 낮춘다 */
  font-size: var(--xc-fs-feat-no-sm); font-weight: var(--xc-fw-extra);
  letter-spacing: -.01em; line-height: 1;
  color: var(--xc-accent); font-variant-numeric: tabular-nums;
}
/* ⚠️ 크기를 직접 적지 않고 척도 토큰을 쓴다. 전에는 clamp(17px, 1.4vw, 20px) 이 적혀
   있었는데 이는 --xc-fs-h4 와 같은 값이었다. 토큰으로 두면 한 단계씩 올리고 내리기 쉽다 */
/* ⚠️ 꼬리표(em)는 제목 옆이 아니라 제목 '아래' 줄에 놓는다. 세로 flex 다.
   옆에 두면 칸 폭에 따라 어떤 카드는 옆에, 어떤 카드는 아래에 붙어 제각각이 된다.
   실제로 같은 목록 안에서 03 은 접히고 07 은 옆에 붙어 있었다.
   ⚠️ align-items: flex-start 가 있어야 칩이 칸 폭만큼 늘어나지 않는다.
   ⚠️ 간격은 gap 이 맡는다. 칩이 margin 을 들고 있으면 왼쪽이 밀린다. */
.xc-sol__feat b {
  display: flex; flex-direction: column; align-items: flex-start; gap: 6px;
  margin-top: 12px;
  /* ⚠️ 카드 제목은 이 화면 전체가 --xc-fs-h4 하나로 간다(주요 기능·특징·기대효과·
     TMS 타임라인·ADUP 가지). 한 페이지에 카드가 40장 넘게 이어지므로 종류마다 크기가
     다르면 스크롤하는 동안 제목이 오르내린다 */
  font-size: var(--xc-fs-h4); font-weight: var(--xc-fw-bold);
  letter-spacing: var(--xc-ls-heading); color: var(--xc-text); text-wrap: pretty;
}
/* 제목 옆 꼬리표 — '프로그램 메뉴구성' 처럼 아래 목록이 무엇인지 알려 주는 말.
   ⚠️ 목록 첫 줄에 두면 메뉴 하나처럼 읽힌다. 제목 옆으로 올려 성격을 갈라 둔다 */
/* ⚠️ margin-left 를 주지 않는다. 간격은 부모의 gap 이 맡는다 —
   여백을 자신이 들고 있으면 줄이 바뀔 때 그 여백도 함께 따라가 왼쪽이 밀린다.
   ⚠️ nowrap 을 쓰지 않는다. 제목 옆에 있을 때는 한 줄로 붙잡아야 했지만,
      이제 제 줄을 쓰므로 긴 꼬리표는 접히는 편이 낫다. 실제로 RPA 사례 01 의
      「Excel(대상목록) · Word(Template)」 가 200px 칸을 5px 넘고 있었다.
      문안은 legacy 그대로 두어야 하므로 글자를 줄이지 않고 칸에 맞춘다. */
.xc-sol__feat b em {
  max-width: 100%;
  padding: 3px 10px;
  border-radius: var(--xc-radius-full);
  background: var(--xc-bg); border: 1px solid var(--xc-border-weak);
  font-style: normal; font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-semibold);
  color: var(--xc-text-weak); line-height: 1.5;
}
.xc-sol__feat p { margin-top: 10px; font-size: var(--xc-fs-sm); color: var(--xc-text-sub); line-height: 1.7; text-wrap: pretty; }
/* 기능 설명이 여러 줄인 카드(TMS 시험관리·설비관리)가 있다 */
.xc-sol__flist { margin-top: 10px; display: flex; flex-direction: column; gap: 7px; }
.xc-sol__flist > li {
  position: relative; padding-left: 12px;
  font-size: var(--xc-fs-sm); color: var(--xc-text-sub); line-height: 1.7; text-wrap: pretty;
}
.xc-sol__flist > li::before {
  content: ""; position: absolute; left: 0; top: .68em;
  width: 4px; height: 4px; border-radius: 50%; background: var(--xc-text-weak);
}

/* ── 상세 : 특징 · 기대효과 ──
   항목마다 설명 길이가 크게 다르다(TMS 특징은 한 줄 ~ 세 줄). 카드로 깔면 높이가 들쭉날쭉해서
   제목 열과 설명 열을 나눈 목록으로 둔다. 항목이 4개든 5개든 빈칸이 생기지 않는다 */
.xc-sol__pts {
  margin-top: clamp(20px, 2.4vw, 32px);
  border-top: 1px solid var(--xc-border-weak);
}
.xc-sol__pts > li {
  display: grid; grid-template-columns: minmax(150px, 260px) minmax(0, 1fr);
  gap: clamp(16px, 2.4vw, 48px);
  padding: clamp(18px, 2vw, 28px) 0;
  border-bottom: 1px solid var(--xc-border-weak);
}
.xc-sol__pts b {
  font-size: var(--xc-fs-h4); font-weight: var(--xc-fw-bold);
  letter-spacing: var(--xc-ls-heading); color: var(--xc-text); text-wrap: pretty;
}
.xc-sol__pts p { font-size: var(--xc-fs-sm); color: var(--xc-text-sub); line-height: 1.8; text-wrap: pretty; }

/* 카드형 — 설명이 한 줄로 고른 '기대효과' 에 쓴다.
   ⚠️ 특징(TMS)에는 쓰지 않는다. 설명이 한 줄~세 줄로 달라 카드 높이가 들쭉날쭉해진다 */
/* 열 수와 마지막 줄 메우기는 .xc-fitrow 가 맡는다 */
.xc-sol__pts--cards { border-top: 0; }
.xc-sol__pts--cards > li {
  display: flex; flex-direction: column; gap: 0;
  padding: clamp(22px, 2.4vw, 30px);
  background: var(--xc-gray-50);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius-lg);
}
.xc-sol__pts--cards p { margin-top: 12px; line-height: 1.7; }

/* 기대효과 카드의 아이콘. 오른쪽 위 구석에 앉는다.
   ⚠️ 왼쪽에 두면 설명이 길어질수록 아이콘 아래가 빈 띠로 남는다.
      오른쪽 위면 글이 카드 폭을 다 쓰고, 제목과 같은 높이라 함께 읽힌다.
   ⚠️ 60개 항목에 58개 이름이 있다. 전부 다르게 그리면 「가시성」·「유용성」처럼
      형태가 없는 개념까지 억지 기호가 되어 서로 구분되지 않는다.
      의미가 같은 것끼리 12종으로 묶어 돌려 쓴다 — 반복은 어휘가 된다.
   ⚠️ 아이콘을 마크업이 아니라 mask 로 그린다. 항목마다 SVG 를 넣으면
      60벌이 되고, 색을 바꿀 때 60군데를 고쳐야 한다. */
.xc-sol__pts--cards > li { position: relative; }
.xc-sol__pts--cards > li[data-ico] { padding-right: clamp(58px, 5.4vw, 74px); }
/* ⚠️ --ico 는 li 에 둔다. ::after 에 두면 형제인 b::before 가 못 읽는다
      (표 형태 목록의 아이콘이 전부 안 나왔다). */
.xc-sol__pts--cards > li[data-ico]::after {
  content: ''; position: absolute;
  right: clamp(20px, 2.2vw, 26px); top: clamp(20px, 2.2vw, 26px);
  width: 24px; height: 24px;
  /* ⚠️ 예전에 쓰던 --xc-orange-text 는 토큰에서 사라졌다(포인트색은 #fc6500 하나로
        정리됐다). 없는 변수를 쓰면 background 선언이 통째로 무효가 되어
        아이콘이 투명해진다 — 실제로 그래서 안 보였다. */
  background: var(--xc-orange);
  -webkit-mask: var(--ico) no-repeat center / contain;
          mask: var(--ico) no-repeat center / contain;
}
.xc-dark .xc-sol__pts--cards > li[data-ico]::after { background: var(--xc-grad-2); }

/* 카드가 아닌 「두 열짜리 표」 형태의 기대효과.
   ⚠️ 여기는 행이라 오른쪽 위에 두면 아이콘이 제목에서 멀찍이 떨어진다.
      제목 바로 앞에 붙여야 어느 항목의 아이콘인지 보인다.
   ⚠️ --ico 는 li 에 있고 상속되므로 b::before 에서 그대로 쓸 수 있다. */
.xc-sol__pts:not(.xc-sol__pts--cards) > li[data-ico] > b::before {
  content: ''; display: inline-block; vertical-align: -3px;
  width: 19px; height: 19px; margin-right: 9px;
  /* ⚠️ 예전에 쓰던 --xc-orange-text 는 토큰에서 사라졌다(포인트색은 #fc6500 하나로
        정리됐다). 없는 변수를 쓰면 background 선언이 통째로 무효가 되어
        아이콘이 투명해진다 — 실제로 그래서 안 보였다. */
  background: var(--xc-orange);
  -webkit-mask: var(--ico) no-repeat center / contain;
          mask: var(--ico) no-repeat center / contain;
}
.xc-dark .xc-sol__pts:not(.xc-sol__pts--cards) > li[data-ico] > b::before {
  background: var(--xc-grad-2);
}

.xc-sol__pts > li[data-ico="eye"] { --ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2 12s3.6-6.5 10-6.5S22 12 22 12s-3.6 6.5-10 6.5S2 12 2 12Z M12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6Z'/%3E%3C/svg%3E"); }
.xc-sol__pts > li[data-ico="link"] { --ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 6.5H6.5a5.5 5.5 0 0 0 0 11H9 M15 6.5h2.5a5.5 5.5 0 0 1 0 11H15 M8 12h8'/%3E%3C/svg%3E"); }
.xc-sol__pts > li[data-ico="shield"] { --ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 2.5 20 5.5v6c0 5-3.4 8.3-8 9.5-4.6-1.2-8-4.5-8-9.5v-6Z M8.6 12l2.4 2.4 4.4-4.6'/%3E%3C/svg%3E"); }
.xc-sol__pts > li[data-ico="bolt"] { --ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M13.2 2.5 4.5 13.5H11l-.2 8 8.7-11H13Z'/%3E%3C/svg%3E"); }
.xc-sol__pts > li[data-ico="cost"] { --ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 3.5v13 M7.5 12.5 12 17l4.5-4.5 M4.5 20.5h15'/%3E%3C/svg%3E"); }
.xc-sol__pts > li[data-ico="check"] { --ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 2.5a9.5 9.5 0 1 0 0 19 9.5 9.5 0 0 0 0-19Z M7.6 12.2l3 3 5.8-6.2'/%3E%3C/svg%3E"); }
.xc-sol__pts > li[data-ico="trace"] { --ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4.5 18.5c4-.5 5-3 5-6.5s1-6 5-6.5 M4.5 18.5h2 M17.5 5.5h2 M9.5 12h5'/%3E%3C/svg%3E"); }
.xc-sol__pts > li[data-ico="people"] { --ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M8.5 11a3.2 3.2 0 1 0 0-6.4 3.2 3.2 0 0 0 0 6.4Z M2.5 20c0-3.3 2.7-5.5 6-5.5s6 2.2 6 5.5 M16 5.2a3 3 0 0 1 0 5.9 M17 14.8c2.6.4 4.5 2.4 4.5 5.2'/%3E%3C/svg%3E"); }
.xc-sol__pts > li[data-ico="grid"] { --ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 6.5h16 M4 12h16 M4 17.5h16 M8.2 4v16'/%3E%3C/svg%3E"); }
.xc-sol__pts > li[data-ico="data"] { --ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 20.5h16 M7 20.5v-7 M12 20.5V7 M17 20.5v-10'/%3E%3C/svg%3E"); }
.xc-sol__pts > li[data-ico="gear"] { --ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 15.2a3.2 3.2 0 1 0 0-6.4 3.2 3.2 0 0 0 0 6.4Z M12 2.5l1.3 2.6 2.9-.4.6 2.9 2.6 1.3-1.5 2.5 1.5 2.5-2.6 1.3-.6 2.9-2.9-.4L12 21.5l-1.3-2.6-2.9.4-.6-2.9-2.6-1.3L6.1 12 4.6 9.5l2.6-1.3.6-2.9 2.9.4Z'/%3E%3C/svg%3E"); }
.xc-sol__pts > li[data-ico="gauge"] { --ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 17.5a8.5 8.5 0 1 1 16 0 M12 17.5l4.2-5.4'/%3E%3C/svg%3E"); }

/* ── 상세 : 가로 타임라인(TMS 시험 절차) ────────────────
   선이 왼쪽에서 오른쪽으로 그어지고 번호가 차례로 켜진다.
   ⚠️ 스크롤에 매달지 않는다 — 화면에 들어오면 한 번 재생되는 시간차 애니메이션이다.
      스크롤을 멈춰도 끝까지 재생된다(main.js 의 [data-tl]).
   ⚠️ 선의 양 끝은 첫 번호와 끝 번호의 '한가운데' 다. 4칸이면 각각 12.5% · 87.5% 다.
      칸 수가 바뀌면 이 값도 따라가야 하므로 --tl-n 으로 계산한다.
   ⚠️ 초기 상태를 CSS 에 두지 않는다. 스크립트가 막혀도 전부 보인다.
   ────────────────────────────────────────── */
.xc-tl { --tl-n: 4; --tl-dot: clamp(38px, 3.4vw, 46px); --tl-gap: clamp(10px, 1.2vw, 18px); }
/* 층 순서 — 번호(2) > 가로선(1) > 파문(0) > 카드(흐름)
   ⚠️ 가로선에 z-index 를 줘야 카드에 가리지 않는다. 카드가 DOM 에서 뒤에 온다.
   ⚠️ 번호가 선보다 위여야 선이 원 뒤로 숨는다. 이 순서가 성립하려면 단계(li)에
      transform 이 걸리면 안 된다 — 층 맥락이 생겨 번호가 그 안에 갇힌다(main.js 참고) */
.xc-tl__rail { position: relative; z-index: 1; height: var(--tl-dot); }
.xc-tl__track, .xc-tl__fill {
  position: absolute; top: calc(50% - 1px); height: 2px; border-radius: 2px;
  /* ⚠️ 50% / 칸수 로 잡으면 안 된다. 칸 사이 간격만큼 실제 칸이 좁아져 번호 원의
     한가운데가 그보다 안쪽에 온다 — 첫 칸과 끝 칸에서 선이 원을 지나쳐 삐져나온다.
     간격을 뺀 뒤 나눠야 선 끝과 원 중심이 맞는다 */
  left:  calc((100% - (var(--tl-n) - 1) * var(--tl-gap)) / (var(--tl-n) * 2));
  right: calc((100% - (var(--tl-n) - 1) * var(--tl-gap)) / (var(--tl-n) * 2));
}
.xc-tl__track { background: var(--xc-border); }
.xc-tl__fill { background: var(--xc-accent); transform-origin: 0 50%; }

/* 카드가 번호 원의 한가운데부터 시작한다 — 원이 카드 윗변에 걸터앉는 모양이 된다.
   ⚠️ 위로 당기는 양은 원 지름의 절반이다. 원 전체를 당기면 카드가 선 위로 올라간다 */
.xc-tl__steps {
  margin-top: calc(var(--tl-dot) / -2);
  display: grid; grid-template-columns: repeat(var(--tl-n), minmax(0, 1fr));
  gap: var(--tl-gap);
}
/* ⚠️ align-content: start 가 반드시 있어야 한다. 칸은 가장 높은 칸에 맞춰 늘어나는데,
   격자의 기본값(normal = stretch)은 남는 높이를 줄 사이에 나눠 준다 — 내용이 짧은 칸일수록
   제목이 아래로 밀려 네 제목이 계단처럼 어긋난다 */
/* ⚠️ align-content: start 가 반드시 있어야 한다. 칸은 가장 높은 칸에 맞춰 늘어나는데,
   격자의 기본값(normal = stretch)은 남는 높이를 줄 사이에 나눠 준다 — 내용이 짧은 칸일수록
   제목이 아래로 밀려 네 제목이 계단처럼 어긋난다.
   ⚠️ 카드 위쪽 여백은 원 반지름 + 여유다. 원이 걸터앉은 자리를 글이 침범하면 안 된다 */
/* ⚠️ 단계 자체는 면이 없다. 제목은 카드 밖에 두고 목록만 카드에 담는다.
   ⚠️ 위 여백은 원 반지름 + 여유다. 원이 걸터앉은 자리를 제목이 침범하면 안 된다 */
.xc-tl__step {
  position: relative; display: grid; align-content: start;
  justify-items: center; text-align: center;
  padding-top: calc(var(--tl-dot) / 2 + clamp(14px, 1.6vw, 20px));
  /* 카드 아래 끝을 맞추려면 단계가 먼저 같은 높이여야 한다.
     ⚠️ align-content 는 start 로 두고 이 줄만 늘린다 — stretch 로 되돌리면
        남는 높이가 줄 사이로 흩어져 제목이 다시 계단처럼 어긋난다 */
  grid-template-rows: auto 1fr;
}
/* 선이 이 번호에 닿는 순간 원 뒤에서 파문이 한 번 퍼진다.
   ⚠️ 번호 안(::before)이 아니라 단계(부모)에 둔다. 번호는 z-index 1 로 스택 맥락을
      만들어서, 그 안에 둔 음수 z-index 는 번호 배경 '위' 에 그려진다 — 숫자가 가려진다.
   ⚠️ forwards 로 끝 상태(opacity 0)를 붙잡는다. 안 그러면 끝나고 원이 도로 나타난다. */
.xc-tl__step::before {
  content: ""; position: absolute; z-index: 0;
  top: 0; left: 50%; translate: -50% -50%;
  width: var(--tl-dot); aspect-ratio: 1; border-radius: 50%;
  background: var(--xc-accent); opacity: 0;
  pointer-events: none;
}
.xc-tl__step.is-on::before { animation: xc-tl-ripple 1.6s var(--xc-ease-out) forwards; }
@keyframes xc-tl-ripple {
  from { transform: scale(1);   opacity: .34; }
  to   { transform: scale(2.6); opacity: 0; }
}
/* 모션 최소화에서는 네 단계가 한꺼번에 켜진다 — 파문 넷이 동시에 터지면 소란스럽다 */
@media (prefers-reduced-motion: reduce) {
  .xc-tl__step.is-on::before { animation: none; }
}
.xc-tl__no {
  position: absolute; z-index: 2; top: 0; left: 50%; translate: -50% -50%;
  display: grid; place-items: center;
  width: var(--tl-dot); aspect-ratio: 1; border-radius: 50%;
  background: var(--xc-bg); border: 2px solid var(--xc-border);
  font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-extra);
  color: var(--xc-text-weak); font-variant-numeric: tabular-nums;
  transition: background-color var(--xc-dur-base) var(--xc-ease-standard),
              border-color var(--xc-dur-base) var(--xc-ease-standard),
              color var(--xc-dur-base) var(--xc-ease-standard);
}
/* 선이 닿은 단계 */
.xc-tl__step.is-on .xc-tl__no {
  background: var(--xc-accent); border-color: var(--xc-accent); color: var(--xc-white);
}
.xc-tl__step > b {
  display: block;
  font-size: var(--xc-fs-h4); font-weight: var(--xc-fw-bold);
  letter-spacing: var(--xc-ls-heading); color: var(--xc-text); text-wrap: pretty;
}
/* 목록만 카드에 담는다. 회색 상자 안이라 흰 면이 또렷하다 */
.xc-tl__step ul {
  margin-top: 14px; width: 100%; height: 100%;
  display: flex; flex-direction: column; gap: 8px;
  padding: clamp(16px, 1.8vw, 24px) clamp(12px, 1.4vw, 18px);
  background: var(--xc-bg);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius-lg);
}
.xc-tl__step li {
  font-size: var(--xc-fs-sm); color: var(--xc-text-sub); line-height: 1.7; text-wrap: pretty;
}

@media (max-width: 900px) {
  /* 네 칸이 좁아진다. 두 칸으로 접고 가로선은 뜻이 없어지므로 감춘다 */
  .xc-tl { --tl-n: 2; }
  .xc-tl__rail { display: none; }
  .xc-tl__steps { margin-top: 0; }
}
@media (max-width: 560px) {
  .xc-tl { --tl-n: 1; }
}

/* ── 상세 : CPS 시스템 흐름도 ──
   원본은 이미지 한 장이었다(mate-cps-img-01.png). 글자가 그림 안에 박혀 있어 코드로 옮겼다.
   읽는 순서가 곧 흐름이다 — 화살표는 장식이라 aria-hidden 이다 */
.xc-cps {
  margin-top: clamp(20px, 2.4vw, 32px);
  max-width: 760px; margin-inline: auto;
  display: flex; flex-direction: column; gap: 10px;
}
.xc-cps__srcs { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.xc-cps__box {
  padding: clamp(16px, 1.8vw, 22px); text-align: center;
  border: 1px solid transparent; border-radius: var(--xc-radius);
}
.xc-cps__box b {
  display: block;
  font-size: var(--xc-fs-cps-box); font-weight: var(--xc-fw-bold);
  letter-spacing: var(--xc-ls-heading);
}
.xc-cps__box ul { margin-top: 12px; display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; }
.xc-cps__box li { padding: 5px 13px; border-radius: 999px; font-size: var(--xc-fs-sm); }
.xc-cps__box--navy { background: var(--xc-navy); color: var(--xc-white); }
.xc-cps__box--navy li { background: rgba(255, 255, 255, .10); border: 1px solid rgba(255, 255, 255, .20); }
.xc-cps__box--gray { background: var(--xc-gray-50); border-color: var(--xc-border-weak); color: var(--xc-text); }
.xc-cps__box--gray li { background: var(--xc-bg); border: 1px solid var(--xc-border-weak); color: var(--xc-text-sub); }
/* 사용자만 오렌지로 세운다. 면을 오렌지로 채우면 흰 글자 대비가 모자라 테두리로 표시한다 */
.xc-cps__box--user { background: var(--xc-bg); border: 2px solid var(--xc-accent); color: var(--xc-orange); }
.xc-cps__arw { display: grid; place-items: center; color: var(--xc-text-weak); }
.xc-cps__arw svg { width: 22px; height: 22px; }
.xc-cps__arw--up { color: var(--xc-accent); }

/* ── 상세 : 화면예시 ──
   슬라이더는 사업 특징과 같은 부품(.xc-slide)이다.
   ⚠️ 스크린샷 원본은 380px 폭이다(CPS 380×218, 나머지 380×170).
      이보다 크게 그리면 확대라 흐려진다. 상한을 원본 폭에 맞춘다 */
.xc-slide--wide .xc-slide__item { flex-basis: clamp(240px, 28%, 380px); }
/* 카드 높이를 가장 큰 것에 맞춘다. CPS 는 캡션 줄 수가 2줄·4줄로 달라 그냥 두면 아래가 어긋난다.
   ⚠️ li 는 track 의 flex 로 이미 늘어나 있다. 늘어나야 하는 것은 그 안의 figure 다 */
.xc-slide__item .xc-sol__shot { height: 100%; display: flex; flex-direction: column; }
.xc-sol__shot {
  margin: 0; border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius);
  overflow: hidden; background: var(--xc-gray-50);
}
/* 풀HD(16:9) 틀을 채운다. 너비는 그대로 두고 남는 높이만큼 세로로 늘린다(object-fit: fill).
   ⚠️ 잘리는 곳은 없지만 원본 비율이 유지되지 않는다 — 380×170 은 세로로 1.25배 늘어난다.
      잘리는 것보다 늘어나는 쪽을 택한 결정이다. contain(여백)·cover(잘림)로 바꾸지 말 것.
   원본을 1920×1080 으로 다시 캡처하면 늘어남 없이 꽉 찬다 — 그때도 이 규칙은 그대로 둔다 */
.xc-sol__shot img {
  display: block; width: 100%; height: auto;
  aspect-ratio: 16 / 9; object-fit: fill; background: var(--xc-bg);
}
/* CPS 화면예시에만 캡션이 있다. legacy 도 그림마다 무엇이 보이는지 적어 두었다 */
.xc-sol__shot figcaption {
  flex: 1;                       /* 남는 높이를 캡션이 받는다 — 카드 아래 끝이 맞는다 */
  display: flex; flex-direction: column; gap: 6px;
  padding: clamp(14px, 1.4vw, 20px);
  background: var(--xc-bg); border-top: 1px solid var(--xc-border-weak);
}
.xc-sol__shot figcaption span {
  position: relative; padding-left: 12px;
  font-size: var(--xc-fs-sm); color: var(--xc-text-sub); line-height: 1.6;
}
.xc-sol__shot figcaption span::before {
  content: ""; position: absolute; left: 0; top: .62em;
  width: 4px; height: 4px; border-radius: 50%; background: var(--xc-text-weak);
}
/* 화면예시 위 요약(QP). 슬라이더에 들어가기 전에 무엇을 보는지 알려 준다 */
.xc-sol__dots {
  margin-top: clamp(16px, 1.8vw, 24px);
  display: flex; flex-wrap: wrap; gap: 10px 24px;
}
.xc-sol__dots > li {
  position: relative; padding-left: 14px;
  font-size: var(--xc-fs-sm); color: var(--xc-text-sub);
}
.xc-sol__dots > li::before {
  content: ""; position: absolute; left: 0; top: .62em;
  width: 5px; height: 5px; border-radius: 50%; background: var(--xc-accent);
}

/* ④ 블록 제목 아래 '이 검집이 지키는 것'. 재정의안 §7 의 개념어를 그대로 쓴다.
   ⚠️ 라인업 카드에도 같은 줄을 넣었다가 뺐다. 카드 안에서 설명(15/400 회색)과
      값이 같아 문단 두 개가 이어진 것처럼 보였다. 카드에 다시 넣지 말 것. */
/* 칩 하나로 둔다. 값은 이미 쓰고 있는 칩(.xc-biz__tags li)과 같게 맞춘다 —
   같은 성격의 부품이 화면마다 다르게 생기면 안 된다.
   ⚠️ width: fit-content 가 있어야 글자 폭만큼만 차지한다. 없으면 블록이라
      가로로 늘어나 알약이 아니라 띠가 된다.
   ⚠️ 이 섹션은 data-stain 이다. 배경이 네이비로 넘어가므로 고정색을 쓰지 않는다.
      --xc-chip-bg 는 .xc-dark 에서 흰빛 반투명으로 뒤집히는 역할색이다. */
/* ⚠️ 자리 : 헤더(제목·리드) 밖, 본문 문단 바로 위다. 헤더 안에 두면 제목과 리드 사이를
   갈라 놓아 리드가 제목에서 떨어진다. 지금은 리드를 다 읽은 뒤 본문으로 넘어가는
   길목에 서서 「이 블록이 지키는 것」을 한 번 짚어 준다.
   ⚠️ 앞뒤가 data-reveal="stagger" 라 이 줄에도 data-reveal 을 달아야 한다.
      안 달면 혼자만 처음부터 보인다. */
.xc-sol__keeps {
  margin-top: clamp(20px, 2.4vw, 32px); width: fit-content; max-width: 100%;
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 6px;
  padding: 5px 12px; border-radius: var(--xc-radius-full);
  background: var(--xc-chip-bg); color: var(--xc-text-sub);
  font-size: var(--xc-fs-12); font-weight: var(--xc-fw-medium); line-height: 18px;
}
.xc-sol__keeps b { font-weight: var(--xc-fw-bold); color: var(--xc-text); }
/* 칩 바로 아래 본문은 붙여 둔다. 칩과 그 아래 글은 한 덩어리로 읽힌다.
   ⚠️ .xc-blk__body 의 margin-top 을 직접 줄이지 않는다. 그 부품은 다른 화면도 쓴다.
      이 칩 다음일 때만 인접 선택자로 덮는다. */
.xc-sol__keeps + .xc-blk__body { margin-top: clamp(10px, 1.1vw, 14px); }

/* ── 상세 : 실제로 도는 화면 (hiVe · byDP) ──────────────
   ⚠️ 비율을 상자가 잡는다. 영상이 늦게 오거나 없어도 자리가 무너지지 않는다.
      비율이 없으면 영상이 붙는 순간 아래 내용이 통째로 밀린다.
   ⚠️ 조작 장치를 두지 않는다(사용자 지정). 자동재생·반복·무음이다.
      무음이 아니면 브라우저가 자동재생을 막는다. */
/* ⚠️ 이 섹션 리드는 한 문장이 길다. 두 곳이 폭을 잡고 있으니 둘 다 풀어야 한다 —
   .xc-blk__head(62ch)가 먼저 걸려서 리드만 넓혀 봐야 585px 에서 멈춘다.
   ⚠️ ch 를 쓰지 않는다. ch 는 숫자 '0' 폭이라 한글 한 자가 약 2ch 다.
      62ch 는 한글 30자밖에 안 들어간다. em 으로 잡아야 글자 수와 맞는다. */
.xc-demo-sec .xc-blk__head { max-width: none; }
.xc-demo-sec .xc-blk__head .xc-lead { max-width: 40em; }
/* ⚠️ 폭 상한은 상자가 아니라 figure 에 건다. 상자에만 걸면 상자는 가운데로
      오는데 캡션은 컨테이너 왼쪽에서 그대로 시작해 두 시작점이 어긋난다.
   ⚠️ 그래서 --demo-ar 을 상자가 아니라 figure 에 인라인으로 준다(자식으로 상속). */
.xc-demo {
  margin-top: clamp(24px, 3vw, 40px);
  width: 100%; max-width: calc(72vh * var(--demo-ar, 1.78));
  margin-inline: auto;
}
/* ⚠️ 16:9 로 못박지 않는다. 화면 녹화는 녹화한 창 비율을 그대로 갖는다 —
   hiVe 는 1.45, byDP 는 2.11 이라 16:9 상자에 넣으면 object-fit: cover 가
   위아래(또는 좌우)를 잘라 UI 가 사라진다. 상자가 영상 비율을 따라간다.
   ⚠️ 대신 세로가 무한정 길어지지 않게 높이를 묶는다. 비율을 지키면서 묶으려면
   높이가 아니라 max-width 를 걸어야 한다(높이를 자르면 비율이 깨져 다시 잘린다). */
.xc-demo__frame {
  position: relative;
  aspect-ratio: var(--demo-ar, 1.78);
  width: 100%;
  border-radius: var(--xc-radius-lg); overflow: hidden;
  background: var(--xc-bg-soft); border: 1px solid var(--xc-border-weak);
}
/* 영상이 아직 없을 때 보이는 자리. 영상이 붙으면 그 위를 덮는다.
   ⚠️ CSS 로 감추지 않는다. 감춰 두면 파일이 빠졌을 때 빈 상자만 남아
      무엇이 빠졌는지 아무도 모른다. */
.xc-demo__ph {
  position: absolute; inset: 0;
  display: grid; place-items: center; padding: 16px;
  font-size: var(--xc-fs-sm); color: var(--xc-text-weak);
  text-align: center; word-break: break-all;
}
.xc-demo__video {
  position: absolute; inset: 0; display: block;
  width: 100%; height: 100%; object-fit: cover;
}
/* 영상 안에서 가려야 할 자리(사내 계정·이름·얼굴). 위치는 영상 기준 %로 준다.
   ⚠️ 기본이 '보임' 이다. 스크립트가 막히면 계속 가려진 채로 남아야 한다 —
      기본을 숨김으로 두면 JS 가 안 돌 때 그대로 노출된다. 실패해도 안전한 쪽으로.
   ⚠️ 이건 덮개일 뿐이다. 원본 픽셀은 파일에 그대로 있다. 정말 민감한 것은
      ffmpeg 로 영상에 구워 넣어야 한다(boxblur). 이 방법은 그 전 단계다.
   ⚠️ backdrop-filter 는 자기 영역 안의 화면을 흐린다. 가장자리에서 표본이 모자라
      덜 흐려지므로, 가릴 대상보다 조금 넉넉하게 잡는다. */
.xc-demo__mask {
  position: absolute;
  left: var(--mx); top: var(--my); width: var(--mw); height: var(--mh);
  -webkit-backdrop-filter: blur(7px) saturate(.75);
  backdrop-filter: blur(7px) saturate(.75);
  pointer-events: none;
}
/* 특정 구간에만 필요한 덮개는 main.js 가 이 클래스를 붙였다 뗀다 */
.xc-demo__mask.is-off { opacity: 0; }

.xc-demo__cap {
  margin-top: 12px;
  font-size: var(--xc-fs-sm); color: var(--xc-text-sub);
  line-height: 1.7; text-wrap: pretty;
}

/* ── 상세 : 도입 문의 ── */
.xc-sol__cta {
  margin-top: clamp(24px, 3vw, 40px);
  padding: clamp(28px, 3vw, 44px);
  background: var(--xc-gray-50);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius-lg);
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  gap: clamp(20px, 2.4vw, 40px); align-items: center;
}
.xc-sol__cta b { display: block; font-size: var(--xc-fs-h4); font-weight: var(--xc-fw-bold); color: var(--xc-text); }
.xc-sol__cta p { margin-top: 8px; font-size: var(--xc-fs-sm); color: var(--xc-text-sub); line-height: 1.7; }

@media (max-width: 1024px) {
  .xc-solist { grid-template-columns: repeat(2, 1fr); }
  .xc-sol__cta { grid-template-columns: 1fr; align-items: start; }
  /* 가지 도해의 반응형은 자기 규칙(--hub-n)에서 처리한다 */
  .xc-qp { grid-template-columns: 1fr; }
  /* 알고리즘 두 장·흐름 묶음을 세로로 쌓는다. 잇는 화살표도 아래를 향한다.
     ⚠️ 묶음 안(예측모델 → 불량판정)은 가로를 유지한다. 그것까지 세우면 묶음이 길어져
        '한 묶음' 으로 안 읽힌다 */
  .xc-alg, .xc-opc { grid-template-columns: 1fr; }
  .xc-alg__link::after, .xc-opc > .xc-opc__arw svg { transform: rotate(90deg); }
  /* 3단 흐름도 세로로 세운다. 화살표도 아래를 향한다 */
  .xc-pipe { grid-template-columns: minmax(0, 1fr); }
  .xc-pipe__arw svg { transform: rotate(90deg); }
  /* 레인 흐름은 세로로 세운다. 열이 하나가 되면 레인 머리줄과 영역 상자는 뜻이 없다.
     주체는 칸 안 이름표(data-who)로, 순번은 칸 이름표(data-no)로 남긴다 */
  .xc-swim__heads, .xc-swim__grp,
  .xc-swim__v, .xc-swim__h, .xc-swim__hook, .xc-swim__ret { display: none; }
  .xc-swim__board { grid-template-columns: minmax(0, 1fr); row-gap: 10px; }
  .xc-swim__cell { grid-row: auto; grid-column: 1; }
  .xc-swim__cell.is-fork { clip-path: none; padding: 12px 14px; border: 1px dashed var(--xc-border); }
  .xc-swim__cell > i {
    display: block; margin-bottom: 3px;
    font-style: normal; font-size: var(--xc-fs-12); font-weight: var(--xc-fw-bold);
    color: var(--xc-text-weak);
  }
  /* 프로세스 지도는 세로로 쌓는다. 기둥은 폭을 풀어 가로 띠가 된다 */
  .xc-map__row { grid-template-columns: minmax(0, 1fr) !important; }
  .xc-map__rail { width: auto; }
  .xc-map__body--row { grid-auto-flow: row; }
  /* 계층 도해도 세로로 세운다. 줄 번호를 풀어 순서대로 쌓이게 하고, 한 열이 되면
     갈래가 하나면 되므로 나머지 세로선은 지운다.
     ⚠️ 묶음 띠는 두 줄에 걸치는 장치라 한 열에서는 뜻이 없다. 지운다 */
  .xc-rpa { grid-template-columns: minmax(0, 1fr); }
  .xc-rpa__grp, .xc-rpa__band { display: none; }
  .xc-rpa__box, .xc-rpa__cell, .xc-rpa__v--solo,
  .xc-rpa__fan, .xc-rpa__bus, .xc-rpa__links { grid-row: auto; grid-column: 1; }
  .xc-rpa__fan, .xc-rpa__bus, .xc-rpa__links {
    grid-template-columns: minmax(0, 1fr); height: clamp(20px, 2.4vw, 28px);
  }
  .xc-rpa__fan::before, .xc-rpa__bus::before { display: none; }
  .xc-rpa__fan .xc-rpa__v:nth-child(n + 2),
  .xc-rpa__bus .xc-rpa__v:nth-child(n + 2),
  .xc-rpa__links .xc-rpa__v:nth-child(n + 2) { display: none; }
  /* 가로 단계 흐름도 세로로 세운다. 원은 왼쪽 축에 서고 내용이 오른쪽에 붙는다 */
  .xc-fl__rail { display: none; }
  .xc-fl__steps { grid-template-columns: minmax(0, 1fr); gap: 0; }
  .xc-fl__step {
    grid-template-columns: var(--fl-dot) minmax(0, 1fr);
    justify-items: start; text-align: left;
    column-gap: 16px; row-gap: 8px; padding-bottom: 30px;
  }
  .xc-fl__step:last-child { padding-bottom: 0; }
  .xc-fl__dot { grid-row: 1 / 3; }
  /* 원과 원을 잇는 세로선 */
  .xc-fl__step:not(:last-child)::after {
    content: ""; position: absolute; left: calc(var(--fl-dot) / 2);
    top: calc(var(--fl-dot) + 5px); bottom: 9px; width: 1px;
    background: var(--xc-border-weak);
  }
  /* 화살촉은 아래를 향한다 */
  .xc-fl__step + .xc-fl__step::before {
    top: -15px; left: calc(var(--fl-dot) / 2); rotate: 135deg;
  }
}
@media (max-width: 640px) {
  .xc-solist { grid-template-columns: 1fr; }
  .xc-sol__pts > li { grid-template-columns: 1fr; gap: 8px; }
  .xc-hub__list > li { grid-template-columns: 1fr; gap: 8px; }
  .xc-cps__srcs { grid-template-columns: 1fr; }
}


/* ══════════════════ 카드 격자 : 마지막 줄 빈 칸 메우기 ══════════════════
   카드 개수가 열 수로 나눠떨어지지 않으면 마지막 줄 오른쪽이 빈다. 세 단계로 없앤다.
     ① 개수에 맞는 열 수를 고른다(4 · 3 · 2 중 나머지가 없는 것) — 마크업의 --2 · --3 · --4
     ② 그래도 한 칸이 남으면 마지막 카드가 두 칸을 차지한다
     ③ 4열에서 두 칸이 남으면 마지막 두 장이 각각 두 칸을 차지한다
   카드 하나가 세 칸 이상으로 늘어나는 일은 없다.

   ⚠️ 열 수를 못박은 격자에만 쓴다. auto-fit 은 폭에 따라 열이 바뀌어 :nth-child 셈이 어긋난다.
   ⚠️ 구간을 min·max 로 서로 겹치지 않게 끊는다. 겹쳐 두고 넓은 쪽 규칙을 되돌리려 하면
      되돌리는 쪽(.xc-fitrow > *)이 늘리는 쪽(:nth-child():last-child)보다 명시도가 낮아
      미디어쿼리 안에 있어도 지지 않는다. 미디어쿼리는 명시도를 올려 주지 않는다.
   ⚠️ 중간 폭(1025~1280)은 좌측 목차가 자리를 가져가 4열이 좁다. 이때 몇 열로 갈지는
      개수마다 달라서 마크업이 --md3 · --md2 로 알려 준다 */
.xc-fitrow {
  display: grid; grid-template-columns: minmax(0, 1fr);
  gap: clamp(12px, 1.4vw, 20px);
}
@media (min-width: 641px) and (max-width: 1024px) {
  .xc-fitrow { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .xc-fitrow > :nth-child(2n + 1):last-child { grid-column: span 2; }
}
@media (min-width: 1025px) and (max-width: 1280px) {
  .xc-fitrow--md2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .xc-fitrow--md3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .xc-fitrow--md2 > :nth-child(2n + 1):last-child,
  .xc-fitrow--md3 > :nth-child(3n + 2):last-child { grid-column: span 2; }
}
@media (min-width: 1281px) {
  .xc-fitrow--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .xc-fitrow--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .xc-fitrow--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .xc-fitrow--2 > :nth-child(2n + 1):last-child,
  .xc-fitrow--3 > :nth-child(3n + 2):last-child,
  .xc-fitrow--4 > :nth-child(4n + 3):last-child { grid-column: span 2; }
  /* 4열에서 두 칸이 남는 경우 — 마지막 줄의 두 장을 각각 두 칸으로 */
  .xc-fitrow--4 > :nth-child(4n + 1):nth-last-child(2),
  .xc-fitrow--4 > :nth-child(4n + 1):nth-last-child(2) + * { grid-column: span 2; }
}

/* ── 같은 셈을, 열 수가 이미 정해져 있는 기존 격자에도 ──
   이쪽은 개수가 화면마다 정해져 있으므로 열 수는 그대로 두고 메우기만 얹는다.
   ⚠️ --5 · --3 같은 파생 격자는 열 수가 달라 제외한다. 3열용 규칙을 5열 격자에 걸면
      마지막 장이 한 칸 더 밀려 줄이 넘친다.
   ⚠️ 인증 목록(.xc-cert__list)과 레퍼런스 목록(.xc-ref__list)은 여기 없다. 두 곳은
      분류 탭·더보기로 항목을 [hidden] 처리해 감춘다. :nth-child 는 감춰진 것까지 세므로
      '보이는 마지막 장' 을 고를 수가 없다 — 규칙을 걸면 엉뚱한 카드가 늘어난다 */
@media (min-width: 1025px) {
  /* 3열 구간 */
  .xc-ov__group:not(.xc-ov__group--5):not(.xc-ov__group--1) > li:nth-child(3n + 2):last-child,
  .xc-wel > li:nth-child(3n + 2):last-child,
  .xc-bgrid > li:nth-child(3n + 2):last-child,
  .xc-eff__list--3 > li:nth-child(3n + 2):last-child { grid-column: span 2; }
  /* 4열 구간 */
  .xc-eff__list:not(.xc-eff__list--3) > li:nth-child(4n + 3):last-child,
  .xc-mth__area > li:nth-child(4n + 3):last-child,
  .xc-xc__sol > li:nth-child(4n + 3):last-child { grid-column: span 2; }
  .xc-eff__list:not(.xc-eff__list--3) > li:nth-child(4n + 1):nth-last-child(2),
  .xc-eff__list:not(.xc-eff__list--3) > li:nth-child(4n + 1):nth-last-child(2) + li,
  .xc-mth__area > li:nth-child(4n + 1):nth-last-child(2),
  .xc-mth__area > li:nth-child(4n + 1):nth-last-child(2) + li,
  .xc-xc__sol > li:nth-child(4n + 1):nth-last-child(2),
  .xc-xc__sol > li:nth-child(4n + 1):nth-last-child(2) + li { grid-column: span 2; }
}
@media (min-width: 1025px) and (max-width: 1280px) {
  /* 이 구간에서만 3열이 되는 것들 */
  /* ⚠️ .xc-mth__ability 는 여기 없다. 카드 격자를 접고 세로 목록이 되어
     마지막 줄 빈 칸이라는 개념 자체가 없어졌다(자기 구역 참고). */
  .xc-ov__group--5 > li:nth-child(3n + 2):last-child { grid-column: span 2; }
}
@media (min-width: 641px) and (max-width: 1024px) {
  /* 여기서는 모두 2열이다 */
  .xc-ov__group > li:nth-child(2n + 1):last-child,
  .xc-wel > li:nth-child(2n + 1):last-child,
  .xc-bgrid > li:nth-child(2n + 1):last-child,
  .xc-eff__list > li:nth-child(2n + 1):last-child,
  .xc-mth__area > li:nth-child(2n + 1):last-child,
  .xc-xc__sol > li:nth-child(2n + 1):last-child { grid-column: span 2; }
}


/* ══════════════════ AI 개발 방법론 (ADD) ══════════════════
   설계 : docs/SCREENS.md §D
   ⚠️ 정량 성과는 화면에 없다. 스타일도 만들지 않는다. */

/* ── ② 두 가지 벽 ── */
.xc-mth__wall,
.xc-adds__wall {
  margin-top: clamp(24px, 3vw, 40px);
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(12px, 1.4vw, 20px);
}
/* 무대에서는 카드가 화면 한가운데 홀로 서는 막이라 세로로 넉넉해야 한다.
   ⚠️ 높이를 고정값으로 박지 않는다. 낮은 화면에서 위아래가 잘린다 —
      화면 높이를 따라가는 최소 높이만 주고 내용은 위에서부터 흐르게 둔다 */
.xc-adds.is-stage .xc-adds__wall { margin-top: 0; }
.xc-adds.is-stage .xc-adds__wall > li {
  min-height: clamp(260px, 42vh, 420px);
  padding: clamp(32px, 3.4vw, 52px);
  display: flex; flex-direction: column;
}
/* 인용문과 설명 사이를 벌려 아래쪽 여백이 한쪽으로 몰리지 않게 한다 */
.xc-adds.is-stage .xc-adds__wall .xc-mth__wall-d { margin-top: auto; padding-top: 18px; }
.xc-mth__wall > li,
.xc-adds__wall > li {
  padding: clamp(26px, 2.6vw, 38px);
  background: var(--xc-bg-soft);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius-lg);
}
.xc-mth__wall-t {
  font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-bold);
  letter-spacing: .12em; color: var(--xc-orange);
}
.xc-mth__wall-q {
  margin-top: 12px;
  font-size: var(--xc-fs-card-ttl); font-weight: var(--xc-fw-extra);
  letter-spacing: var(--xc-ls-heading); line-height: 1.4; color: var(--xc-text);
  text-wrap: pretty;
}
.xc-mth__wall-d {
  margin-top: 14px;
  font-size: var(--xc-fs-sm); color: var(--xc-text-sub); line-height: 1.7;
}
.xc-mth__wall-sum {
  margin-top: clamp(28px, 3vw, 44px); text-align: center;
  font-size: var(--xc-fs-card-ttl); font-weight: var(--xc-fw-bold);
  letter-spacing: var(--xc-ls-heading); line-height: 1.6; color: var(--xc-text);
}

/* ── 고정 무대 : 왜 ADD 인가 ──────────────────────────
   한 화면을 붙잡고 네 막이 지나간다. 세 덩어리가 같은 칸에 겹쳐 있고
   JS 가 막마다 --op / --paint / --p 를 바꿔 서로 교대시킨다.

   ⚠️ 흐름 모드(좁은 화면·모션 최소화·GSAP 미로드)에서는 겹치지 않는다.
      is-stage 가 붙을 때만 겹친다 — 안 그러면 스크립트가 막혔을 때 세 덩어리가
      한자리에 포개져 글자가 겹쳐 보인다.
   ⚠️ 초기 opacity 를 CSS 에 두지 않는다. 기본값 1 이라 스크립트가 없어도 다 보인다.
   ────────────────────────────────────────── */
.xc-adds { padding-block: clamp(72px, 10vw, 160px); }
.xc-adds__area { display: grid; gap: clamp(28px, 4vw, 56px); }

/* 1막 — 좌측 제목 + 우측 본문 */
.xc-adds__intro {
  display: grid; grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  gap: clamp(40px, 5vw, 88px); align-items: start;
}
.xc-adds__head { position: relative; }
/* ⚠️ 회사소개 About(.xc-decl__ttl)과 같은 값이다. 두 화면의 같은 성격의 무대라
   크기·굵기·행간이 달라지면 안 된다 */
.xc-adds__ttl {
  font-size: var(--xc-fs-decl-ttl); font-weight: var(--xc-fw-bold);
  letter-spacing: var(--xc-ls-heading); line-height: var(--xc-lh-heading);
  color: var(--xc-text); text-wrap: balance;
}
.xc-adds__ln { display: block; }
/* ⚠️ 본문도 회사소개 About(.xc-decl__body p)과 같은 값이다.
   보조색(--xc-text-sub)이 아니라 본문색을 쓴다 — 리드 문단이라 굵기 500 과 함께
   한 단계 위로 둔다. 여기만 흐리면 두 화면이 다른 위계로 읽힌다 */
.xc-adds__body p {
  max-width: 72ch;
  font-size: var(--xc-fs-sub-lead);
  font-weight: var(--xc-fw-medium);
  color: var(--xc-text);
  line-height: 1.6; letter-spacing: -.015em;
  text-wrap: pretty;
}
.xc-adds__body p ~ p { margin-top: clamp(18px, 2vw, 26px); }

/* 3막 — 마무리 두 줄 */
/* 마무리 두 줄은 이 무대의 결론이다. 1막 제목과 같은 크기로 둔다 —
   작으면 앞선 카드의 보조 문구처럼 읽힌다 */
.xc-adds__sum {
  text-align: center; text-wrap: balance;
  font-size: var(--xc-fs-h2); font-weight: var(--xc-fw-bold);
  letter-spacing: var(--xc-ls-heading); line-height: 1.45; color: var(--xc-text);
}
.xc-adds__sum-ln { display: block; }

/* ══ 고정 모드 ══ */
.xc-adds.is-stage {
  height: 100dvh;
  padding-block: calc(var(--gnb-top) + var(--gnb-row));
  display: flex; flex-direction: column; justify-content: center;
}
/* 세 덩어리를 같은 칸에 포갠다. 높이는 가장 큰 것이 정한다 */
.xc-adds.is-stage .xc-adds__area { gap: 0; }
.xc-adds.is-stage .xc-adds__intro,
.xc-adds.is-stage .xc-adds__wall,
.xc-adds.is-stage .xc-adds__sum {
  grid-area: 1 / 1; align-self: center;
  opacity: var(--op, 1);
}
/* 자기 차례가 아닌 막은 눌러도 안 잡히게 한다 */
.xc-adds.is-stage .xc-adds__intro,
.xc-adds.is-stage .xc-adds__wall { pointer-events: none; }

/* 제목 채색. 줄마다 자기 --paint 를 갖는다 —
   상자를 글자 폭에 맞춰야 그라디언트가 그 줄의 글자 시작~끝에 대응한다 */
.xc-adds.is-stage .xc-adds__ln {
  --paint: 0%;
  width: fit-content;
  background-image: linear-gradient(90deg,
    var(--xc-text) 0 var(--paint),
    var(--xc-decl-ghost) var(--paint) 100%);
  background-clip: text; -webkit-background-clip: text;
  color: transparent; -webkit-text-fill-color: transparent;
}
/* eyebrow 를 흐름에서 빼 제목 윗변을 우측 첫 문단과 맞춘다 */
.xc-adds.is-stage .xc-eyebrow {
  position: absolute; bottom: calc(100% + 16px); left: 0;
  margin: 0; white-space: nowrap;
}
/* 본문 글자 단위 등장. 회사소개 선언 블록과 같은 계산이다 */
.xc-adds.is-stage .xc-adds__ch {
  --tail: 9;
  --o: clamp(0, calc((var(--p, 0) * (var(--n) + var(--tail)) - var(--i)) / var(--tail)), 1);
  font-style: normal; display: inline-block;
  opacity: var(--o);
  transform: translateY(calc((1 - var(--o)) * 8px));
  will-change: opacity, transform;
}
.xc-adds.is-stage .xc-adds__w { display: inline-block; white-space: nowrap; }

/* 2막 카드 — 하나씩 올라온다 */
.xc-adds.is-stage .xc-adds__wall > li {
  opacity: var(--c-op, 1);
  transform: translateY(calc((1 - var(--c-op, 1)) * 40px));
  will-change: opacity, transform;
}
/* 3막 줄 — 첫 줄은 왼쪽에서, 둘째 줄은 오른쪽에서 들어와 가운데에 선다 */
.xc-adds.is-stage .xc-adds__sum-ln {
  opacity: var(--s-op, 1);
  transform: translateX(calc((1 - var(--s-op, 1)) * var(--s-from, 0px)));
  will-change: opacity, transform;
}
.xc-adds.is-stage .xc-adds__sum-ln:nth-child(1) { --s-from: -140px; }
.xc-adds.is-stage .xc-adds__sum-ln:nth-child(2) { --s-from:  140px; }

@media (max-width: 1024px) {
  .xc-adds__intro { grid-template-columns: 1fr; gap: clamp(20px, 3vw, 32px); }
}
/* ⚠️ 강제 색상 모드에서는 background-clip:text + 투명 글자가 통째로 사라진다 */
@media (forced-colors: active) {
  .xc-adds.is-stage .xc-adds__ln {
    background-image: none; color: CanvasText; -webkit-text-fill-color: CanvasText;
  }
}

/* ── ③ 흐름의 변화 : 이 페이지의 유일한 고정 구간 ──
   기존과 ADD 를 같은 행에 짝지어 놓는다. 가운데 표시가 그 행의 성격을 말한다.
   ⚠️ 두 목록을 따로 세우면 단계 수가 5 대 6 이라 행이 어긋난다 — 무엇이 무엇으로
      바뀌었는지 눈으로 세어야 한다. 행 하나에 짝을 묶는 것이 이 구조의 핵심이다.
   ⚠️ 세 칸의 폭을 행과 머리글이 같은 값으로 나눠야 세로줄이 맞는다. --mth-cols 하나로 둔다 */
/* 높이가 곧 스크롤 길이다. 고정된 무대가 붙잡혀 있는 거리 = 이 높이 - 화면 높이.
   220 → 300 → 420 → 580vh 로 늘려 왔다. 지금은 480vh 동안 여섯 행이 오른다.
   ⚠️ 오른쪽 알약은 화면 밖에서 들어오느라 이동 거리가 길다(자기 폭의 115%).
      같은 스크롤 안에서 왼쪽보다 훨씬 빨리 움직이므로, 구간이 짧으면 그쪽만 튄다.
   ⚠️ 여기만 고치면 속도가 바뀐다. main.js 의 스크럽 구간은 이 높이를 그대로 따른다. */
.xc-mth-flow {
  height: var(--xc-mth-flow-h, 580vh);
  /* 왼 | 겹침 | 오른. 왼쪽 칸은 1~2, 오른쪽 칸은 2~3 을 차지해 가운데에서 포개진다.
     나란히 두면 '비교'로만 읽히지만, 포개면 '이것이 저것을 덮는다'로 읽힌다. */
  --mth-cols: minmax(0, 1fr) var(--mth-lap) minmax(0, 1fr);
  --mth-lap: clamp(48px, 7vw, 120px);
  --mth-badge: clamp(34px, 3vw, 44px);   /* 이음매 배지 지름 */
}
/* 고정 무대. GNB 아래 남은 화면을 통째로 차지하고 그 안에서 세로 가운데에 앉는다.
   ⚠️ top 에 여백만 더해 밀어 내리면 안 된다. 그러면 무대가 제 콘텐츠 높이만큼만
      차지해서 화면이 클수록 아래만 남는다 — 2560x1440 에서 위 160 아래 638 로
      478px 이 한쪽으로 쏠려 있었다. 남은 높이를 차지해야 위아래가 같이 나뉜다.
   ⚠️ 무대 아래끝이 화면 아래끝과 만나면서, 고정이 풀리는 지점이
      main.js 스크럽의 end('bottom bottom')와 같아진다. 전에는 표가 다 찬 뒤에도
      330px 남짓 더 붙잡혀 있었다.
   ⚠️ 세로가 콘텐츠보다 짧으면 min-height 가 걸리지 않아 예전과 같이 아래가 넘친다.
      그때도 지금보다 나쁘지는 않다(top 여백이 없어진 만큼 덜 잘린다). */
.xc-mth__stage {
  position: sticky; top: calc(var(--gnb-top) + var(--gnb-row));
  /* ⚠️ GNB 를 한 번만 빼면(100dvh - gnb) 'GNB 아래 남은 공간'의 가운데가 되어
     화면 전체 기준으로는 GNB 높이의 절반만큼 아래로 내려앉는다. 실측으로 60px 이었다.
     GNB 는 위에서 --gnb-top 만큼 떠 있는 막대라 캔버스는 화면 전체다.
     두 번 빼면 무대가 [gnb, 100dvh - gnb] 를 차지해 한가운데가 정확히 50dvh 가 된다.
     ⚠️ 내용이 이보다 크면 min-height 가 안 걸려 아래로 자란다. 위가 잘리지는 않는다. */
  min-height: calc(100dvh - 2 * (var(--gnb-top) + var(--gnb-row)));
  /* 위아래 같은 값이라 가운데는 그대로 두고, 세로가 짧아 내용이 넘칠 때만
     GNB·화면 끝과 붙지 않게 막는다. 한쪽에만 주면 그만큼 가운데가 밀린다. */
  padding-block: clamp(8px, 1.2vh, 16px);
  display: flex; flex-direction: column; justify-content: center;
}
.xc-mth__cmp {
  margin-top: clamp(24px, 3vw, 40px);
  display: grid; grid-template-columns: var(--mth-cols);
  gap: clamp(12px, 1.6vw, 24px);
}
.xc-mth__head {
  font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-bold);
  letter-spacing: .12em; text-transform: uppercase; color: var(--xc-text-weak);
}
/* 가운데 표시 칸을 건너뛰어 오른쪽 머리글이 ADD 열 위에 오게 한다 */
.xc-mth__head--new {
  grid-column: 2 / 4; justify-self: start;
  padding-left: calc(var(--mth-lap) + clamp(8px, 1vw, 16px));
  color: var(--xc-orange);
}
/* 이 라벨이 가리키는 것이 그라디언트 알약이므로 라벨도 같은 그라디언트로 둔다.
   ⚠️ 어두운 구간에서만 쓴다. 흰 배경에서는 골드(#FBE38A)가 1.2:1 로 사라진다.
      밝을 때는 위의 포인트 오렌지가 그대로 쓰인다. */
.xc-dark .xc-mth__head--new {
  background: var(--xc-gradient);
  -webkit-background-clip: text; background-clip: text;
  color: transparent;
}

/* ⚠️ 오른쪽 알약이 화면 밖에서 들어온다. 여기서 잘라야 문서 폭이 늘지 않는다.
   overflow-x 만 지정하면 overflow-y 가 auto 로 계산돼 세로 막대가 생긴다. 양쪽 다 지정한다. */
.xc-mth__rows { margin-top: 12px; display: grid; gap: clamp(8px, 1vw, 12px); overflow: clip; }
.xc-mth__row {
  display: grid; grid-template-columns: var(--mth-cols);
  gap: clamp(12px, 1.6vw, 24px); align-items: stretch;
}
/* ── 겹침 배치 ──
   ⚠️ 겹치는 쪽(오른쪽)이 왼쪽 글자를 덮는다. 왼쪽 글자는 왼쪽에 붙여 두고
      겹치는 폭(--mth-lap)에는 글자가 오지 않게 한다. */
/* ⚠️ grid-row 를 반드시 같이 준다. 열만 지정하면 열이 겹칠 때 자동배치가
   다음 줄로 밀어내 세 덩어리가 위아래로 흩어진다(실제로 그랬다). */
.xc-mth__cell--old { grid-row: 1; grid-column: 1 / 3; z-index: 1; }
.xc-mth__cell--new { grid-row: 1; grid-column: 2 / 4; z-index: 2; }
/* 기호 배지. 겹치는 칸(2번) 한가운데에 둔다 — 그 칸은 그라디언트 알약이 덮고 있으므로
   배지가 밝은 면 안에 온전히 들어앉는다.
   ⚠️ 경계에 반씩 걸치게 두어 봤으나 어두운 원이 알약 밖으로 삐져나와 어색했다.
   ⚠️ transform 으로 옮기지 않는다. 스크롤 등장에서 JS 가 transform 을 덮어쓴다. */
.xc-mth__mark {
  grid-row: 1; grid-column: 2 / 3; z-index: 3;
  justify-self: start; align-self: center;
  margin-left: clamp(10px, 1vw, 16px);
}

.xc-mth__cell {
  display: flex; align-items: center; gap: 14px;
  padding: clamp(14px, 1.4vw, 20px) clamp(16px, 1.6vw, 22px);
  /* 알약. 참조 시안처럼 두 덩어리가 포개졌을 때 경계가 부드럽게 지나가야 한다 */
  border-radius: 999px;
  /* ⚠️ --xc-gray-50 이 아니라 역할색을 쓴다. 라이트에서는 값이 같고,
     다크 구간(.xc-dark)에서는 네이비 계열로 따라 바뀐다 */
  background: var(--xc-bg-soft); border: 1px solid var(--xc-border-weak);
}
/* 왼쪽(기존)은 물러나 있고, 오른쪽(ADD)이 브랜드 그라디언트로 올라선다.
   ⚠️ 아래 세 줄은 .xc-mth__cell 뒤에 와야 한다. 앞에 두면 padding 단축 속성과
      background 가 여기서 준 값을 지운다(실제로 지워졌다).
   ⚠️ 그라디언트 위 글자는 어두워야 한다. 흰 글자는 골드 구간(#FBE38A)에서 1.2:1 로 사라진다.
   ⚠️ 행 종류(그대로/바뀜/추가)는 이제 가운데 기호가 맡는다. 오른쪽 알약에 종류별
      테두리를 더 얹으면 그라디언트 위에서 읽히지도 않고 여섯 줄이 산만해진다. */
.xc-mth__cell--old .xc-mth__step { color: var(--xc-text-sub); }
.xc-mth__cell--new {
  padding-left: calc(var(--mth-lap) + clamp(8px, 1vw, 16px));
  background: var(--xc-gradient); border-color: transparent;
}
.xc-mth__cell--new .xc-mth__step { color: var(--xc-navy-deep); font-weight: var(--xc-fw-bold); }
/* 추가된 행은 왼쪽이 비어 있다 — 거기서 하나 늘었다는 것이 형태로 보인다 */
.xc-mth__none {
  width: 100%; text-align: center; color: var(--xc-text-weak);
}
/* 비어 있는 칸 — '여기엔 없다' 가 형태로 보여야 한다.
   ⚠️ 배경 없이 점선만 두었더니 어두운 무대 위에서 거의 안 보였다.
      기존 방식 알약보다 한 단계 더 어둡게 깔고 점선을 굵고 진하게 한다.
   ⚠️ 두께는 다른 알약과 같은 1px 로 둔다. 굵게 하면 이 칸만 테두리가 도드라져
      '비어 있다' 가 아니라 '강조된 칸' 으로 읽힌다. 잘 보이게 하는 몫은 색이 맡는다.
   ⚠️ 점선 색은 흰색 42% 다. 30% 로는 바탕과 2.5:1 이라 비문자 최소대비 3:1 을 못 넘는다. */
.xc-mth__row[data-kind="add"] .xc-mth__cell--old {
  background: var(--xc-gray-200);
  border: 1px dashed rgba(22, 29, 41, .30);
}
/* ⚠️ 무대(#0D1119)보다 더 어둡게 깔면 알약이 아니라 페이지에 뚫린 구멍처럼 보인다.
   기존 방식 알약(#2E3A50)보다는 진하고 무대보다는 한 단계 밝은 자리에 둔다.
   무대와의 구분 1.28:1 · 점선 3.85:1 · ― 글자 5.10:1 */
.xc-dark .xc-mth__row[data-kind="add"] .xc-mth__cell--old {
  background: #202836;
  border-color: rgba(255, 255, 255, .42);
}
.xc-mth__mark {
  display: grid; place-items: center;
  width: var(--mth-badge); height: var(--mth-badge); border-radius: 50%;
  background: var(--xc-white);
  /* ⚠️ 흰 원이 골드 구간(#FBE38A) 위에 놓인다. 면끼리는 1.2:1 이라 테두리가 안 보인다.
     그림자로 원을 띄워야 형태가 읽힌다. 선으로 두르면 알약 위에서 때가 낀 것처럼 보였다. */
  box-shadow: 0 2px 10px rgba(13, 17, 25, .22);
  font-size: var(--xc-fs-mark-no); font-weight: var(--xc-fw-extra);
  color: var(--xc-navy-deep);
}
/* '그대로' 인 행은 기호를 한 단계 죽인다. 바뀐 행이 먼저 눈에 들어와야 한다.
   ⚠️ 배지 면은 그대로 둔다. 면이 옅어지면 형태가 무너진다. 글자만 낮춘다(흰 면 위 5.0:1). */
.xc-mth__row[data-kind="same"] .xc-mth__mark { color: rgba(13, 17, 25, .60); }
.xc-mth__mark i { font-style: normal; line-height: 1; }
/* 알약이 커진 만큼 글자도 올린다. 15px 은 이 크기의 면 안에서 너무 작았다.
   ⚠️ 값을 직접 쓰지 않고 척도 토큰을 쓴다(--xc-fs-h4 = clamp(17px, 1.4vw, 20px)). */
.xc-mth__no {
  flex: none; font-size: var(--xc-fs-sm); font-weight: var(--xc-fw-bold);
  color: var(--xc-text-weak); font-variant-numeric: tabular-nums;
}
.xc-mth__step {
  font-size: var(--xc-fs-h4); font-weight: var(--xc-fw-semibold);
  color: inherit; line-height: 1.4; text-wrap: pretty;
}

@media (max-width: 640px) {
  /* 좁아도 한 행은 한 줄로 둔다. 기호가 두 알약 사이 한가운데 놓여야
     「요구사항 = 요구사항」 이 한눈에 한 짝으로 읽힌다.
     ⚠️ 위아래로 접었더니 기호가 어느 두 줄을 잇는 것인지 안 보였다(사용자 지적).
     ⚠️ 겹침(--mth-lap)은 푼다. 좁은 폭에서 겹치면 오른쪽 알약이 왼쪽 글자를 덮는다.
        대신 가운데 칸을 배지 지름만큼만 잡아 세 덩어리를 나란히 세운다. */
  .xc-mth-flow {
    --mth-cols: minmax(0, 1fr) var(--mth-badge) minmax(0, 1fr);
    --mth-lap: 0px;
    --mth-badge: 28px;
    height: auto;
  }
  /* ⚠️ min-height 와 padding 도 함께 푼다. 고정을 풀어도 남겨 두면
     화면 하나만큼 빈 칸이 생기고, 위아래 여백도 그대로 남는다 */
  .xc-mth__stage { position: static; min-height: 0; padding-block: 0; display: block; }
  /* 겹침이 없으므로 세 덩어리가 제 칸을 하나씩 쓴다.
     ⚠️ 2/4 열은 이 격자에 없다. 열 번호를 반드시 다시 준다 */
  .xc-mth__row { gap: clamp(6px, 2vw, 10px); }
  .xc-mth__cell--old { grid-column: 1; }
  .xc-mth__mark { grid-column: 2; justify-self: center; margin-left: 0; }
  .xc-mth__cell--new { grid-column: 3; padding-left: clamp(12px, 3vw, 16px); }
  /* 칸이 좁아진 만큼 알약도 줄인다. 그대로 두면 글자가 서너 줄로 늘어진다 */
  .xc-mth__cell { gap: 8px; padding: 12px clamp(12px, 3vw, 16px); }
  .xc-mth__step { font-size: var(--xc-fs-sm); }
  .xc-mth__mark { font-size: var(--xc-fs-sm); box-shadow: 0 1px 6px rgba(13, 17, 25, .22); }
  .xc-mth__rows { overflow: visible; }
  /* 머리글을 되살린다. 두 알약이 나란히 서면 어느 쪽이 기존인지 글로 말해 줘야 한다 */
  .xc-mth__cmp { gap: clamp(6px, 2vw, 10px); margin-top: 20px; }
  .xc-mth__head--new { grid-column: 3; justify-self: start; padding-left: 0; }
}


/* ── ④ AI 가 맡는 영역 ── */
.xc-mth__area {
  margin-top: clamp(24px, 3vw, 40px);
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(12px, 1.4vw, 20px);
}
.xc-mth__area > li {
  padding: clamp(22px, 2.4vw, 32px);
  background: var(--xc-bg);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius-lg);
}
/* 커서 가까이 있는 카드들이 그쪽으로 기운다. 한 장이 아니라 주변 여러 장이 같이 반응한다.
   그림자는 지금 가리키고 있는 카드에만 깔린다.
   ⚠️ 마우스가 있는 환경에서만. 터치에서 :hover 는 한 번 누르면 붙어 있는 상태가 된다.
   ⚠️ 기울기(transform)는 JS 가 직접 쓴다. 이 목록은 등장 애니메이션(GSAP)이 같은
      transform 을 쓰므로 CSS 에 상시 transition 을 걸면 등장이 뭉개진다.
      되돌아올 때만 JS 가 is-tilt-back 을 붙여 잠깐 완화 곡선을 태운다. */
@media (hover: hover) and (pointer: fine) {
  .xc-mth__area > li {
    transition: box-shadow .28s var(--xc-ease-out), border-color .28s var(--xc-ease-out);
  }
  .xc-mth__area.is-tilt-back > li {
    transition: transform .35s var(--xc-ease-out),
                box-shadow .28s var(--xc-ease-out), border-color .28s var(--xc-ease-out);
  }
  .xc-mth__area > li:hover {
    box-shadow: 0 16px 38px rgba(252, 101, 0, .32);
    border-color: rgba(252, 101, 0, .45);
  }
}
@media (prefers-reduced-motion: reduce) {
  .xc-mth__area > li { transition: none; }
}
.xc-mth__ico {
  width: 30px; height: 30px;
  fill: none; stroke: currentColor; stroke-width: 1.4;
  stroke-linecap: round; stroke-linejoin: round;
  /* ⚠️ 고정 네이비를 쓰면 다크 구간에서 아이콘이 사라진다. 역할색으로 따라가게 한다 */
  color: var(--xc-text); opacity: .4;
}
/* 항목 제목 표준(--xc-fs-h4). 한 단계 아래인 --xc-fs-md 를 쓰고 있었는데,
   칸이 좁아서가 아니었다 — 같은 326px 폭의 xCalibur 라인업이 28px 을 쓰고,
   글자칸이 더 좁은(249px) MATE 기대효과 카드도 20px 이다.
   같은 화면 ⑥ 필요한 역량이 20px 이라 한 화면 안에서 갈리기도 했다. */
.xc-mth__area-name {
  margin-top: 16px;
  font-size: var(--xc-fs-h4); font-weight: var(--xc-fw-bold);
  letter-spacing: var(--xc-ls-heading); color: var(--xc-text);
}
.xc-mth__area-desc {
  margin-top: 8px;
  font-size: var(--xc-fs-sm); color: var(--xc-text-sub); line-height: 1.6;
}

/* ── ⑤ 최종 책임은 사람에게 ── */
.xc-mth__human {
  margin-top: clamp(24px, 3vw, 40px);
  padding: clamp(28px, 3vw, 48px);
  background: var(--xc-bg-soft);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius-lg);
}
.xc-mth__human-lead {
  font-size: var(--xc-fs-card-ttl-sm); font-weight: var(--xc-fw-bold);
  letter-spacing: var(--xc-ls-heading); line-height: 1.55; color: var(--xc-text);
}
/* 개발자 역할 비교 탭 (기존 ↔ ADD).
   ⚠️ button 은 배경·서체를 제 것으로 갖는다. 지우지 않으면 회색 상자에 다른 글꼴이 뜬다 */
.xc-role { margin-top: clamp(24px, 2.6vw, 36px); }
.xc-role__tabs {
  display: inline-flex; gap: 6px; padding: 6px;
  background: var(--xc-bg); border: 1px solid var(--xc-border-weak);
  border-radius: 999px;
}
.xc-role__tab {
  appearance: none; border: 0; background: none; font: inherit;
  padding: clamp(11px, 1.1vw, 15px) clamp(28px, 3vw, 44px);
  border-radius: 999px; cursor: pointer;
  font-size: var(--xc-fs-card-ttl-sm); font-weight: var(--xc-fw-bold);
  letter-spacing: .04em; color: var(--xc-text-weak);
  transition: color var(--xc-dur-fast) var(--xc-ease-standard),
              background-color var(--xc-dur-fast) var(--xc-ease-standard);
}
.xc-role__tab:hover { color: var(--xc-text); }
.xc-role__tab.is-on { background: var(--xc-navy); color: #fff; }

/* 두 판을 같은 칸에 겹친다. 높이는 항상 긴 쪽(ADD)이 정하므로 오갈 때 안 튄다 */
.xc-role__stage { display: grid; margin-top: clamp(22px, 2.4vw, 32px); }
.xc-role__panel {
  grid-area: 1 / 1;
  opacity: 0; visibility: hidden;                 /* ⚠️ display:none 이면 높이 계산에서 빠진다 */
  transform: translateY(6px);
  transition: opacity var(--xc-dur-fast) var(--xc-ease-standard),
              transform var(--xc-dur-fast) var(--xc-ease-standard),
              visibility 0s linear var(--xc-dur-fast);
}
.xc-role__panel.is-on {
  opacity: 1; visibility: visible; transform: none;
  transition-delay: 0s;
}
/* ⚠️ 네 칸 격자다. 「기존」 판은 카드가 하나뿐이라 나머지 세 칸이 빈다.
      그 빈자리가 「하나였다」 를 보여 주는 자리이므로 채우지 않는다.
      flex 로 두면 카드 하나가 폭에 맞춰 늘어나 ADD 판과 크기가 달라진다 */
.xc-role__steps {
  --role-gap: clamp(20px, 2vw, 34px);              /* 화살표가 앉을 자리이기도 하다 */
  --role-arw: clamp(22px, 2.1vw, 30px);            /* 화살표 기준 크기. 간격보다 커도 된다 */
  --role-head: calc(var(--role-arw) * .36);        /* 머리 폭. 세로 길이는 이것의 1.75배 */
  /* ⚠️ 머리는 viewBox 8 폭에 선굵기 2.4 인 그림이라, 화면 굵기가 폭에 비례해 커진다.
        선 두께를 고정값으로 두면 화면이 넓어질수록 머리만 굵어 보인다.
        2.4 / 8 × 머리폭 = 0.3 × 머리폭 이 실제로 그려지는 굵기다 */
  --role-th: calc(var(--role-head) * .3);
  --role-shaft: calc(var(--role-arw) - var(--role-head) * .85);    /* 선 길이 */
  /* ⚠️ 꺾쇠의 꼭짓점은 viewBox 8 폭에서 x 6.6, 즉 머리 폭의 82.5% 지점이다.
        선을 머리 상자의 왼쪽 끝에 맞추면 그 82.5% 까지 가지 못해 사이가 벌어진다.
        머리 폭의 10% 만 남기고 선을 밀어 넣어 꼭짓점을 지나가게 한다 */
  --role-join: calc(var(--role-head) * .1);
  --role-len: calc(var(--role-shaft) + var(--role-join));          /* 선 + 머리 실제 길이 */
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--role-gap);
}
.xc-role__steps > li {
  position: relative;                               /* 화살표를 칸 밖에 놓는 기준 */
  display: flex; flex-direction: column; gap: clamp(10px, 1.1vw, 16px);
  min-height: clamp(130px, 11vw, 168px);
  padding: clamp(20px, 2vw, 28px);
  background: var(--xc-bg); border: 1px solid var(--xc-border-weak);
  border-radius: var(--xc-radius-lg);
}
/* 카드 사이 화살표. 선(::after)과 머리(::before)를 따로 둔다.
   선이 다 그려진 다음 머리가 얹히는 순서를 만들려면 한 요소로는 안 된다.
   ⚠️ 마지막 카드에는 붙이지 않는다. 붙이면 격자 밖으로 나가 가로 스크롤이 생긴다.
   ⚠️ 「기존」 판은 카드가 하나뿐이라 :last-child 로 저절로 빠진다 */
.xc-role__steps > li:not(:last-child)::after,
.xc-role__steps > li:not(:last-child)::before {
  content: ''; position: absolute; top: 50%;
  background: var(--xc-text-weak);
}
/* 선 */
.xc-role__steps > li:not(:last-child)::after {
  right: calc(var(--role-gap) / -2 - var(--role-len) / 2 + var(--role-join));
  width: var(--role-shaft);
  height: var(--role-th); border-radius: var(--role-th);
  transform: translateY(-50%);
  transform-origin: left center;                  /* 왼쪽에 붙어 오른쪽으로 자란다 */
}
/* 머리 */
.xc-role__steps > li:not(:last-child)::before {
  right: calc(var(--role-gap) / -2 - var(--role-len) / 2);
  width: var(--role-head); height: calc(var(--role-head) * 1.75);
  transform: translateY(-50%);
  -webkit-mask: var(--role-head-svg) center / contain no-repeat;
          mask: var(--role-head-svg) center / contain no-repeat;
}
.xc-role__steps {
  --role-head-svg: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 14' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='1.4 1.4 6.6 7 1.4 12.6'/%3E%3C/svg%3E");
}
.xc-role__ico {
  flex: none; width: clamp(30px, 2.8vw, 40px); height: clamp(30px, 2.8vw, 40px);
  color: var(--xc-orange);
}
.xc-role__ico svg { width: 100%; height: 100%; display: block; }
.xc-role__nm {
  margin-top: auto;                                /* 이름은 카드 아래에 붙는다 */
  font-size: var(--xc-fs-card-ttl); font-weight: var(--xc-fw-bold);
  letter-spacing: var(--xc-ls-heading); line-height: 1.4; color: var(--xc-text);
}
.xc-role__sum {
  margin-top: clamp(18px, 1.8vw, 26px);
  font-size: var(--xc-fs-lead); color: var(--xc-text-sub); line-height: 1.7;
}
/* ADD 판이 처음 열릴 때 한 번만 도는 등장.
   카드 하나 → 화살표 하나 → 다음 카드 순으로 이어진다.
   ⚠️ 기본 상태가 「다 보이는 상태」다. backwards 로 두어 대기 중에만 감춘다.
      기본을 opacity:0 으로 두면 스크립트가 막혔을 때 카드가 영영 안 보인다.
   ⚠️ 화살표는 clip-path 로 왼쪽에서 오른쪽으로 걷어낸다. 1열에서는 요소가
      90도 돌아 있어 같은 값이 위에서 아래로 걷히는 방향이 된다 */
/* ⚠️ 시간·거리를 여기 직접 적지 않는다. 사이트의 모든 페이드인업이
      --xc-dur-reveal 하나를 읽는다. 여기만 다르면 같은 화면에서 속도가 어긋난다 */
@keyframes roleCardIn  { from { opacity: 0; transform: translateY(26px); } }
@keyframes roleShaftIn { from { transform: translateY(-50%) scaleX(0); } }
@keyframes roleHeadIn  { from { opacity: 0; transform: translateY(-50%) translateX(-5px); } }

.xc-role__panel.is-intro .xc-role__steps > li {
  animation: roleCardIn var(--xc-dur-reveal) var(--xc-ease-out) backwards;
}
.xc-role__panel.is-intro .xc-role__steps > li:nth-child(1) { animation-delay: .05s; }
.xc-role__panel.is-intro .xc-role__steps > li:nth-child(2) { animation-delay: .45s; }
.xc-role__panel.is-intro .xc-role__steps > li:nth-child(3) { animation-delay: .85s; }
.xc-role__panel.is-intro .xc-role__steps > li:nth-child(4) { animation-delay: 1.25s; }

/* ⚠️ 머리 대기 시간 = 선 대기 시간 + 선 그리는 시간. 선이 도착하기 전에 머리가 뜨면
      화살표가 두 조각으로 보인다 */
.xc-role__panel.is-intro .xc-role__steps > li:not(:last-child)::after {
  animation: roleShaftIn calc(var(--xc-dur-reveal) * .34) var(--xc-ease-out) backwards;
}
.xc-role__panel.is-intro .xc-role__steps > li:not(:last-child)::before {
  animation: roleHeadIn calc(var(--xc-dur-reveal) * .2) var(--xc-ease-out) backwards;
}
.xc-role__panel.is-intro .xc-role__steps > li:nth-child(1)::after  { animation-delay: .28s; }
.xc-role__panel.is-intro .xc-role__steps > li:nth-child(1)::before { animation-delay: .60s; }
.xc-role__panel.is-intro .xc-role__steps > li:nth-child(2)::after  { animation-delay: .68s; }
.xc-role__panel.is-intro .xc-role__steps > li:nth-child(2)::before { animation-delay: 1.00s; }
.xc-role__panel.is-intro .xc-role__steps > li:nth-child(3)::after  { animation-delay: 1.08s; }
.xc-role__panel.is-intro .xc-role__steps > li:nth-child(3)::before { animation-delay: 1.40s; }

/* ⚠️ 2열이 되면 두 번째 카드는 줄 끝이다. 화살표가 허공을 가리키므로 지운다 */
@media (max-width: 900px) {
  .xc-role__steps { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .xc-role__steps > li:nth-child(2)::after,
  .xc-role__steps > li:nth-child(2)::before { content: none; }
}
/* 1열에서는 화살표를 아래로 내리고 90도 돌린다 */
@media (max-width: 560px) {
  .xc-role__steps { grid-template-columns: minmax(0, 1fr); }
  .xc-role__steps > li { min-height: 0; }
  .xc-role__steps > li:nth-child(2)::after,
  .xc-role__steps > li:nth-child(2)::before { content: ''; }
  /* 세로로 세운다. 선은 위에서 아래로 자라고 머리는 그 끝에 얹힌다 */
  .xc-role__steps > li:not(:last-child)::after {
    top: 100%; bottom: auto; right: 50%;
    width: var(--role-th); height: var(--role-shaft);
    margin-top: calc(var(--role-gap) / 2 - var(--role-len) / 2);
    transform: translateX(50%);
    transform-origin: center top;
  }
  .xc-role__steps > li:not(:last-child)::before {
    top: 100%; bottom: auto; right: 50%;
    width: calc(var(--role-head) * 1.75); height: var(--role-head);
    margin-top: calc(var(--role-gap) / 2 + var(--role-len) / 2 - var(--role-head));
    transform: translateX(50%) rotate(90deg);
  }
  @keyframes roleShaftIn { from { transform: translateX(50%) scaleY(0); } }
  @keyframes roleHeadIn  { from { opacity: 0; transform: translateX(50%) rotate(90deg) translateX(-5px); } }
}
@media (prefers-reduced-motion: reduce) {
  .xc-role__panel { transition: none; transform: none; }
  /* ⚠️ 화살표 규칙이 :not(:last-child)::after 라 그보다 구체적으로 써야 이긴다.
        li::after 로 쓰면 명시도에서 밀려 화살표가 잘린 채 영영 안 보인다 */
  .xc-role__panel.is-intro .xc-role__steps > li,
  .xc-role__panel.is-intro .xc-role__steps > li:not(:last-child)::after,
  .xc-role__panel.is-intro .xc-role__steps > li:not(:last-child)::before {
    animation: none;
  }
}
/* ⚠️ 리드 바로 아래에 붙는다. 같은 이야기의 이어지는 문장이라 사이를 좁게 둔다.
      아래 탭과의 간격(.xc-role)이 이보다 넓어야 문단과 장치가 갈린다 */
.xc-mth__human-desc {
  margin-top: clamp(8px, .9vw, 12px);
  font-size: var(--xc-fs-body); color: var(--xc-text-sub);
  line-height: 1.8; text-wrap: pretty;
}
/* ⚠️ ch 를 쓰면 blockquote 자신의 글자 크기로 계산된다. 큰 글자는 안쪽 p 에 있다 */
.xc-mth__quote {
  margin: clamp(36px, 4vw, 64px) auto 0; max-width: min(100%, 860px); text-align: center;
}
.xc-mth__quote p {
  font-size: var(--xc-fs-mth-quote); font-weight: var(--xc-fw-extra);
  letter-spacing: var(--xc-ls-heading); line-height: 1.45;
  color: var(--xc-text); text-wrap: balance;
}

/* ── ⑥ QA 규율 ──
   ⚠️ 이 페이지에 목록이 이미 둘이다. ④ 는 카드 격자, ⑦ 은 세로 목록이라
      여기는 세 번째 형태여야 한다. 번호를 크게 앞세운 2열 격자로 갈라 둔다.
   ⚠️ 번호는 순서가 있다. 규율 ①이 나머지를 떠받치고 ⑤로 갈수록 앞단으로 당기는
      흐름이라, 여기서는 번호가 장식이 아니라 차례다. 그래서 ol 이고 크게 쓴다. */
.xc-mth__qa-q {
  margin-top: clamp(20px, 2.4vw, 32px);
  padding-left: clamp(16px, 1.6vw, 22px);
  border-left: 2px solid var(--xc-accent);
}
.xc-mth__qa-q p {
  font-size: var(--xc-fs-h4); font-weight: var(--xc-fw-bold);
  letter-spacing: var(--xc-ls-heading); line-height: 1.6;
  color: var(--xc-text); text-wrap: pretty;
}
.xc-mth__qa {
  margin-top: clamp(24px, 3vw, 40px);
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(16px, 2vw, 28px) clamp(20px, 2.6vw, 44px);
}
/* 마지막 하나가 홀로 남는다. 두 칸을 차지해 오른쪽이 비지 않게 한다 */
.xc-mth__qa > li:nth-child(2n + 1):last-child { grid-column: span 2; }
.xc-mth__qa > li {
  display: grid; grid-template-columns: auto minmax(0, 1fr);
  gap: 2px clamp(12px, 1.4vw, 18px);
  padding-top: clamp(14px, 1.6vw, 20px);
  border-top: 1px solid var(--xc-border-weak);
}
.xc-mth__qa-no {
  grid-row: 1 / 3;
  font-size: var(--xc-fs-h3); font-weight: var(--xc-fw-extra);
  line-height: 1; color: var(--xc-accent);
  font-variant-numeric: tabular-nums;
}
.xc-mth__qa-name {
  font-size: var(--xc-fs-h4); font-weight: var(--xc-fw-bold);
  letter-spacing: var(--xc-ls-heading); line-height: 1.4;
  color: var(--xc-text); text-wrap: pretty;
}
.xc-mth__qa-desc {
  margin-top: 6px;
  font-size: var(--xc-fs-sm); color: var(--xc-text-sub);
  line-height: 1.75; text-wrap: pretty;
}
.xc-mth__qa-note {
  margin-top: clamp(22px, 2.6vw, 36px);
  padding: clamp(20px, 2.2vw, 30px);
  background: var(--xc-gray-50);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius-lg);
  font-size: var(--xc-fs-sm); color: var(--xc-text-sub);
  line-height: 1.8; text-wrap: pretty;
}
@media (max-width: 900px) {
  .xc-mth__qa { grid-template-columns: 1fr; }
  .xc-mth__qa > li:nth-child(2n + 1):last-child { grid-column: 1; }
}

/* ── ⑦ 필요한 역량 ──
   ⚠️ 카드 격자로 두지 않는다. 바로 위 ④ 'AI 가 맡는 영역'(.xc-mth__area)이 이미
      카드 격자라, 같은 형태면 이 페이지의 핵심 대비인 「AI 가 하는 것 ↔ 사람이 하는 것」이
      흐려진다. AI 쪽은 격자, 사람 쪽은 목록으로 갈라 둔다.
   ⚠️ 상자·배경을 쓰지 않는다. 가는 선으로만 나눈다. 다섯 줄이라 길지 않다.
   ⚠️ 번호는 순서가 아니라 표식이다. 원천 문서(1_브랜드코어/ADD_방법론.md)도 불릿이다.
      크기를 제목보다 키우지 않는다 — 키우면 단계처럼 읽힌다.
   ⚠️ 이름 칸의 폭을 고정해야 설명이 세로로 줄맞춰 훑힌다. 목록으로 바꾸는 이유가 그것이다. */
.xc-mth__ability {
  margin-top: clamp(24px, 3vw, 40px);
  border-top: 1px solid var(--xc-border-weak);
}
/* ⚠️ 이름 칸을 em 으로 잡지 않는다. em 은 격자를 가진 li 의 글자 크기를 따르는데
   정작 커지는 것은 자식(.xc-mth__ab-name)이라 칸이 안 따라 늘고 이름이 접힌다.
   px clamp 로 직접 잡는다. 이름 크기를 바꾸면 이 값도 같이 봐야 한다. */
.xc-mth__ability > li {
  display: grid;
  grid-template-columns: auto clamp(160px, 19vw, 260px) minmax(0, 1fr);
  gap: clamp(14px, 2.2vw, 40px);
  align-items: baseline;
  padding-block: clamp(18px, 2.2vw, 28px);
  border-bottom: 1px solid var(--xc-border-weak);
}
/* ⚠️ 크기는 이 프로젝트의 「항목 이름 + 설명」 표준을 그대로 쓴다.
   MATE 솔루션 특징·기대효과(.xc-sol__pts)가 세 페이지에서 같은 값을 쓰고 있고,
   설명(--xc-fs-sm)은 xCalibur 라인업·세 축까지 포함해 예외 없이 같다.
   한 번 h3(28)/lead(21)로 키웠다가 이 목록만 유독 커서 되돌렸다 —
   설명 21px 는 두 브랜드 통틀어 이 목록에만 있던 값이었다.
   번호는 라벨이다. .xc-xc__sol-kind · .xc-xc__en 과 같은 --xc-fs-xs 를 쓴다. */
.xc-mth__ab-no {
  font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-extra);
  color: var(--xc-orange); font-variant-numeric: tabular-nums;
}
.xc-mth__ab-name {
  font-size: var(--xc-fs-h4); font-weight: var(--xc-fw-bold);
  letter-spacing: var(--xc-ls-heading); line-height: 1.4; color: var(--xc-text);
  text-wrap: pretty;
}
.xc-mth__ab-desc {
  font-size: var(--xc-fs-sm); color: var(--xc-text-sub); line-height: 1.8;
  text-wrap: pretty;
}

/* ── ⑦ 우리는 이렇게 개발합니다 ──
   솔루션 상세의 '도입 문의' 배너(.xc-sol__cta)와 같은 상자로 페이지를 맺는다.
   ⚠️ 형태만 같고 이동하는 배너는 아니다. 오른쪽 버튼 칸이 없어 한 단이다.
   ⚠️ 네이비를 쓰지 않는다. 본문 안의 배너 상자는 회색이 이 프로젝트의 규칙이다.
      값은 .xc-sol__cta 와 같게 둔다 — 두 배너가 다르게 보이면 안 된다.
   ⚠️ 글자 크기를 여기서 다시 정하지 않는다. 안쪽은 다른 섹션과 똑같이
      .xc-blk__head · .xc-blk__body 를 쓴다. 한 번 배너 눈금(h4·15px)으로
      낮췄다가 혼자만 작아 보여 되돌렸다. 이 상자가 맡는 것은 '상자'뿐이다.
      덤으로 eyebrow 도 <p> 라서, 여기서 p 를 건드리면 13px 라벨이 함께 커진다. */
.xc-mth__ours {
  padding: clamp(28px, 3vw, 44px);
  background: var(--xc-gray-50);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius-lg);
}

/* 역량 목록은 좁아지면 두 단으로 접는다. 번호는 이름 옆에 그대로 두고
   설명만 아래로 내린다 — 번호까지 따로 줄을 차지하면 다섯 줄이 열다섯 줄이 된다. */
@media (max-width: 900px) {
  .xc-mth__ability > li {
    grid-template-columns: auto minmax(0, 1fr);
    gap: 6px 12px;
  }
  .xc-mth__ab-desc { grid-column: 2; }
}
@media (max-width: 1024px) {
  .xc-mth__area { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 640px) {
  /* 흐름 대조표는 위쪽 자기 미디어쿼리에서 접는다. 여기서는 나머지만 */
  .xc-mth__wall, .xc-adds__wall { grid-template-columns: 1fr; }
  /* ⚠️ 여기서 1열로 접지 않는다(사용자 지시). 한 장씩 세우면 여덟 장이
     화면 세 개를 차지해 「AI 가 이만큼을 맡는다」 는 덩어리가 안 보였다.
     이름·설명이 모두 짧아 반 폭에서도 줄이 거의 안 늘어난다.
     ⚠️ 대신 안쪽 여백을 줄인다. 32px 그대로 두면 167px 칸에서 글자칸이 123px 밖에 안 남는다. */
  .xc-mth__area { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
  .xc-mth__area > li { padding: 16px 14px; }
  .xc-mth__area-name { margin-top: 12px; }
  /* 홀수 장이면 마지막 한 장이 반만 남는다. 그때만 한 줄을 다 쓴다 */
  .xc-mth__area > li:nth-child(2n + 1):last-child { grid-column: span 2; }
}


/* ══════════════════ 이상탐지 무대 (MATE-AI for AD) ══════════════════
   제품개요 그림을 이미지 대신 SVG 로 그린다. 확대해도 선이 유지되고
   설비 하나를 좌표로 특정해 그 지점으로 시점을 옮길 수 있다.
   ⚠️ 접두사 .xc-anom. 메인의 .xc-add 처럼 겹치면 남의 규칙을 받는다. */
.xc-anom {
  margin-top: var(--xc-sol-figgap);
  /* 아래 여유를 따로 준다. 이 무대는 테두리 있는 카드로 끝나는데,
     딱딱한 경계선 뒤의 여백은 글줄 뒤의 같은 여백보다 좁아 보인다.
     .xc-blk + .xc-blk 의 160px 만으로는 다음 제목이 붙어 보인다.
     ⚠️ margin 으로 주면 안 된다. 섹션의 마지막 자식이라 아래 마진이 섹션 밖으로
        빠져나가 다음 섹션의 margin-top 160px 과 상쇄돼 그대로 160px 이 된다 */
  padding-bottom: clamp(16px, 2.4vw, 40px);
  display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
  gap: clamp(16px, 2vw, 28px); align-items: stretch;
}
.xc-anom__map {
  margin: 0; position: relative; overflow: hidden;
  background: var(--xc-gray-50);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius-lg);
}
.xc-anom__map svg { display: block; width: 100%; height: 100%; }
/* 등각 투영 바닥·구역 */
.xc-anom__slab { fill: var(--xc-bg); stroke: rgba(22, 29, 41, .16); stroke-width: 1.5; }
.xc-anom__hall { fill: rgba(22, 29, 41, .05); }
.xc-anom__room { fill: rgba(22, 29, 41, .022); stroke: rgba(22, 29, 41, .12); stroke-width: 1.2; }

/* 설비 상자. 윗면이 가장 밝고 앞왼쪽 면이 가장 어둡다 —
   한 광원에서 온 것처럼 보여야 입체로 읽힌다. 처음에는 숨어 있다가 JS 가 차례로 켠다 */
/* ⚠️ 모서리를 둥글게 잇는다. 기본값(miter)은 예각 꼭짓점에서 선을 뾰족하게 뻗는다.
   등각 투영이라 상자마다 60° 꼭짓점이 둘씩 생겨 가시처럼 튀어나온다 */
.xc-anom__eq polygon { stroke-linejoin: round; }
.xc-anom__f-t { fill: #FFFFFF; stroke: rgba(22, 29, 41, .30); stroke-width: 1.2; }
.xc-anom__f-r { fill: #E9ECF1; stroke: rgba(22, 29, 41, .30); stroke-width: 1.2; }
.xc-anom__f-l { fill: #D6DAE2; stroke: rgba(22, 29, 41, .30); stroke-width: 1.2; }
.xc-anom__eq text {
  fill: var(--xc-text-sub); font-size: var(--xc-fs-15); text-anchor: middle;
  font-family: var(--xc-font-ko); font-weight: 600;
}
/* 이상 설비. 같은 명암 단계를 오렌지로 옮긴다 */
.xc-anom__eq.is-bad .xc-anom__f-t { fill: #FFF1E6; stroke: var(--xc-orange); stroke-width: 2; }
.xc-anom__eq.is-bad .xc-anom__f-r { fill: #FBC79A; stroke: var(--xc-orange); stroke-width: 2; }
.xc-anom__eq.is-bad .xc-anom__f-l { fill: #F5A661; stroke: var(--xc-orange); stroke-width: 2; }
.xc-anom__eq.is-bad text { fill: var(--xc-orange); }
/* 표시와 설비를 잇는 선. 공중에 뜬 표시가 어디를 가리키는지 알려 준다 */
.xc-anom__pin { stroke: var(--xc-orange); stroke-width: 1.6; stroke-dasharray: 3 3; }

/* 경고 표시 */
.xc-anom__dot { fill: var(--xc-orange); }
.xc-anom__bang {
  stroke: #fff; stroke-width: 3.4; stroke-linecap: round; fill: none;
}
/* 파동은 선이 아니라 면으로 채운 원 세 겹이다. 시차를 두고 차례로 퍼진다 */
.xc-anom__wave {
  fill: var(--xc-orange); stroke: none;
  transform-box: fill-box; transform-origin: center;
  opacity: 0;
}
/* 시간에 묶는다. 스크롤에 묶으면 멈춰 서 있을 때 알림이 죽어 보인다 */
.xc-anom.is-on .xc-anom__wave { animation: xcAnomWave 2.7s var(--xc-ease-out) infinite; }
.xc-anom.is-on .xc-anom__wave--2 { animation-delay: .9s; }
.xc-anom.is-on .xc-anom__wave--3 { animation-delay: 1.8s; }
@keyframes xcAnomWave {
  0%   { transform: scale(1);   opacity: .42; }
  70%  { opacity: .12; }
  100% { transform: scale(3.6); opacity: 0; }
}

/* ── 우측 패널 ── */
.xc-anom__panel {
  padding: clamp(24px, 2.6vw, 36px);
  background: var(--xc-bg);
  border: 1px solid var(--xc-border); border-radius: var(--xc-radius-lg);
  display: flex; flex-direction: column;
}
.xc-anom__panel-ico svg { display: block; margin-inline: auto; fill: none; }
.xc-anom__panel-ico path:first-child {
  stroke: var(--xc-orange); stroke-width: 1.8; stroke-linejoin: round;
}
.xc-anom__panel-bang { stroke: var(--xc-orange); stroke-width: 2.2; stroke-linecap: round; }
/* 카드 안의 제목이다. 섹션 제목만큼 클 이유가 없다.
   아이콘도 26px 로 줄여 둘이 한 덩어리로 읽히게 한다.
   ⚠️ 최솟값은 20px 그대로 둔다. 줄인 것은 최댓값(26 → 22)뿐이다 */
.xc-anom__panel-t {
  margin-top: 10px; text-align: center;
  font-size: var(--xc-fs-panel-t); font-weight: var(--xc-fw-extra);
  letter-spacing: var(--xc-ls-heading); color: var(--xc-text);
}
/* ⚠️ 최대 폭을 반드시 건다. 이 차트는 패널 안의 곁그림인데 상자 폭이 화면에 따라
   320~906px 로 출렁인다(1024 에서 한 단으로 접히며 패널이 전체 폭을 먹는다).
   SVG 는 viewBox 배율로 글자까지 함께 늘리므로, 안 막으면 같은 라벨이
   어떤 화면에서는 12px, 어떤 화면에서는 30px 로 보인다.
   380px 로 묶으면 배율이 0.94~1.19 밴드에 들어가 라벨이 12.2~15.4px 를 유지한다. */
.xc-anom__chart { margin-top: clamp(18px, 2vw, 26px); }
.xc-anom__chart svg {
  display: block; width: 100%; max-width: 380px; margin-inline: auto; height: auto;
}
/* 축은 바닥 한 줄뿐이다.
   ⚠️ 눈금값 없는 가로선을 여러 줄 긋지 않는다. 척도가 없으면 알려 주는 것이 없고
      선만 늘어 그래프가 촌스러워진다. 강조 띠·고리도 같은 이유로 없앴다 */
.xc-anom__axis { fill: none; stroke: rgba(22, 29, 41, .12); stroke-width: 1; }
/* 임계선. 이 그래프에서 가장 중요한 것은 봉우리가 아니라 넘어선 선이다.
   라벨은 선 오른쪽 끝에 물려 둔다. 선은 라벨에 닿기 전에 끊어 둔다(생성기가 계산) */
.xc-anom__thr path {
  fill: none; stroke: rgba(252, 101, 0, .6);
  stroke-width: 1.2; stroke-dasharray: 4 4;
}
/* ⚠️ SVG 안 글자는 뷰박스 배율을 탄다. 여기 적는 13 은 화면 px 이 아니다.
   배율은 .xc-anom__chart 의 max-width 가 0.94~1.19 로 묶어 두었다.
   그 규칙을 풀면 1024 에서 배율이 2.83 까지 뛰어 이 글자가 30px 로 보인다. */
.xc-anom__thr text {
  fill: var(--xc-gray-500); font-size: 13px; font-weight: var(--xc-fw-medium);
  font-family: var(--xc-font-ko); text-anchor: end; letter-spacing: -.01em;
}
/* 선 아래를 채우는 면. 같은 경로를 두 벌 그리고 임계선에서 서로 반대로 잘라 낸다 */
.xc-anom__fill { fill: url(#xcAnomFill); stroke: none; }
.xc-anom__fill--over { fill: url(#xcAnomOverFill); }
/* 가늘고 진하게. 표본이 촘촘하므로 굵으면 뭉개진다.
   ⚠️ 중간 회색 + 중간 굵기는 스타일을 정하지 않은 기본값으로 보인다. 한쪽으로 정한다 */
.xc-anom__line {
  fill: none; stroke: var(--xc-gray-600); stroke-width: 1.6;
  stroke-linecap: round; stroke-linejoin: round;
}
.xc-anom__peak { fill: var(--xc-orange); }
.xc-anom__list { margin-top: clamp(18px, 2vw, 26px); display: grid; gap: 14px; }
/* ⚠️ 아이콘을 ::before 로 그리지 않는다. 원과 체크를 따로 얹으면 글자 크기가 바뀔 때마다
   둘이 어긋난다. 하나의 SVG 로 두고 flex 로 글줄에 맞춘다 */
.xc-anom__list li {
  display: flex; align-items: flex-start; gap: 12px;
  font-size: var(--xc-fs-panel-li); color: var(--xc-text); line-height: 1.5;
}
.xc-anom__chk {
  flex: none; margin-top: .1em;
  fill: none; stroke: var(--xc-orange); stroke-width: 1.7;
  stroke-linecap: round; stroke-linejoin: round;
}
/* ⚠️ 네이비 띠를 쓰지 않는다. 네이비 바탕은 푸터에만 둔다 */
.xc-anom__result {
  margin-top: clamp(20px, 2.2vw, 28px); padding: clamp(18px, 2vw, 24px);
  background: var(--xc-bg-muted); border-radius: var(--xc-radius);
  font-size: var(--xc-fs-card-ttl-sm); font-weight: var(--xc-fw-bold);
  color: var(--xc-text); line-height: 1.55; text-align: center; text-wrap: balance;
}
/* 그래프 등장 — 선이 그려지고, 이상 지점에 점이 찍히고, 그 구간이 물든다.
   점은 반지름으로 키운다(main.js). transform 으로 키우면 제자리에서 자라지 않는다 */

@media (max-width: 1024px) {
  .xc-anom { grid-template-columns: 1fr; }
}
@media (prefers-reduced-motion: reduce) {
  .xc-anom.is-on .xc-anom__wave { animation: none; opacity: .4; }
}


/* ══════════════════ 반응형 ══════════════════ */
/* ══════════════════ 반응형 ══════════════════
   브레이크포인트는 3개만 쓴다. 새 화면도 이 기준을 따를 것.
     LG  1280  노트북       4열 → 3열
     MD  1024  태블릿 가로   GNB → ☰, 3열 → 2열
     SM   640  모바일       전부 1열, 핀 해제
   ⚠️ 크기·여백·글자는 대부분 clamp() 유동 스케일이 처리한다.
      미디어쿼리는 '열 수'와 '구조 전환'에만 쓴다.
   ────────────────────────────────────────── */

/* ── LG 1280 · 노트북 ── */
/* 균등 칸에 영문 최장 메뉴(「Company Introduction」)가 들어가야 한다.
   칸은 화면이 좁아질수록 줄어드는데 글자는 안 줄어서 넘쳤다. 두 단계로 낮춘다.
     1440px 이하 : 15px  (1440 기준 칸 170px · 글자 147px)
     1366px 이하 : 14px  (1281 기준 칸 147px · 글자 137px)
   ⚠️ 1024px 이하는 메뉴 자체가 숨고 전체메뉴 버튼만 남는다. 그 아래는 볼 필요 없다. */
@media (max-width: 1440px) {
  .xc-gnb__link { font-size: var(--xc-fs-15); }
}
@media (max-width: 1366px) {
  .xc-gnb__link { font-size: var(--xc-fs-14); padding-inline: 2px; }
}

@media (max-width: 1280px) {
  /* ⚠️ 여기서 다시 15px 로 올리던 줄이 있었다. 위 1366px 규칙(14px)보다 뒤에 있어
        그 값을 되돌려 놨다. 글자 크기는 위에서만 정한다. */

  /* 전체메뉴 */
  :root {
    --sm-pad-x: 60px;
    --sm-d1-w: 300px;
    --sm-d1-fs: clamp(24px, 3vh, 30px);
  }
  .xc-sitemap__d2 { gap: 12px 50px; }
  .xc-sitemap__d2 > li > a { font-size: var(--xc-fs-15); }

  /* 본문 — 아코디언은 유지하되 접힌 카드 폭이 줄어드는 만큼 이름을 줄인다 */
  /* ★ 접힌 카드가 전체에서 제일 좁아지는 구간이다. 여기가 기준선이다.
     펼침 비율을 5.6 에서 내려 접힌 카드를 지킨다. 1025px 에서 컨테이너는
     1025 - 좌우여백 48 - gap 48 = 929px 이고, 4.6 이면 접힌 폭이 87.6px,
     카드 좌우 border 를 뺀 spine 자리가 85.6px 다. 하한은 padding 32 +
     이름 28.5 + 번호 19.5 = 80px 이라 실측 여유가 4.91px 남는다(2026-08-10).
     ⚠️ 5px 이 채 안 된다. --card-grow 를 올리거나 padding 을 되돌리면 여기서
        제일 먼저 이름과 번호가 맞붙는다. 손대기 전에 이 숫자를 다시 잴 것.
     (이 구간은 예전 값 3.6 + padding 24 + line-height 1.75 조합에서 하한이 104px 라
      1100px 아래에서 이름과 번호가 이미 겹쳐 있었다. 같이 풀린다.) */
  /* ⚠️ gap 을 직접 쓰지 않고 --card-gap 을 갈아 끼운다. 사진 판의 폭 계산
     (--card-w-open) 이 같은 값을 다시 읽으므로 둘이 갈라지면 사진이 어긋난다. */
  .xc-lineup__acc { --card-gap: 8px; --card-grow: 4.6; }
  .xc-card__spine { top: 24px; padding-inline: 16px; }
}

/* ── 1200 · 가로 메뉴를 접는 지점 ──
   큰메뉴를 균등 폭으로 나눈 뒤 칸이 얼마나 남는지 재 보니, 1200px 아래에서는
   영문 최장 메뉴(「Company Introduction」)가 들어가려면 글자가 13px 밑으로 내려가야 한다.
   1100px 에서는 11.8px, 1025px 에서는 10.6px 이다. 읽을 수 있는 크기가 아니다.
   그래서 이 아래로는 가로 메뉴 대신 우측 전체메뉴(☰)만 남긴다.
   ⚠️ 지점을 1240px 으로 잡았다. 폭을 1px 씩 좁혀 가며 잰 결과 1240px 에서 여유가 1px,
      1230px 부터 「Company Introduction」이 칸을 넘겼다. 그 한 칸 위에서 접는다.
   ⚠️ 헤더 높이·여백은 그대로 둔다. 그건 1024px 블록이 따로 맡는다. */
@media (max-width: 1240px) {
  .xc-gnb__nav { display: none; }
  .xc-gnb__util { margin-left: auto; }
}

/* ── MD 1024 · 태블릿 가로 ── */
@media (max-width: 1024px) {
  /* GNB — 메가메뉴 대신 ☰(전체메뉴). 레퍼런스 모바일: padding 20px */
  :root { --gnb-top: 20px; --gnb-side: 20px; --gnb-row: 64px; --gnb-r: 32px; --gnb-padx: 24px; }
  .xc-gnb__nav { display: none; }
  .xc-gnb__shell,
  .xc-gnb.is-open .xc-gnb__shell { height: var(--gnb-row); }
  .xc-gnb__bg { height: var(--gnb-row); clip-path: none; }
  .xc-gnb__util { margin-left: auto; }

  /* 전체메뉴 — 대분류 폭을 풀고 세로로 */
  :root { --sm-pad-x: 24px; --sm-d1-fs: clamp(20px, 2.6vh, 24px); }
  .xc-sitemap__body { padding-left: 0; }
  .xc-sitemap__d1 > li { display: block; }
  .xc-sitemap__d1 > li > a { width: auto; display: block; margin-bottom: 8px; }

  /* 본문 — 4열/3열 계열을 2열로 */
  .xc-two__grid { grid-template-columns: 1fr; }

  /* ── 라인업 : 아코디언 해제 ──
     접힌 카드 폭이 안 나오고, 터치 기기에는 hover 가 없다.
     세로로 쌓고 설명을 항상 펼쳐 둔다. */
  .xc-lineup__acc { flex-direction: column; height: auto; gap: 12px; }
  .xc-card { flex: none; }
  /* 사진 — 아코디언이 아니므로 '펼친 폭 고정'이 새어 나오면 안 된다. 카드가 곧 창이다.
     ⚠️ 스크림도 평평하게 만든다. 여기서는 카드가 가로로 누워 본문이 폭의 89% 까지
        차고, 접힘 번호(.xc-card__no)는 오른쪽 끝(98% 지점)에 앉는다. 가로 그라디언트를
        그대로 두면 그 번호가 걷힌 자리에 놓여 3.74:1 로 떨어진다(실측). 평평하면 5.16:1. */
  .xc-card__media { width: 100%; }
  .xc-card__media::after { background: rgb(80, 86, 94); }
  /* ⚠️ 접힘용 배율을 여기서 되돌린다. 이 구간은 카드가 세로로 눕고 패널 본문이
     항상 펼쳐져 있어(opacity:1) 글자가 늘 사진 위에 있다. 배율을 그대로 두면
     일곱 장 전부에서 본문 대비가 얕아진다. 데스크톱에서만 접힘이 얇아져야 한다. */
  .xc-card { }
  .xc-card:is(:hover, :has(.xc-card__link:focus-visible)) { flex-grow: 0; }
  /* 세로 이름은 감추고 번호만 우측에 남긴다. 카드가 가로로 눕으므로 번호도 가로로. */
  .xc-card__spine { top: 20px; padding-inline: 20px; justify-content: flex-end; }
  .xc-card__label { display: none; }
  /* 다시 가로로 눕는다. 눕힌 글자의 가로폭을 줄이려고 걸어 둔 1.5 는 여기서 뜻이
     사라지고 글자만 위로 3px 올라가므로 본문값으로 되돌린다 */
  .xc-card__no { writing-mode: horizontal-tb; margin-top: 0; line-height: var(--xc-lh-body); }
  /* 우측 여백 108 → 56.
     108 은 우하단 장식 도형(right 20 + 폭 64 = 84)을 피하려고 잡아 둔 값이었다.
     도형이 없어졌으니 이제 피할 것은 우상단 번호(.xc-card__no) 하나다.
       spine padding-inline 20 + 번호 폭(13px 두 자 · letter-spacing .08em ≈ 17)
       + 사이 여백 19 = 56
     번호와 같은 줄에 놓이는 것은 첫 줄(.xc-card__cat) 뿐이고, 그 아래 이름·태그·
     본문은 번호보다 밑이라 원래 걸리지 않는다. 그래서 첫 줄 기준으로만 잡는다.
     ⚠️ 이 값을 더 줄이면 좁은 태블릿에서 카테고리 글이 번호에 닿는다. */
  .xc-card__panel {
    position: static; width: auto; opacity: 1;
    padding: 26px 56px 24px 24px;
  }
  .xc-card:is(:hover, :has(.xc-card__link:focus-visible)) .xc-card__panel { transition-delay: 0s; }
  /* 기본값(--xc-gap)이 이 구간에서 20.5~32px 이라 세로 목록에서는 너무 벌어진다.
     원래 비율(26 → 14 = 0.54)을 유지해 새 기준값 20.5 에 맞춰 16 으로 잡는다.
     ⚠️ padding-top 도 0 으로 되돌린다. 여기서는 패널이 static 이고 카드 높이가 auto 라
        남는 공간이 없어 위아래 분리(margin-top:auto)가 성립하지 않는다. 그대로 두면
        간격이 16 + 20.5 로 겹쳐 쌓인다. */
  /* 아코디언이 없는 구간이라 그어지는 동작 자체가 없다. 처음부터 그어 둔다. */
  .xc-card { --card-line: 1; }
  /* ⚠️ 여기서는 선을 카드 끝까지 보내면 안 된다. 카드가 가로로 누우면서 번호
     (.xc-card__no)가 우측 상단으로 올라와 소제목과 같은 줄에 놓이므로 선이 번호를
     가로지른다. 패널 우측 여백(56px)이 이미 번호 자리를 비워 두고 있으니 거기서 멈춘다. */
  .xc-card__cat::after { margin-right: 0; }
  .xc-card__tag { margin-top: 16px; padding-top: 0; }
  /* 여기서는 카드가 가로로 누워 설명 폭이 화면 전체를 먹는다. vw1024 실측으로
     박스 폭 879px, 한글 약 56자였다(권장 25~40자).
     ⚠️ ch 를 쓰지 않는다. ch 는 숫자 0 의 폭 기준이라 한글에서는 과도하게 좁아진다
        (46ch = 391px = 한글 26자). 한글 줄길이는 em 으로 잡는다. */
  .xc-card__desc { max-width: 40em; }
  /* 사업분야 — 가로 넉 장을 세로로 푼다.
     ⚠️ 덮개를 아예 들어낸다. 좁은 화면에서는 걸지 않으니 내려갈 일이 없고,
        남겨 두면 글을 가린 채로 굳는다. */
  .xc-biz__head .xc-lead { max-width: 60ch; }
  .xc-biz__list { flex-direction: column; gap: clamp(12px, 1.6vw, 18px) !important; }
  .xc-biz__card { height: auto !important; }
  .xc-biz__cover { display: none; }

  /* 푸터 */
  :root { --ft-pad-t: 70px; --ft-wrap-mt: 60px; --ft-go: 100px; }
  .xc-footer__contact { flex-direction: column; align-items: flex-start; gap: 20px; }
  .xc-footer__policy { gap: 35px; }
  .xc-footer__bot { flex-direction: column; align-items: flex-start; gap: 20px; }
  .xc-footer__info { gap: 12px 40px; }
  .xc-quick { right: 30px; bottom: 50px; }

  /* 고객사 로고 축소 */
  .xc-clients__row li { width: 152px; height: 74px; }
  .xc-clients__row li img { max-height: 44px; }
}

/* ── SM 640 · 모바일 ── */
@media (max-width: 640px) {
  :root { --hero-frame: 10px; --hero-frame-r: 12px; }

  /* 히어로 — 핀 해제, 레이어 세로 배치.
     🔴 높이를 auto 로 두면 첫 화면을 안 채운다. 390x844 에서 545px(65%)까지 떨어져
        열자마자 다음 섹션이 보였다(실측 2026-09-17). 화면을 채우되 내용이 더 길면
        늘어나도록 min-height 로 잡는다.
     ⚠️ 단위는 **svh** 다. vh 는 주소창이 숨은 높이라 열자마자 아래가 잘리고,
        dvh 는 주소창이 접힐 때 값이 변해 아래 내용이 밀린다. svh 는 주소창이
        보이는 높이라 「열었을 때 꽉 참」이고 그 뒤로 안 변한다.
     ⚠️ svh 를 못 읽는 브라우저를 위해 vh 를 먼저 적어 둔다(뒤 선언이 이긴다).
     ⚠️ 무대의 height:100% 는 min-height 만으로는 안 먹는다(부모 높이가 확정이
        아니라서). 히어로를 flex 로 세우고 무대가 남는 세로를 받아 가게 한다. */
  .xc-hero {
    height: auto;
    min-height: 100vh;
    min-height: 100svh;
    display: flex;
    padding-block: 140px 90px;
  }
  .xc-hero__stage { flex: 1; height: auto; }
  .xc-hero__scroll { display: none; }
  .xc-add__pin { min-height: 0; }
  .xc-add__body { grid-template-columns: 1fr; }
  .xc-add__steps { padding-bottom: 0; gap: 26px; }
  /* ⚠️ 어두운 무대 시절의 흰 글자였다(2026-08-31 정정). 지금은 흰 무대라 흰 글자면
     안 보인다. 지금까지 안 드러난 것은 모바일에서 세 단계가 전부 .is-on 이라
     그쪽 규칙(--xc-navy)이 이겨 왔기 때문이다 — 죽은 값이지 안전한 값이 아니었다.
     .is-on 을 모바일에서 걷어내는 순간 흰 바탕에 흰 글자가 된다. */
  .xc-add__step h3 { color: var(--xc-navy); }
  .xc-add__ko { color: var(--xc-gray-600); }
  /* 설명문을 흐름 안으로 되돌린다 */
  .xc-add__step p { position: static; opacity: 1; transform: none; margin-top: 8px; }
  /* 모바일에서는 세 판을 처음부터 쌓아 둔다 */
  .xc-slab { opacity: 1; transform: none; }

  /* 전부 1열 */


  /* 라인업 카드 — 여백 축소.
     우측 84 → 52. 위 1024 블록과 같은 계산이고 spine padding 만 16 으로 줄어든다.
       16 + 번호 폭 약 17 + 사이 여백 19 = 52 */
  .xc-card__panel { padding: 24px 52px 22px 20px; }
  .xc-card__spine { top: 16px; padding-inline: 16px; }

  /* 고객사 로고 */
  .xc-clients__row li { width: 130px; height: 64px; padding: 0 12px; }
  .xc-clients__row li img { max-height: 38px; }

  /* 푸터 */
  :root { --ft-gap: 10px; --ft-r: 12px; --ft-pad-t: 56px; --ft-go: 84px; }
  .xc-footer__info { flex-direction: column; gap: 10px; }
  .xc-footer__list { gap: 12px; }
  /* 라벨 고정 폭(80px)에 '사업자등록번호' 가 안 들어가 라벨이 스스로 두 줄로
     갈라졌다. 좁은 화면에서는 라벨을 값 위로 올려 폭 제약을 없앤다. */
  .xc-footer__list li { flex-direction: column; gap: 2px; }
  .xc-footer__list span { font-size: var(--xc-fs-14); }
  .xc-footer__list .tit1, .xc-footer__list .tit2 { width: auto; }
  .xc-footer__policy { gap: 20px; }
  .xc-footer__policy a { font-size: var(--xc-fs-14); }
  .xc-footer__sns a { width: 50px; height: 50px; }
  /* ⚠️ 크기를 지우면 안 된다. 기본값은 14px 이고 여기서만 13px 로 줄인다 */
  .xc-footer__copy { text-align: left; font-size: var(--xc-fs-13); }
  .xc-quick { right: 20px; bottom: 30px; }
  .xc-quick a, .xc-quick button { width: 45px; height: 45px; }
  .xc-quick li:hover a { width: 130px; gap: 10px; }
}

/* 모션 최소화
   ⚠️ GNB·사이트맵·액자는 tokens.css 의 --xc-dur-* 이 아니라 자체 변수를 쓴다.
      여기서 함께 줄이지 않으면 모션 최소화 설정이 무시된다. */
@media (prefers-reduced-motion: reduce) {
  :root {
    --gnb-dur: .01ms; --gnb-hide-dur: .01ms;
    --gnb-d2-dur: .01ms; --gnb-d2-delay: 0s; --gnb-d2-step: 0s;
    --sm-dur: .01ms; --sm-content: .01ms; --sm-delay: 0s;
    --hero-frame-dur: .01ms;
    /* 라인업 카드 : 폭은 즉시 스냅되는데 패널만 늦게 뜨면 판이 두 번 튄다 */
    --card-panel-delay: 0s;
  }
  html { scroll-behavior: auto; }
  .xc-hero__title .ch { will-change: auto; }
  .xc-clients__row { animation: none; }
  /* 연혁 구간 전환. 크기가 커지는 움직임을 없애고 상태만 즉시 바꾼다 */
  .xc-hist__navi button { transition-duration: .01ms; }
  .xc-hero__scroll span:last-child::after { animation: none; }
  .xc-hero { transition: none; }
  /* 사업분야 — 덮개가 내려가는 것도 모션이다. 다 내려간 자리에 처음부터 둔다 */
  .xc-biz__list { gap: 15px !important; }
  .xc-biz__cover { top: var(--biz-open) !important; }
}

/* ══════════════════ 고대비 모드 ══════════════════
   Windows 고대비는 배경 이미지(그라디언트 포함)를 제거한다.
   background-clip:text + color:transparent 조합은 글자가 통째로 사라지므로 되돌린다. */
@media (forced-colors: active) {
  .xc-mark, .xc-grad-text {
    background: none; color: CanvasText; forced-color-adjust: none;
  }
  .xc-btn--fill, .xc-footer__go { border: 1px solid CanvasText; }
}

/* ══════════════════ ② ~ ⑤ 는 라이트 고정 ══════════════════
   2026-08-28 사용자 결정. 그전에는 「AI 개발 방법론」에 다가갈수록 화면 전체가
   네이비로 물들고(--xc-stain · .xc-veil) CLIENTS 에서 다시 밝아졌다.
   지금은 두 갈래 · ADD · 라인업 · CLIENTS 가 전부 흰 바탕이다.

   🔴 되살리려면 사용자에게 먼저 묻는다. 값만 되돌리면 안 된다 — 아래가 같이 딸려 온다.
      ① .xc-veil(고정 네이비 판) 마크업 세 벌 + main.js 의 진행도 구동
      ② two-hand.js 의 setStain/progressStain (이어받기 박자 ③)
      ③ html.is-stained .xc-card 반투명 유리면
      ④ .xc-add 의 .xc-dark 와 어두운 무대 배경 · 불티
      ⑤ hand.mjs / lineup.mjs 의 물듦 검사
      경위와 걷어낸 목록은 docs/HANDOFF-2026-08-28-라이트.md

   ⚠️ 히어로(.xc-hero)와 두 갈래의 xCalibur 카드(.xc-two__card--xcal)는 그대로 다크다.
      이 둘은 물듦 장치가 아니라 제 마크업의 .xc-dark 로 어둡다. 건드리지 않았다.
   ⚠️ 솔루션 상세의 축 물듦([data-stain] · .xc-stain-veil · html.is-staining)은 다른 장치다.
      이름이 비슷할 뿐 메인과 무관하다. 이 결정으로 걷어내지 않는다. */

/* MATE 카드는 흰 페이지 위에서 면이 안 읽히므로 회색을 직접 지정한다.
   ⚠️ var(--xc-bg-soft) 를 쓰지 않는다 — 어느 스코프에 걸리느냐에 따라 흰색을 되받아
      흰 페이지 위 흰 카드가 된다. 카드면은 값을 직접 쓴다.
   ⚠️ xCalibur 카드는 제 마크업에 .xc-dark 를 갖고 있다(항상 다크). 두 카드의 대비가 요점이다. */
.xc-two__card--mate { background: var(--xc-gray-50); }

/* 카드 안 CTA 를 없애면서 높이가 428 → 365px 로 줄었다. 되돌린다.
   1024 이하는 1열이라 카드가 가로로 길어지므로 최소 높이를 걸지 않는다. */
/* ⚠️ 1024.001px 로 쓰면 Chromium 이 1024 로 내림해 1열 구간에서도 참이 된다 */
@media (min-width: 1025px) {
  .xc-two__card { min-height: clamp(360px, 27vw, 440px); }
}


/* ══════════════════ xMeister 솔루션 상세 ══════════════════
   접두사 .xc-xm. main.css 는 모든 페이지가 공유하므로 쓰기 전에 충돌을 확인했다(0건).
   ⚠️ 이 페이지에는 고정(pin)을 쓰지 않는다 — INTERACTION.md 2-3
      「핀 스크롤은 쓰지 않는다. 읽는 화면이라 방해된다」 */

/* 히어로 보조 — 버튼 줄. 페이지 헤더 공용에는 없던 것이다.
   (제목 위 한 줄 .xc-ph__eyebrow 는 쓰는 데가 없어져 지웠다) */
.xc-ph__acts {
  margin-top: clamp(24px, 3vw, 40px);
  display: flex; flex-wrap: wrap; gap: clamp(10px, 1.2vw, 16px);
}
/* 전체화면 변형은 가운데 정렬이다. 버튼 줄도 따라가야 한다 */
.xc-ph--full .xc-ph__acts { justify-content: center; }

/* ② 인용 한 줄. 스크롤에 따라 왼쪽부터 칠해진다.
   ⚠️ DrawSVG 를 쓰지 않는다. 이 프로토타입은 GSAP 코어와 ScrollTrigger 만 불러온다.
      회사소개 선언 블록과 같은 background-clip 방식으로 처리한다.
   ⚠️ 처음 상태를 CSS 로 감추지 않는다. 스크립트가 막히면 --paint 가 100% 로 남아
      글자가 온전히 보인다. */
.xc-xm__quote {
  --paint: 100%;
  margin-top: clamp(32px, 4vw, 56px);
  width: fit-content;
  font-size: var(--xc-fs-h3); font-weight: var(--xc-fw-extra);
  letter-spacing: var(--xc-ls-heading); line-height: 1.4;
  background-image: linear-gradient(90deg,
    var(--xc-text) 0 var(--paint),
    var(--xc-border) var(--paint) 100%);
  background-clip: text; -webkit-background-clip: text;
  color: transparent; -webkit-text-fill-color: transparent;
}

/* ③ 시그니처 · 왼쪽에서 묻고 답하고, 오른쪽에서 그 답의 근거를 되짚는다.
   ⚠️ 등장은 JS 가 스크롤 진행도로 몬다(핀 없음). 처음 상태도 JS 가 정한다 —
      CSS 에 opacity:0 을 두면 스크립트가 막혔을 때 내용이 영영 안 보인다.
   ⚠️ 안의 데이터는 전부 가상 예시다. 실제 SOP 체계·LOT 규칙이 나오면 그 형식에 맞춘다. */
.xc-xm__sig {
  margin-top: clamp(28px, 3.2vw, 44px);
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(16px, 2vw, 28px); align-items: stretch;
}
.xc-xm__talk,
.xc-xm__graph {
  /* ⚠️ 아래만 넓게 준다. 위에는 13px 캡션뿐인데 아래에는 입력칸 알약과
        그라디언트 노드가 붙는다. 위아래를 같게 주면 아래가 좁아 보인다.
        늘어난 몫은 아래 그래프를 줄여서 되돌려 받는다 — 무대가 커지면
        900px 화면에서 고정이 풀린다. */
  padding: clamp(24px, 2.6vw, 36px);
  padding-bottom: clamp(34px, 3.6vw, 52px);
  background: var(--xc-bg-soft);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius-lg);
}

/* ── 왼쪽 · 주고받는 대화 ──
   작업자가 입력칸에 치고, 보내고, 답이 흘러나오는 순서를 그대로 보여 준다. */
.xc-xm__talk { display: flex; flex-direction: column; }
.xc-xm__chat {
  /* 대화가 아래에서 위로 쌓여 입력칸에 붙는다. 진짜 메신저와 같은 방향이다.
     ⚠️ min-height 는 JS 가 완성 높이를 재서 넣는다. 안 넣으면 답이 흐르는 동안
        판이 계속 커지면서 아래 내용이 밀린다. CSS 에 고정값을 박으면 글이
        바뀔 때마다 어긋나므로 여기서 정하지 않는다. */
  flex: 1; margin-top: 16px;
  display: flex; flex-direction: column; justify-content: flex-end; gap: 14px;
}
.xc-xm__row { display: flex; flex-direction: column; }
.xc-xm__row--me { align-items: flex-end; }
.xc-xm__row--ai { align-items: flex-start; }

/* 보낸 쪽은 오른쪽에 붙고 채워진다. 받은 쪽은 왼쪽에 붙고 비어 있다 */
.xc-xm__msg { max-width: 92%; border-radius: var(--xc-radius-lg); }
.xc-xm__msg--me {
  padding: 14px 18px;
  background: var(--xc-navy); color: var(--xc-white);
  border-bottom-right-radius: 6px;
  font-size: var(--xc-fs-body); font-weight: var(--xc-fw-semibold); line-height: 1.5;
  word-break: keep-all;
}
.xc-xm__msg--ai {
  max-width: 100%; padding: 18px 20px;
  background: var(--xc-bg); border: 1px solid var(--xc-border-weak);
  border-bottom-left-radius: 6px;
}
/* 이름은 말풍선 밖 왼쪽 위에 둔다. 안에 넣으면 답변 첫 줄과 붙어 읽힌다 */
.xc-xm__who {
  display: block; margin: 0 0 6px 4px;
  font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-extra);
  letter-spacing: .06em; color: var(--xc-orange);
}
/* 답이 오기 전 잠깐 뜨는 표시. 세 점이 물결치듯 차례로 솟았다 가라앉는다.
   ⚠️ 이제 말풍선 「안」에 있다. 배경·테두리를 주면 풍선 속 풍선이 된다 */
.xc-xm__typing { display: flex; gap: 6px; padding: 2px 0 3px; }
.xc-xm__typing i {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--xc-text-weak);
  animation: xcXmDot 1.1s ease-in-out infinite;
}
.xc-xm__typing i:nth-child(2) { animation-delay: .18s; }
.xc-xm__typing i:nth-child(3) { animation-delay: .36s; }
@keyframes xcXmDot {
  0%, 60%, 100% { transform: translateY(0); opacity: .45; }
  30%           { transform: translateY(-5px); opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .xc-xm__typing i { animation: none; opacity: .6; }
}

/* ── 입력칸 ──
   ⚠️ <input> 도 <button> 도 아니다. 시연이라 아무 동작이 없으므로
      누를 수 있게 보이면 안 된다. 초점도 받지 않는다. */
.xc-xm__bar { margin-top: 18px; display: flex; align-items: flex-end; gap: 10px; }
.xc-xm__field {
  flex: 1; min-width: 0;
  display: flex; align-items: center; min-height: 46px; padding: 11px 18px;
  background: var(--xc-bg); border: 1px solid var(--xc-border);
  border-radius: 999px;
  font-size: var(--xc-fs-body); color: var(--xc-text); line-height: 1.5;
  word-break: keep-all;
}
.xc-xm__send {
  flex: none; width: 42px; height: 42px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--xc-border); color: var(--xc-text-weak);
  transition: background .22s var(--xc-ease-out), color .22s var(--xc-ease-out);
}
/* 칠 게 생기면 보낼 수 있는 모양이 된다 */
.xc-xm__send.is-on { background: var(--xc-navy); color: var(--xc-white); }
/* 어두워졌을 때. 네이비끼리 겹쳐 덩어리가 사라지는 것만 막으면 된다 */
.xc-dark .xc-xm__msg--me { box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .16); }
/* ⚠️ 이름이 말풍선 밖으로 나오면서 더 밝은 판(--xc-navy-2) 위에 앉는다.
      포인트 오렌지는 거기서 대비가 떨어져 작은 글자 기준 4.5:1 에 못 미친다.
      그라디언트 가운데 색으로 올린다. 이 판 위에서 6.0:1 이다. */
.xc-dark .xc-xm__who { color: var(--xc-grad-2); }
.xc-dark .xc-xm__send.is-on { background: var(--xc-white); color: var(--xc-navy-deep); }

.xc-xm__steps { margin-top: 12px; display: grid; gap: 7px; }
/* ⚠️ hidden 속성만으로는 안 숨는다. 위 display:grid 와 UA 의 [hidden] 이
      명시도가 같은데 저자 스타일이 이기기 때문이다. 여기서 못 박는다. */
.xc-xm__steps[hidden], .xc-xm__steps > li[hidden] { display: none; }
.xc-xm__steps > li {
  position: relative; padding-left: 32px;
  font-size: var(--xc-fs-body); color: var(--xc-text-sub); line-height: 1.7;
}
/* 번호는 채운 동그라미로. 조치 「절차」라 순서가 눈에 먼저 들어와야 하고,
   바로 아래 근거 태그가 이미 주황 알약이라 번호까지 주황이면 둘이 싸운다. */
/* 번호 대신 라벨을 다는 변형 (mateX).
   ⚠️ 라벨은 마크업이 아니라 attr() 로 그린다. 답이 한 자씩 흐르는 동안
      JS 가 li 의 글자를 통째로 갈아 끼우기 때문에, 마크업에 넣으면 지워진다. */
/* ⚠️ ol.~ 로 명시도를 한 단계 올린다. 아래 기본 번호 규칙과 명시도가 같으면
      뒤에 온 쪽이 이겨 라벨이 번호로 되돌아간다(실제로 그랬다). */
ol.xc-xm__steps--lb > li { padding-left: 0; }
ol.xc-xm__steps--lb > li::before {
  content: attr(data-lb);
  position: static; display: inline-block;
  width: auto; height: auto; margin-right: 8px;
  padding: 2px 8px; border-radius: 999px;
  background: var(--xc-chip-accent-bg);
  border: 1px solid rgba(252, 101, 0, .30);
  color: var(--xc-orange);
  font-size: var(--xc-fs-12); font-weight: var(--xc-fw-bold); line-height: 1.5;
  vertical-align: 1px;
}
/* 못 찾은 것은 색을 쓰지 않는다. 한계를 강조색으로 말하면 자랑처럼 보인다 */
ol.xc-xm__steps--lb > li[data-lb="확인 불가"]::before {
  background: var(--xc-chip-bg); border-color: var(--xc-border);
  color: var(--xc-text-weak);
}

.xc-xm__steps > li::before {
  content: counter(list-item);
  position: absolute; left: 0; top: .22em;
  width: 21px; height: 21px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--xc-navy); color: var(--xc-white);
  font-size: var(--xc-fs-12); font-weight: var(--xc-fw-extra);
  line-height: 1; letter-spacing: 0;
}
/* ⚠️ 어두워지면 네이비 동그라미가 판에 묻힌다. 흑백을 뒤집는다 */
.xc-dark .xc-xm__steps > li::before { background: var(--xc-white); color: var(--xc-navy-deep); }
/* 출처 태그. 이 페이지가 말하는 「출처를 인용해 답한다」를 눈으로 보게 하는 장치다 */
.xc-xm__src { margin-top: 14px; display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.xc-xm__src[hidden] { display: none; }
.xc-xm__src-lb {
  margin-right: 2px;
  /* 칩과 같은 크기로 둔다. 라벨만 크면 칩이 딸려 붙은 것처럼 보인다 */
  font-size: var(--xc-fs-12); font-weight: var(--xc-fw-extra); color: var(--xc-text-weak);
}
/* ⚠️ 글자는 --xc-fs-12 가 하한이다(토큰 §3 「칩·배지·탭 안 숫자」).
      더 줄이고 싶으면 글자가 아니라 안여백을 줄인다. */
.xc-xm__tag {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 10px; border-radius: 999px;
  background: var(--xc-chip-accent-bg);
  border: 1px solid rgba(252, 101, 0, .34);
  font-size: var(--xc-fs-12); font-weight: var(--xc-fw-bold); color: var(--xc-orange);
}
.xc-xm__tag i { font-style: normal; opacity: .7; }

/* ── 오른쪽 · 지식그래프 ──
   ⚠️ 세로로 세운다. 가로로 눕히면 좁은 열과 모바일에서 글자가 4px 대로 줄어 못 읽는다. */
.xc-xm__graph { display: flex; flex-direction: column; }
.xc-xm__graph-cap {
  font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-extra);
  letter-spacing: .06em; color: var(--xc-text-weak);
}
/* ⚠️ 폭으로 크기를 정한다. max-height 로 누르면 viewBox 비율 때문에
      좌우에 빈 띠가 생긴다(preserveAspectRatio 기본값). */
.xc-xm__graph svg {
  display: block; width: 100%; height: auto; margin: 16px auto 0; max-width: 470px;
}
.xc-xm__ln { fill: none; stroke: var(--xc-border-strong); stroke-width: 1.6; stroke-dasharray: 5 4; }
.xc-xm__nd rect { fill: var(--xc-bg); stroke: var(--xc-border); stroke-width: 1.2; }
.xc-xm__nd text {
  font-family: var(--xc-font-ko); font-size: 17px; font-weight: var(--xc-fw-bold);
  fill: var(--xc-text); text-anchor: middle;
}
.xc-xm__nd tspan { font-size: 14px; font-weight: var(--xc-fw-semibold); fill: var(--xc-text-weak); }
/* 지나온 노드 */
.xc-xm__nd--hit rect { fill: var(--xc-navy); stroke: var(--xc-navy); }
.xc-xm__nd--hit text { fill: var(--xc-white); }
.xc-xm__nd--hit tspan { fill: rgba(255, 255, 255, .62); }
/* 마지막 하나. 여기만 브랜드 그라디언트다 */
.xc-xm__nd--cause rect { fill: url(#xmGrad); stroke: transparent; }
.xc-xm__nd--cause text { fill: var(--xc-navy-deep); }
.xc-xm__nd--cause tspan { fill: rgba(13, 17, 25, .65); }

@media (max-width: 1024px) {
  .xc-xm__sig { grid-template-columns: 1fr; }
}

/* ③ 무대(제목 + 시그니처)가 화면 위에 걸린다.
   xcalibur.html Principles(.is-axis-pin)와 같은 방식이다.
   ⚠️ 이 페이지에서 #sword 통째로는 못 건다. 1091px 라 화면(900)보다 커서 고정하면
      아래 카드 셋이 화면 밖에 갇혀 스크롤로도 못 본다.
      그래서 「제목 + 시그니처」까지만 무대로 묶고, 카드 셋은 풀린 뒤에 흐른다.
   ⚠️ GNB 가 위에 떠 있다. 그만큼 비워야 제목이 GNB 밑에 깔리지 않는다.
   ⚠️ 세로가 좁으면 아예 안 건다(JS 의 min-height 조건). 안 그러면 무대가
      화면보다 커져 시그니처 아랫부분이 잘린 채 고정된다. */
.xc-sig__stage.is-sig-pin {
  min-height: 100dvh;
  display: flex; flex-direction: column; justify-content: center;
  /* ⚠️ GNB 한 줄(120px)을 다 비우면 위 140 / 아래 20 으로 크게 기운다.
        게다가 GNB 는 아래로 스크롤하는 동안 화면 밖으로 숨어 있어(.is-hide)
        그 120px 이 그냥 빈칸으로 보인다.
        그래서 바깥 여백(--gnb-top)만 비운다. 위 100 / 아래 60 으로 균형이 잡힌다.
        대신 위로 되짚어 올라가 GNB 가 다시 내려오면 눈썹 줄이 20px 겹친다.
        제목(h2)은 안 가린다 — 거기까지가 맞바꾼 값이다. */
  padding-top: var(--gnb-top);
}

/* ══ 솔루션 시그니처 공용 키트 ═══════════════════════════
   xCalibur 솔루션 7개가 모두 같은 6블록이라 ③ 검 블록의 부품을 공용으로 뺐다.
   페이지마다 새로 그리면 CSS 가 일곱 벌이 되고, 무엇보다 판 크기가 조금씩
   달라져 페이지를 오갈 때 한 제품군으로 안 읽힌다.
   ⚠️ 치수를 xMeister·xMES 시그니처와 같게 맞춰 두었다. 여기를 고치면 전부 움직인다.
   ⚠️ 처음 상태는 JS 가 정한다. 여기에 opacity:0 을 두면 스크립트가 막혔을 때
      내용이 영영 안 보인다. */
.xc-sig__two {
  margin-top: clamp(28px, 3.2vw, 44px);
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(16px, 2vw, 28px); align-items: stretch;
}
.xc-sig__one { margin-top: clamp(28px, 3.2vw, 44px); }
.xc-sig__panel {
  display: flex; flex-direction: column;
  padding: clamp(24px, 2.6vw, 36px);
  padding-bottom: clamp(34px, 3.6vw, 52px);
  background: var(--xc-bg-soft);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius-lg);
}
/* 판이 하나뿐일 때. 폭을 그대로 두면 1365px 짜리 띠 한가운데 그림만 덩그러니 남아
   좌우로 400px 씩 빈다. 가운데로 모아 「원 하나를 위한 판」으로 읽히게 한다.
   ⚠️ .xc-sig__panel 보다 뒤에 둔다. 명시도가 같아서 앞에 두면 아래 여백이 안 먹는다
      — 실제로 그랬고, 그만큼 무대가 높아져 핀 여유가 0px 이 됐다.
   ⚠️ container-type 은 안의 원이 제 판 폭에 맞춰 줄어들기 위한 것이다(cqw).
      화면 폭이 아니라 판 폭이 기준이라야 좁은 화면에서 글자가 잘리지 않는다. */
.xc-sig__panel--wide {
  /* 판이 컨테이너 폭을 그대로 쓴다. 800px 로 묶어 두었더니 좌우가 290px 씩 비었다.
     ⚠️ 고리 반지름은 넓혀도 안 커진다. 세로(100vh-530px)에 먼저 걸리기 때문이다.
        고리를 키우려면 무대가 높아져 핀이 풀린다. 넓히는 것은 판까지다. */
  max-width: 100%; margin-inline: auto;
  container-type: inline-size;
  /* 목록형 판의 넉넉한 아래 여백을 그대로 두면 원 밑에만 빈자리가 남아 위로 쏠린다 */
  padding-bottom: clamp(24px, 2.6vw, 36px);
}
/* 원이 커진 만큼 한가운데 글자도 같이 키운다. 작게 두면 원 안이 휑하다 */
.xc-sig__panel--wide .xc-xe__now > b  { font-size: var(--xc-fs-h3); }
.xc-sig__panel--wide .xc-xe__core     { font-size: var(--xc-fs-xs); }
.xc-sig__panel--wide .xc-xe__core > b { font-size: var(--xc-fs-h4); }
.xc-sig__cap {
  font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-extra);
  letter-spacing: .06em; color: var(--xc-text-weak);
}

/* 세로로 쌓이는 행 목록. 대부분의 시그니처가 이 형태다 */
.xc-sig__list {
  flex: 1; margin-top: 18px;
  display: flex; flex-direction: column; justify-content: center;
  gap: clamp(10px, 1.2vw, 14px);
}
/* 네 항목을 두 줄씩 두 열로. 세로로 길게 늘어놓으면 왼쪽 도면과 높이가 안 맞는다.
   ⚠️ 좁은 화면에서는 한 열로 되돌린다. 두 열이면 글이 두 글자씩 끊긴다. */
.xc-sig__list--two {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  /* ⚠️ 칸을 꽉 채운다. align-content: center 로 두면 네 장이 가운데 뭉치고
        위아래가 비어 왼쪽 도면판과 높이가 안 맞는다.
        1fr 이라 두 줄이 남는 높이를 똑같이 나눠 가진다. */
  grid-auto-rows: 1fr; align-content: stretch;
}
/* 카드가 커진 만큼 글은 가운데로 */
.xc-sig__list--two .xc-sig__row {
  display: flex; flex-direction: column; justify-content: center;
}
@media (max-width: 640px) {
  .xc-sig__list--two { grid-template-columns: 1fr; }
}

.xc-sig__row {
  padding: 14px 18px;
  background: var(--xc-bg);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius);
}
.xc-sig__lb {
  display: block; margin-bottom: 5px;
  font-size: var(--xc-fs-12); font-weight: var(--xc-fw-extra);
  letter-spacing: .04em; color: var(--xc-orange);
}
.xc-sig__tx {
  display: block;
  font-size: var(--xc-fs-body); color: var(--xc-text-sub); line-height: 1.6;
}
.xc-sig__tx b { font-weight: var(--xc-fw-extra); color: var(--xc-text); }
.xc-sig__tx i { font-style: normal; font-size: var(--xc-fs-12); color: var(--xc-text-weak); }
/* 강조되는 행 하나. 여럿을 물들이면 어디가 중요한지 안 보인다 */
.xc-sig__row--hit {
  background: var(--xc-chip-accent-bg);
  border-color: rgba(252, 101, 0, .45);
}
.xc-sig__row--hit .xc-sig__tx,
.xc-sig__row--hit .xc-sig__tx b { color: var(--xc-orange); }

/* 타일 격자 */
.xc-sig__grid {
  flex: 1; margin-top: 18px;
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px; align-content: center;
}
.xc-sig__grid > li {
  padding: 13px 10px; text-align: center;
  background: var(--xc-bg);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius);
}
.xc-sig__grid b {
  display: block; font-size: var(--xc-fs-15); font-weight: var(--xc-fw-extra);
  color: var(--xc-text);
}
.xc-sig__grid span {
  display: block; margin-top: 3px;
  font-size: var(--xc-fs-12); color: var(--xc-text-weak);
}
.xc-sig__grid > li[data-hit] {
  background: var(--xc-chip-accent-bg); border-color: rgba(252, 101, 0, .45);
}
.xc-sig__grid > li[data-hit] b,
.xc-sig__grid > li[data-hit] span { color: var(--xc-orange); }

/* 칩. 근거·출처·검증 같은 작은 표식 */
.xc-sig__chips { margin-top: 14px; display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.xc-sig__chip {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 10px; border-radius: 999px;
  background: var(--xc-chip-accent-bg);
  border: 1px solid rgba(252, 101, 0, .34);
  font-size: var(--xc-fs-12); font-weight: var(--xc-fw-bold); color: var(--xc-orange);
}
.xc-sig__chip i { font-style: normal; opacity: .7; }

/* ── byDP · AI 코드 리뷰가 도는 자리 ────────────────────
   실제로 리뷰가 한 번 돌아가는 장면이다. 읽는 표시가 뜨고, 짚은 것이 하나씩 붙는다.
   ⚠️ 원래 있던 한 줄(.xc-sig__tx i) 자리를 그대로 쓴다. 상자를 따로 세우면 무대가
      한 화면에 안 들어가 핀이 풀린다(xcSigStage 는 무대가 화면에 들어갈 때만 건다).
      그래서 세로로 쌓지 않는다 — 도는 표시와 짚은 것이 한 줄에 나란히 선다.
   ⚠️ 마크업의 기본 모습은 「완료」다. 스크립트가 막혀도 짚은 것이 다 보인다.
      JS 가 잡을 때만 .is-live 를 달아 비우고 처음부터 굴린다.
   ⚠️ 도는 표시는 .is-run 에서만 돈다. 멈춘 고리를 계속 돌리면 끝난 줄 모른다 */
.xc-rv { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 7px; }
.xc-rv__spin {
  position: relative; flex: none;
  width: 12px; height: 12px; border-radius: 50%;
  border: 2px solid var(--xc-border); border-top-color: var(--xc-orange);
}
/* 완료 표시 — 기본값이자 .is-done 의 모습 */
.xc-rv__spin::after {
  content: ""; position: absolute; left: 50%; top: 44%;
  width: 3px; height: 6px; translate: -50% -50%; rotate: 45deg;
  border: 0 solid var(--xc-orange); border-right-width: 2px; border-bottom-width: 2px;
}
.xc-rv.is-live:not(.is-done) .xc-rv__spin::after { display: none; }
.xc-rv.is-done .xc-rv__spin { border-color: var(--xc-orange); }
.xc-rv.is-run .xc-rv__spin { animation: xc-rv-spin .8s linear infinite; }
@keyframes xc-rv-spin { to { rotate: 360deg; } }
/* 「읽는 중」 — 짚은 것이 하나라도 뜨면 자리를 내준다 */
.xc-rv__state:empty { display: none; }
.xc-rv__found { display: contents; }
/* 가운뎃점으로 잇는다. 원래 한 줄이 그렇게 적혀 있었다 */
.xc-rv__found > span + span::before { content: "· "; color: var(--xc-text-weak); }
.xc-rv.is-live .xc-rv__found > span { display: none; }
.xc-rv.is-live .xc-rv__found > span.is-on {
  display: inline;
  animation: xc-rv-in .34s var(--xc-ease-out) both;
}
@keyframes xc-rv-in { from { opacity: 0; translate: 0 4px; } to { opacity: 1; translate: 0 0; } }
@media (prefers-reduced-motion: reduce) {
  .xc-rv.is-run .xc-rv__spin { animation: none; }
  .xc-rv.is-live .xc-rv__found > span.is-on { animation: none; }
}

/* 왼쪽에 색 띠를 두른 알림 상자 */
/* 겁들이는 사실 한 덩어리.
   ⚠️ 왼쪽에 색 막대를 세우지 않는다. 그건 경고문의 언어다. 이 판은 말풍선이
      언어라 막대를 세우면 대화 밑에 이질적인 덩어리가 앉는다.
      옅은 강조 바탕과 작은 아이콘이면 「사실」로 읽힌다.
   ⚠️ 아이콘을 마크업에 넣지 않고 mask 로 그린다. 쓰는 데가 네 페이지 다섯 곳이라
      마크업에 넣으면 고칠 때 다섯 군데를 손대야 한다. mask 라 색도 따라온다. */
.xc-sig__note {
  position: relative;
  margin-top: 16px; padding: 15px 18px 15px 46px;
  background: var(--xc-chip-accent-bg);
  border-radius: var(--xc-radius);
}
.xc-sig__note::before {
  content: ''; position: absolute; left: 17px; top: 16px;
  width: 18px; height: 18px; background: var(--xc-orange);
  --ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 2a10 10 0 1 0 0 20 10 10 0 0 0 0-20Zm4.7 7.7-5.6 6a1 1 0 0 1-1.5 0L7 13a1 1 0 1 1 1.4-1.4l2 2 4.9-5.2a1 1 0 1 1 1.4 1.3Z'/%3E%3C/svg%3E");
  -webkit-mask: var(--ico) no-repeat center / contain;
          mask: var(--ico) no-repeat center / contain;
}
/* 밝은 구간이든 어두운 구간이든 포인트 오렌지 하나로 간다 */
.xc-sig__note-t { font-size: var(--xc-fs-sm); font-weight: var(--xc-fw-bold); color: var(--xc-text); }
.xc-sig__note-d {
  margin-top: 6px;
  font-size: var(--xc-fs-12); color: var(--xc-text-sub); line-height: 1.6;
}
.xc-sig__note-d a {
  font-weight: var(--xc-fw-bold); color: var(--xc-orange);
  text-decoration: underline; text-underline-offset: 3px;
}

/* 대화 말풍선. xVerse·mateX 가 함께 쓴다.
   ⚠️ xMeister 의 .xc-xm__msg 와 생김새를 맞춘다. 같은 제품군에서 말풍선이
      페이지마다 다르면 다른 제품처럼 보인다.
   ⚠️ 보낸 쪽은 오른쪽, 받은 쪽은 왼쪽. 꼬리 쪽 모서리만 각지게 해 방향을 준다. */
.xc-sig__talk {
  flex: 1; margin-top: 18px;
  display: flex; flex-direction: column; justify-content: center;
  gap: clamp(12px, 1.4vw, 16px);
}
.xc-sig__msg { max-width: 92%; border-radius: var(--xc-radius-lg); }
.xc-sig__msg--me {
  align-self: flex-end; padding: 14px 18px;
  background: var(--xc-navy); color: var(--xc-white);
  border-bottom-right-radius: 6px;
  font-size: var(--xc-fs-body); font-weight: var(--xc-fw-semibold); line-height: 1.5;
  word-break: keep-all;
}
.xc-sig__msg--ai {
  align-self: flex-start; max-width: 100%; padding: 16px 20px;
  background: var(--xc-bg); border: 1px solid var(--xc-border-weak);
  border-bottom-left-radius: 6px;
  font-size: var(--xc-fs-body); color: var(--xc-text-sub); line-height: 1.6;
}
.xc-sig__msg--ai b { font-weight: var(--xc-fw-extra); color: var(--xc-text); }
.xc-sig__msg--ai i { font-style: normal; font-size: var(--xc-fs-12); color: var(--xc-text-weak); }
/* 이름은 말풍선 밖 왼쪽 위. 안에 넣으면 첫 줄과 붙어 읽힌다 */
.xc-sig__who {
  align-self: flex-start; margin: 0 0 -6px 4px;
  font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-extra);
  letter-spacing: .06em; color: var(--xc-orange);
}
.xc-dark .xc-sig__msg--me { box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .16); }
/* ⚠️ 물듦 구간에서 판이 --xc-navy-2 로 밝아지면 포인트 오렌지가 3.81:1 로
      떨어진다. 그라디언트 가운데 색으로 올린다(xMeister 이름표와 같은 처방). */
.xc-dark .xc-sig__who { color: var(--xc-grad-2); }

/* 도면. xVerse·hiVe 가 함께 쓴다 */
.xc-sig__draw {
  flex: 1; margin-top: 18px; display: flex; align-items: center; justify-content: center;
}
.xc-sig__draw svg { display: block; width: 100%; height: auto; max-width: 470px; }

@media (max-width: 1024px) {
  .xc-sig__two { grid-template-columns: 1fr; }
}

/* ── 등각 도면 (xVerse). hiVe 좌석배치도가 같은 좌표계를 쓴다 ──
   ⚠️ 면마다 밝기를 달리해야 입체로 보인다. 윗면 > 왼쪽면 > 오른쪽면 순.
      한 색으로 칠하면 육면체가 육각형으로 납작해진다. */
.xc-xv__floor path {
  fill: none; stroke: var(--xc-border); stroke-width: 1;
}
.xc-xv__floor path:first-child { fill: var(--xc-bg); stroke: var(--xc-border-strong); }
.xc-xv__eq path { fill: var(--xc-navy); stroke: none; }
.xc-xv__eq path.is-side { fill: #1c2534; }
.xc-xv__eq path.is-top  { fill: #384660; }
/* 말로 더한 설비 하나. 여기만 브랜드 그라디언트다 */
.xc-xv__eq--new path { fill: #F18757; }
.xc-xv__eq--new path.is-side { fill: #e0713f; }
.xc-xv__eq--new path.is-top  { fill: url(#xvGrad); }
/* 컨베이어. 설비보다 낮고 길다 */
.xc-xv__conv path { fill: var(--xc-navy); stroke: none; }
.xc-xv__conv path.is-side { fill: #1c2534; }
.xc-xv__conv path.is-top  { fill: #384660; }
/* 비워진 자리 */
.xc-xv__ghost path {
  fill: none; stroke: var(--xc-border-strong); stroke-width: 1.4; stroke-dasharray: 5 4;
}
.xc-xv__tag path { fill: none; stroke: var(--xc-border-strong); stroke-width: 1.4; stroke-dasharray: 4 3; }
.xc-xv__tag rect { fill: var(--xc-navy); }
.xc-xv__tag text {
  font-family: var(--xc-font-ko); font-size: 13px; font-weight: var(--xc-fw-bold);
  fill: var(--xc-white); text-anchor: middle;
}

/* ── 좌석배치도 (hiVe) · 층을 쌓고 돌려 보고 한 층을 연다 ──
   ⚠️ 회전은 CSS 3D 로 한다. 층 5장을 translateZ 로 띄우고 부모의 rotateZ
      하나만 돌리면 진짜로 돌아간다. 각도마다 좌표를 다시 계산할 필요가 없다.
   ⚠️ preserve-3d 는 이 프로젝트에서 마우스 판정을 깨뜨린 적이 있다
      (What AI Does 카드). 여기는 호버가 없어 안전하다 —
      나중에 이 판에 호버를 붙이면 그때 다시 터진다.
   ⚠️ 돌면 건물이 제 상자를 넘는다. 무대에서 잘라 낸다. */
.xc-hv__stage {
  position: relative; flex: 1;
  min-height: clamp(300px, 26vw, 380px);
  margin-top: 18px; overflow: clip;
}

/* 층 번호 */
.xc-hv__rail {
  position: absolute; left: 0; top: 50%; transform: translateY(-50%);
  z-index: 2; display: flex; flex-direction: column; gap: 8px;
}
.xc-hv__rail > li {
  width: 30px; height: 30px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--xc-bg); border: 1px solid var(--xc-border-weak);
  font-size: var(--xc-fs-12); font-weight: var(--xc-fw-extra); color: var(--xc-text-weak);
  transition: background .3s var(--xc-ease-out), color .3s var(--xc-ease-out);
}
.xc-hv__rail > li.is-on {
  background: var(--xc-orange); border-color: transparent; color: var(--xc-white);
}

/* 3D 건물 */
.xc-hv__scene {
  position: absolute; left: 50%; top: 52%; width: 0; height: 0;
  transform-style: preserve-3d;
  transform: rotateX(58deg) rotateZ(var(--hv-rot, -30deg)) scale(var(--hv-sc, 1));
  will-change: transform;
}
/* ⚠️ 층은 판이 아니라 「블럭」이어야 한다. 윗면만 쌓으면 종잇장이 겹친 것처럼
      보인다. 옆벽 넷을 세워 두께를 준다.
   ⚠️ 옆벽이 3D 로 서려면 슬래브 자신이 preserve-3d 여야 한다.
      안 그러면 벽이 납작하게 눌려 윗면 위에 겹쳐 보인다. */
/* 건물이 서 있는 바닥. 장면 안에 있으니 같이 돌아간다 —
   따로 그리면 회전할 때 건물만 돌고 바닥은 가만히 있어 떠 보인다.
   ⚠️ 1층 벽이 닿는 높이(z = -40)에 깐다. 0 에 두면 바닥이 1층 안에 박힌다. */
.xc-hv__ground {
  position: absolute; display: block;
  width: 470px; height: 470px; margin: -235px 0 0 -235px;
  transform: translateZ(-40px);
  border-radius: 50%;
  /* ⚠️ 번지는 그림자가 아니라 「깔린 원판」이다. 가장자리가 분명해야
        건물이 그 위에 서 있는 것으로 읽힌다.
     ⚠️ 정사각형으로 잡는다. 장면이 기울어져 있어 화면에서는 저절로
        타원으로 보인다. 여기서 미리 납작하게 만들면 회전할 때 찌그러진다. */
  background: rgba(35, 43, 58, .08);
}

.xc-hv__slab {
  position: absolute; width: 300px; height: 200px; margin: -100px 0 0 -150px;
  transform: translateZ(var(--z));
  transform-style: preserve-3d;
  /* ⚠️ 층 두께 = 층 간격(--z 40px). 같아야 블럭끼리 딱 붙어 하나의 건물이 된다.
        작게 주면 층 사이가 벌어져 종잇장을 띄워 놓은 것처럼 보인다. */
  --wall: 40px;
}
/* ⚠️ 옆면과 안쪽 선은 연하게 둔다. 겹쳐 보이는 선까지 진하면 층이 다섯 겹
      쌓였을 때 선이 뒤엉켜 건물 모양이 안 보인다.
      진한 선은 각 층 판의 바깥 테두리(rect) 하나뿐이다. */
.xc-hv__wall {
  position: absolute; display: block;
  /* ⚠️ 두 요구가 맞선다. 너무 연하면 홀로 내려앉는 층의 벽이 안 보이고,
        너무 진하면 다섯 겹 쌓였을 때 선이 뒤엉킨다.
        판 테두리(진한 네이비)보다는 확실히 연하되 벽 하나로도 읽히는 값이다. */
  /* ⚠️ 옆면은 「면」으로 채우고 「선」은 연하게 둔다. 선을 진하게 하면 다섯 겹
        쌓였을 때 뒤엉키고, 면이 없으면 천장만 뜬 것처럼 보인다.
        부피는 면이 만들고, 윤곽은 판 테두리가 만든다. */
  background: rgba(35, 43, 58, .16);
  border: 1px solid rgba(35, 43, 58, .42);
  box-sizing: border-box;
}
/* 네 벽이 윗면 테두리에 경첩을 걸고 「아래로」 내려간다.
   ⚠️ 부호를 뒤집으면 벽이 위로 선다(그렇게 만들었다가 되돌렸다).
      규칙 : 경첩에서 몸통이 뻗는 방향이 -Z 로 가야 아래다.
        rotateX(+90) 은 +Y 를 +Z 로 보낸다  → 위쪽 경첩은 -90
        rotateY(+90) 은 +X 를 -Z 로 보낸다  → 왼쪽 경첩은 +90 */
.xc-hv__wall--n { left: 0; top: 0; width: 100%; height: var(--wall);
  transform-origin: top; transform: rotateX(-90deg); }
.xc-hv__wall--s { left: 0; bottom: 0; width: 100%; height: var(--wall);
  transform-origin: bottom; transform: rotateX(90deg); }
.xc-hv__wall--w { left: 0; top: 0; width: var(--wall); height: 100%;
  transform-origin: left; transform: rotateY(90deg); }
.xc-hv__wall--e { right: 0; top: 0; width: var(--wall); height: 100%;
  transform-origin: right; transform: rotateY(-90deg); }
/* 고른 층의 벽만 브랜드 색이다 */
.xc-hv__slab.is-on .xc-hv__wall {
  background: rgba(252, 101, 0, .14); border-color: rgba(252, 101, 0, .55);
}
.xc-hv__slab svg { display: block; width: 100%; height: 100%; }
/* ⚠️ 천장 선만 진하면 맨 위층이 「벽 없는 천장」으로 보인다. 아래층들은 벽이
      겹쳐 쌓여 진해 보이지만 맨 위는 홀로라 그렇지 않다.
      천장과 벽의 진하기를 비슷하게 맞춰야 한 덩어리로 읽힌다. */
.xc-hv__slab rect, .xc-hv__slab path {
  fill: none; stroke: rgba(35, 43, 58, .62); stroke-width: 1.1;
  vector-effect: non-scaling-stroke;
}
.xc-hv__slab rect { fill: rgba(35, 43, 58, .04); }
/* 안쪽 칸막이는 겹쳐 보이는 선이라 연하게 */
.xc-hv__slab path { stroke: rgba(35, 43, 58, .26); }
/* 고른 층 하나. 여기만 브랜드 색이다 */
.xc-hv__slab.is-on rect { fill: rgba(252, 101, 0, .16); stroke: var(--xc-orange); stroke-width: 1.8; }
.xc-hv__slab.is-on path { stroke: var(--xc-orange); }
/* ⚠️ transition 을 걸지 않는다. GSAP 이 매 프레임 opacity 를 넣는데
      전환이 겹치면 값이 서로 밀려 층이 늦게 따라온다. 흐려짐도 GSAP 이 맡는다. */

/* 잡고 돌리는 커서 */
.xc-hv__cursor {
  position: absolute; left: 0; top: 0; z-index: 3;
  width: 26px; height: 30px; opacity: 0; pointer-events: none;
}
.xc-hv__cursor svg { display: block; width: 100%; height: 100%; }
/* 누르는 순간 손 모양이 바뀐다. 잡는 손 그대로면 「눌렀다」가 안 보인다 */
.xc-hv__cursor .xc-hv__click { display: none; }
.xc-hv__cursor.is-click .xc-hv__grab { display: none; }
.xc-hv__cursor.is-click .xc-hv__click { display: block; }
.xc-hv__cursor path {
  fill: var(--xc-white); stroke: var(--xc-navy-deep); stroke-width: 1.6;
  stroke-linecap: round; stroke-linejoin: round;
}
/* 누르는 순간 번지는 테. 자리를 안 차지해 커서가 안 밀린다 */
.xc-hv__ring {
  position: absolute; left: 3px; top: 8px; width: 20px; height: 20px;
  border-radius: 50%; border: 2px solid var(--xc-orange);
  opacity: 0; transform: scale(.4);
}

/* 열린 층의 좌석배치도. 확대해 두어 일부만 보인다 */
/* ⚠️ 여기에 opacity:0 을 두지 않는다. 스크립트가 막히면 좌석배치도가 영영
      안 보인다. 처음 상태는 JS 가 정한다. 커서는 순수 장식이라 예외다. */
.xc-hv__plan {
  position: absolute; inset: 0; z-index: 4;
  display: flex; align-items: center; justify-content: center;
}
/* ⚠️ 왼쪽 층 표시(.xc-hv__rail)가 이 위에 떠 있다. 폭을 다 쓰면 도면이
      숫자 밑으로 들어간다. 레일 폭만큼 비우고 그만큼 좁힌다. */
.xc-hv__plan { padding-left: 46px; }
.xc-hv__plan svg { display: block; width: 118%; height: auto; }
/* 구역 면. 벽보다 먼저 깔린다 */
.xc-hv__zone rect { fill: var(--xc-bg); }
.xc-hv__zone rect.is-hall { fill: #eef1f6; }
/* ⚠️ 벽은 굵은 단선이다. 실선 하나로는 다이어그램처럼 보인다.
      도면 느낌의 대부분이 이 두께에서 나온다. */
.xc-hv__wallline path {
  fill: none; stroke: var(--xc-navy); stroke-width: 7;
  stroke-linecap: square; stroke-linejoin: miter;
}
/* 문 열림 호. 얇게 그려야 벽과 구분된다 */
.xc-hv__door path {
  fill: none; stroke: var(--xc-navy); stroke-width: 1.6;
  stroke-linecap: round;
}
.xc-hv__rooms text {
  font-family: var(--xc-font-ko); font-size: 19px; font-weight: var(--xc-fw-semibold);
  fill: var(--xc-text-sub); text-anchor: middle;
}
.xc-hv__desks rect { fill: #dde3ec; stroke: var(--xc-border-strong); stroke-width: 1.2; }
/* 자리 주인. 얼굴 사진·실명 대신 실루엣과 부서 라벨이다 */
.xc-hv__who .xc-hv__who-b { fill: var(--xc-white); stroke: var(--xc-navy); stroke-width: 1.6; }
.xc-hv__who circle:not(.xc-hv__who-b), .xc-hv__who path { fill: var(--xc-navy); stroke: none; }
.xc-hv__who text {
  font-family: var(--xc-font-ko); font-size: 13px; font-weight: var(--xc-fw-bold);
  fill: var(--xc-text); text-anchor: middle;
}

@media (prefers-reduced-motion: reduce) {
  .xc-hv__cursor { display: none; }
}

/* ── 사내 자료 훑기 (mateX) ──
   xMeister 는 한 줄기로 원인을 거슬러 올라가고, mateX 는 소스·문서·프로젝트·
   조직도 네 갈래를 동시에 뒤진다. 그 차이를 그림으로 보인다.
   ⚠️ 막대에 「건수」 말고 다른 뜻을 붙이지 않는다. 도입 성과로 읽히면 안 된다
      (정량 성과는 실데이터 확보 전까지 노출 금지). 라벨은 「찾은 곳」이다. */
/* 네 갈래를 두 줄씩 두 열로. 세로로 늘어놓으면 막대가 길어져
   진행 막대처럼 보이고, 「동시에 훑는다」가 순서대로 훑는 것으로 읽힌다. */
.xc-mx__scan {
  flex: 1; margin-top: 18px;
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-auto-rows: 1fr; align-content: stretch; gap: 12px;
}
@media (max-width: 640px) {
  .xc-mx__scan { grid-template-columns: 1fr; }
}
.xc-mx__scan > li {
  display: flex; flex-direction: column; justify-content: center;
  padding: 13px 16px;
  background: var(--xc-bg);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius);
}
.xc-mx__scan-h {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
}
.xc-mx__scan-n {
  font-size: var(--xc-fs-sm); font-weight: var(--xc-fw-bold); color: var(--xc-text);
}
.xc-mx__scan-c {
  font-size: var(--xc-fs-12); color: var(--xc-text-weak);
}
.xc-mx__scan-c b { font-weight: var(--xc-fw-extra); color: var(--xc-orange); }
/* 찾은 곳을 점으로 센다. 하나씩 켜진다.
   ⚠️ 빈 점을 두지 않는다. 스무 개 중 일곱을 켜면 「모수 스무 곳」이라는,
      실제로 없는 정보가 생긴다. 점 개수 = 찾은 곳 수다.
   ⚠️ 그래서 줄마다 점 길이가 다르다. 그 길이 차이가 「어디에 많은가」를 말한다. */
.xc-mx__dots {
  display: flex; flex-wrap: wrap; gap: 5px; margin-top: 10px;
}
.xc-mx__dots i {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--xc-border);
  transition: background .25s var(--xc-ease-out);
}
.xc-mx__dots i.is-on { background: var(--xc-orange); }
@media (prefers-reduced-motion: reduce) {
  .xc-mx__dots i { transition: none; }
}

/* ── 영향 범위 그래프 (mateX) ──
   xMeister 지식그래프와 같은 결이지만 뜻이 다르다. 저기는 「원인을 거슬러 간다」,
   여기는 「지우면 어디까지 닿는가」다. 그래서 뿌리가 위에 있고 아래로 퍼진다. */
.xc-mx__ln { fill: none; stroke: var(--xc-border-strong); stroke-width: 1.6; stroke-dasharray: 5 4; }
.xc-mx__ln--hit { stroke: var(--xc-orange); stroke-dasharray: none; }
.xc-mx__nd rect { fill: var(--xc-bg); stroke: var(--xc-border); stroke-width: 1.2; }
.xc-mx__nd text {
  font-family: var(--xc-font-ko); font-size: 15px; font-weight: var(--xc-fw-bold);
  fill: var(--xc-text); text-anchor: middle;
}
.xc-mx__nd tspan { font-size: 13px; font-weight: var(--xc-fw-semibold); fill: var(--xc-text-weak); }
/* 지우려는 컬럼. 시작점이라 짙게 */
.xc-mx__nd--root rect { fill: var(--xc-navy); stroke: var(--xc-navy); }
.xc-mx__nd--root text { fill: var(--xc-white); }
.xc-mx__nd--root tspan { fill: rgba(255, 255, 255, .62); }
/* 먼저 멈추는 곳 하나. 여기만 브랜드 그라디언트다 */
.xc-mx__nd--hit rect { fill: url(#mxGrad); stroke: transparent; }
.xc-mx__nd--hit text { fill: var(--xc-navy-deep); }
.xc-mx__nd--hit tspan { fill: rgba(13, 17, 25, .65); }

/* ── byDP 한 사이클 · 단계가 이어져 있다는 표시 ── */
.xc-dp__cycle > li:not(:last-child) { position: relative; }
.xc-dp__cycle > li:not(:last-child)::after {
  content: ''; position: absolute; left: 32px;
  bottom: calc(-1 * clamp(10px, 1.2vw, 14px) - 1px);
  width: 1px; height: clamp(10px, 1.2vw, 14px);
  background: var(--xc-border-strong);
}
/* ══ xMESe 시그니처 : 한 바퀴 도는 원 ═══════════════════
   지시 → 생산 → 실적 → 품질 → 이력 다섯이 원을 이루고, 고리가 한 바퀴 그려진다.
   다 그려지면 되감겨 처음부터 다시 돈다 — 「몇 번이든 다시」가 이 제품의 성질이라
   글로 적지 않고 동작으로 보인다. 실제 현장(xMES)은 되감을 수 없다.

   ⚠️ 처음 상태는 JS 가 정한다. CSS 에 opacity:0 을 두면 스크립트가 막혔을 때
      내용이 영영 안 보인다.
   ⚠️ 단계 자리는 각도(--a)로 준다. 「돌려서 밀고 되돌리기」 —
      rotate(a) translateY(-r) rotate(-a) 라야 글자가 눕지 않는다.
   ⚠️ 판이 높아지면 안 된다. 무대(xcSigStage)는 한 화면에 들어갈 때만 걸린다. */
.xc-xe__loop {
  /* ⚠️ 단계는 고리보다 바깥에 앉힌다. 고리 위에 두면 두 줄짜리 설명이
     선을 가로질러 글자와 선이 겹친다 */
  --xe-gap: 44px;                          /* 고리와 단계 사이 */
  --xe-lab: clamp(96px, 10vw, 124px);      /* 단계 한 칸의 폭 */
  --xe-out: calc(var(--xe-r) + var(--xe-gap));

  /* 고리 반지름은 두 가지 한계 중 작은 쪽이다.
     ① 세로 — 무대(xcSigStage)는 한 화면에 들어갈 때만 걸린다. 넘치면 핀이 통째로 풀린다.
        530px = 고리가 아닌 부분(제목·캡션·여백 250) + GNB(120) + 안전분(16)
                + 고리 상자가 반지름 위에 더 쓰는 몫(48 + 바깥 여백 44×2).
        ⚠️ 8.6vw 로 두었을 때 1366×768 에서 무대가 8px 넘쳐 핀이 안 걸렸다.
     ② 가로 — 판 폭(100cqw)에서 좌우 안여백과 단계 한 칸을 빼고 남는 절반.
        ⚠️ 이게 없으면 390px 화면에서 좌우 단계 글자가 판 밖으로 나가 잘렸다.
           실제로 「이력 / 되짚기 가능」이 반쯤 잘려 있었다. */
  --xe-fit: calc((100cqw - 2 * clamp(24px, 2.6vw, 36px) - var(--xe-lab)) / 2 - var(--xe-gap));
  --xe-r: clamp(56px, min(calc((100vh - 530px) / 2), var(--xe-fit)), 196px);

  position: relative; flex: 1;
  margin-top: clamp(16px, 1.8vw, 24px);
  /* 48 = 위아래 끝 단계가 제 자리(--xe-out) 밖으로 반쯤 걸치는 몫 */
  min-height: calc(2 * var(--xe-out) + 48px);
}
.xc-xe__ring {
  position: absolute; left: 50%; top: 50%; translate: -50% -50%;
  width: calc(2 * var(--xe-r)); height: calc(2 * var(--xe-r));
  overflow: visible;
}
/* ⚠️ 이 규칙을 「.xc-xe__ring > circle」 로 두면 안 된다. 점(.xc-xe__dot)까지 걸려
   명시도(0,1,1)로 점의 설정(0,1,0)을 덮는다 — 실제로 그랬다.
   점이 안 채워지고(fill: none), 자리도 90° 돌아가 엉뚱한 데 찍혔다.
   고리 두 개만 골라 건다. */
.xc-xe__track, .xc-xe__draw {
  fill: none; stroke-width: 5; stroke-linecap: round;
  /* 12시에서 출발해 시계 방향으로 그려진다 */
  transform: rotate(-90deg); transform-origin: 50% 50%;
}
.xc-xe__track { stroke: var(--xc-border); }
.xc-xe__draw  { stroke: var(--xc-orange); }
/* 채워지는 끝을 따라 도는 점. 자리는 JS 가 각도로 찍는다.
   주황으로 채우고 테두리는 흰색 — 고리 위에 얹혀도 끝이 어디인지 또렷하다 */
.xc-xe__dot {
  fill: var(--xc-orange); stroke: var(--xc-bg); stroke-width: 3;
}
.xc-xe__steps { position: absolute; inset: 0; }
.xc-xe__steps > li {
  position: absolute; left: 50%; top: 50%;
  width: var(--xe-lab);
  translate: -50% -50%;
  transform: rotate(var(--a)) translateY(calc(-1 * var(--xe-out))) rotate(calc(-1 * var(--a)));
  text-align: center;
}
/* 단계 이름은 칩이다. 켜지면 옅은 주황 면으로 바뀐다 */
.xc-xe__steps > li > b {
  display: inline-block;
  padding: 2px 9px; border-radius: var(--xc-radius-full);
  background: var(--xc-chip-bg);
  font-size: var(--xc-fs-12); font-weight: var(--xc-fw-bold);
  letter-spacing: .04em; color: var(--xc-text-weak); line-height: 1.5;
  transition: background-color var(--xc-dur-fast) var(--xc-ease-out),
              color var(--xc-dur-fast) var(--xc-ease-out);
}
.xc-xe__steps > li > span {
  display: block; margin-top: 2px;
  font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-bold);
  color: inherit; line-height: 1.4; text-wrap: pretty;
}
.xc-xe__steps > li > span > i {
  font-style: normal; color: var(--xc-orange); font-variant-numeric: tabular-nums;
}
/* 고리가 지나간 단계 */
.xc-xe__steps > li[data-xe-on] > b {
  background: var(--xc-chip-accent-bg); color: var(--xc-orange);
}
/* 한가운데. 되감기는 이 글이 말한다 */
.xc-xe__core {
  position: absolute; left: 50%; top: 50%; translate: -50% -50%;
  width: calc(2 * var(--xe-r) - 34px); text-align: center;
  font-size: var(--xc-fs-12); color: var(--xc-text-weak); line-height: 1.5;
}
/* 뒤에 은은하게 번지는 주황 빛.
   ⚠️ 글자의 ::before 로 두지 않는다. 그러면 글자와 같은 opacity 를 타서
      빛과 글자가 한꺼번에 뜬다. 빛이 먼저 번지고 글자가 따라 떠야 하므로 따로 둔다.
   ⚠️ 글자보다 뒤에 둔다. 위에 두면 글자가 뿌옇게 덮인다 */
.xc-xe__glow {
  position: absolute; z-index: 0;
  left: 50%; top: 50%; translate: -50% -50%;
  width: calc(2 * var(--xe-r) - 8px); aspect-ratio: 1; border-radius: 50%;
  background: radial-gradient(circle, rgba(252, 101, 0, .22) 0%,
                                      rgba(252, 101, 0, .07) 45%, transparent 72%);
  pointer-events: none;
}
.xc-xe__core { z-index: 1; }
/* 도는 동안 한가운데. 지금 켜진 단계를 보여 준다 */
.xc-xe__now {
  position: absolute; z-index: 1;
  left: 50%; top: 50%; translate: -50% -50%;
  width: calc(2 * var(--xe-r) - 34px); text-align: center;
}
.xc-xe__now > b {
  display: block;
  font-size: var(--xc-fs-h4); font-weight: var(--xc-fw-extra);
  letter-spacing: var(--xc-ls-heading); color: var(--xc-text); line-height: 1.3;
}
.xc-xe__now > span {
  display: inline-block; margin-top: 6px;
  padding: 2px 9px; border-radius: var(--xc-radius-full);
  background: var(--xc-chip-accent-bg);
  font-size: var(--xc-fs-12); font-weight: var(--xc-fw-bold); color: var(--xc-orange);
  line-height: 1.5;
}

.xc-xe__core > b {
  display: block;
  font-size: var(--xc-fs-sm); font-weight: var(--xc-fw-extra); color: var(--xc-text);
}

/* ══ xMES 시그니처 ══════════════════════════════════════
   왼쪽은 라인 한 줄을 옆에서 본 단면, 오른쪽은 거기서 걸린 한 건을 되짚는 판.
   두 판이 같은 사건(A-12 불량)을 나눠 갖는다.

   ⚠️ 처음 상태는 JS 가 정한다. CSS 에 opacity:0 을 두면 스크립트가 막혔을 때
      내용이 영영 안 보인다. 마크업에는 값이 그대로 들어 있다.
   ⚠️ 판·카드 치수를 xMeister 시그니처와 같게 맞춘다. 두 페이지를 오가면
      같은 자리에 같은 크기의 판이 있어야 한 제품군으로 읽힌다.
   ⚠️ 판이 높아지면 안 된다. 무대(xcSigStage)는 한 화면에 들어갈 때만 걸린다 —
      넘치면 핀이 풀려 시그니처가 스크롤에 흘러가 버린다. */
.xc-mes__sig {
  margin-top: clamp(28px, 3.2vw, 44px);
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(16px, 1.8vw, 26px);
}
.xc-mes__live, .xc-mes__watch {
  padding: clamp(20px, 2.2vw, 30px);
  background: var(--xc-bg);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius-lg);
}
/* 왼쪽이 오른쪽보다 짧다. 남는 높이는 라인이 받는다.
   ⚠️ 다 주지 않는다(max 로 막는다). 전부 주면 빈 상자만 길쭉해져
      「설비가 크다」가 아니라 「채울 게 없다」로 보인다 */
.xc-mes__live { display: flex; flex-direction: column; }
.xc-mes__live .xc-mes__line { flex: 1; max-height: clamp(96px, 10vw, 140px); }
.xc-mes__live .xc-mes__eqs { height: 100%; }
.xc-mes__cap {
  display: flex; align-items: center; gap: 8px;
  font-size: var(--xc-fs-12); font-weight: var(--xc-fw-bold);
  letter-spacing: .06em; color: var(--xc-text-weak);
}
/* 조회가 도는 표시. 줄마다 달지 않고 판 제목 옆에 하나만 둔다 —
   조회는 하나고 채워지는 자리가 넷이다. 넷이 각각 돌면 따로 도는 일처럼 보인다.
   ⚠️ 기본 모습은 「끝난 상태」(체크)다. 스크립트가 막혀도 조회 중으로 굳지 않는다. */
.xc-mes__spin {
  position: relative; flex: none;
  width: 13px; height: 13px; border-radius: 50%;
  border: 2px solid var(--xc-border); border-top-color: var(--xc-orange);
}
.xc-mes__spin::after {
  content: ""; position: absolute; left: 50%; top: 45%;
  width: 3px; height: 6px; translate: -50% -50%; rotate: 45deg;
  border: 0 solid var(--xc-orange); border-right-width: 2px; border-bottom-width: 2px;
}
.xc-mes__spin.is-run { animation: xc-mes-spin .8s linear infinite; }
.xc-mes__spin.is-run::after { display: none; }
.xc-mes__spin.is-done { border-color: var(--xc-orange); animation: none; }
@keyframes xc-mes-spin { to { rotate: 360deg; } }
@media (prefers-reduced-motion: reduce) {
  .xc-mes__spin.is-run { animation: none; }
}
.xc-mes__wo, .xc-mes__lot {
  margin-top: 8px;
  display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px;
  font-size: var(--xc-fs-xs); color: var(--xc-text-sub); line-height: 1.6;
}
.xc-mes__wo b, .xc-mes__lot b {
  font-weight: var(--xc-fw-bold); color: var(--xc-text);
  font-variant-numeric: tabular-nums;
}
/* 지시 내용은 회색 칩으로. 사업분야 태그(.xc-biz__tags)와 같은 값이다 —
   같은 뜻(딸린 정보)에 같은 모양을 쓴다 */
.xc-mes__wo > span {
  padding: 3px 10px; border-radius: var(--xc-radius-full);
  background: var(--xc-chip-bg); color: var(--xc-text-sub);
  font-size: var(--xc-fs-12); line-height: 1.5;
}

/* ── 왼쪽 : 라인 단면 ──
   ⚠️ 3D 로 그리지 않는다. 공장을 복제한 3D 사본은 xVerse 의 자리고,
      3D 층을 쌓는 언어는 hiVe 가 쓴다. 여기는 관제 화면의 평면이다. */
/* 라인 위 알림 한 줄. ⚠️ 다섯 칸이라 가운데가 곧 A-12 자리다 —
   칸 수가 바뀌면 이 정렬도 다시 봐야 한다 */
.xc-mes__alarm {
  margin-top: clamp(14px, 1.6vw, 20px);
  display: flex; align-items: center; justify-content: center; gap: 7px;
  font-size: var(--xc-fs-12); font-weight: var(--xc-fw-bold); color: var(--xc-orange);
}
.xc-mes__line {
  --mes-n: 5;
  position: relative; margin-top: clamp(8px, 1vw, 12px);
}
/* 설비가 놓인 바닥선.
   ⚠️ 상자보다 위(z 1)에 둔다. 상자가 z auto 라 뒤에 두면 선이 가려지고
      상자 사이 틈에서만 보인다 — 실제로 그렇게 보였다. */
.xc-mes__rail, .xc-mes__run {
  position: absolute; z-index: 1; left: 0; bottom: 0; height: 2px;
}
.xc-mes__rail { right: 0; background: var(--xc-border); }
/* 지시가 지나간 자취. --run 을 JS 가 0 → 100% 로 민다 */
.xc-mes__run { width: var(--run, 100%); background: var(--xc-orange); }
.xc-mes__eqs {
  display: grid; grid-template-columns: repeat(var(--mes-n), minmax(0, 1fr));
  gap: clamp(6px, .8vw, 12px);
}
.xc-mes__eqs > li {
  position: relative;
  display: grid; place-items: center;
  min-height: clamp(52px, 5vw, 68px);
  background: var(--xc-bg-soft);
  border: 1px solid var(--xc-border-weak);
  border-radius: var(--xc-radius) var(--xc-radius) 0 0;
  border-bottom: 0;
  font-size: var(--xc-fs-12); color: var(--xc-text-sub);
}
.xc-mes__eqs > li b {
  font-weight: var(--xc-fw-bold); color: var(--xc-text);
  font-variant-numeric: tabular-nums;
}
/* 불량이 걸린 설비. ⚠️ 처음부터 켜 두지 않는다. 켜져 있으면
   「지나가다 걸렸다」가 아니라 「원래 불량이었다」로 읽힌다 */
.xc-mes__eqs > li[data-mes-hit] {
  background: var(--xc-chip-accent-bg);
  border-color: rgba(252, 101, 0, .45);
}
.xc-mes__eqs > li[data-mes-hit] b { color: var(--xc-orange); }
/* 걸린 설비의 경고 표시. 동그라미 안에 느낌표.
   ⚠️ 퍼지는 고리는 ::after 로 따로 그린다. 아이콘을 키우면 느낌표까지 커진다.
   ⚠️ 계속 뛴다. 한 번만 뛰면 재생을 놓친 사람에게는 그냥 주황 상자로 보인다 */
/* 동그라미 배경은 느낌표에만 준다. 옆 글자는 배경 없이 주황 글씨다 */
.xc-mes__warn {
  display: grid; place-items: center; flex: none;
  position: relative;
  width: 18px; height: 18px; border-radius: 50%;
  background: var(--xc-orange); color: var(--xc-white);
  font-style: normal; font-size: var(--xc-fs-12); font-weight: var(--xc-fw-extra);
  line-height: 1;
}
.xc-mes__warn::after {
  content: ""; position: absolute; inset: 0; border-radius: 50%;
  border: 2px solid var(--xc-orange);
  animation: xc-mes-ping 1.8s var(--xc-ease-out) infinite;
}
@keyframes xc-mes-ping {
  0%   { transform: scale(1);   opacity: .55; }
  70%  { transform: scale(2.1); opacity: 0; }
  100% { transform: scale(2.1); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .xc-mes__warn::after { animation: none; opacity: 0; }
}
/* 실적 세 값을 카드로. 이름표 아래 숫자가 크게 선다.
   ⚠️ 카드 폭을 1fr 셋으로 나눈다. 글자 길이에 맞춰 두면 「생산실적」 칸만 넓어져
      세 값이 나란히 안 읽힌다. */
.xc-mes__nums {
  margin-top: clamp(14px, 1.6vw, 20px);
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(8px, 1vw, 14px);
}
.xc-mes__nums > li {
  padding: clamp(10px, 1.1vw, 14px) clamp(12px, 1.3vw, 16px);
  background: var(--xc-bg-soft);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius);
}
.xc-mes__nums > li > span {
  display: flex; align-items: center; gap: 6px;
  font-size: var(--xc-fs-12); line-height: 1.5; color: var(--xc-text-weak);
}
/* 「진행 중」 — 알약을 빼고 점 하나만 앞에 둔다.
   ⚠️ 연두는 밝을수록 점이 안 보인다. #84cc16 은 흰 바탕에서 1.98:1 이라 사라진다.
      #4d9e2a 는 회색 바탕에서 3.19:1 로 비텍스트 기준을 넘긴다 — 색감은 연두, 대비는 확보 */
/* ⚠️ 점과 글자가 같은 색이므로 「글자 기준」을 넘겨야 한다.
   #4d9e2a 는 회색 바탕에서 3.19:1 로 점(비텍스트 3:1)은 되지만 글자(4.5:1)는 안 된다.
   #3b7a20 은 5.00:1 이다 — 색감은 연두 계열을 지키면서 글자로도 쓸 수 있다.
   ⚠️ 줄높이를 1 로 고정한다. 그래야 6px 점과 글자가 같은 세로 한가운데에 선다 —
      기본 줄높이(1.75)면 글상자가 커져 점이 위로 뜬 것처럼 보인다. */
.xc-mes__nums > li > span > i {
  position: relative;
  display: inline-flex; align-items: center; gap: 5px;
  font-style: normal; font-weight: var(--xc-fw-bold); line-height: 1;
  color: #3b7a20;
}
.xc-mes__nums > li > span > i::before {
  content: ""; flex: none; width: 6px; height: 6px; border-radius: 50%;
  background: #3b7a20;
}
/* 점에서 퍼져 나가는 연한 원. 경고 아이콘(.xc-mes__warn)과 같은 방식이다 —
   같은 뜻(지금 살아 있다)을 같은 언어로 말한다 */
.xc-mes__nums > li > span > i::after {
  content: ""; position: absolute; left: 0; top: 50%;
  width: 6px; height: 6px; margin-top: -3px; border-radius: 50%;
  background: #3b7a20;
  animation: xc-mes-ping 1.8s var(--xc-ease-out) infinite;
}
.xc-mes__nums > li > b {
  display: inline-block; margin-top: 4px;
  font-size: var(--xc-fs-h3); font-weight: var(--xc-fw-extra);
  color: var(--xc-text); font-variant-numeric: tabular-nums; line-height: 1.2;
}
/* 지시수량. 실적 옆에 붙어 「846 중 1,200」으로 읽힌다 */
.xc-mes__nums > li > em {
  margin-left: 4px;
  font-style: normal; font-size: var(--xc-fs-12); color: var(--xc-text-weak);
  font-variant-numeric: tabular-nums;
}
/* 불량 내역은 숫자 옆에 둔다 — 생산실적 카드의 「/ 1,200」과 같은 자리·같은 모양이다.
   ⚠️ 아래로 내리면 그 카드만 한 줄 높아지고, 격자가 가장 높은 카드에 맞춰 늘어나
      나머지 두 카드 밑에 빈 자리가 생긴다.
   ⚠️ 숫자와 붙이지 않는다. 간격을 벌려야 「15 표면 9」로 안 읽힌다 */
.xc-mes__nums > li:last-child > em { margin-left: 8px; }

/* ── 판이 좁을 때 (모바일) ──
   ⚠️ 390px 실측: 카드 셋이 92px 씩이라 「생산실적 ● 진행 중」이 12px 넘쳐
      「진행 / 중」으로 쪼개지고, 「846 /」과 「1,200」이 갈리고, 「· 치수 6」이
      가운뎃점부터 다음 줄로 넘어갔다.
   ① 낱말 묶음이 쪼개지지 않게 한다 — 모자라면 묶음째 다음 줄로 간다.
      넓은 판에서는 한 줄에 다 들어가므로 아무것도 바뀌지 않는다.
   ② 판 안쪽 폭이 400px 아래면 「생산실적」을 한 줄 전체로, 양품·불량을 그 아래 둘로 둔다.
      셋이 한 줄에 들어가려면 카드 하나가 125px 은 돼야 한다(실측 383px 에서 처음 들어감).
   ⚠️ 뷰포트가 아니라 판 폭으로 판단한다. 판 폭은 격자 칸이 정하므로
      inline-size 격리를 걸어도 내용 때문에 폭이 줄지 않는다.
      데스크톱(1025 이상)에서 이 판의 안쪽 폭은 430px 이상이라 여기 안 걸린다 —
      시그니처가 한 화면에 들어가야 핀이 걸리는 조건을 건드리지 않는다. */
.xc-mes__nums > li > span { flex-wrap: wrap; row-gap: 2px; }
.xc-mes__nums > li > span > i { white-space: nowrap; }
/* ⚠️ 내역(em)에는 nowrap 을 걸지 않는다. 영문 「surface 9 · dimensional 6」 은
   반 칸보다 길어 카드 밖으로 21~56px 삐져나갔다. 통째로 내려가되, 그래도 길면
   칸 안에서 두 줄을 고르게 나눈다(가운뎃점이 줄 머리에 오지 않게). */
.xc-mes__nums > li > em { display: inline-block; max-width: 100%; text-wrap: balance; }
.xc-mes__live { container: mes-live / inline-size; }
@container mes-live (max-width: 399px) {
  .xc-mes__nums { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .xc-mes__nums > li:first-child { grid-column: 1 / -1; }
}

/* ── 오른쪽 : 되짚기 ── */
.xc-mes__trace { margin-top: clamp(16px, 1.8vw, 22px); display: grid; gap: 8px; }
.xc-mes__trace > li {
  display: flex; align-items: baseline; gap: 10px;
  padding: 10px 14px;
  background: var(--xc-bg-soft);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius);
}
.xc-mes__trace > li > span {
  flex: none; min-width: 5.6em;
  font-size: var(--xc-fs-12); font-weight: var(--xc-fw-bold); color: var(--xc-text);
}
.xc-mes__trace > li > i {
  font-style: normal; font-size: var(--xc-fs-12);
  color: var(--xc-text-weak); line-height: 1.5; text-wrap: pretty;
}
/* 판정이 아직 안 나온 줄. 글자 자리에 불러오는 막대를 대신 둔다.
   ⚠️ 줄 자체를 숨기면 재생 앞부분에 오른쪽 판이 통째로 빈 상자로 보인다.
   ⚠️ 막대 폭을 글자 길이에 맞추지 않는다. 「설비 A-12」 줄만 길어져
      답이 뭔지 미리 알려 주는 꼴이 된다. 넷 다 같은 폭으로 둔다. */
.xc-mes__trace > li[data-mes-wait] > i { position: relative; visibility: hidden; }
.xc-mes__trace > li[data-mes-wait] > i::before {
  content: ""; visibility: visible;
  position: absolute; left: 0; top: 50%; translate: 0 -50%;
  width: 64px; height: 8px; border-radius: 4px;
  background: linear-gradient(90deg,
    var(--xc-gray-200) 0%, var(--xc-gray-100) 40%,
    var(--xc-gray-200) 60%, var(--xc-gray-200) 100%);
  background-size: 220% 100%;
  animation: xc-mes-skel 1.25s linear infinite;
}
@keyframes xc-mes-skel {
  from { background-position: 120% 0; }
  to   { background-position: -120% 0; }
}
@media (prefers-reduced-motion: reduce) {
  .xc-mes__trace > li[data-mes-wait] > i::before {
    animation: none; background: var(--xc-gray-200);
  }
}
/* 걸린 줄. 넷 다 물들이지 않는다 — 어디가 걸렸는지 안 보인다 */
.xc-mes__trace > li[data-mes-found] {
  background: var(--xc-chip-accent-bg);
  border-color: rgba(252, 101, 0, .45);
}
.xc-mes__trace > li[data-mes-found] > span,
.xc-mes__trace > li[data-mes-found] > i { color: var(--xc-orange); }

@media (max-width: 1024px) {
  .xc-mes__sig { grid-template-columns: 1fr; }
}

/* ── 세 카드가 한 구간을 통째로 차지하고 화면에 걸리는 변형 (xMES) ──
   처음에는 제목만 왼쪽 위. 스크롤하면 오른쪽 아래 아이콘과 제목 아래 설명이 나온다.
   ⚠️ is-cap-pin 은 JS 가 붙인다. 세로가 좁으면 안 붙어 그냥 흐른다 —
      화면보다 큰 판을 고정하면 아래가 잘려 못 읽는다.
   ⚠️ 설명·아이콘을 CSS 로 숨기지 않는다. 스크립트가 막히면 영영 안 보인다. */
.xc-xm__caproom--pin.is-cap-pin {
  min-height: 100dvh; padding-block: 0;
  display: flex; flex-direction: column; justify-content: center;
  padding-top: var(--gnb-top);
}
/* 카드가 높아진다. 제목이 위, 아이콘이 아래 구석이라 사이가 비어야 형태가 산다 */
.xc-xm__cap--tall > li {
  position: relative;
  min-height: clamp(280px, 30vw, 400px);
  display: flex; flex-direction: column;
}
.xc-xm__cap--tall h3 { max-width: 15ch; text-wrap: balance; }
/* 아이콘은 오른쪽 아래 구석. 설명과 겹치지 않게 설명 쪽에 아래 여백을 준다 */
.xc-xm__cap-ico {
  position: absolute;
  right: clamp(24px, 2.6vw, 36px); bottom: clamp(24px, 2.6vw, 36px);
  width: clamp(34px, 3vw, 44px); height: clamp(34px, 3vw, 44px);
  color: var(--xc-orange);
}
.xc-xm__cap-ico svg {
  display: block; width: 100%; height: 100%;
  fill: none; stroke: currentColor; stroke-width: 1.6;
  stroke-linecap: round; stroke-linejoin: round;
}
/* 기하 선화 방식. 선을 얇게 하고 끝을 각지게 해서 제도(製圖) 느낌을 낸다.
   ⚠️ 둥근 끝(round)을 그대로 두면 얇아질수록 점처럼 뭉친다. */
.xc-xm__cap-ico--fine svg {
  stroke-width: 1.05; stroke-linecap: butt; stroke-linejoin: miter;
}
.xc-xm__cap--tall p { padding-bottom: clamp(48px, 4.6vw, 64px); }
/* ⚠️ 물듦 구간이라 판이 --xc-navy-2 로 밝아진다. 거기서 포인트 오렌지는
      3.81:1 로 떨어진다. 아이콘은 선이라 비텍스트 기준 3:1 이면 되지만
      그래도 아슬아슬해 그라디언트 가운데 색으로 올린다. */
.xc-dark .xc-xm__cap-ico { color: var(--xc-grad-2); }

/* ③ 세 가지 설명이 한 구간을 차지하도록 위아래를 비우는 상자.
   ⚠️ padding 이다. margin 으로 주면 섹션 끝에서 상쇄돼 사라진다(전에 겪었다). */
.xc-xm__caproom { padding-block: clamp(104px, 13vw, 208px); }
/* 카드 판 안에 든 리드와 각주(xMES). 카드와 한 덩어리로 읽혀야 해서 판 안에 뒀다.
   ⚠️ data-reveal 을 붙이지 않는다. 핀 구간은 페이드인업 제외 대상이고,
      고정된 요소 안에서는 트리거 위치가 어긋나 영영 안 나타날 수 있다. */
.xc-xm__cap-lead { margin-top: 0; margin-bottom: clamp(20px, 2.4vw, 32px); }
.xc-xm__cap + .xc-sol__note { margin-top: clamp(16px, 1.8vw, 24px); }

/* ③ 세 가지 설명. 시그니처 그림 아래에 붙는 카드 셋.
   면·테두리·모서리를 위 대화판(.xc-xm__talk)과 똑같이 맞춘다 — 한 덩어리로 읽혀야 한다. */
.xc-xm__cap {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(16px, 2vw, 28px);
}
.xc-xm__cap > li {
  padding: clamp(24px, 2.6vw, 36px);
  background: var(--xc-bg-soft);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius-lg);
}
.xc-xm__cap h3 {
  font-size: var(--xc-fs-card-ttl-sm); font-weight: var(--xc-fw-extra);
  letter-spacing: var(--xc-ls-heading); color: var(--xc-text);
  text-wrap: balance;
}
.xc-xm__cap p {
  margin-top: 10px;
  font-size: var(--xc-fs-body); color: var(--xc-text-sub);
  line-height: 1.7; text-wrap: pretty;
}
/* 한 열로 접는 건 아래 @media (max-width: 1024px) 에 이미 있다. 여기 또 쓰지 않는다 */

/* ④ 검집의 근거 둘. 물듦 구간 안이라 역할색만 쓴다 — .xc-dark 가 통째로 뒤집는다 */
.xc-xm__trust {
  margin-top: clamp(24px, 3vw, 40px);
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(12px, 1.4vw, 20px);
}
/* ⚠️ 여기서 자르지 않는다. 카드가 화면 밖에서 날아와야 하는데 여기서 자르면
      섹션 가장자리에서 불쑥 나타난다(그렇게 만들었다가 되돌렸다).
      가로 넘침은 html·body 의 overflow-x:clip 이 막는다. */
.xc-xm__trust > li {
  padding: clamp(22px, 2.4vw, 32px);
  /* GNB 와 같은 서리유리. 값을 새로 적지 않고 토큰을 그대로 쓴다.
     ⚠️ 틴트가 거의 투명해서 글자색이 뒤 배경을 탄다. 이 구간은 어두운 배경 사진
        위이므로 글자를 흰색으로 둔다. 배경이 밝은 화면으로 옮기면 다시 봐야 한다. */
  background: var(--gnb-tint);
  -webkit-backdrop-filter: blur(var(--gnb-blur)) saturate(1.4);
          backdrop-filter: blur(var(--gnb-blur)) saturate(1.4);
  border: 1px solid rgba(255, 255, 255, .22); border-radius: var(--xc-radius-lg);
  color: #fff;
}
.xc-xm__trust h3, .xc-xm__trust p { color: inherit; }
.xc-xm__trust p { opacity: .88; }
.xc-xm__trust .xc-xm__tag {
  background: rgba(255, 255, 255, .16); color: #fff;
}
.xc-xm__trust h3 {
  font-size: var(--xc-fs-card-ttl-sm); font-weight: var(--xc-fw-extra);
  letter-spacing: var(--xc-ls-heading); color: var(--xc-text);
  /* 칩이 제목과 같은 줄에 붙는다. 좁아지면 아래로 접힌다.
     ⚠️ baseline 으로 맞춘다. center 로 두면 글자 크기가 달라 제목이 떠 보인다 */
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 8px;
}
/* 용어 칩. 본문에 괄호로 넣던 것을 제목 옆으로 뺐다.
   ⚠️ 제목보다 한 단계 낮춘다. 같은 무게로 두면 무엇이 제목인지 흐려진다 */
.xc-xm__tag {
  flex: none;
  /* ⚠️ 다른 규칙에서 주황 테두리를 물려받는다. 여기서 명시적으로 끈다.
        용어를 알려 주는 표지지 강조가 아니다. */
  border: 0;
  padding: 3px 10px; border-radius: var(--xc-radius-full);
  background: var(--xc-chip-bg); color: var(--xc-text-sub);
  font-size: var(--xc-fs-12); font-weight: var(--xc-fw-medium);
  letter-spacing: 0; line-height: 18px;
}
.xc-xm__trust p {
  margin-top: 10px;
  font-size: var(--xc-fs-body); color: var(--xc-text-sub); line-height: 1.7;
}

/* ⑤ 보유 건수. 성과 수치가 아니라 자격 건수다 */
.xc-xm__facts {
  margin-top: clamp(24px, 3vw, 40px);
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(12px, 1.4vw, 20px);
}
.xc-xm__facts > div {
  padding: clamp(22px, 2.4vw, 32px);
  background: var(--xc-bg-soft);
  border: 1px solid var(--xc-border-weak); border-radius: var(--xc-radius-lg);
}
.xc-xm__facts dt {
  font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-bold);
  letter-spacing: .06em; color: var(--xc-text-weak);
}
.xc-xm__facts dd {
  margin: 10px 0 0;
  display: flex; align-items: baseline; gap: 4px;
  font-size: var(--xc-fs-hist-on); font-weight: var(--xc-fw-extra);
  letter-spacing: var(--xc-ls-display); color: var(--xc-text);
  font-variant-numeric: tabular-nums;
}
.xc-xm__unit {
  font-size: .4em; font-weight: var(--xc-fw-bold); color: var(--xc-text-sub);
  letter-spacing: 0;
}

/* ⑥ CTA 아래 단서. 보안 구성은 협의 사항이라는 것을 여기서만 말한다 */
/* 라인업 카드 제목의 링크. 카드 어디를 눌러도 상세로 간다 (stretched link).
   일곱 장 모두 상세 페이지가 있어 일곱 장 다 <a> 다.

   ⚠️ 밑줄을 쓰지 않는다. 카드 전체가 클릭 영역인데 제목에만 선이 그어지면
      거기만 눌러야 하는 것으로 읽힌다. 갈 수 있다는 신호는 커서(VIEW 원)가 맡는다.
   ⚠️ ::after 가 카드를 덮으므로 li 에 position: relative 가 있어야 한다.
   ⚠️ 링크 자신의 초점 테두리는 끈다 — 글자만 감싸면 클릭 영역과 어긋난다.
      테두리는 li 가 그린다(위 .xc-xc__sol 구역). */
.xc-xc__sol-name a { color: inherit; text-decoration: none; }
.xc-xc__sol-name a::after { content: ""; position: absolute; inset: 0; }
.xc-xc__sol-name a:focus-visible { outline: none; }

.xc-xm__note {
  margin-top: clamp(18px, 2vw, 26px);
  font-size: var(--xc-fs-sm); color: var(--xc-text-sub);
  line-height: 1.7; text-wrap: pretty;
}

@media (max-width: 1024px) {
  .xc-xm__cap { grid-template-columns: 1fr; }
  .xc-xm__facts { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 640px) {
  .xc-xm__trust, .xc-xm__facts { grid-template-columns: 1fr; }
}

/* ══════════════════ 팝업 · 우측 하단 카드 ══════════════════
   관리자가 등록한 팝업을 오른쪽 아래 카드로 띄운다.
   가운데 덮개형은 들어오자마자 시야를 막고 닫아야 진행된다. 이쪽은 본문을 안 가린다.

   ⚠️ 퀵버튼(.xc-quick)이 같은 자리를 쓴다. 팝업이 떠 있는 동안 퀵버튼을 위로 밀어
      겹치지 않게 한다. 서로 모르는 채 두면 문의 버튼이 카드에 덮인다.
   ⚠️ 본문은 관리자가 에디터로 쓴 HTML 이 그대로 들어온다. main.css 맨 위 리셋이
      p 여백과 ul 불릿을 지워 놨으므로 이 스코프에서만 되살린다.
   ⚠️ 처음 상태를 CSS 로 감추지 않는다. 스크립트가 막히면 영영 안 보인다.
      JS 가 is-on 을 붙이기 전까지는 화면 밖에 두되 보이기는 하는 상태로 둔다. */
.xc-pop {
  position: fixed; z-index: calc(var(--xc-z-float) + 1);
  right: 40px; bottom: 70px;
  /* 폭 : 하한 360 · 상한 460 · 화면이 좁으면 화면에 맞춘다.
     ⚠️ clamp 만 쓰면 안 된다. 26vw 는 1366px 에서 355px 이라 지금(360)보다 작아진다.
        하한을 clamp 안에 두고, 화면에 맞추는 몫은 바깥 min 이 맡게 갈라 놓는다.
     ⚠️ 팝업 그림 원본은 800px 이 넘는다. 360px 은 그림 안 글씨가 뭉갠다.
        460 이면 읽을 만하면서 「구석의 조용한 카드」 성격은 그대로다. */
  width: min(clamp(360px, 26vw, 460px), calc(100vw - 32px));
  /* 검은 서리유리 + 흰 글자. 퀵버튼(.xc-quick)과 같은 재질이라 한 벌로 보인다.
     ⚠️ 팝업은 고정이라 스크롤하면 영상 위 → 흰 섹션 → 네이비를 차례로 지나간다.
        어두운 틴트면 뒤가 무엇이든 흰 글자가 6.5:1 이상이라 한 벌로 끝난다.
     ⚠️ .68 보다 옅게 하면 흰 섹션 위에서 4.5:1 을 못 넘는다. 여기가 하한이다. */
  background: rgba(17, 17, 17, .68);
  -webkit-backdrop-filter: blur(var(--gnb-blur)) saturate(1.4);
          backdrop-filter: blur(var(--gnb-blur)) saturate(1.4);
  border: 1px solid rgba(255, 255, 255, .22);
  color: #fff;
  transition: transform var(--xc-dur-reveal) var(--xc-ease-out);
  transition: transform var(--xc-dur-reveal) var(--xc-ease-out),
              background-color var(--xc-dur-fast) var(--xc-ease-standard);
  border-radius: var(--xc-radius-lg);
  box-shadow: 0 18px 48px rgba(22, 29, 41, .18);
  overflow: hidden;
  transform: translateY(calc(100% + 90px));
}
.xc-pop.is-on { transform: none; }
.xc-pop[hidden] { display: none; }

/* 팝업이 떠 있는 동안 퀵버튼을 위로 비킨다 */
body.has-pop .xc-quick { bottom: calc(70px + var(--pop-h, 320px) + 16px); }

.xc-pop__head {
  display: flex; align-items: center; gap: 10px;
  padding: 14px 16px 12px;
  border-bottom: 1px solid rgba(255, 255, 255, .18);
}
.xc-pop__ttl {
  flex: 1; min-width: 0;
  font-size: var(--xc-fs-sm); font-weight: var(--xc-fw-bold);
  color: inherit; line-height: 1.4;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.xc-pop__count {
  flex: none; font-size: var(--xc-fs-12); color: inherit; opacity: .8;
  font-variant-numeric: tabular-nums;
}
/* ⚠️ button 은 배경·서체를 제 것으로 갖는다. 지우지 않으면 회색 상자가 뜬다 */
.xc-pop__x {
  appearance: none; border: 0; background: none; font: inherit;
  flex: none; width: 28px; height: 28px; border-radius: 50%;
  display: grid; place-items: center; cursor: pointer;
  color: inherit;
}
.xc-pop__x:hover { background: rgba(127, 127, 127, .22); }
.xc-pop__x svg { width: 16px; height: 16px; }

/* ⚠️ 관리자가 쓴 HTML 이 들어오는 자리다. 색을 여기서 흰색으로 못 박으면
      에디터에서 색을 지정한 글자는 그대로 남는다. 지정 없는 글자만 흰색이 된다 */
/* 높이 : 내용이 길면 여기서 잘리고 안에서 굴린다.
   ⚠️ vh 만 쓰면 4K 에서 700px 짜리 스크롤 상자가 되고, 짧은 가로 화면에서는
      200px 도 안 남는다. 위아래를 다 묶는다.
   ⚠️ 아래 img 의 max-height 와 같은 값을 봐야 한다. 둘이 어긋나면 그림이 상자보다
      커져서 스크롤이 생긴다. 한쪽만 고치지 말 것.
   ⚠️ 팝업 그림은 세로로 긴 것이 많다(예: 891x1260). 그래서 가로형 기준으로 잡았던
      46vh/520px 로는 그림이 눌려 카드 좌우가 비었다. 60vh/640px 로 올렸다. */
.xc-pop__body { max-height: clamp(220px, 60vh, 640px); overflow-y: auto; overflow-x: hidden; padding: 16px; }
/* ⚠️ 팝업 안에 들어오게 맞추되 비율은 유지한다.
      max-width 만 주면 세로로 긴 그림이 상자를 넘어 스크롤해야 보인다.
      width/height 를 auto 로 두고 두 방향 모두 상한을 걸면 비율이 안 깨진다. */
.xc-pop__body img {
  max-width: 100%; max-height: calc(clamp(220px, 60vh, 640px) - 32px);
  width: auto; height: auto;
  display: block; margin-inline: auto;
}
.xc-pop__body p { margin: 0 0 .6em; line-height: 1.7; font-size: var(--xc-fs-sm); }
.xc-pop__body p:last-child { margin-bottom: 0; }
.xc-pop__body ul { list-style: disc; padding-left: 1.2em; margin: 0 0 .6em; }
.xc-pop__body ol { list-style: decimal; padding-left: 1.4em; margin: 0 0 .6em; }
.xc-pop__body a { color: var(--xc-orange); text-decoration: underline; }

.xc-pop__foot {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 16px 14px;
}
.xc-pop__nav { display: flex; gap: 4px; margin-right: auto; }
.xc-pop__nav button {
  appearance: none; border: 1px solid currentColor; background: none; font: inherit;
  width: 28px; height: 28px; border-radius: 50%;
  display: grid; place-items: center; cursor: pointer; color: inherit; opacity: .8;
}
.xc-pop__nav button:hover { opacity: 1; background: rgba(127, 127, 127, .18); }
.xc-pop__nav svg { width: 14px; height: 14px; }
.xc-pop__today {
  appearance: none; border: 0; background: none; font: inherit;
  font-size: var(--xc-fs-12); color: inherit; opacity: .85;
  text-decoration: underline; text-underline-offset: 3px; cursor: pointer;
}
.xc-pop__today:hover { opacity: 1; }

@media (max-width: 640px) {
  .xc-pop { right: 16px; left: 16px; bottom: 16px; width: auto; }
  /* ⚠️ 여기서 본문 높이를 40vh 로 따로 낮추던 줄이 있었다. 위쪽 img 의 상한은
        그대로 60vh 라 그림이 상자보다 커져 폰에서만 스크롤이 생겼다.
        상한은 한 곳(위 .xc-pop__body)에서만 정한다. 여기서 다시 잡지 않는다. */
}
@media (prefers-reduced-motion: reduce) {
  .xc-pop { transition: none; }
}

/* ══════════════════════════════════════════════════════════════════════
   조직도 (.xc-org) · 회사소개 > 일반현황
   ──────────────────────────────────────────────────────────────────────
   선 긋는 법 — SVG 를 쓰지 않는다. 마디마다 세 조각으로 나눠 CSS 로 긋는다.

        [상위 카드]
             |         내림선 : ul.xc-org__lv::before
        =====+=====    가로선 : li::before(왼쪽 반) + li::after(오른쪽 반)
        |         |    줄기   : i.xc-org__stem
      [카드]   [카드]

   ⚠️ 가로선을 li 폭의 50% 짜리 반쪽 둘로 만든다. 형제 li 가 서로 붙어 있어야
      앞 li 의 오른쪽 반과 뒤 li 의 왼쪽 반이 정확히 이어진다.
      그래서 li 에 margin 을 주면 안 된다 — 간격은 li 안쪽 padding 으로 준다.

   ⚠️ 모든 선은 transform(scaleX/scaleY)로 자란다. width/height 를 애니메이션하면
      매 프레임 레이아웃이 다시 계산된다.
   ══════════════════════════════════════════════════════════════════════ */

.xc-org {
  --org-gap:   28px;                    /* 단 사이 세로 간격 = 선 길이 */
  --org-pad:    6px;                    /* 형제 카드 사이 간격의 절반 */
  --org-line:  var(--xc-border);
  --org-w:      2px;                    /* 선 굵기 */
  --org-card:  132px;                   /* 대체값. 아래 @supports 가 못 도는 브라우저용 */
  /* 칸 하나 = 카드 + 좌우 여백. 폭을 '몇 칸' 으로 말할 수 있게 이름을 붙여 둔다.
     ⚠️ 262px 같은 숫자를 직접 적지 않는다. 그러면 카드 폭이 바뀔 때 따로 놀아
        2칸처럼 보이던 것이 2.03칸이 된다. 그 어긋남이 '대충 두 배' 로 읽히는 원인이다. */
  --org-col:   calc(var(--org-card) + var(--org-pad) * 2);
  --org-cell:  56px;                    /* 카드 한 장의 높이. 모든 카드가 같다 */
  position: relative;
  margin-top: clamp(28px, 3.4vw, 48px);
}

/* 카드 폭을 본문 폭에서 역산한다 — 트리가 좌우로 꽉 차게.
   단마다 폭을 똑같이 나누므로(아래 grid) 트리는 --org-cols 칸짜리 격자가 된다.
   칸 하나 = 카드 + 좌우 여백이므로 카드 = 본문폭/칸수 - 여백*2 가 된다.
   칸 수는 블레이드가 트리에서 계산해 style 로 넘긴다.

   ⚠️ 100cqw 를 쓴다. % 로 쓰면 카드의 부모(li) 기준으로 풀려서 전혀 다른 값이 된다.
      cqw 는 컨테이너(.xc-org)의 폭이라 화면이 어떤 폭이든 정확히 들어맞는다.
   ⚠️ 8px 은 .xc-org__scroll 의 좌우 안쪽 여백이다. 안 빼면 그만큼 넘친다.
   ⚠️ @supports 로 감싼다. 이 함수가 안 되는 브라우저에서 var 가 무효가 되면
      min-width 자체가 죽어 카드가 글자 크기로 쪼그라든다. 위 대체값이 그때 쓰인다. */
@supports (container-type: inline-size) {
  .xc-org {
    container-type: inline-size;
    --org-card: min(160px, calc((100cqw - 8px) / var(--org-cols, 9) - var(--org-pad) * 2));
  }
}

/* 상자보다 트리가 넓을 때만 오른쪽 끝을 흐린다. 더 있다는 것을 알린다.
   ⚠️ 늘 켜 두지 않는다. 딱 맞게 들어온 화면에서 공연히 흐려지면 잘린 것처럼 보인다.
   ⚠️ 한글은 어느 폭에서도 들어온다. 이 장치는 영문 1025~1300px 구간을 위한 것이다. */
.xc-org.is-over::after {
  content: ''; position: absolute; right: 0; top: 0; bottom: 10px; width: 56px;
  pointer-events: none;
  background: linear-gradient(90deg, rgba(255, 255, 255, 0), var(--xc-white));
}

/* 가로가 모자랄 때 페이지가 아니라 이 상자만 밀린다.
   ⚠️ overflow-x 만 적으면 overflow-y 가 auto 로 계산돼 세로로도 잘린다. 둘 다 적는다.
   ⚠️ 키보드로도 넘길 수 있어야 해서 tabindex=0 을 마크업에 달았다. 초점 표시가 필요하다. */
.xc-org__scroll {
  overflow-x: auto;
  overflow-y: hidden;
  padding: 4px 4px 10px;
  scrollbar-width: thin;
}
.xc-org__scroll:focus-visible { outline: 2px solid var(--xc-focus); outline-offset: 3px; }

/* ── 단 ─────────────────────────────────────────────── */
/* ⚠️ flex 가 아니라 균등 폭 grid 다. flex(내용 폭)로 두면 가지마다 폭이 달라져
      가지 사이 간격이 들쭉날쭉해진다 — 자식이 하나뿐인 '경영기획실' 가지가 다른 가지의
      절반이 되어, 본부 카드 줄의 한가운데가 트리 한가운데보다 38px 왼쪽으로 밀렸다.
      1fr 로 나누면 모든 가지가 같은 폭이 되어 간격이 일정해지고 좌우 대칭이 맞는다.
   ⚠️ 칸이 서로 붙어 있어야 가로선 반쪽 둘이 이어진다. grid 는 빈틈 없이 채우므로
      gap 을 주면 안 된다. 간격은 카드의 margin 으로 준다. */
.xc-org__lv {
  position: relative;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  align-items: start;
  list-style: none;
  margin: var(--org-gap) 0 0;
  padding: 0;
}
/* 뿌리 단은 위에서 내려올 것이 없다 */
.xc-org__lv--root { margin-top: 0; width: 100%; }

/* 상위 카드에서 가로선으로 내려오는 선 */
.xc-org__lv::before {
  content: '';
  position: absolute; left: 50%; top: calc(-1 * var(--org-gap));
  width: var(--org-w); height: var(--org-gap);
  margin-left: calc(-1 * var(--org-w) / 2);
  background: var(--org-line);
  transform: scaleY(0); transform-origin: 50% 0;
}
.xc-org__lv--root::before { display: none; }

/* ── 마디 ───────────────────────────────────────────── */
/* ⚠️ 형제 사이 간격을 li 의 좌우 padding 으로 주면 안 된다.
      마디 폭 = max(카드, 자식단 폭) + padding 이라, 자식이 있는 마디마다 12px 이
      한 겹씩 더 붙어 위로 갈수록 누적된다(실측: 계산 1368px → 실제 1468px).
      간격을 카드의 margin 으로 옮기면 마디 폭이 자식단 폭과 같아져 누적이 사라지고,
      트리 전체 폭이 정확히 (가장 넓은 단의 마디 수) x (카드 + 여백*2) 가 된다.
   ⚠️ 세로 padding 은 그대로 둔다. 그 자리가 줄기(.xc-org__stem)가 서는 곳이다. */
/* ⚠️ align-items 가 stretch 여야 한다. center 로 두면 카드도 자식 단도 '내용 폭' 으로
      쪼그라들어 제 칸을 안 채운다. 그러면 자식이 하나뿐인 가지(경영기획실 아래)의
      칸이 274px 인데 카드는 125px 로 남아 그 가지만 휑하게 빈다.
      stretch 면 카드 폭 = 칸 폭 - 카드 margin 이 되어 어느 단이든 저절로 들어맞는다. */
.xc-org__node {
  position: relative;
  padding: var(--org-gap) 0 0;
  display: flex; flex-direction: column; align-items: stretch;
}
/* 뿌리만 예외 — 늘리면 대표이사 카드가 본문 폭 전체가 된다 */
.xc-org__lv--root > .xc-org__node { align-items: center; }
/* 가로선 왼쪽 반 · 오른쪽 반 */
.xc-org__node::before,
.xc-org__node::after {
  content: '';
  position: absolute; top: 0;
  width: 50%; height: var(--org-w);
  background: var(--org-line);
  transform: scaleX(0);
}
.xc-org__node::before { right: 50%; transform-origin: 100% 50%; }
.xc-org__node::after  { left:  50%; transform-origin:   0 50%; }
/* 양 끝은 바깥쪽으로 뻗을 곳이 없다. 외동은 가로선 자체가 필요 없다 */
.xc-org__node:first-child::before,
.xc-org__node:last-child::after,
.xc-org__node:only-child::before,
.xc-org__node:only-child::after { display: none; }

/* 가로선에서 카드로 내려오는 줄기 */
.xc-org__stem {
  position: absolute; left: 50%; top: 0;
  width: var(--org-w); height: var(--org-gap);
  margin-left: calc(-1 * var(--org-w) / 2);
  background: var(--org-line);
  transform: scaleY(0); transform-origin: 50% 0;
}

/* ── 카드 ───────────────────────────────────────────── */
.xc-org__card {
  position: relative;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
  min-width: var(--org-card);
  min-height: var(--org-cell);
  margin-inline: var(--org-pad);
  padding: 15px 14px;
  border: 1px solid var(--xc-border);
  /* ⚠️ 6px 은 도구 기본값이라 어디서나 본 모서리가 된다. 3px 이면 '그려진 칸' 으로 읽히고
        모서리가 날카롭지도 않다. 대표이사 카드가 배지처럼 떠 보이던 원인이기도 하다. */
  border-radius: 3px;
  background: var(--xc-white);
}

/* 폭이 곧 단이다 — 대표이사·본부는 2칸, 팀 이하는 1칸.
   ⚠️ 이 규칙이 없으면 '경영지원팀' 처럼 형제가 없는 팀이 부모의 2칸을 그대로 채워
      본부와 같은 크기가 된다. 그러면 폭이 계급을 뜻하지 않게 되고, 262 대 125 가
      '큰 카드 대 작은 카드' 로 보인다. 1칸으로 묶어야 '2칸 대 1칸' 으로 읽힌다.
   ⚠️ 가운데 세우기는 align-self 로 한다. margin-inline: auto 를 쓰면 안 된다 —
      auto 여백은 격자가 칸 폭을 잴 때 0 으로 계산돼 칸이 274px 에서 250px 로 줄고
      트리 전체가 본문 폭보다 120px 좁아진다(실측 채움 98.5% → 89.8%). */
.xc-org__node:not(.xc-org__node--lv1) > .xc-org__card {
  max-width: var(--org-card);
  align-self: center;
}
/* 다만 형제가 없는 마디는 제 칸을 채운다.
   ⚠️ 위 규칙만 두면 '경영지원팀' 이 부모(경영기획실 2칸)의 한가운데에 1칸으로만 서서
      그 가지만 좌우가 휑하게 빈다.
   ⚠️ 형제가 있는 마디에는 안 걸린다. 그쪽은 둘이서 이미 칸을 나눠 채우고 있다.
   ⚠️ 'AI팀' 과 파트 카드도 외동이지만 부모가 1칸이라 폭이 그대로다. 실제로 넓어지는 것은
      부모가 2칸인 경영지원팀 하나뿐이다. */
.xc-org__lv:not(.xc-org__lv--root) > .xc-org__node:only-child > .xc-org__card {
  max-width: none;
  align-self: stretch;
}
.xc-org__name {
  font-size: 15px; font-weight: 600; line-height: 1.35;
  color: var(--xc-text);
  text-align: center;
  white-space: nowrap;
}

/* 대표이사 — 격자 위에 세운다.
   ⚠️ 184px 이라는 임의의 폭에 24px 안쪽 여백, 둥근 모서리, 그림자까지 겹치면
      조직도의 한 칸이 아니라 버튼 하나가 떠 있는 것처럼 보인다. 그게 가장 흔한
      '어디서나 본 UI' 의 표시다. 본부와 같은 2칸으로 맞추고, 위계는 색과 굵기로만 준다.
   ⚠️ 폭을 칸으로 적는다. 2칸 = 칸폭 x 2 에서 좌우 여백을 뺀 값이다. */
.xc-org__lv--root > .xc-org__node > .xc-org__card {
  background: var(--xc-navy);
  border-color: var(--xc-navy);
  width: calc(var(--org-col) * 2 - var(--org-pad) * 2);
  max-width: none;
  align-self: center;
}
.xc-org__lv--root > .xc-org__node > .xc-org__card .xc-org__name { font-size: 16px; font-weight: 700; }
.xc-org__lv--root > .xc-org__node > .xc-org__card .xc-org__name { color: var(--xc-white); }

/* 본부 단 — 한 단계 굵게, 그리고 제 칸을 꽉 채운다.
   ⚠️ 본부는 5개인데 칸은 10개다(가장 많은 본부가 팀을 둘 가진다). 그래서 본부 카드가
      팀 카드 크기 그대로면 칸의 절반만 차고 좌우에 빈자리가 크게 남는다.
      칸을 채우게 하면 본문 폭에 딱 맞고, 본부 > 팀 위계도 눈에 보인다.
   ⚠️ 팀 단에는 걸지 않는다. 팀은 이미 제 칸을 거의 채우고 있고, 여기까지 늘리면
      자식이 하나뿐인 가지(경영기획실 아래)만 카드가 두 배로 커져 들쭉날쭉해진다. */
/* 본부 — 팀과 같은 부품이고 칸 수만 다르다.
   ⚠️ 안쪽 여백과 글자 크기를 팀과 다르게 두면 '다른 부품' 으로 보여, 폭 차이가
      모듈이 아니라 우연으로 읽힌다. 위계는 바탕색과 글자 굵기로만 준다. */
.xc-org__node--lv1 > .xc-org__card { background: var(--xc-gray-50); }

/* 약어 풀이 (SFI·BA·VE·VD)
   ⚠️ 이 줄이 붙는 단(사업부·팀)의 카드 높이를 통째로 올린다. 넷만 키우면
      한 줄 안에서 높이가 섞여 폭이 모듈로 안 읽힌다. 자리를 비워 두더라도 맞춘다.
   ⚠️ 'Smart Factory Intelligence' 는 카드 폭(125px)에서 두 줄이 된다. 그 두 줄까지
      들어가는 높이로 잡았다. */
/* 이름 + 영문 표기 (사업부·팀 줄, 한글 화면)
   ⚠️ 격자로 짠다. flex 로 두면 영문이 한 줄인 카드와 두 줄인 카드에서 카드 높이가
      달라져 줄 전체가 어긋난다. 영문 칸을 두 줄 높이로 고정하면 어느 카드든
      전체 높이가 같아지고, 이름은 늘 같은 자리에 온다.
   ⚠️ 한글 화면에만 건다. 영문 화면은 이 값이 이미 카드 이름이다. */
html[lang="ko"] .xc-org__node--lv2 > .xc-org__card {
  --org-sub: 24px;                      /* 영문 표기 두 줄 높이 */
  display: grid;
  /* ⚠️ 열을 명시한다. 안 적으면 열 폭이 '가장 넓은 글줄' 을 따라가서, 선 길이를 %로 줬을 때
        카드마다 기준이 달라진다(실측 17~42px 로 제각각이었다). 1fr 이면 카드 안쪽 폭이 기준이 된다. */
  grid-template-columns: minmax(0, 1fr);
  /* 이름 · 가르는 선 · 영문 표기 */
  grid-template-rows: auto 1px var(--org-sub);
  align-content: center; justify-items: center;
  gap: 5px;
  min-height: 84px;
}
.xc-org__abbr {
  align-self: start;                    /* 한 줄짜리는 선 쪽으로 붙어 올라온다 */
  font-size: 9px; line-height: 1.28; letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--xc-gray-400);
  text-align: center;
}
/* ⚠️ 줄을 블록으로 세운다. 끊는 자리는 블레이드가 정하므로 여기서 또 접히면 안 된다.
      낱말 안에서 잘리는 것만 막고(nowrap), 그래도 넘치면 줄바꿈보다 축소가 낫다. */
.xc-org__abbr > span { display: block; white-space: nowrap; }

/* 이름과 영문 표기를 가르는 선. 카드 안쪽 폭을 꽉 채운다(테두리 안쪽 여백까지만).
   ⚠️ 100% 는 카드가 아니라 '격자 열' 기준이다. 그래서 위에 열을 minmax(0,1fr) 로
      명시해 뒀다. 열 지정이 없으면 열이 가장 넓은 글줄을 따라가서 카드마다 길이가
      달라진다(실측 17~42px 로 제각각이었다). */
.xc-org__rule {
  width: 100%; height: 1px;
  background: var(--xc-border);
}
/* 강조 카드는 바탕과 같은 계열로 */
.xc-org__node.is-hi .xc-org__rule { background: rgba(190, 106, 60, .45); }
/* 강조 카드의 머리말은 카드 바탕과 같은 계열로 */
.xc-org__node.is-hi .xc-org__abbr { color: rgba(190, 106, 60, .85); }

/* 칸이 좁아지면 머리말이 세 줄로 넘친다. 글자와 자간을 함께 줄여 두 줄에 잡아 둔다 */
@media (max-width: 1400px) {
  .xc-org__abbr { font-size: 8px; letter-spacing: .07em; }
}
/* 🔴 1025~1120 : 카드가 가장 좁아지는 구간이다(1100 에서 안폭 163px).
   8px 로도 7~13px 이 넘쳐 글자가 카드 밖으로 흘러나오고 있었다(실측 2026-09-01).
   더 줄이는 대신 **이 구간에서만** 줄을 접는다 — 세 줄이 되어도 min-height 84px 안에 든다. */
@media (max-width: 1120px) and (min-width: 1025px) {
  .xc-org__abbr { letter-spacing: .02em; }
  .xc-org__abbr > span { white-space: normal; }
}
/* 🔴 1024 아래는 조직도가 세로로 풀려 카드가 넓어진다 — 1024 에서 안폭 859px,
   360 에서도 226px 다. 여기까지 8px 을 끌고 갈 이유가 없었다. 읽으라고 두는 크기가 아니다.
   12px 로 올려도 어느 폭에서도 안 넘친다(실측 1024·768·430·360 전부 여유). */
@media (max-width: 1024px) {
  .xc-org__abbr { font-size: 12px; letter-spacing: .06em; }
}
.xc-org__node--lv1 > .xc-org__card .xc-org__name { font-weight: 700; }


/* ── 강조 (AI 조직) ─────────────────────────────────────
   카드 바탕을 옅은 앰버로 칠한다.
   ⚠️ 그라디언트 테두리를 쓰지 않는다. 작은 카드에 세 색이 흐르는 테두리는 값싸 보이고,
      2px 테두리라 색이 띠처럼 끊겨 보인다. 면으로 칠하는 편이 조용하면서 더 눈에 든다.
   ⚠️ 바탕색은 브랜드 골드(#FBE38A)와 오렌지(#F9A85C)를 섞어 흰 바탕에 28% 로 얹은 값이다.
      임의로 고른 노랑이 아니라 토큰에서 끌어낸 값이라 다른 화면과 톤이 맞는다.
   ⚠️ 글자는 네이비 그대로 둔다. 이 바탕 위 대비가 15:1 이 넘어 안전하다. */
.xc-org__node.is-hi > .xc-org__card {
  background: #FEEFD8;
  border-color: rgba(241, 135, 87, .38);
}
.xc-org__node.is-hi > .xc-org__card .xc-org__name { font-weight: 700; }
/* ⚠️ 연결선에는 색을 주지 않는다. 선은 어느 마디가 어디에 붙는지만 알리는 뼈대라
      색이 붙으면 그림이 어수선해진다. 강조는 카드 바탕 하나로만 한다. */

/* 진입이 끝난 뒤 한 번 스치는 빛. 눈이 여기부터 읽게 만든다.
   ⚠️ 무한 반복하지 않는다. 계속 움직이는 것이 화면에 있으면 읽기를 방해한다. */
.xc-org__node.is-hi > .xc-org__card::after {
  content: '';
  position: absolute; inset: 0;
  border-radius: inherit;
  background: linear-gradient(100deg, transparent 32%, rgba(255, 255, 255, .55) 50%, transparent 68%);
  opacity: 0; pointer-events: none;
}
.xc-org.is-in .xc-org__node.is-hi > .xc-org__card::after {
  animation: xc-org-sweep 1s var(--xc-ease-standard) 1.15s 1;
}
@keyframes xc-org-sweep {
  0%   { opacity: 0; transform: translateX(-60%); }
  35%  { opacity: 1; }
  100% { opacity: 0; transform: translateX(60%); }
}

/* ── 파트 카드 ──────────────────────────────────────── */
.xc-org__card--parts { padding: 11px 12px; }
.xc-org__parts { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; }
.xc-org__parts li {
  font-size: 13.5px; line-height: 1.45; color: var(--xc-gray-600);
  text-align: center;
  white-space: nowrap;
}
/* ⚠️ 점 색을 기본으로 오렌지로 두지 않는다. 강조색을 평범한 팀에까지 쓰면
      정작 AI 조직 강조가 묻힌다. 강조 가지 안에서만 오렌지로 바꾼다. */
.xc-org__parts li::before {
  /* 절대배치로 왼쪽에 붙이지 않는다. 가운데 정렬에서는 글줄 길이가 제각각이라
     점만 왼쪽 끝에 남아 줄이 어긋나 보인다. 글자 앞에 붙여 같이 가운데로 오게 한다. */
  content: ''; display: inline-block; vertical-align: .18em;
  width: 4px; height: 4px; margin-right: 6px; border-radius: 50%;
  background: var(--xc-gray-400);
}
.xc-org__node.is-hi > .xc-org__lv .xc-org__parts li::before { background: var(--xc-grad-2); }

/* ⚠️ 마우스를 올렸을 때의 효과는 두지 않는다. 조직도는 읽는 그림이지 고르는 목록이 아니다.
      카드마다 반응하면 눈이 계속 끌려다닌다. */

/* ── 등장 ───────────────────────────────────────────────
   선이 자란 뒤 카드가 떠오른다. 단이 깊을수록 늦게 온다.
   ⚠️ 시간은 --xc-dur-reveal 하나를 나눠 쓴다. 값을 직접 적지 않는다.
      모션 최소화에서 그 토큰이 .01ms 로 바뀌면 여기도 같이 즉시가 된다. */
.xc-org__card { opacity: 0; transform: translateY(14px); }
.xc-org__lv::before,
.xc-org__stem,
.xc-org__node::before,
.xc-org__node::after {
  transition: transform calc(var(--xc-dur-reveal) * .45) var(--xc-ease-out);
  transition-delay: calc(var(--lv, 0) * 130ms);
}
.xc-org__card {
  transition: opacity   var(--xc-dur-reveal) var(--xc-ease-out),
              transform var(--xc-dur-reveal) var(--xc-ease-out);
  transition-delay: calc(var(--lv, 0) * 130ms + 120ms);
}
.xc-org.is-in .xc-org__lv::before,
.xc-org.is-in .xc-org__stem { transform: scaleY(1); }
.xc-org.is-in .xc-org__node::before,
.xc-org.is-in .xc-org__node::after { transform: scaleX(1); }
.xc-org.is-in .xc-org__card { opacity: 1; transform: none; }

/* 스크립트가 아예 죽어도 초점이 닿으면 드러난다. 마지막 안전장치다 */
.xc-org__scroll:focus-within .xc-org__card { opacity: 1; transform: none; }

/* ── 영문 ───────────────────────────────────────────────
   영문 부서명이 길다. 한 줄로 두면 카드가 넓어져 트리가 본문 폭(1380px)을 넘는다
   (실측 1518px — 'Smart Factory Intelligence' 한 장이 150px 을 먹는다).
   ⚠️ 영문에서만 두 줄까지 접는다. 한글은 그대로 한 줄이다 — 한글에 wrap 을 풀면
      '기술지원본부' 같은 이름이 애매하게 쪼개진다.
   ⚠️ 높이를 맞춰 둔다. 안 맞추면 같은 단의 카드 높이가 제각각이 되어
      그 아래 단이 삐뚤빼뚤 시작한다. */
/* ⚠️ 폭 제한은 위의 공통 규칙(팀 이하 1칸)이 이미 맡는다. 여기서 또 걸면
      본부 카드까지 1칸으로 묶여 영문만 좌우가 뜬다(전에 채움 88.6% 대 98.5% 로 어긋났다). */
html[lang="en"] .xc-org { --org-cell: 60px; }
html[lang="en"] .xc-org__name { white-space: normal; font-size: 14px; line-height: 1.25; }
html[lang="en"] .xc-org__parts li { white-space: normal; }
/* 칸이 좁아지면 이름이 세 줄로 접히는 것이 생긴다. 그때 셀 높이를 올려
   한 단 안의 카드 높이를 같게 유지한다. 높이가 섞이면 폭이 모듈로 안 읽힌다.
   ⚠️ 넓은 화면까지 74px 로 두지 않는다. 두 줄이면 되는 자리가 휑해진다. */
@media (max-width: 1400px) {
  html[lang="en"] .xc-org { --org-cell: 76px; }   /* 세 줄 + 안쪽 여백. 74 면 1px 넘치는 카드가 생긴다 */
}

/* ── 좁은 화면 : 세로 트리 ──────────────────────────────
   가로 트리는 폭이 모자라 가로 스크롤에 기대게 된다. 세로로 접어 읽게 한다.
   선을 왼쪽으로 옮긴다 — 세로 기둥 하나 + 마디마다 오른쪽으로 나가는 짧은 가지. */
@media (max-width: 1024px) {
  .xc-org { --org-gap: 16px; }
  .xc-org__scroll { overflow-x: hidden; }

  .xc-org__lv { display: block; width: auto; margin: 0 0 0 22px; }
  .xc-org__lv--root { width: auto; min-width: 0; margin-left: 0; }

  /* 세로 기둥은 상위 카드 아래에서 마지막 자식까지 내려온다 */
  .xc-org__lv::before {
    top: 0; bottom: 0; left: 0; height: auto;
    margin-left: 0;
    transform-origin: 50% 0;
  }
  .xc-org__lv--root::before { display: none; }

  .xc-org__node { display: block; padding: 8px 0 0; }
  /* 가로선 반쪽 둘 대신, 기둥에서 카드로 나가는 가지 하나만 쓴다 */
  .xc-org__node::before { display: none; }
  .xc-org__node::after {
    display: block;
    left: 0; top: 26px; right: auto;
    width: 22px; height: var(--org-w);
    transform-origin: 0 50%;
  }
  .xc-org__lv--root > .xc-org__node::after { display: none; }
  .xc-org__stem { display: none; }

  /* 세로에서는 칸이 없다. 폭 제한과 칸 지정을 전부 푼다.
     ⚠️ 안 풀면 카드가 1칸(125px)에 갇히거나, 2칸 지정에 margin-left 22px 가 더해져 넘친다. */
  .xc-org__card,
  .xc-org__node:not(.xc-org__node--lv1) > .xc-org__card,
  .xc-org__lv:not(.xc-org__lv--root) > .xc-org__node:only-child > .xc-org__card,
  .xc-org__lv--root > .xc-org__node > .xc-org__card {
    min-width: 0; max-width: none; width: auto;
    margin: 0 0 0 22px;
  }
  .xc-org__lv--root > .xc-org__node > .xc-org__card { margin: 0; }
  /* 세로에서는 카드 높이도 내용에 맡긴다. 머리말 칸 고정도 푼다 */
  html[lang="en"] .xc-org__card { min-height: 0; }
  html[lang="ko"] .xc-org__node--lv2 > .xc-org__card { grid-template-rows: auto auto auto; min-height: 0; }
  .xc-org__name { white-space: normal; }
  .xc-org__parts li { white-space: normal; }
}

@media (max-width: 560px) {
  .xc-org__card { padding: 9px 10px; }
  .xc-org__name { font-size: 13px; }
}

/* 모션 최소화 — 선도 카드도 처음부터 제자리에 둔다.
   ⚠️ .is-in 이 붙지 않아도 보여야 한다. 스크립트가 늦거나 막힐 수 있다. */
@media (prefers-reduced-motion: reduce) {
  .xc-org__lv::before, .xc-org__stem { transform: scaleY(1); }
  .xc-org__node::before, .xc-org__node::after { transform: scaleX(1); }
  .xc-org__card { opacity: 1; transform: none; }
  .xc-org.is-in .xc-org__node.is-hi > .xc-org__card::after { animation: none; }
}

/* ══════════════════════════════════════════════════════════════════════
   스크롤이 여는 영상 (.xc-scrub) · 메인 히어로 아래
   ──────────────────────────────────────────────────────────────────────
   가운데 작은 네모로 시작해 스크롤과 함께 화면을 덮고, 다 덮은 뒤부터 영상이 진행한다.
   여는 동안에는 영상이 첫 프레임에 멈춰 있다 — 작은 창으로 보여 주고 마는 장면이 없다.

   ⚠️ 확대는 clip-path 로 한다. width/height 를 애니메이션하면 매 프레임 레이아웃이
      다시 계산되고, transform: scale 로 키우면 영상이 늘어나 뭉개진다.
      영상은 처음부터 화면 크기로 두고 '보이는 창' 만 넓힌다.
      히어로의 액자 마스크(.xc-hero.is-framed)와 같은 방식이다.
   ⚠️ inset() 안의 100% 는 이 상자(테두리 상자) 기준이다. --p 가 0 이면 가운데 작은
      네모만 남고, 1 이면 잘라내는 폭이 0 이 되어 화면을 꽉 채운다.
   ⚠️ 바깥은 페이지 바탕색이다. 작은 네모일 때 뒤가 비치면 안 되므로 __pin 에 바탕을 깐다.
   ══════════════════════════════════════════════════════════════════════ */

.xc-scrub {
  position: relative;
  /* 스크롤 길이를 두 도막으로 나눠 둔다. 합이 섹션 높이다.
       --open  액자가 작은 네모에서 화면 가득차로 열리는 동안. 영상은 첫 프레임에 멈춰 있다.
       --play  다 열린 뒤 영상이 도는 동안. 재생 속도와 자막 체류를 정하는 것은 이쪽뿐이다.
     ⚠️ JS 가 이 두 값을 읽어 '어디서 영상이 시작하는지'를 계산한다(EXPAND = open / (open+play)).
        비율을 양쪽에 따로 적으면 높이를 고칠 때마다 어긋난다. 숫자는 여기에만 있다.
     ⚠️ --play 가 자막 체류를 정한다. 560 에서 장당 0.58~0.76초였다.
        2026-08-25 에 780 으로 늘려 0.81~1.06초가 됐다(사용자 지시).
        줄이면 그만큼 짧아진다 — 지난번에 0.3초로 스쳐 지나가 글이 안 읽혔다.
     ⚠️ 자막을 3장으로 줄이는 안도 있었으나, 네 줄이 한 문장이라 문장을 다시 써야 한다.
        문장을 안 건드리는 대신 스크롤을 늘리는 쪽을 골랐다. */
  --open: 120;                   /* 액자가 열리는 동안의 스크롤 길이 (vh) */
  --play: 780;                   /* 영상이 도는 동안의 스크롤 길이 (vh) */
  /* 영상이 끝난 뒤, 가운데에서 원이 커지며 다음 섹션(② 두 갈래)이 드러나는 길이.
     ⚠️ 세 번째 도막이다. JS 가 셋을 다 읽어 EXPAND(액자 끝) · PLAY_END(영상 끝)를 낸다.
        숫자는 여기에만 있다 — 위 두 값과 같은 규칙이다.
     ⚠️ 이 값을 키우면 원이 천천히 커진다. 영상 재생 길이(--play)는 안 건드린다.
        자막 체류는 --play 가 정하고, 2026-08-25 에 사용자 지시로 780 으로 늘린 값이다. */
  --wipe: 140;
  height: calc((var(--open) + var(--play)) * 1vh);
  background: var(--xc-white);
}

/* ── 원이 커지며 다음 섹션이 드러난다 ──────────────────────────────
   ⚠️ 클래스는 **JS 가 붙인다.** 아래 두 규칙이 CSS 에만 있으면, JS 가 막힌 화면에서
      다음 섹션의 첫 화면이 영상 뒤에 깔린 채 그대로 지나가 머리글을 통째로 건너뛴다.
      모션 최소화·640 이하에서도 안 붙는다.
   ⚠️ 겹치는 자리(margin-top 음수)와 원(clip-path)·제자리 붙듦(transform)은 JS 가
      인라인으로 준다. 셋 다 화면 높이에서 계산해야 해서 CSS 로는 못 잡는다.
   ⚠️ position: relative 가 반드시 있어야 한다. .xc-scrub 가 position:relative 라
      그것이 그냥 흐름에 있는 .xc-two 위에 그려진다. 둘 다 자리가 잡혀 있어야
      나중에 온 .xc-two 가 위로 온다. */
.xc-scrub--wipe { height: calc((var(--open) + var(--play) + var(--wipe)) * 1vh); }
.xc-scrub--wipe + .xc-two { position: relative; }

/* ⚠️ GSAP pin 을 쓰지 않고 position: sticky 로 붙인다. pin 은 pin-spacer 를 끼워 넣어
      위아래 섹션의 여백 계산을 바꾼다. Lenis 는 실제 스크롤 위치를 옮기는 방식이라
      sticky 가 그대로 산다(layouts/xc.blade.php 주석 참고).
   ⚠️ 높이는 100svh 다. dvh 는 모바일 주소창이 접힐 때 값이 변해 고정된 상자가
      스크롤 도중 늘었다 줄었다 한다.
   ⚠️ overflow 를 hidden 으로 명시한다. 영상이 cover 로 넘칠 때 가로 스크롤이 생기면 안 된다. */
.xc-scrub__pin {
  position: sticky; top: 0;
  height: 100svh;
  overflow: hidden;
  background: var(--xc-white);
}

.xc-scrub__frame {
  --p:  0;                       /* 0 = 작은 네모 · 1 = 화면 가득. JS 가 스크롤로 몬다 */
  --w0: min(40vw, 480px);        /* 처음 가로 */
  --h0: min(28svh, 280px);       /* 처음 세로 */
  --r0: 14px;                    /* 처음 모서리. 다 열리면 0 이 된다 */
  position: absolute; inset: 0;
  clip-path: inset(
    calc((100% - var(--h0)) / 2 * (1 - var(--p)))
    calc((100% - var(--w0)) / 2 * (1 - var(--p)))
    round calc(var(--r0) * (1 - var(--p)))
  );
}

/* ⚠️ 이 영상도 우하단에 생성 도구의 AI 마크(별)가 박혀 있다. 히어로 영상과 같은 도구로
      만든 것이라 자리도 같다 — 실측 1280x720 기준 x 1140~1180 · y 576~623.
      .xc-hero__video 와 똑같이 왼쪽 위를 붙잡고 1.16 배로 키워 오른쪽·아래만 잘라 낸다.
   ⚠️ 근본 해결은 아니다. 원본 화소는 파일에 그대로 있다. ffmpeg 로 잘라 굽는 것이 맞다. */
.xc-scrub__video {
  width: 100%; height: 100%; object-fit: cover; display: block;
  transform: scale(1.16); transform-origin: 0 0;
  background: var(--xc-navy);    /* 영상이 뜨기 전에는 네이비가 보이도록 */
}

/* 위아래만 눌러 준다. GNB 가 얹히는 위쪽과, 다음 섹션으로 넘어가는 아래쪽.
   ⚠️ 위쪽 경사를 42% 까지 늘렸다(아래쪽은 74%). 자막이 좌상단에 앉기 때문이다.
      26% 로 두면 자막 자리의 알파가 0.10 밖에 안 되어, 밝은 장면에서 흰 글자가 묻힌다.
      자막을 아래로 옮기면 이 두 값을 서로 바꿔야 한다. */
.xc-scrub__scrim {
  position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(180deg,
    rgba(22, 29, 41, .62) 0%,
    rgba(22, 29, 41, .10) 42%,
    rgba(22, 29, 41, .10) 74%,
    rgba(22, 29, 41, .55) 100%);
}

/* 진행선 — 스크롤이 곧 재생위치라는 것을 눈으로 알려 준다.
   ⚠️ 액자(__frame) 안에 둔다. 밖에 두면 작은 네모일 때 화면 끝까지 그어져
      영상과 따로 노는 막대가 된다. */
.xc-scrub__bar {
  position: absolute; left: 0; right: 0; bottom: 0; height: 3px;
  background: rgba(255, 255, 255, .16);
}
.xc-scrub__bar span {
  display: block; height: 100%;
  background: var(--xc-gradient);
  transform: scaleX(0); transform-origin: 0 50%;
}

/* 모바일 : 고정도 확대도 스크럽도 걸지 않는다. 화면에 들어오면 그냥 도는 영상이다.
   ⚠️ 바깥 통의 높이(--open + --play)도 같이 걷어낸다. 안 걷으면 빈 화면만 여러 번 지나간다. */
@media (max-width: 640px) {
  .xc-scrub { height: auto; }
  .xc-scrub__pin { position: static; height: 62svh; }
  .xc-scrub__frame { clip-path: none; }
  .xc-scrub__bar { display: none; }
}

/* 모션 최소화 : 스크롤에 묶인 움직임을 전부 걷고 한 장면만 세워 둔다.
   ⚠️ 액자도 처음부터 열어 둔다. 작은 네모인 채로 굳으면 무슨 화면인지 알 수 없다. */
@media (prefers-reduced-motion: reduce) {
  .xc-scrub { height: auto; }
  .xc-scrub__pin { position: static; height: 62svh; }
  .xc-scrub__frame { clip-path: none; }
  .xc-scrub__bar { display: none; }
}

/* ── 스크롤이 여는 영상 · 자막 ───────────────────────────────────────────
   문안은 C:\xCalibur\brand\5_홈페이지\홈페이지_소개문안_재정의판.md §6 이 원천이다.
   여기서 문구를 고치지 않는다 — 원천을 고친 뒤 옮긴다.

   ⚠️ __frame 안이 아니라 __pin 안에 둔다. __frame 은 clip-path 로 잘리는 상자라
      그 안에 넣으면 액자가 작을 때 자막도 같이 잘려 사라진다. 어차피 액자가 다 열린
      뒤에만 뜨지만, 잘림에 기대는 구조는 창 크기가 바뀔 때 어긋난다.
   ⚠️ 자리는 좌상단이다. 영상 가운데 피사체를 가리지 않고, 우측 퀵버튼과도 안 겹친다.
      ⚠️ 옮기면 __scrim 의 위·아래 경사(42% / 74%)도 같이 옮겨야 한다. 안 그러면 글자가 묻힌다.
   ⚠️ 네 장을 겹쳐 두고 투명도만 바꾼다. 자리를 서로 밀지 않아야 글이 튀지 않는다. */
.xc-scrub__caps {
  position: absolute; left: 0; right: 0; top: 0;
  /* ⚠️ 위 여백이 GNB 를 비켜 앉는 자리다. GNB 는 80px 이고, 스크롤을 위로 올리면
        감춰져 있던 것이 다시 나타난다(is-hide 해제). 80px 만 주면 그때 겹친다. */
  padding: clamp(116px, 12vw, 172px) var(--xc-pad) 0;
  pointer-events: none;
}
.xc-scrub__caps-in {
  position: relative;
  max-width: var(--xc-area); margin-inline: auto;
  /* 네 장을 겹치므로 가장 긴 것의 높이를 미리 잡아 둔다. 두 줄까지 */
  min-height: calc(clamp(26px, 3.4vw, 52px) * 1.3 * 2);
}
.xc-scrub__cap {
  position: absolute; left: 0; top: 0; margin: 0;
  max-width: 22ch;
  font-size: clamp(26px, 3.4vw, 52px);
  font-weight: var(--xc-fw-bold, 700);
  line-height: 1.3; letter-spacing: -.015em;
  color: var(--xc-white);
  /* 아래 스크림(rgba .55)만으로는 밝은 장면에서 약하다. 글자 자체에 그림자를 준다 */
  text-shadow: 0 1px 2px rgba(22, 29, 41, .45), 0 2px 18px rgba(22, 29, 41, .35);
  opacity: 0;
  /* ⚠️ transition 을 걸지 않는다. 값을 매 프레임 스크롤에서 직접 받으므로
        전이가 겹치면 스크롤을 되감을 때 뒤늦게 따라오며 흐물거린다. */
  will-change: opacity, transform;
}

/* 모바일·모션 최소화 : 스크롤에 물리지 않는다. 영상을 화면 높이로 세우고
   자막 네 줄을 그 위에 흰 글자로 얹는다(2026-09-17 사용자 지시).
   ⚠️ 스크럽이 없으므로 한 줄씩 바꿔 보일 수가 없다. 네 줄을 한꺼번에 둔다.
   ⚠️ 자막은 **아래쪽**에 붙인다. 위쪽은 GNB 가 다시 나타나면 겹친다.
      스크림도 아래가 어둡다(74%부터 .55 까지).
   ⚠️ __pin 을 relative 로 둔다. static 이면 자막(absolute)이 무엇을 기준으로
      앉는지 달라진다.
   ⚠️ __pin 높이를 auto 로 풀고 __frame 에 높이를 준다. __frame 이 absolute 라
      부모 높이에 기대고 있어서, 부모를 풀면 같이 접힌다. */
@media (max-width: 640px), (prefers-reduced-motion: reduce) {
  .xc-scrub__pin { height: auto; position: relative; }
  /* 🔴 overflow 를 반드시 막는다. 영상은 워터마크를 잘라 내려고 1.16배로 키워 둬서
     틀보다 84~89px 크다. 여기서는 clip-path 를 껐으므로(위 640 블록) 아무것도
     자르지 않아 영상이 아래로 흘러 **자막 두 줄을 덮었다** — 어두운 영상 위에
     어두운 글자라 안 읽혔다(실측 2026-09-17 · 390·360 전부). */
  .xc-scrub__frame { position: relative; inset: auto; height: 100svh; overflow: hidden; }
  .xc-scrub__caps {
    position: absolute; top: auto; bottom: 0; left: 0; right: 0;
    padding: 0 var(--xc-pad) clamp(30px, 7vw, 52px);
  }
  .xc-scrub__caps-in { min-height: 0; display: grid; gap: clamp(8px, 2.2vw, 14px); }
  .xc-scrub__cap {
    position: static; opacity: 1; max-width: none;
    font-size: clamp(17px, 4.4vw, 22px);
    color: var(--xc-white);
    /* 밝은 장면 위에서도 읽히게 글자 자체에 그림자를 둔다(데스크톱과 같은 값) */
    text-shadow: 0 1px 2px rgba(22, 29, 41, .45), 0 2px 18px rgba(22, 29, 41, .35);
    transform: none !important;       /* 스크립트가 남긴 값이 있어도 무시한다 */
  }
  /* 네 줄이 한꺼번에 얹히므로 아래쪽을 더 가라앉힌다. 밑동 스크림만으로는 얇다 */
  .xc-scrub__scrim {
    background: linear-gradient(180deg,
      rgba(22, 29, 41, .50)  0%,
      rgba(22, 29, 41, .10) 34%,
      rgba(22, 29, 41, .34) 62%,
      rgba(22, 29, 41, .78) 100%);
  }
}

/* ══════════════════════════════════════════════════════════════════════════
   온라인문의 폼 (2026-09-01)

   🔴 이 화면만 **옛 마크업 그대로** 새 레이아웃에 얹혀 있다. 게시판 스킨은 마크업까지
      새 클래스로 다시 썼지만, 문의는 폼 필드가 설정에서 동적으로 만들어지고
      검증·캡차·첨부·약관 동의가 전부 거기 걸려 있어 손대지 않았다.
      그래서 옛 클래스 이름을 그대로 두고 **모양만 여기서 다시 준다.**

   🔴 화면은 클래스 **둘을 함께** 단다 - `xc-inq xc-inqf`.
        .xc-inq   좌측 고정 + 우측 폼 격자 (이 파일 3777행. 프로토타입 new/support-inquire.html
                  이 쓰는 그것이다. 라라벨도 같은 모양이라야 한다)
        .xc-inqf  그 안 폼의 **옛 클래스**에 모양을 주는 것 (여기)
      ⚠️ 둘을 하나로 합치지 말 것. .xc-inq 는 프로토타입도 쓰므로 여기 규칙을 그 이름에
         넣으면 프로토타입 폼(.xc-form)까지 덮는다 - 실제로 한 번 그렇게 만들었다가 되돌렸다.
      ⚠️ 그래서 .xc-inqf 에는 **폭·격자를 넣지 않는다.** 그건 .xc-inq 의 몫이다.

   ⚠️ 반드시 `.xc-inqf` 안으로 한정한다. main.css 는 모든 화면이 함께 쓰는데
      `.section`·`.inner`·`.article`·`.txt` 는 흔한 이름이라 밖으로 새면 다른 화면을
      통째로 망가뜨린다.
   ⚠️ 옛 스타일시트(/css/style.css · 249KB)를 다시 부르지 않는다. 전역 선택자가 들어
      있어 새 헤더·푸터까지 바꾼다. 옛 디자인이라 겉돌기도 한다.
   ⚠️ 값은 .xc-form(프로토타입 폼)과 같은 토큰을 쓴다. 두 폼이 달라 보이면 안 된다.
   ══════════════════════════════════════════════════════════════════════════ */


/* 스크린리더 전용. 밑동은 .xc-blind 지만 이 화면 마크업은 .sr-only 를 쓴다.
   ⚠️ 전역으로 별칭을 만들지 않는다 — 여기 안에서만 통한다 */
.xc-inqf .sr-only {
  position: absolute; width: 1px; height: 1px;
  margin: -1px; padding: 0; overflow: hidden;
  clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

/* ── 묶음 ── */
.xc-inqf fieldset {
  margin: 0; padding: 0; border: 0; min-width: 0;
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(16px, 2vw, 28px);
}
.xc-inqf fieldset + fieldset { margin-top: clamp(40px, 5vw, 72px); }
.xc-inqf fieldset > h3 { grid-column: 1 / -1; }
/* 여러 줄 입력·첨부·캡차는 한 줄을 다 쓴다.
   ⚠️ :has() 를 못 읽는 브라우저에서는 한 칸으로 남는다. 좁아질 뿐 깨지지 않는다 */
.xc-inqf fieldset > div:has(textarea),
.xc-inqf fieldset > div:has(input[type="file"]),
.xc-inqf fieldset > div:has(.g-recaptcha) { grid-column: 1 / -1; }
/* 빈 칸(캡차가 꺼져 있을 때)은 자리를 먹지 않게 한다 */
.xc-inqf fieldset > div:empty { display: none; }
/* 약관 동의는 이제 「문의내용」 묶음 안의 한 항목이다(2026-09-10). 그 묶음이 한 칸이라
 저절로 한 줄을 다 쓴다 - 여기서 칸을 다시 정하지 않는다.
 제목은 첨부파일 라벨과 같은 꼴이다(.xc-inqf label.txt2 와 값을 맞춘다). */
.xc-inqf__sub {
  /* ⚠️ <h4> 의 브라우저 기본 위 여백(약 20px)을 지운다. 격자 항목이라 그 여백이
     바깥으로 합쳐지지 않고 **안에서 자리를 먹어** 첨부파일과의 사이만 28+20 이 됐다
     (실측 2026-09-11). 옆 라벨(label.txt2)은 margin-top 이 0 이다 - 그것과 맞춘다. */
  display: block; margin: 0 0 10px;
  font-size: var(--xc-fs-sm); font-weight: var(--xc-fw-semibold); color: var(--xc-text);
}

.xc-inqf .sect-title {
  grid-column: 1 / -1;
  font-size: var(--xc-fs-card-ttl); font-weight: var(--xc-fw-extra);
  letter-spacing: var(--xc-ls-heading); color: var(--xc-text);
  padding-bottom: clamp(12px, 1.4vw, 18px);
  border-bottom: 2px solid var(--xc-text);
}

/* ── 입력 칸 ──
   테두리가 아니라 면으로 구분한다. 테두리는 투명하게 남겨 둔다 —
   포커스에서 선을 켤 때 높이가 2px 튀지 않게 자리를 미리 잡는다 */
.xc-inqf label.txt2 {
  display: block; margin-bottom: 10px;
  font-size: var(--xc-fs-sm); font-weight: var(--xc-fw-semibold); color: var(--xc-text);
}
.xc-inqf input[type="text"], .xc-inqf input[type="tel"],
.xc-inqf input[type="email"], .xc-inqf input[type="number"],
.xc-inqf select, .xc-inqf textarea {
  width: 100%; padding: 0 18px;
  border: 1px solid transparent; border-radius: var(--xc-radius);
  background: var(--xc-gray-100);
  font-size: var(--xc-fs-sm); color: var(--xc-text);
  transition: background-color var(--xc-dur-fast) var(--xc-ease-out),
              border-color var(--xc-dur-fast) var(--xc-ease-out);
}
.xc-inqf input[type="text"], .xc-inqf input[type="tel"],
.xc-inqf input[type="email"], .xc-inqf input[type="number"], .xc-inqf select { height: 54px; }
.xc-inqf textarea {
  min-height: clamp(180px, 24vh, 240px); padding: 16px 18px;
  line-height: 1.7; resize: vertical;
}
.xc-inqf ::placeholder { color: var(--xc-text-weak); }
/* ⚠️ `input:hover` 로 쓰면 **파일 고르기와 체크박스까지** 회색 면이 깔린다(실측).
   회색 면은 글자를 쓰는 칸의 표시다. 파일 고르기는 버튼이고 체크박스는 상자다.
   아래 목록은 위 「입력 칸」 규칙과 **같은 것을 유지해야 한다.** */
.xc-inqf input[type="text"]:hover, .xc-inqf input[type="tel"]:hover,
.xc-inqf input[type="email"]:hover, .xc-inqf input[type="number"]:hover,
.xc-inqf select:hover, .xc-inqf textarea:hover { background: var(--xc-gray-200); }
/* 파일·체크박스는 브라우저 기본 포커스 표시를 그대로 둔다 - 지우면 키보드로 못 따라간다 */
.xc-inqf input[type="text"]:focus, .xc-inqf input[type="tel"]:focus,
.xc-inqf input[type="email"]:focus, .xc-inqf input[type="number"]:focus,
.xc-inqf select:focus, .xc-inqf textarea:focus {
  outline: 0; background: var(--xc-bg); border-color: var(--xc-text);
}
/* ⚠️ 자동완성이 들어오면 브라우저가 연노랑을 강제로 칠한다. background 로는 못 막는다 */
.xc-inqf input:-webkit-autofill,
.xc-inqf input:-webkit-autofill:hover,
.xc-inqf input:-webkit-autofill:focus {
  -webkit-box-shadow: 0 0 0 1000px var(--xc-gray-100) inset;
  -webkit-text-fill-color: var(--xc-text);
}

/* ── 첨부 ──
   ⚠️ 네이티브 파일 입력은 브라우저마다 모양이 다르고 「선택된 파일 없음」을 숨길 수 없다.
      마크업을 못 바꾸니 고르기 버튼만 사이트 꼴로 맞춘다 */
.xc-inqf input[type="file"] { font-size: var(--xc-fs-sm); color: var(--xc-text-sub); max-width: 100%; }
.xc-inqf input[type="file"]::file-selector-button {
  margin-right: 12px; min-height: 40px; padding: 0 18px; cursor: pointer;
  border: 1px solid var(--xc-border-strong); border-radius: var(--xc-radius-full);
  background: var(--xc-bg); color: var(--xc-text);
  font-size: var(--xc-fs-xs); font-weight: var(--xc-fw-semibold);
  transition: var(--xc-trans-fast);
}
.xc-inqf input[type="file"]::file-selector-button:hover { border-color: var(--xc-text); }
.xc-inqf .txt3 {
  margin-top: 8px; font-size: var(--xc-fs-xs);
  color: var(--xc-text-weak); line-height: 1.6;
}
.xc-inqf .txt3:first-of-type { margin-top: 12px; }

/* ── 약관 동의 ── */
.xc-inqf .sect-cont {
  padding: clamp(20px, 2.2vw, 28px);
  border: 1px solid var(--xc-border); border-radius: var(--xc-radius-lg);
}
/* 처리방침 전문이 400줄쯤 들어온다. 상자 안에서만 굴린다.
   🔴 overflow-y 만 주면 overflow-x 가 auto 로 계산된다. hidden 을 명시한다 */
.xc-inqf .article-box {
  /* 2026-09-10 : 절반으로 줄였다(340 → 170). 처리방침 전문이 400줄쯤이라
     상자가 화면을 다 먹고 있었다. 굴려서 읽는 상자다. */
  max-height: clamp(120px, 17vh, 170px);
  overflow-y: auto; overflow-x: hidden;
  padding-right: 14px;
  font-size: var(--xc-fs-xs); color: var(--xc-text-sub); line-height: 1.8;
  overscroll-behavior: contain;
}
.xc-inqf .article-box .article + .article { margin-top: 22px; }
.xc-inqf .article-box strong.txt2 {
  display: block; margin-bottom: 8px;
  font-size: var(--xc-fs-sm); font-weight: var(--xc-fw-bold); color: var(--xc-text);
}
.xc-inqf .article-box p + p, .xc-inqf .article-box p + ul { margin-top: 10px; }
.xc-inqf .article-box ul { margin-top: 10px; padding-left: 18px; }
.xc-inqf .article-box li + li { margin-top: 6px; }
.xc-inqf .article-box .num-list { list-style: decimal; }
.xc-inqf .article-box .num-list.circle { list-style: circle; }
.xc-inqf .article-box .num-list.dash { list-style: "- "; }
.xc-inqf .article-box table { width: 100%; border-collapse: collapse; margin-top: 10px; }
.xc-inqf .article-box th, .xc-inqf .article-box td {
  border: 1px solid var(--xc-border-weak); padding: 8px 10px; text-align: left;
}

/* 동의 줄. 첫 라벨은 옛 CSS 가 네모를 그리던 자리라 지금은 쓸모가 없다 —
   네이티브 상자를 그대로 쓰고 그 라벨만 뺀다(글자 라벨은 남긴다) */
.xc-inqf .check-box {
  display: flex; align-items: center; gap: 10px;
  margin-top: clamp(18px, 2vw, 24px);
  padding-top: clamp(18px, 2vw, 24px); border-top: 1px solid var(--xc-border-weak);
}
.xc-inqf .check-box > label:first-of-type { display: none; }
.xc-inqf .check-box input[type="checkbox"] {
  width: 20px; height: 20px; flex: none; margin: 0;
  accent-color: var(--xc-navy); cursor: pointer;
}
.xc-inqf .check-box label { font-size: var(--xc-fs-sm); color: var(--xc-text); cursor: pointer; }

/* ── 보내기 ── 약관 상자 **밖**이다(2026-09-01 사용자 지시).
   버튼 자체는 사이트 표준(.xc-pill + .xc-hover-circle)을 그대로 쓴다.
   ⚠️ 여기서 버튼 모양을 다시 만들지 않는다. 표준이 .xc-sub 안에서의 색까지 이미 정해 두었다 */
.xc-inqf__submit { margin-top: clamp(28px, 3.4vw, 48px); display: flex; justify-content: center; }
.xc-inqf__submit .d-none { display: none; }

@media (max-width: 720px) {
  .xc-inqf fieldset { grid-template-columns: minmax(0, 1fr); }
}

/* 약관 본문의 <br class="pc-br"> 는 옛 CSS 가 폭에 따라 껐다 켰다 하던 것이다.
   그 규칙이 없으니 늘 끊겨 글줄이 들쭉날쭉해진다. 상자 안에서는 그냥 흘린다 */
.xc-inqf .article-box .pc-br { display: none; }
/* 첫 조(條) 제목이 앞 문단에 붙어 보인다 */
.xc-inqf .article-box p + .article { margin-top: 22px; }

/* 좌측 안내 문장 - 여기서는 이것이 제목 자리다.
   ⚠️ 프로토타입에는 <h2 class="xc-inq__ttl"> 이 따로 있고 리드는 그 아래 작은 글이다.
      라라벨은 히어로가 이미 제목을 그려서 h2 를 빼고 이 문장 하나만 남겼다.
      그래서 리드 크기(21px)로 두면 좌측이 비어 보인다 - 제목 크기로 올린다.
   ⚠️ 반드시 .xc-inqf 로 한정한다. .xc-inq__lead 를 그냥 고치면 프로토타입 문의
      페이지의 리드까지 커진다. */
.xc-inqf .xc-inq__lead {
  margin-top: clamp(14px, 1.6vw, 18px);
  font-size: var(--xc-fs-blk-h2); font-weight: var(--xc-fw-extra);
  letter-spacing: var(--xc-ls-heading); line-height: var(--xc-lh-heading);
  color: var(--xc-text); word-break: keep-all;
}

/* ══════════════════════════════════════════════════════════════════════════
   개인정보처리방침 · 옛 마크업에 모양만 다시 주기 (2026-09-01)

   🔴 문의 폼(.xc-inqf)과 같은 사정이다. 개편 때 이 화면은 본문 마크업을 옮기지 않아
      옛 클래스만 남았고, 그 CSS(/css/style.css)를 새 레이아웃이 부르지 않는다.
      고치기 전에는 글이 x=0 에 붙고 GNB 가 제목을 덮고 있었다(실측).
   ⚠️ 반드시 `.xc-pp` 안으로 한정한다. `.txt`·`.article`·`.section` 은 흔한 이름이다.
   ⚠️ .xc-inqf 의 약관 상자와 규칙을 합치지 않는다. 그쪽은 폼 안이라 상자에 가두고
      굴리지만, 여기는 화면 전체가 그 문서다.
   ══════════════════════════════════════════════════════════════════════════ */

.xc-pp { max-width: 900px; margin-inline: auto; }

/* 머리말 */
.xc-pp .sect-cont > .sect-subtitle {
  font-size: var(--xc-fs-lead); color: var(--xc-text-sub);
  line-height: 1.8; text-wrap: pretty;
}

/* 조(條) 목록 */
.xc-pp .slide-list { margin-top: clamp(32px, 4vw, 56px); list-style: none; padding: 0; }
.xc-pp .slide-list > li { padding-top: clamp(24px, 3vw, 40px); border-top: 1px solid var(--xc-border); }
.xc-pp .slide-list > li + li { margin-top: clamp(24px, 3vw, 40px); }
.xc-pp h2.sect-subtitle {
  font-size: var(--xc-fs-card-ttl); font-weight: var(--xc-fw-extra);
  letter-spacing: var(--xc-ls-heading); color: var(--xc-text);
  text-wrap: pretty; word-break: keep-all;
}
.xc-pp .slide-cont { margin-top: clamp(14px, 1.8vw, 20px); }
.xc-pp .article + .article { margin-top: 20px; }
.xc-pp strong.txt2 {
  display: block; margin-bottom: 8px;
  font-size: var(--xc-fs-sm); font-weight: var(--xc-fw-bold); color: var(--xc-text);
}

/* 본문 글 */
.xc-pp .txt {
  font-size: var(--xc-fs-sm); color: var(--xc-text-sub);
  line-height: 1.9; text-wrap: pretty;
}
.xc-pp .txt + .txt, .xc-pp .txt + ul, .xc-pp ul + .txt { margin-top: 10px; }
.xc-pp .txt span { display: block; margin-top: 4px; }
/* 별표 딸린 주석 두 곳. 본문보다 한 단계 낮춘다 */
.xc-pp .star2 { font-size: var(--xc-fs-xs); color: var(--xc-text-weak); }

/* 번호 목록. 옛 CSS 가 모양만 바꿔 쓰던 수식어 둘을 그대로 살린다 */
.xc-pp .num-list { margin-top: 10px; padding-left: 20px; list-style: decimal; }
.xc-pp .num-list.circle { list-style: circle; }
.xc-pp .num-list.dash { list-style: "- "; }
.xc-pp .num-list li + li { margin-top: 6px; }
.xc-pp .num-list .num-list { margin-top: 6px; }

/* ⚠️ .pc-br 은 옛 CSS 가 폭에 따라 껐다 켰다 하던 것이다. 그 규칙이 없으니 늘 끊겨
   글줄이 들쭉날쭉해진다(실측). 여기서는 그냥 흘린다 - 문의 약관 상자와 같은 처리다 */
.xc-pp .pc-br { display: none; }

/* 약관동의 제목만 밑선을 뺀다 (2026-09-01 사용자 지시).
   ⚠️ 위계는 그대로 둔다 - 크기·굵기는 앞 두 묶음과 같다. 선만 없앤다.
      바로 아래 약관 상자가 이미 테두리를 갖고 있어 선이 겹쳐 보였다.
   ⚠️ 밑여백도 함께 지운다. 선이 없으면 그 여백은 격자 gap 과 겹쳐 46px 이 된다. */


/* 「문의내용」 묶음은 한 칸으로 쓴다 (2026-09-01 사용자 지시).
   제목이 절반 폭이라 바로 아래 내용(전체 폭)과 어긋나 보였다. 높이는 그대로 54px 다.
   ⚠️ 묶음 번호(:nth-of-type)로 집지 않는다. 묶음은 관리자 설정의 구분자로 만들어져
      개수가 바뀔 수 있다. **여러 줄 입력이 든 묶음**이라는 성질로 집는다 —
      긴 글을 쓰는 자리는 한 칸이 맞다.
   ⚠️ :has() 를 못 읽는 브라우저는 두 칸 그대로다. 좁아질 뿐 깨지지 않는다. */
.xc-inqf fieldset:has(textarea) { grid-template-columns: minmax(0, 1fr); }
