@charset "utf-8";
/* [index02 전용 사본] 원본 : /df/kwaa/css/motion.css (2026-09-10 복사)
   index02.html 만 이 파일을 쓴다. index.html 쪽 원본을 고쳐도 여기엔 반영되지 않는다(반대도 같다). */
/* ============================================================================
   motion.css  —  메인 비주얼 슬라이드 콘텐츠 모션

   짝 파일 : /df/kwaa/js/motion.js
   대상    : #main_con > .visual_slide_con ... .swiper-slide > .contents_con 내부 객체

   ※ index_ttt.html 은 손대지 않는다.
      이미 걸어두신 두 줄(motion.css · motion.js)만으로 전부 동작한다.
      GSAP 은 motion.js 가 스스로 불러온다.

   기법 출처 (_lib/motion)
     250902-capsules-landing-page-reveal : SplitText mask 리빌 · clip-path circle 아이콘
     250624-konpo-lp-reveal              : scaleX/scaleY 바 리빌 · clip-path 와이프
   타이밍/이징 : recipes/04-timing-reference.md · recipes/05-easing-references.md
   ============================================================================ */

/* ---- SplitText 산출물 ----------------------------------------------------
   mask 옵션이 각 줄 바깥에 overflow:clip 래퍼(.split_line-mask)를 만들어 준다.
   여기서는 조각이 transform 을 받을 수 있게만 해준다. */
#main_con > .visual_slide_con .split_line {
	display: inline-block;
	position: relative;
	will-change: transform;
	white-space: nowrap;
}

/* ---- 협회명 타이핑 (KOREA / DIGITAL AGENCY / ASSOCIATION) -----------------
   motion.js 가 같은 규칙을 스스로 주입한다. 여기 있는 것은 편집용 사본이다.
   (두 곳이 어긋나면 js 쪽이 나중에 삽입돼 이긴다 — 고칠 때 양쪽 다 고칠 것)

   글자는 처음부터 자리를 차지한 채 투명하게 있다가 하나씩 켜진다.
   글자를 넣었다 뺐다 하면 3줄 블록의 폭이 매 글자마다 흔들린다. */
/* 줄 — 'chars' 만으로 쪼개면 SplitText 가 <br> 을 흡수해 3줄이 한 줄로 붙는다.
   그래서 'lines,chars' 로 쪼개고, 각 줄을 블록으로 세워 원래 배치를 지킨다. */
#main_con > .visual_slide_con .type_line {
	display: block;
}
#main_con > .visual_slide_con .type_char {
	display: inline-block;
}

/* 커서 — 폭 0 으로 흐름에 끼어들지 않게 하고 막대는 :before 로 그린다.
   · width 를 주면 커서가 지나갈 때마다 뒷글자가 그만큼 밀린다
   · letter-spacing:0 도 같은 이유다. 이 블록은 자간이 3.436px(모바일 8px)라
     커서가 글자 사이에 끼면 한 칸이 더 벌어진다 */
#main_con > .visual_slide_con .type_caret {
	display: inline-block;
	position: relative;
	width: 0;
	height: 0.92em;
	vertical-align: -0.06em;
	letter-spacing: 0;
	pointer-events: none;
}
/* [2026-09-10] 세로 막대(|) → 밑줄(_). 다음 글자가 찍힐 자리 "아래" 에서 기다린다.
   · 기준선 바로 밑(약 -0.08em)에 둔다. 더 내리면 여러 줄 블록의 줄 마스크(overflow:clip)에 잘린다
   · 폭은 글자 하나 남짓(0.6em). 커서 자체는 폭 0 이라 뒷글자를 밀지 않는다
   · 두께는 글자 크기를 따른다 — 제목(120px)은 약 9px, 작은 글자는 최소 2px
   (motion.js 가 같은 규칙을 주입한다 — 고칠 땐 양쪽 다) */
#main_con > .visual_slide_con .type_caret:before {
	content: "";
	position: absolute;
	left: 0.05em;
	bottom: -0.02em;
	width: 0.6em;
	height: max(2px, 0.075em);
	background: currentColor;   /* 글자색(#FFFAEE)을 그대로 따른다 */
}
/* 다 치고 난 뒤에만 깜빡인다. 치는 동안은 켜져 있어야 커서로 읽힌다.
   ※ CSS 애니메이션은 인라인 스타일보다 우선한다. 그래서 GSAP 이 넣은
     opacity 값이 있어도 깜빡임이 이긴다 — 퇴장 때는 js 가 이 클래스를 뗀다. */
#main_con > .visual_slide_con .type_caret.is_blink {
	animation: hdg_type_caret 1s steps(1) infinite;
}
@keyframes hdg_type_caret {
	0%, 50% { opacity: 1; }
	50.01%, 100% { opacity: 0; }
}

/* ---- 회비납부 버튼이 천천히 둥둥 뜬다 --------------------------------------
   [2026-09-10] 오버 시 배경 띠는 뺐다. 대신 늘 조금씩 떠 있게 해서
   "눌러도 되는 것" 이라는 신호를 준다.
   (motion.js 가 같은 규칙을 스스로 주입한다 — 고칠 땐 양쪽 다)

   ※ 움직이는 대상은 .a_btn (링크) 이다. 바깥의 .btn_con 은 GSAP 이 등장·퇴장에서
     y / opacity / clipPath 를 쓰므로, 거기에 CSS transform 을 같이 걸면 서로 덮어쓴다.
     안쪽 링크는 GSAP 이 건드리지 않으므로 안전하다. */
#main_con > .visual_slide_con .swiper-slide .a_btn {
	position: relative;
	animation: hdg_btn_float 3.2s ease-in-out infinite;
	will-change: transform;
}
/* 글자와 화살표는 GSAP 이 색을 입히므로 위층에 둔다 */
#main_con > .visual_slide_con .swiper-slide .a_btn > span,
#main_con > .visual_slide_con .swiper-slide .a_btn > .btn_arrow {
	position: relative;
	z-index: 1;
}
@keyframes hdg_btn_float {
	0%, 100% { transform: translateY(0); }
	50%      { transform: translateY(-4px); }
}
/* 무한 반복 모션이라 동작 줄이기 설정에서는 멈춘다 */
@media (prefers-reduced-motion: reduce) {
	#main_con > .visual_slide_con .swiper-slide .a_btn { animation: none; }
}

/* ---- 모션 시작 전 감추기 --------------------------------------------------
   html.has-motion 은 motion.js 가 붙인다.
   - GSAP 로드 실패 / 모션 최소화 설정이면 붙지 않는다
   - 로드가 끝내 실패하면 motion.js 가 이 클래스를 다시 떼어낸다
   → 어떤 경우에도 "텍스트가 영영 안 보이는" 사고가 나지 않는다.

   motion.js 는 마크업보다 먼저 실행되므로 첫 페인트 전에 붙어 깜빡임이 없다. */
html.has-motion #main_con > .visual_slide_con .swiper-slide > .contents_con > .text_con,
html.has-motion #main_con > .visual_slide_con .swiper-slide > .contents_con > .option_con,
html.has-motion #main_con > .visual_slide_con .swiper-slide > .contents_con > .info_con {
	opacity: 0;
}

/* 슬라이드 좌/우 버튼 — 첫 장 텍스트가 옵션까지 쳐진 뒤에 올라온다 (motion.js initSlides)
   visibility 까지 감춰야 안 보이는 버튼이 눌리거나 탭 포커스를 받지 않는다.
   motion.js 가 실패하면 has-motion 이 떨어져 이 규칙도 풀린다 → 버튼이 영영 안 보이는 일은 없다. */
html.has-motion #main_con > .visual_slide_con > .slide_ui {
	opacity: 0;
	visibility: hidden;
}

/* ---- JS 가 못 떴을 때의 안전장치 -----------------------------------------
   main_style.css 에 임시로 있던
       .swiper-slide > .contents_con {opacity:0}
       .swiper-slide-active > .contents_con {opacity:1}
   두 줄은 제거했다. 슬라이드가 비활성이 되는 순간 .contents_con 이 즉시 꺼져서
   텍스트가 위로 빠지는 퇴장 연출이 통째로 안 보였기 때문이다.

   다만 Swiper 는 loop 복제 슬라이드 일부를 opacity 1 로 남겨두므로,
   motion.js 가 뜨지 않으면 여러 슬라이드의 텍스트가 겹쳐 보일 수 있다.
   그래서 "모션이 돌지 않을 때만" 원래 규칙과 같은 역할을 하도록 되돌려 둔다.
   (motion.js 가 정상 동작하면 html 에 has-motion 이 붙어 이 규칙은 적용되지 않고,
    비활성 슬라이드는 JS 가 감춘다) */
html:not(.has-motion) #main_con > .visual_slide_con .swiper-slide:not(.swiper-slide-active) > .contents_con {
	opacity: 0;
}

/* ---- 진행바 트랙 ---------------------------------------------------------
   scaleX 로 좌→우로 그어지듯 나타난다. 안쪽 채움(div)은 main_style.css 의
   5.5s width 트랜지션이 그대로 담당하므로 건드리지 않는다. */
html.has-motion #main_con > .visual_slide_con .swiper-slide > .contents_con > .info_con .bar {
	transform-origin: left center;
}

/* ---- 모션 최소화 설정 ----------------------------------------------------
   CLAUDE.md 지켜야 할 것 1번 / recipes/01

   ※ 여기서 transform / clip-path 를 !important 로 눌러버리면,
     OS "동작 줄이기"가 켜진 PC 에서는 전체 연출을 쓰기로 해도 제목·설명이
     끝내 움직이지 않는다. (GSAP 인라인 스타일을 CSS !important 가 이기기 때문)
     그래서 이 파일에서는 위치 관련 속성을 건드리지 않는다.

   모션 최소화 정책은 motion.js 의 RESPECT_REDUCED_MOTION 한 곳에서만 정한다.
     false → 설정과 무관하게 항상 전체 연출 (현재 값, 담당자 요청)
     true  → 설정이 켜져 있으면 페이드만 도는 간소 모드
*/
