/* ==========================================================================
   가나다하우스 — style.css
   레퍼런스: rxkstudio.com (그리드 시스템 / 컬러 변수 / 타이포 스케일 / 반응형 breakpoint 동일하게 이식)
   ========================================================================== */

/* 로컬 자체 호스팅 (file:// 환경에서도 항상 로드되도록 CDN 대신 로컬 파일 사용) */
/* 영문 전용: Switzer (Fontshare 무료 라이선스) — 레퍼런스가 쓰는 유료 NeueMontreal은
   저작권상 그대로 가져올 수 없어서, 같은 계열의 기하학적 그로테스크 중 무료로 쓸 수 있고
   시각적으로 가장 가까운 폰트를 골라 자체 호스팅함 */
@font-face{
  font-family:"Switzer";
  font-weight:500;
  font-style:normal;
  font-display:swap;
  src:url("../fonts/Switzer-Medium.woff2") format("woff2");
}
@font-face{
  font-family:"Switzer";
  font-weight:600;
  font-style:normal;
  font-display:swap;
  src:url("../fonts/Switzer-Semibold.woff2") format("woff2");
}
@font-face{
  font-family:"Switzer";
  font-weight:700;
  font-style:normal;
  font-display:swap;
  src:url("../fonts/Switzer-Bold.woff2") format("woff2");
}
@font-face{
  font-family:"Pretendard";
  font-weight:100;
  font-style:normal;
  font-display:swap;
  src:url("../fonts/Pretendard-Thin.woff2") format("woff2");
}
@font-face{
  font-family:"Pretendard";
  font-weight:200;
  font-style:normal;
  font-display:swap;
  src:url("../fonts/Pretendard-ExtraLight.woff2") format("woff2");
}
@font-face{
  font-family:"Pretendard";
  font-weight:300;
  font-style:normal;
  font-display:swap;
  src:url("../fonts/Pretendard-Light.woff2") format("woff2");
}
@font-face{
  font-family:"Pretendard";
  font-weight:500;
  font-style:normal;
  font-display:swap;
  src:url("../fonts/Pretendard-Medium.woff2") format("woff2");
}
@font-face{
  font-family:"Pretendard";
  font-weight:700;
  font-style:normal;
  font-display:swap;
  src:url("../fonts/Pretendard-Bold.woff2") format("woff2");
}
@font-face{
  font-family:"Pretendard";
  font-weight:800;
  font-style:normal;
  font-display:swap;
  src:url("../fonts/Pretendard-ExtraBold.woff2") format("woff2");
}
@font-face{
  font-family:"Pretendard";
  font-weight:900;
  font-style:normal;
  font-display:swap;
  src:url("../fonts/Pretendard-Black.woff2") format("woff2");
}

:root{
  --color-noir:#171717;
  --color-blanc:#f4f3ed;

  --grid-columns:12;
  --grid-gutter:20px;
  --grid-margin:20px;
  --grid-width:calc(100vw - var(--grid-margin)*2);
  --grid-column-width:calc((var(--grid-width) - ((var(--grid-columns) - 1)*var(--grid-gutter)))/var(--grid-columns));

  --font-kr:"Pretendard",-apple-system,BlinkMacSystemFont,"Apple SD Gothic Neo","Malgun Gothic",sans-serif;
  --font-en:"Switzer","Helvetica Neue",Helvetica,Arial,var(--font-kr);

  --line:2px; /* 구획 사이 블랙 라인 두께 */
}

@media (min-width:1440px){
  :root{
    --grid-gutter:1.4vw;
    --grid-margin:1.4vw;
  }
}

/* ---------- Reset ---------- */
*{
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
  box-sizing:border-box;
  margin:0;
  padding:0;
  border:0;
}
html{ overflow-x:hidden; }
body,html{ min-height:100vh; min-height:100dvh; }
body{
  background:var(--color-blanc);
  color:var(--color-noir);
  font:500 normal clamp(16px,1.11vw,21px)/normal var(--font-kr);
}
ul{ list-style:none; }
a{ color:inherit; text-decoration:none; }
button{
  background:transparent;
  color:inherit;
  cursor:pointer;
  font:inherit;
  appearance:none;
}
img{ max-width:100%; display:block; }
h1,h2,h3{ font:inherit; }

.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;
}

/* ---------- Typography utilities ---------- */
.t-h1{
  font:900 normal clamp(9px,7.25vw,139px)/1.05 var(--font-kr);
  letter-spacing:-.03em;
  text-align:center;
  text-transform:uppercase;
  -webkit-text-stroke:0 transparent; /* footer "가나다" 워드마크처럼 외곽선 없이 */
  text-stroke:0 transparent;
}
@media (max-width:500px){
  .t-h1{ font:900 normal clamp(9px,7vw,139px)/1.05 var(--font-kr); }
}

/* © 기호: 실제 &copy; 글리프를 쓰되, 이 스팬만 세리프(명조) 폰트로 — 나머지 고딕 글자들 사이에서
   ⓒ만 살짝 다른 서체로 포인트를 줌(옛 저작권 표기 느낌). all:unset으로 부모(.t-h1)의
   text-stroke/letter-spacing/weight 상속을 차단. 크기는 1.12em의 95%(1.06em), 가로 위치는
   인라인 그대로 두고 top을 음수로 살짝 올려 "스"와 세로 중심이 맞게 미세 정렬 */
.hero-title .copyright{
  all:unset;
  display:inline-block;
  font-family:Georgia,"Times New Roman","Nanum Myeongjo",serif;
  font-weight:500;
  font-size:1.06em;
  line-height:1;
  vertical-align:baseline;
  position:relative;
  top:-.1em;
  letter-spacing:0;
  color:var(--color-noir);
  -webkit-text-stroke:0 transparent;
}

/* "/" 구분 기호는 가늘게 */
.hero-title .slash{
  display:inline-block;
  font-weight:200;
  -webkit-text-stroke:0;
  text-stroke:0;
}
.t-h2{
  font:700 normal clamp(25px,5.83vw,300px)/.8 var(--font-en);
  letter-spacing:-.02em;
  text-align:center;
  text-transform:uppercase;
}
/* 작은 텍스트(라벨/리스트/본문) 전용 — 대형 디스플레이 타이틀(.t-h1/.t-h2/footer 워드마크)은
   제외하고, 히어로 소개문부터 카테고리 라벨·footer까지 전부 이 가는 weight로 통일 */
.t-big-text{
  font:500 normal clamp(14px,1.1vw,19px)/normal var(--font-en);
}

/* ---------- Layout utilities ---------- */
.grid{
  display:grid;
  grid-template-columns:repeat(var(--grid-columns),minmax(0,1fr));
  column-gap:var(--grid-gutter);
}
.grid-padding{ padding-inline:var(--grid-margin); }

/* ---------- Reveal animation ---------- */
.reveal{
  opacity:0;
  transform:translateY(24px);
  transition:opacity .8s cubic-bezier(.16,.03,.08,1), transform .8s cubic-bezier(.16,.03,.08,1);
}
.reveal.is-visible{
  opacity:1;
  transform:translateY(0);
}
.reveal-stagger.is-visible > *{ transition-delay:calc(var(--i,0) * 60ms); }

@media (prefers-reduced-motion:reduce){
  .reveal{ transition:none; opacity:1; transform:none; }
}

/* ==========================================================================
   1. 상단바 (Top Bar)
   ========================================================================== */
.app-header{
  position:absolute;
  top:calc(var(--grid-gutter) - .2em);
  left:0;
  width:100%;
  z-index:5;
  display:flex;
  justify-content:space-between;
  /* 2026-07-23: 메뉴 버튼(.menu-toggle)이 "Ganada House" 텍스트와 정확히
     같은 세로 중심선에 오도록 align-items:center 추가 — 버튼 크기 자체도
     em 단위로 이 font-size를 그대로 물려받게 해서(아래 .menu-toggle),
     헤더 텍스트 크기가 바뀌면 버튼도 항상 비례해서 같이 커지고 작아짐 */
  align-items:center;
  font-size:clamp(22px,2.2vw,34px); /* 레퍼런스(RXK)처럼 더 크고 굵게 */
  font-weight:700;
}
/* 2026-07-29: 사이트 기본은 헤더가 position:absolute라 스크롤하면 문서와
   함께 같이 사라짐 — about.html/contact-v2.html 등은 이미 각자 페이지에서
   fixed로 오버라이드해 스크롤 중에도 항상 화면 상단에 고정되어 있는데,
   인덱스 페이지만 빠져 있어 대표님 요청으로 동일하게 맞춤("Ganada House"
   타이틀 + 오른쪽 햄버거 메뉴 아이콘, 이 헤더 안의 두 요소가 스크롤해도
   내려가지 않고 계속 화면에 고정). top/left/width/배경은 기존 절대배치
   값을 그대로 물려받아 스크롤 0 지점에서의 위치는 전혀 바뀌지 않고,
   스크롤 중에도 사라지지 않는 동작만 새로 추가됨. z-index는 다른 고정
   헤더 페이지(about.html 등)와 동일하게 50으로 올려 스크롤되는 다른
   콘텐츠 위에 항상 그려지도록 함 */
.index-page .app-header{
  position:fixed;
  z-index:50;
}
.app-header h1{ font:inherit; }
.app-header a{
  pointer-events:auto;
}
/* 2026-07-23: "MENU" 텍스트 링크 대신 3줄(햄버거) 아이콘 버튼으로 교체 —
   사이트 전체 헤더(인덱스+6개 카테고리 페이지)에서 공용으로 사용. 클릭하면
   menu.html(전체 메뉴 전용 검정 배경 페이지)로 이동하는 평범한 <a> 링크라서
   JS 없이도 항상 동작함(뒤로가기/새 탭 열기 등 표준 링크 동작 그대로 유지).
   menu.html 자신의 헤더에서는 같은 버튼에 .is-open을 추가해 X 모양으로 바꿔
   "닫기"를 의미하도록 함(아래 .menu-toggle.is-open 규칙) */
.menu-toggle{
  position:relative;
  /* em 단위 — .app-header에서 물려받는 font-size(clamp(22px,2.2vw,34px))에
     항상 비례해서 "Ganada House" 텍스트와 같은 크기로 스케일됨(기존엔 별도
     clamp로 고정돼 있어서 헤더 텍스트 크기와 어긋날 수 있었음) */
  width:.85em;
  height:.6em;
  padding:0;
  display:inline-block;
  pointer-events:auto;
}
.menu-toggle span{
  position:absolute;
  left:0;
  width:100%;
  height:2px;
  background:currentColor;
  border-radius:1px;
  transition:transform .35s cubic-bezier(.16,1,.3,1), opacity .25s ease, top .35s cubic-bezier(.16,1,.3,1);
}
.menu-toggle span:nth-child(1){ top:0; }
.menu-toggle span:nth-child(2){ top:50%; transform:translateY(-50%); }
.menu-toggle span:nth-child(3){ top:100%; transform:translateY(-100%); }
/* 호버 시 위/아래 줄만 살짝 좌우로 어긋나게 — "눌러보고 싶은" 느낌의 미세한 반응 */
.menu-toggle:hover span:nth-child(1),
.menu-toggle:focus-visible span:nth-child(1){ transform:translateX(-3px); }
.menu-toggle:hover span:nth-child(3),
.menu-toggle:focus-visible span:nth-child(3){ transform:translateY(-100%) translateX(3px); }
/* 열림(X) 상태 — menu.html 헤더의 "닫기" 버튼 전용 */
.menu-toggle.is-open span:nth-child(1){ top:50%; transform:translateY(-50%) rotate(45deg); }
.menu-toggle.is-open span:nth-child(2){ opacity:0; }
.menu-toggle.is-open span:nth-child(3){ top:50%; transform:translateY(-50%) rotate(-45deg); }
.menu-toggle.is-open:hover span:nth-child(1),
.menu-toggle.is-open:focus-visible span:nth-child(1){ transform:translateY(-50%) rotate(45deg); }
.menu-toggle.is-open:hover span:nth-child(3),
.menu-toggle.is-open:focus-visible span:nth-child(3){ transform:translateY(-50%) rotate(-45deg); }
@media (prefers-reduced-motion:reduce){
  .menu-toggle span{ transition:none; }
}
.app-header .menu-link{
  padding-bottom:.1em;
}

/* ==========================================================================
   2. 히어로 섹션
   ========================================================================== */
.hero{
  min-height:100vh;
  min-height:100dvh;
  display:flex;
  align-items:center;
  position:relative;
}
.hero-inner{ padding-block:6vw; width:100%; }

/* .hero-title 자체는 정적 컨테이너 (세로 95% 축소만 항상 적용) */
.hero-title{
  width:100%;
  transform-origin:center top;
  transform:scaleY(.97); /* footer "가나다" 워드마크와 같은 속성(세로 97%) */
}
/* 등장 애니메이션은 줄(.ligne) 4개 각각에 개별로 적용.
   전부 transition-delay:0(동시 시작)이며, 각 .ligne 자신에게 is-in이 붙는 순간 애니메이션 시작.
   .footer-title-kinetic(푸터 매니페스토 문구)도 동일한 효과를 공유함 */
.hero-title .ligne,
.footer-title-kinetic .ligne{
  display:block;
  white-space:nowrap;
  overflow:visible;
  opacity:0;
  transform:translateY(36px);
  transition:opacity .9s cubic-bezier(.16,.03,.08,1), transform .9s cubic-bezier(.16,.03,.08,1);
  transition-delay:0s;
}
/* 35차: 대표님 요청 — "4째줄 빼고 1,2,3줄은 모두 대문자로만 썼는데, 대소문자
   섞어서 수정해줘" — 34차 때는 마지막 줄("Ganada House")만 대문자 강제를
   취소했지만, 이제 4줄 전부 원본 텍스트(HTML) 그대로의 대소문자로 표시.
   .t-h2의 text-transform:uppercase를 .footer-title-kinetic 전체에서 취소
   (히어로 타이틀 쪽은 대상이 아니라서 .footer-title-kinetic에만 한정) —
   :last-child 전용 오버라이드는 이제 전체 규칙에 포함되어 중복이라 삭제 */
.footer-title-kinetic{
  text-transform:none;
}
/* 34차: 4줄 카피가 되면서 .t-h2의 line-height:.8(원래 1줄 대형 타이틀 기준
   타이트한 값)이 줄 사이가 너무 붙어 보인다는 요청 — 이 요소에서만 살짝
   넓힘 */
.footer-title-kinetic{
  line-height:.92;
}
.hero-title .ligne.is-in,
.footer-title-kinetic .ligne.is-in{
  opacity:1;
  transform:translateY(0);
}
@media (prefers-reduced-motion:reduce){
  .hero-title .ligne,
  .footer-title-kinetic .ligne{ transition:none; opacity:1; transform:none; }
}
.hero-title .word{ display:inline-block; }

/* 히어로 타이틀 글자 롤(hover) — 등장 애니메이션과 별개.
   마우스/터치 시 각 글자가 위로 롤되고, 떼면 되돌아옴. ⓒ배지·"/"기호는 롤 대상 아님(그대로).
   .footer-title-kinetic(푸터 매니페스토 문구)도 동일한 효과를 공유함 */
.hero-title .roll,
.footer-title-kinetic .roll{ position:relative; display:inline-block; overflow:hidden; vertical-align:top; }
.hero-title .slash{ vertical-align:top; }
.hero-title .roll .ra,
.hero-title .roll .rb,
.footer-title-kinetic .roll .ra,
.footer-title-kinetic .roll .rb{ display:block; transition:transform .5s cubic-bezier(.16,.03,.08,1); transition-delay:var(--rd,0ms); }
.hero-title .roll .rb,
.footer-title-kinetic .roll .rb{ position:absolute; left:0; top:100%; }
.hero-title.is-rolling .roll .ra,
.hero-title.is-rolling .roll .rb,
.footer-title-kinetic.is-rolling .roll .ra,
.footer-title-kinetic.is-rolling .roll .rb{ transform:translateY(-100%); }
@media (prefers-reduced-motion:reduce){
  .hero-title .roll .ra,
  .hero-title .roll .rb,
  .footer-title-kinetic .roll .ra,
  .footer-title-kinetic .roll .rb{ transition:none; }
}

/* "가나다하우스©" 바로 아래, 한 줄씩 타이핑/삭제를 반복하는 타이프라이터 문구.
   .ligne이 아닌 별도 요소 — main.js의 hover 롤 글자분해 로직이 여기 텍스트를 건드리지 않도록 함.
   폰트 크기는 .hero-title(.t-h1)과 동일한 clamp에서 출발 — 가장 긴 문장이 넘칠 때만
   js/main.js의 fitTypewriter()가 그 문장 기준으로 한 번만 축소함(타이핑 중 크기가 흔들리지 않게) */
.hero-typewriter{
  margin-top:0; /* 2줄-3줄 간격을 1줄-2줄 간격(순수 line-height만으로 생기는 여백)과 동일하게 */
  font:900 normal clamp(9px,7.25vw,139px)/1.05 var(--font-kr);
  letter-spacing:-.03em;
  text-align:center;
  white-space:nowrap;
}
@media (max-width:500px){
  .hero-typewriter{ font:900 normal clamp(9px,7vw,139px)/1.05 var(--font-kr); }
}
.hero-typewriter #tw-cursor{
  display:inline-block;
  width:.06em;
  height:1em;
  margin-left:2px;
  background:currentColor;
  vertical-align:-.12em;
}

/* 모바일 전용 kinetic 박스 — Lottie 컴포지션을 1280x892(박스 원본 비율)로
   재작업했으므로 박스도 동일 비율로 맞춤(크롭/여백 문제 자체가 없음) */
.hero-kinetic{
  aspect-ratio:1280/892;
  margin:clamp(40px,7vw,90px) auto;
  max-width:400px;
  width:100%;
  position:relative;
}
@media (min-width:1025px){
  .hero-kinetic{ display:none; }
}

/* 3단 정보 그리드 */
.hero-info{
  padding-block:3.5vw 0;
  row-gap:40px;
  color:var(--color-noir); /* 얇은 굵기 탓에 회색빛으로 보이던 것을 확실한 블랙으로 고정 */
}
.hero-info .col1{
  grid-column:2 / span 2;
  line-height:1.5;
  font-family:var(--font-en); /* 서비스 목록(.col2bis/.col3)·footer(.footer-data)와 동일한 폰트·크기·자간으로 통일 */
  font-size:clamp(14px,1.1vw,19px);
  font-weight:500;
  letter-spacing:normal;
  word-break:keep-all; /* 36차: 강제 줄바꿈(col1-break) 제거 후 자연 줄바꿈에
    맡기니 "가나다하우스"가 "가 / 나다하우스"처럼 글자 중간에서 잘리는
    문제 발생 — 한글 어절 단위로만 줄이 바뀌도록 고정 */
}
.hero-info .col1-nowrap{ white-space:nowrap; } /* 36차: "지킵니다. 가나다하우스"가
  항상 같은 줄에 붙어 보이도록 이 두 단어만 통째로 줄바꿈 금지 */
/* 기본적으로는 자연스러운 줄바꿈에 맡기고, .col1이 좁은 그리드 컬럼(span:3 / span:2)을
   쓰는 데스크톱 대~광폭 구간에서만 "가나다하우스"가 단어 중간에서 잘리지 않도록
   그 앞에서 강제 줄바꿈 (1024px 이하는 폭이 넓은 flex 1열 레이아웃이라 자연 줄바꿈으로 충분) */
.hero-info .col1 br.col1-break{ display:none; }
@media (min-width:1025px){
  .hero-info .col1 br.col1-break{ display:block; }
}
.hero-info .info-cols{
  display:flex;
  grid-column:7 / span 4;
}
.hero-info .col2bis{ width:50%; }
.hero-info .col2bis li,
.hero-info .col3 li,
.hero-info .col4 li{
  margin-bottom:.2em;
  font-family:var(--font-en);
  font-size:clamp(14px,1.1vw,19px);
  font-weight:500;
  letter-spacing:normal;
}
.hero-info .col4{
  grid-column:11 / span 2;
}
.hero-info .col4 a{ border-bottom:1px solid transparent; }
.hero-info .col4 a:hover{ border-color:currentColor; }

/* 페이지 바깥쪽 여백(헤더와 동일선상)이 아니라, 본문 그리드의 2번째 컬럼(.col1이 시작하는 자리)
   x좌표에 맞춤: --grid-margin(여백) + 1개 컬럼폭 + 1개 거터 = 그리드 2번째 트랙의 시작점.
   .hero-info의 position:relative를 없애서 .hero-scroll의 기준 박스가 .hero가 되도록 했으므로,
   left 값은 뷰포트 왼쪽 끝 기준 절대 좌표임.
   세로 위치(top)는 JS에서 .hero-info 하단 실제 위치를 측정해서 정확히 맞춤 (js/main.js의 positionHeroScroll). */
.hero-scroll{
  position:absolute;
  left:calc(var(--grid-margin) + var(--grid-column-width) + var(--grid-gutter));
  bottom:40px; /* JS 측정 전 기본값, positionHeroScroll()이 즉시 정확한 값으로 덮어씀 */
  font-size:clamp(22px,2.2vw,34px); /* 좌상단 "Ganada House"(.app-header)와 동일 크기·굵기 */
  font-weight:700;
  text-transform:none;
}

@media (max-width:1280px){
  .hero-info .col1{ grid-column:2 / span 3; }
}
@media (max-width:1024px){
  .hero{ min-height:auto; }
  .hero-inner{ padding-block:110px 70px; }
  .hero-scroll{ display:none; }
  .hero-info{
    display:flex;
    flex-direction:column;
    row-gap:60px;
    padding-block:0;
  }
  .hero-info .col1{ padding-right:60px; }
  .hero-info .info-cols{ margin:0 0 -10px; }
  .hero-info .col2bis{
    width:calc(var(--grid-column-width)*7 + var(--grid-gutter)*6);
  }
}

/* ==========================================================================
   중앙 반복 그래픽 — 돌쌓기(테트리스) 애니메이션 박스
   바깥 사각형 테두리 유지 + 내부는 canvas 애니메이션
   ========================================================================== */
.stone-stack{
  position:relative;
  width:100%;
  height:100%;
  border:var(--line) solid var(--color-noir); /* Category 섹션 상단 구분선과 동일한 두께, 내부 칸 구분선과도 1:1 */
  overflow:hidden;
}
.stone-stack canvas{
  display:block;
  width:100%;
  height:100%;
}
.stone-stack.stone-stack--accent{
  aspect-ratio:1280/892;
}

/* ---------- 카테고리 보조 그래픽 — 색깔 라벨 정렬 애니메이션 ----------
   01번 카테고리 옆 자리(stone-stack--accent) 전용. js/category-labels.js가
   .label-stack 안에 라벨 7개를 절대배치로 쌓아 넣는다. 각 라벨 높이는
   테트리스 그리드의 정사각형 한 칸(박스 폭/8)과 동일. 처음엔 각자 무작위
   각도로 삐뚤게 놓여있다가, 스크롤로 화면에 들어오면 맨 아래 라벨부터
   순서대로(위로 갈수록 약간의 딜레이) rotate:0으로 정렬됨 */
:root{
  --label-yellow:#e8b400;
  --label-pink:#f0a8d0;
  --label-blue:#4fb0e0;
  --label-white:#f4f3ed;
  --label-red:#f16a58;
}
.label-stack{
  position:relative;
  width:100%;
  height:100%;
}
.label-stack .label{
  position:absolute;
  left:0;
  width:100%;
  display:flex;
  align-items:center;
  justify-content:center;
  overflow:hidden;
  font:700 normal clamp(11px,1.7vw,20px)/1 var(--font-en);
  color:var(--color-noir);
  text-align:center;
  white-space:nowrap;
  text-overflow:ellipsis;
  padding-inline:.5em;
  transform:rotate(var(--rot,0deg));
  transition:transform .7s cubic-bezier(.16,.8,.24,1);
}
.label-stack .label.is-aligned{
  transform:rotate(0deg);
}
@media (prefers-reduced-motion:reduce){
  .label-stack .label{ transition:none; }
}

/* ---------- 메인 자리(Lottie) ----------
   hero-kinetic(모바일/중간 폭)과 Category ligne1(큰 화면 폭)이 공유하는 자리.
   js/hero-lottie.js가 .lottie-target 안에 애프터이펙트로 만든 Lottie
   애니메이션(assets/lottie/hero-ganada.json)을 렌더링해 넣는다. 2차 AE
   작업본부터 컴포지션 자체가 1280x892(박스 원본 비율)로 재구성되어 있어
   컨텐츠 비율 = 박스 비율이라 크롭/여백이 구조적으로 생기지 않는다.
   배경은 그래도 순검정(#000)으로 유지 — 애니메이션 배경과 완전히
   동일하게 맞춰서 혹시 모를 서브픽셀 오차도 티 나지 않게 함 */
.stone-stack--primary{
  background:#000;
  color:var(--color-blanc);
}
.lottie-target{
  width:100%;
  height:100%;
}
.lottie-target svg{
  display:block;
  width:100%;
  height:100%;
}

/* ==========================================================================
   4. Category 섹션 (Selected Work → Category)
   ========================================================================== */
.category{
  padding-block:0 0;
}
.category .ligne{
  border-top:var(--line) solid var(--color-noir);
  display:flex;
  padding-block:.7vw;
}
.category .cell{
  position:relative;
  width:25%;
  aspect-ratio:1280/892;
}
.category h2{
  margin:var(--grid-gutter) 0 0;
  font:500 normal clamp(14px,1.1vw,19px)/normal var(--font-en);
  text-transform:none;
  letter-spacing:0;
}
/* 최상단 구분선은 .category(섹션 자체, 화면 끝까지 꽉 참) 대신 ligne1(grid-padding 안쪽 요소)에
   둬서, 아래 다른 ligne 구분선들과 동일하게 좌우에 grid-margin만큼의 여백이 생기게 함 */
.category .ligne1{ border-top:var(--line) solid var(--color-noir); }
@media (max-width:639px){
  /* 모바일(640px 미만)에서만 숨김 — 중간(640~1024)·큰(1024 초과)에서는 유지 */
  .category .ligne1{ border-top:0; }
}
/* ligne1 첫 번째 칸(Lottie 메인 자리) — 2차 AE 작업본이 1280x892(박스
   원본 비율)로 나와서 별도 정사각형 오버라이드가 더 이상 필요 없음.
   .stone-stack.stone-stack--accent{aspect-ratio:1280/892} 그대로 적용됨 */
.category .ligne1 .cell:last-child{ margin-left:50%; }
.category .ligne2 .cell{ margin-left:25%; }
.category .ligne3 .cell{ margin-left:50%; }
.category .ligne4 .cell{ margin-left:25%; }
.category .ligne5 .cell:last-child{ margin-left:25%; }
.category .ligne6 .cell{ margin-left:25%; }
.category .ligne7 .cell{ margin-left:50%; }

/* 카테고리 라벨(01~06, 석재시공 등)도 서비스 목록(.hero-info li)과 같은 폰트·굵기·자간으로 통일 */
.category .index{
  position:absolute;
  top:var(--grid-gutter);
  left:calc(100% + var(--grid-gutter));
  font:500 normal clamp(14px,1.1vw,19px)/normal var(--font-en);
  letter-spacing:normal;
  white-space:nowrap;
}
/* 카테고리 제목 + 세부 항목 리스트를 함께 담는 래퍼 — 01번만 세부 항목 리스트가
   있어서 래퍼 단위로 절대배치함(02~06은 이 래퍼 없이 h3가 직접 절대배치됨) */
.category .cat-title{
  position:absolute;
  bottom:var(--grid-gutter);
  left:calc(100% + var(--grid-gutter));
  white-space:nowrap;
  /* 2026-07-21: 슬라이드쇼에 동영상(석재시공 01번)을 넣은 뒤로 "마우스 오버로는
     세부 항목 리스트가 안 나오고 클릭(포커스)해야만 잠깐 나온다"는 문제 보고 —
     Safari/Chrome 계열 브라우저에서 <video>가 하드웨어 가속 합성 레이어로
     승격되면서, 같은 .cell 안의 형제 요소(.cat-title)보다 위에 그려지며 마우스
     오버 히트테스트를 가로채는 경우가 있음(비디오 자체는 pointer-events:none
     이라 클릭은 통과되지만, 실제 :hover 판정에는 영향을 줄 수 있는 브라우저별
     차이가 있어 안전하게 z-index로 항상 위에 오도록 명시) */
  z-index:5;
}
/* 기본: h3 자신이 절대배치(02~06 전부 여기 해당) */
.category h3{
  position:absolute;
  bottom:var(--grid-gutter);
  left:calc(100% + var(--grid-gutter));
  font:500 normal clamp(14px,1.1vw,19px)/normal var(--font-en);
  letter-spacing:normal;
  white-space:nowrap;
}
/* .cat-title 안의 h3(01번)는 래퍼가 이미 위치를 잡아주므로 자기 자신은 그냥 문서 흐름대로
   (position:static) — 그래야 h3 위로 세부 리스트가 붙어 나올 수 있음 */
.category .cat-title h3{
  position:static;
  bottom:auto;
  left:auto;
}
/* "Stone" 같은 영문 라벨: 한글 제목 바로 옆에 나란히, Category 타이틀과 동일한 스타일 */
.category h3 .en{
  display:inline;
  margin-left:.5em;
  font-family:var(--font-en);
  font-weight:500;
  font-size:1em;
  opacity:1;
  letter-spacing:normal;
}

/* ---------- 카테고리 제목 호버 시 세부 시공 항목 리스트 등장 ----------
   h3(석재시공 Stone) 위로 세부 항목(대리석보수 등)이 아래에서 위로 순서대로
   슬라이드+페이드 — 히어로 자모 애니메이션과 같은 "아래→위" 모션 언어로 통일.
   가장 아래(h3에 가장 가까운) 항목부터 먼저 올라오도록 delay를 역순으로 줌 */
.category .sub-list-wrap{
  position:relative;
  max-height:0;
  overflow:hidden;
  transition:max-height .5s cubic-bezier(.16,1,.3,1);
}
.category .cat-title:hover .sub-list-wrap,
.category .cat-title:focus-within .sub-list-wrap{
  max-height:220px;
}
.category .sub-list{
  list-style:none;
  margin:0 0 3px; /* 세부 항목끼리의 간격(gap:3px)과 동일하게 — h3 제목과의 간격만 유독 넓어 보이지 않도록 */
  padding:0; /* h3 제목과 왼쪽 정렬을 맞추려고 좌측 들여쓰기 제거 */
  display:flex;
  flex-direction:column;
  gap:3px;
}
.category .sub-list li{
  /* h3(석재시공 Stone)와 폰트 크기를 동일하게 통일 */
  font:500 normal clamp(14px,1.1vw,19px)/normal var(--font-en);
  letter-spacing:normal;
  opacity:0;
  transform:translateY(8px);
  transition:opacity .4s ease, transform .4s cubic-bezier(.16,1,.3,1), color .2s ease, text-decoration-color .2s ease;
}
.category .sub-list li:hover{ text-decoration:underline; }
/* 2026-07-21: 세부 항목(외벽석재 등) 클릭 시 세부페이지로 이동해야 한다는
   요청으로 li 안에 <a>를 추가함 — 링크의 기본 파란색/밑줄을 지우고
   li와 완전히 동일하게 보이도록(밑줄은 위 li:hover에서 그대로 담당) */
.category .sub-list li a{
  color:inherit;
  text-decoration:none;
  display:block;
}
.category .cat-title:hover .sub-list li,
.category .cat-title:focus-within .sub-list li{
  opacity:1;
  transform:translateY(0);
}
.category .sub-list li:nth-last-child(1){ transition-delay:0s; }
.category .sub-list li:nth-last-child(2){ transition-delay:.05s; }
.category .sub-list li:nth-last-child(3){ transition-delay:.1s; }
.category .sub-list li:nth-last-child(4){ transition-delay:.15s; }
.category .sub-list li:nth-last-child(5){ transition-delay:.2s; }
.category .sub-list li:nth-last-child(6){ transition-delay:.25s; }
.category .sub-list li:nth-last-child(7){ transition-delay:.3s; }
.category .cat-title:not(:hover):not(:focus-within) .sub-list li{ transition-delay:0s !important; }
@media (prefers-reduced-motion:reduce){
  .category .sub-list li{ transition:none; }
}

/* ---------- 카테고리 제목 글자 롤(hover) ----------
   히어로 타이틀(가나다하우스)과 동일한 "드르륵" 롤 모션 — 등장 애니메이션이 아니라
   마우스를 올릴 때(건드릴 때)마다 매번 재생됨. 움직이는 점(dot) 대신 이 효과로 대체.
   js/category-subnav.js가 h3 텍스트를 글자 단위 .roll/.ra/.rb 스팬으로 한 번 감싸두면,
   나머지는 순수 CSS :hover/:focus-within로 처리(히어로처럼 JS로 클래스 토글할 필요 없음) */
.category h3 .roll{ position:relative; display:inline-block; overflow:hidden; vertical-align:top; }
.category h3 .roll .ra,
.category h3 .roll .rb{ display:block; transition:transform .5s cubic-bezier(.16,.03,.08,1); transition-delay:var(--rd,0ms); }
.category h3 .roll .rb{ position:absolute; left:0; top:100%; }
.category h3:hover .roll .ra,
.category h3:hover .roll .rb,
.category .cat-title:hover h3 .roll .ra,
.category .cat-title:hover h3 .roll .rb,
.category .cat-title:focus-within h3 .roll .ra,
.category .cat-title:focus-within h3 .roll .rb{
  transform:translateY(-100%);
}
@media (prefers-reduced-motion:reduce){
  .category h3 .roll .ra,
  .category h3 .roll .rb{ transition:none; }
}

/* ---------- [테스트 A → 채택] 이미지 슬라이드쇼 (01) ----------
   기본은 사이트 전체 무드와 맞춘 흑백(grayscale) — 넘기려고 터치하는 순간
   컬러로 반짝였다가(.is-touched), 새 이미지가 자리 잡으면 다시 흑백으로 */
.category .slide-wrap{
  position:absolute;
  inset:0;
  cursor:pointer;
}
.category .slide-track{
  display:flex;
  width:100%;
  height:100%;
  transition:transform .7s cubic-bezier(.65,0,.35,1);
  /* Safari에서 flex 자식 폭이 소수점 px(예: 349.921875px)로 계산되면, 슬라이드가
     넘어갈 때 인접 슬라이드 경계에서 배경색(크림톤)이 실선처럼 살짝 비치는
     서브픽셀 이음선(seam) 현상이 생길 수 있음 — GPU 합성 레이어를 강제해 방지 */
  transform:translateZ(0);
  -webkit-backface-visibility:hidden;
  backface-visibility:hidden;
}
.category .slide-track img,
.category .slide-track video{
  display:block;
  flex:0 0 100%;
  width:100%;
  height:100%;
  object-fit:cover;
  object-position:center;
  filter:grayscale(1);
  transition:filter .35s ease;
  transform:translateZ(0);
  -webkit-backface-visibility:hidden;
  backface-visibility:hidden;
}
.category .slide-track video{
  pointer-events:none;
}
.category .slide-wrap.is-touched .slide-track img,
.category .slide-wrap.is-touched .slide-track video{
  filter:grayscale(0);
}
.category .slide-dots{
  position:absolute;
  bottom:var(--grid-gutter);
  left:var(--grid-gutter);
  display:flex;
  align-items:center;
  gap:5px;
  z-index:2;
}
.category .slide-dots span{
  width:4px;
  height:4px;
  border-radius:50%;
  background:rgba(244,243,237,.55);
  transition:background .3s ease, transform .3s ease;
  cursor:pointer;
}
.category .slide-dots span.active{
  background:var(--color-blanc);
  transform:scale(1.3);
}
@media (prefers-reduced-motion:reduce){
  .category .slide-track img,
  .category .slide-track video{ transition:none; }
}

/* [비교 테스트 옵션 2] 얇은 세그먼트 틱 바 — 02번.
   동그란 점 대신 가늘고 긴 직사각형 틱. 활성 틱만 더 길고 진하게 —
   비포/애프터 슬라이더에 적용한 "얇은 선" 무드와 통일감을 주려는 시도 */
.category .slide-ticks{
  position:absolute;
  bottom:var(--grid-gutter);
  left:50%;
  transform:translateX(-50%);
  display:flex;
  align-items:center;
  gap:6px;
  z-index:2;
}
.category .slide-ticks span{
  width:14px;
  height:2px;
  background:rgba(244,243,237,.45);
  cursor:pointer;
  transition:background .3s ease, width .3s ease;
}
.category .slide-ticks span.active{
  width:22px;
  background:var(--color-blanc);
}

/* [비교 테스트 옵션 4] "01 — 05" 숫자 카운터 + 하단 얇은 진행 라인 — 03번.
   카테고리 인덱스 번호(01,02..) 스타일과 통일감 있는 얇은 텍스트 카운터를
   좌측 하단에, 박스 맨 아래 가장자리엔 재생바 같은 얇은 진행 라인을 깐다 */
.category .slide-counter-wrap{
  position:absolute;
  inset:0;
  pointer-events:none;
  z-index:2;
}
.category .slide-counter{
  position:absolute;
  bottom:var(--grid-gutter);
  left:var(--grid-gutter);
  display:flex;
  align-items:baseline;
  gap:6px;
  font:500 normal clamp(12px,1vw,15px)/1 var(--font-en);
  color:var(--color-blanc);
}
.category .slide-counter-now{ color:var(--color-blanc); }
.category .slide-counter-sep{ opacity:.5; }
.category .slide-counter-total{ opacity:.6; }
.category .slide-progress{
  position:absolute;
  left:0;
  right:0;
  bottom:0;
  /* 카테고리 구획 사이 블랙 라인(.ligne1 border-top)과 동일한 두께/색 — var(--line), var(--color-noir) */
  height:var(--line);
  background:rgba(23,23,23,.25);
}
.category .slide-progress-bar{
  display:block;
  height:100%;
  width:0%;
  background:var(--color-noir);
  transition:width .5s cubic-bezier(.65,0,.35,1);
}

/* ---------- [B2/B3] 배경 영상 (01번·04번 옆 액센트 박스) ----------
   2026-07-21: 조건 — 소리 없이 자동재생(autoplay/muted/playsinline),
   무한반복(loop), 컨트롤러 완전 숨김(controls 속성 자체를 안 씀),
   박스 크기에 맞춰 비틀림 없이 꽉 채움(object-fit:cover, 필요시 크롭),
   클릭해도 아무 반응 없음(pointer-events:none) */
.stone-stack--bgvideo video{
  display:block;
  width:100%;
  height:100%;
  object-fit:cover;
  object-position:center;
  pointer-events:none;
  /* 2026-07-21 추가: "동영상도 이미지처럼 첨엔 채도 빠진 것처럼 나오다가
     마우스오버시 컬러로" — .category .media img.ph와 완전히 동일한 흑백↔컬러
     전환 패턴 재사용(기본 grayscale(1) → hover 시 grayscale(0)) */
  filter:grayscale(1);
  transition:filter .25s; /* 2026-07-21: .4s→.15s(너무 빠름 아님, 사용자 요청)→.25s로 재조정 */
}
.stone-stack--bgvideo:hover video{
  filter:grayscale(0);
}
/* 2026-07-21 추가: "b2,b3 박스 테두리를 없애줘" — .stone-stack 공통 규칙의
   border(var(--line) solid var(--color-noir))를 이 두 박스에서만 제거.
   다른 곳(Lottie 메인 자리 등)의 .stone-stack 테두리는 그대로 유지되므로
   .stone-stack--bgvideo로 범위를 좁혀서 오버라이드 */
.stone-stack--bgvideo{
  border:0;
}

/* ---------- [B2] 시공 전/후 비교 슬라이더 — img-comparison-slider (04번 옆 액센트 박스) ----------
   sneas/img-comparison-slider(MIT, 무료/오픈소스) 사용 — 기본 제공 드래그가 우리가 직접 만든
   것보다 훨씬 부드러워서 채택. 라이브러리가 제공하는 CSS 커스텀 프로퍼티로 스타일 조정:
   - 기본 동그란 핸들(그립)은 opacity 0으로 완전히 숨김 → 선(divider)만 남음
   - divider(선) 두께는 박스 테두리(--line)와 동일하게, 색은 검정(--color-noir)으로 */
.stone-stack--ba2 img-comparison-slider{
  --divider-width: var(--line);
  --divider-color: var(--color-noir);
  --default-handle-opacity: 0;
  display:block;
  width:100%;
  height:100%;
}
/* first/second 슬롯은 반드시 img 태그 그대로 둬야 함 — 라이브러리 내부 shadow DOM이
   ::slotted(img)로 스타일(절대배치+클리핑)을 입히는데, div로 한 번 감싸면 그 스타일이
   안 먹어서 second(after) 쪽이 겹쳐지지 않고 아래로 밀려나는 버그가 있었음(수정 완료) */
.stone-stack--ba2 img-comparison-slider img{
  display:block;
  width:100%;
  height:100%;
  object-fit:cover;
  object-position:center;
}
/* BEFORE/AFTER 텍스트 배지 대신 "<"/">" 기호만 깔끔하게 — 슬라이더 내부(슬롯)가 아니라
   박스(.stone-stack--ba2) 기준으로 양쪽 모서리에 고정 오버레이로 얹음(드래그 위치와
   무관하게 항상 같은 자리) */
.ba2-label{
  position:absolute;
  bottom:var(--grid-gutter);
  font:500 normal clamp(15px,1.3vw,20px)/1 var(--font-en);
  color:var(--color-noir);
  z-index:2;
  pointer-events:none;
}
.ba2-label-before{ left:var(--grid-gutter); }
.ba2-label-after{ right:var(--grid-gutter); }

/* ---------- (미사용) 02번에 테스트했던 자체 제작 비포/애프터 슬라이더 ----------
   지금은 02가 기본 이미지로 되돌아갔고, B2는 위 img-comparison-slider로 대체되어
   아래 .ba-wrap 계열 스타일은 현재 어디서도 쓰이지 않음. 나중에 다른 자리에
   다시 쓸 수도 있어 일단 남겨둠(js/category-beforeafter.js도 동일하게 대기 상태) */
.category .ba-wrap{
  position:absolute;
  inset:0;
  cursor:ew-resize;
  touch-action:none;
}
.category .ba-wrap img{
  position:absolute;
  inset:0;
  height:100%;
  object-fit:cover;
  object-position:center;
  display:block;
  user-select:none;
  -webkit-user-drag:none;
  pointer-events:none;
}
.category .ba-after{ width:100%; }
.category .ba-before-clip{
  position:absolute;
  inset:0;
  width:50%;
  overflow:hidden;
}
.category .ba-handle{
  position:absolute;
  top:0;
  bottom:0;
  left:50%;
  width:0;
  transform:translateX(-50%);
  display:flex;
  align-items:center;
  justify-content:center;
  z-index:2;
}
.category .ba-handle-line{
  position:absolute;
  top:0;
  bottom:0;
  left:50%;
  width:1px;
  transform:translateX(-50%);
  background:var(--color-blanc);
}
.category .ba-handle-grip{
  position:relative;
  width:28px;
  height:28px;
  border-radius:50%;
  background:var(--color-blanc);
  color:var(--color-noir);
  display:flex;
  align-items:center;
  justify-content:center;
  font-size:12px;
  transition:transform .2s ease;
}
.category .ba-wrap.dragging .ba-handle-grip{ transform:scale(1.12); }
.category .ba-label{
  position:absolute;
  bottom:var(--grid-gutter);
  font:500 normal clamp(10px,0.75vw,12px)/normal var(--font-en);
  letter-spacing:.06em;
  color:var(--color-blanc);
  background:rgba(23,23,23,.55);
  padding:2px 8px;
  z-index:2;
  pointer-events:none;
}
.category .ba-label-before{ left:var(--grid-gutter); }
.category .ba-label-after{ right:var(--grid-gutter); }
@media (prefers-reduced-motion:reduce){
  .category .slide-track{ transition:none; }
}

.category .item{
  display:block;
  width:100%;
  height:100%;
  position:relative;
}
.category .media{
  display:block;
  width:100%;
  height:100%;
  overflow:hidden;
  position:relative;
  /* 2026-07-21: 위 .cat-title z-index 조치와 짝 — 동영상 슬라이드가 생기면서
     이 박스(overflow:hidden) 자신도 함께 합성 레이어로 승격시켜, 내부 video의
     하드웨어 가속 레이어가 이 박스의 클리핑 경계를 무시하고 밖으로 삐져나오는
     일부 브라우저의 알려진 렌더링 버그를 방지 */
  transform:translateZ(0);
  -webkit-backface-visibility:hidden;
  backface-visibility:hidden;
}
/* 카테고리 사진: 틀 비율이 반응형으로 바뀌어도(가로↔세로) 사진이 찌그러지지 않고
   중앙 기준으로 꽉 차게(object-fit:cover) — 넘치는 부분만 잘림. 기본 흑백 → hover 시 컬러 */
.category .media img.ph{
  width:100%;
  height:100%;
  object-fit:cover;
  object-position:center;
  display:block;
  filter:grayscale(1);
  transition:filter .4s;
}
.category .item:hover .media img.ph,
.category .item:focus-visible .media img.ph{
  filter:grayscale(0);
}
/* hover-effect(WebGL)가 .media 안에 직접 넣는 canvas — 꽉 차게, inline 기본 여백 제거 */
.category .media canvas{
  display:block;
}

@media (max-width:1024px){
  .category .ligne{ padding-block:10px; }
  .category .ligne1{ padding:0 0 20px; }
  .category .ligne1 .cell:last-child{ margin:0; }
  .category .stone-stack,
  .category .ligne1 .cell:first-child{ display:none; }
  /* 2026-08-04(추가): ligne2(석재시공 옆 B2 영상)·ligne5(트렌치 옆 B3 영상)처럼
     실제 카테고리 카드 옆에 장식용 .stone-stack만 담긴 "빈 셀"이 함께 있는
     줄에서는, 그 장식 셀이 내용 없이도 width:100%를 그대로 요구해서 flex
     한 줄 안에서 진짜 카드와 폭을 반씩 나눠 가져버림(카드 이미지가 절반
     너비로 찌그러져 보이는 원인) — 장식만 담긴 셀 자체를 통째로 문서
     흐름에서 제거해서 진짜 카드가 항상 폭 100%를 온전히 쓰게 함 */
  .category .cell:has(.stone-stack){ display:none; }
  /* 2026-08-04: 대표님이 카카오톡(모바일)에서 발견 — 세부 항목이 6개인
     카테고리(석재시공, 도로안전시설물)에서 제목/세부목록이 위 카드 사진을
     덮어버리는 버그. 원인: 기존엔 .index/.cat-title가 이미지 옆(오른쪽)에
     position:absolute로 "떠 있는" 형태였고, .cat-title은 bottom기준으로
     고정된 채 내용이 많아질수록 위쪽으로만 자라나서 실제 문서 흐름(카드
     높이)에는 전혀 반영되지 않았음 — 세부 항목이 적을 땐(3~5개) 우연히
     이미지 높이 안에 들어와 안 보였을 뿐, 항목이 늘어나면(6개) 곧바로 위
     카드를 침범. position:static으로 바꿔서 문서 흐름에 실제로 반영되게
     하는 것이 핵심 수정(펼침/접힘 여부와 무관하게 항상 유지) */
  /* 2026-08-04(재수정): 세부 항목 리스트까지 접힘 없이 항상 펼쳐 보이게 했더니 대표님이
     보시기에 기존 데스크톱처럼 "사진 옆에 텍스트가 있는 2단(2컬럼) 느낌"이
     사라져서 아쉽다고 하심 — 겹침 버그(문서 흐름에 반영 안 되는 절대배치)는
     그대로 두되, 사진은 왼쪽/제목+세부목록은 오른쪽에 나란히 두는 grid
     2컬럼 레이아웃으로 재구성. 핵심은 grid는 각 행(row) 높이가 오른쪽 칸의
     실제 내용 높이(세부 항목 개수)에 맞춰 "자동으로" 늘어난다는 것 — absolute
     배치와 달리 문서 흐름에 그대로 반영되므로, 항목이 몇 개든(6개든 그 이상
     이든) 사진 카드를 침범할 수가 없음. 즉 2단 느낌은 살리고 겹침 버그의
     원인(절대배치)만 제거 */
  .category .cell{
    margin:0 !important;
    width:100% !important;
    aspect-ratio:auto;
    display:grid;
    /* 2026-08-04(재재수정): 55%에서 다시 130% 추가 확대(55%→71.5%) —
       1:1 정사각형 비율은 그대로라 폭이 커진 만큼 세로도 같이 커짐 */
    grid-template-columns:71.5% 1fr;
    grid-template-rows:auto minmax(0,1fr);
    column-gap:4vw;
    align-items:start;
  }
  .category .item{
    grid-column:1;
    grid-row:1 / 3;
    width:100%;
  }
  .category .media{
    /* 2026-08-04(재수정): 3:4(세로로 긴 비율) → 1:1(정사각형)로 대표님 요청 —
       사진 박스 세로폭이 짧아지면서 사진 칼럼 쪽에 여유(빈 공간)가 생겨,
       세부 항목이 펼쳐져도 시각적으로 더 여유 있게 보임(겹침 자체는 이미
       grid 흐름 구조라 비율과 무관하게 안 생기지만, 여백 확보 차원) */
    aspect-ratio:1/1;
    width:100%;
  }
  .category .index{
    grid-column:2;
    grid-row:1;
    position:static;
    margin-top:0;
    white-space:normal;
  }
  .category h3{
    position:static;
    white-space:normal;
  }
  .category .cat-title{
    grid-column:2;
    grid-row:2;
    align-self:end; /* 2026-08-04: 사진이 1:1로 길어진 만큼, 제목이 가운데로
      떠 보이지 않고 데스크톱처럼 사진 하단에 맞춰 아래쪽에 위치하도록.
      index(위)와는 별개의 행(row2)에 있어서 제목이 아무리 길어져도(세부
      항목이 펼쳐져도) index 쪽을 침범하지 않음 — row2 자체가 필요한
      만큼 늘어날 뿐, index가 있는 row1과는 항상 분리되어 있음 */
    position:static;
    margin-top:4px;
    white-space:normal;
    display:flex;
    flex-direction:column;
  }
  /* 2026-08-04(재수정): "세부 항목이 펼쳐질 때 제목은 가만히 있고, 목록만
     그 위로 펼쳐져야 한다"는 요청으로 order:-1(제목을 항상 맨 위로 고정)을
     제거하고 마크업 원래 순서(세부목록 먼저, 제목 나중)로 되돌림 —
     .cat-title 박스 자체가 align-self:end로 "아래쪽 끝"이 고정돼 있고,
     제목(h3)이 그 박스의 맨 마지막(가장 아래) 자식이라, 박스 아래쪽 끝은
     항상 제목의 아래쪽 끝과 일치함 → 목록이 늘어나든 줄어들든 제목의
     화면상 위치는 절대 안 바뀌고, 목록만 제목 위쪽으로 펼쳐짐(데스크톱과
     동일한 동작). 이전에 order:-1을 넣었던 이유(펼친 뒤 같은 자리를 다시
     탭하면 밀려난 제목 대신 목록 링크가 눌리는 문제)도 이걸로 자동 해결—
     제목 위치 자체가 안 바뀌니 "같은 자리를 다시 탭"하면 항상 제목이 그
     자리에 그대로 있음 */
  /* 2026-08-04(재수정): 세부 항목 리스트는 데스크톱과 똑같이 평소엔 접혀 있다가
     펼쳐지는 방식을 유지 — 대신 터치 기기는 마우스가 없어서 ":hover"가 아예
     안 먹고, 터치 시 대신 걸리는 ":focus-within"만으로는 다른 곳을 터치해도
     포커스가 그대로 남아 "펼쳐진 채로 안 닫히는" 문제가 있었음(대표님 확인).
     js/category-mobile-toggle.js가 제목을 탭할 때마다 .is-open 클래스를 직접
     붙이고 떼는 방식으로 펼침/닫힘을 관리(브라우저의 :hover/:focus-within에
     기대지 않고 확실하게 동작하도록) — 다른 카테고리를 탭하면 이전 것부터
     닫고, 바깥을 탭하면 전부 닫음. 닫힐 때 스르륵 줄어드는 애니메이션은
     이미 있는 max-height 트랜지션을 그대로 재사용. */
  /* 터치 기기는 hover가 남아있는 채로 굳어버리는 경우가 있어(원래 버그의
     원인) 모바일 폭에서는 :hover/:focus-within로는 열리지 않게 막고,
     오직 JS가 붙이는 .is-open 클래스로만 펼침 여부를 결정 */
  .category .cat-title:hover .sub-list-wrap,
  .category .cat-title:focus-within .sub-list-wrap{
    max-height:0;
  }
  .category .cat-title.is-open .sub-list-wrap{
    max-height:320px;
  }
  /* max-height만으로는 안 됨 — 개별 항목(li) 자체도 기본은 opacity:0로 숨겨져
     있다가 hover/focus-within일 때만 보이도록 되어 있어서, 위에서 그 두
     트리거를 꺼버린 만큼 .is-open에서도 항목이 보이도록 별도로 켜줘야 함 */
  .category .cat-title.is-open .sub-list li{
    opacity:1;
    transform:translateY(0);
  }
  /* 2026-08-04: 도로안전시설물(05, ligne6)만 영문 라벨("Road Safety")까지
     붙으면 한글보다 훨씬 길어져서 오른쪽 칼럼 폭 밖으로 튀어나가 보임 —
     이 카테고리만(다른 5개는 그대로) 모바일에서 영문 라벨을 뺌 */
  .category .ligne6 h3 .en{
    display:none;
  }
}
@media (max-width:420px){
  /* 아주 좁은 폰 화면(420px 미만)에서는 55%/45% 2단이 너무 빡빡해서
     세부 항목 텍스트가 줄바꿈이 잦아질 수 있어 컬럼 비율만 살짝 조정
     (기본값과 동일한 비율로 130% 확대 반영: 38%→49%) */
  .category .cell{
    grid-template-columns:63.7% 1fr;
    column-gap:3vw;
  }
}

/* ==========================================================================
   5 / 6. 푸터 + 대형 워드마크
   ========================================================================== */
.app-footer{
  padding-block:0 6vw; /* 워드마크 아래 숨 쉴 여백 — 화면 맨 아래에 딱 붙어 잘린 듯 보이던 것을 넉넉하게 */
}
.footer-manifesto{
  border-top:var(--line) solid var(--color-noir);
  padding-block:8vw;
}
/* white-space:pre-line은 예전 <br> 방식(줄바꿈 문자를 그대로 줄바꿈으로 렌더링)일 때만
   필요했음 — 지금은 .ligne(span) 구조로 줄을 나누는데, 이 속성이 남아있으면 태그
   사이 소스코드 줄바꿈(들여쓰기용 개행 문자)까지 빈 줄로 렌더링돼서 행간이 두 배로
   벌어져 보였음(줄 사이에 보이지 않는 빈 줄이 하나씩 더 끼는 것과 같은 효과).
   .ligne가 알아서 줄바꿈을 담당하므로 이 속성 자체가 더는 필요 없어 제거함 */

/* footer-data: 2단 배치.
   왼쪽 = location(위) + credit(아래·바닥 정렬),  오른쪽 = 링크 세로 컬럼(우측 정렬).
   credit("Coded by/Afternoon")은 왼쪽 아래에서 링크 목록의 바닥선(빨간 라인)에 맞춰 정렬됨. */
.footer-data{
  border-top:var(--line) solid var(--color-noir);
  display:grid;
  grid-template-columns:auto 1fr;   /* 왼쪽 텍스트 | 오른쪽 링크 */
  grid-template-rows:auto auto;
  align-items:start;
  column-gap:var(--grid-gutter);
  padding-block:var(--grid-gutter);
}
.footer-data .location{ font:inherit; grid-column:1; grid-row:1; }
.footer-data .links{
  grid-column:2;
  grid-row:1 / 3;                   /* 오른쪽에서 두 행에 걸쳐 세로 배치 */
  justify-self:end;
  display:flex;
  flex-direction:column;
  align-items:flex-end;            /* 우측 정렬 */
  text-align:right;
  gap:.2em;
}
/* 푸터 링크(인스타/유튜브/블로그/한바름설비공사/카카오톡) 호버 —
   카테고리 제목(01~06)에 이미 적용된 것과 완전히 동일한 글자 롤("드르륵") 효과.
   js/category-subnav.js가 링크 텍스트를 .roll/.ra/.rb 스팬으로 감싸두면
   나머지는 카테고리와 동일하게 순수 CSS :hover/:focus-within로 처리 */
.footer-data .links a{ display:block; }
.footer-data .links a .roll{ position:relative; display:inline-block; overflow:hidden; vertical-align:top; }
.footer-data .links a .roll .ra,
.footer-data .links a .roll .rb{ display:block; transition:transform .5s cubic-bezier(.16,.03,.08,1); transition-delay:var(--rd,0ms); }
.footer-data .links a .roll .rb{ position:absolute; left:0; top:100%; }
.footer-data .links a:hover .roll .ra,
.footer-data .links a:hover .roll .rb,
.footer-data .links a:focus-visible .roll .ra,
.footer-data .links a:focus-visible .roll .rb,
.footer-data .links a.is-rolling .roll .ra,
.footer-data .links a.is-rolling .roll .rb{
  transform:translateY(-100%);
}
@media (prefers-reduced-motion:reduce){
  .footer-data .links a .roll .ra,
  .footer-data .links a .roll .rb{ transition:none; }
}
.footer-data .credit{
  grid-column:1;
  grid-row:2;
  align-self:end;                  /* 왼쪽 아래 = 링크 바닥선(빨간 라인)에 맞춤 */
  text-align:left;
}
.footer-data .credit a{ text-decoration:underline; }

/* 넓은 데스크탑(1200px 이상): 레퍼런스처럼 footer를 가로 한 줄로.
   location 왼쪽 - 링크 5개 가로로 고르게 펼침 - credit 오른쪽.
   1200px 미만에서는 위의 기본 2단(grid) 배치가 그대로 유지됨(폰 포함). */
@media (min-width:1200px){
  .footer-data{
    display:flex;
    align-items:flex-end;
    justify-content:space-between;
    gap:var(--grid-gutter);
  }
  .footer-data .links{
    flex:1;
    flex-direction:row;
    flex-wrap:wrap;
    justify-content:space-between;
    align-items:flex-end;
    text-align:left;
    gap:.4em 1em;
    padding-inline:2em;
  }
  .footer-data .credit{
    text-align:right;
  }
}

@media (max-width:1024px){
  .footer-manifesto{ padding-block:50px; }
}

/* footer-data(위치/링크/크레딧)는 1024px가 아니라 훨씬 좁은 폭(640px)에서만 세로로 쌓임.
   레퍼런스 사이트는 태블릿/좁은 데스크톱 폭에서도 계속 한 줄(가로) 배치를 유지하는데,
   여기 breakpoint를 다른 섹션과 같은 1024px로 맞춰뒀던 탓에 레퍼런스라면 아직 가로 배치일
   폭에서 우리만 먼저 세로로 꺾여버렸음 — footer-data 전용으로 훨씬 좁은 기준을 따로 둠 */
@media (max-width:640px){
  /* 레퍼런스 사이트는 진짜 폰 폭에서도 footer 2단(왼쪽 location+credit / 오른쪽 링크)을
     그대로 유지함 -> 세로로 쌓지 않고 모든 폭에서 2단 grid 유지. 좁은 화면에선 여백만 축소. */
  .footer-data{
    padding-block:20px;
  }
}

.footer-wordmark{
  display:block;
  width:100%;
  position:relative;
  font:900 normal clamp(60px,17vw,340px)/.8 var(--font-kr);
  text-align:center;
  letter-spacing:-.01em;
  padding-block:.05em 0;
  white-space:nowrap;
  /* 순수 장식용 대형 텍스트(가나다) — 글자 크기가 매우 커서(최대 340px) 폰트
     메트릭(줄상자)이 실제 잉크보다 위로 넓게 잡혀, 화면 폭에 따라 바로 위
     푸터 링크 줄(카카오톡 등 오른쪽 링크)의 클릭/호버를 가로채는 경우가
     있었음 — 클릭할 일이 없는 장식 요소이므로 포인터 이벤트를 아예 꺼서
     절대 위의 링크를 가리지 못하게 함 */
  pointer-events:none;
}
.footer-wordmark .wordmark-text{ display:inline-block; }
/* © 기호: 텍스트 흐름 안에 나란히 두지 않고, 글자 바깥 우측 상단에 작게 떠 있는
   배지 형태로 완전히 분리(position:absolute). fitWordmark()의 폭 측정도
   .wordmark-text만 대상으로 하므로 이 배지는 폭 계산에 영향을 주지 않음 */
.footer-wordmark .wordmark-copy{
  position:absolute;
  top:-.01em; /* 살짝 위로 띄워 "다"의 'ㅏ' 세로획과 안 붙게 */
  right:-.03em; /* 살짝 오른쪽으로 띄워 'ㅏ' 세로획과 안 붙게 */
  font-size:.117em; /* 기존(.13em)의 90% */
  font-family:Georgia,"Times New Roman","Nanum Myeongjo",serif;
  font-weight:500;
  letter-spacing:0;
}
