/* ═══════════════════════════════════════════════════════════════
   골격 C — 사이드바 + 격자 (skeleton-c.css)
   문서: docs/DESIGN_SYSTEM.md §0

   "공간을 만든 기록"이 곧 상품인 업종 — 인테리어·시공, 건축, 조경,
   가구 공방, 사진 스튜디오. 뼈대가 "고정 메뉴 + 사진 격자 → 사례 상세"다.

   골격 B(포트폴리오형)와의 차이 — 왜 새 골격인가
   ─────────────────────────────────────────────────────────────
   B 는 헤더가 위에 눕고 작품이 간격을 두고 떠 있다. C 는 메뉴가 왼쪽에
   서고 사진이 **여백 없이** 화면을 덮는다. 이 둘은 같은 골격의 변주가
   아니다 — 컨테이너 폭 계산이 다르고(사이드바가 뷰포트를 상시 차지한다),
   그래서 이미지 슬롯 실측 프로필도 다르다.

   불러오는 순서 (반드시 이 순서)
     1) ../_shared/base.css              시스템 토큰
     2) tokens.css                       데모별 무드
     3) ../_shared/skeleton.css          공용 부품
     4) ../_skeleton-c/skeleton-c.css    ← 이 파일. 골격 C 구성

   ★ 3번을 걷어내고 이 파일만 쓰지 않는다.
     버튼·자리표시자·스크롤 모션·입력칸·푸터는 공용 부품을 그대로 쓴다.
     여기에는 골격 C 에만 있는 것만 둔다 —
     셸(사이드바+본문 열) · 사이드바 · 모바일 전환 · 무여백 격자 ·
     사례 상세(스펙 + 사진 세로 나열).

   ★ 색·서체·여백 리터럴은 두지 않는다. 값은 base.css / tokens.css 토큰이다.
     예외는 **값이 아니라 구조인 것들**뿐이다 —
       · 격자 열 수와 셀 비율
       · 스크림·그라디언트의 위치 %
       · 확대 보기(§11)의 검정 바탕과 흰 글자. 사진을 제 색으로 보여 주는
         화면이라 데모의 무드를 따라가면 안 된다. 그래도 바꿀 수 있게
         --lb-bg / --lb-fg 를 먼저 보고 없을 때만 기본값을 쓴다.
   ═══════════════════════════════════════════════════════════════ */


/* ═══════════════════════════════════════════════════════════════
   0. 밝은 면의 링크 — 색이 아니라 밑줄로 구분한다

   ★ 강조색(--c-accent)이 #18120a 로, 본문 글자색(#241f1a)과 휘도비가
     1.14 다. 두 색을 나란히 놓으면 사람 눈에 같은 검정이다 — 문단 안의
     링크를 **색으로는 찾을 수 없다.**
   ★ 그래서 색 외 수단으로 표시한다: 밑줄 + 호버 시 굵기. 밑줄을 글자에서
     3px 띄워 한글 받침과 겹치지 않게 한다.
   ★ 격자 셀(.pcell)·버튼(.btn)·칩(.pchip)은 통째로 누르는 면이라 뺀다.
     사진 위에 밑줄이 그어지거나 버튼에 줄이 생기면 오히려 잘못 읽힌다.
   ═══════════════════════════════════════════════════════════════ */
.shell-main a:not(.btn):not(.pcell):not(.pchip),
.ft a {
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
}
.shell-main a:not(.btn):not(.pcell):not(.pchip):hover,
.ft a:hover { text-decoration-thickness: 2px; }
/* 사이드바는 어두운 면이고 강조가 흰색이라 색만으로 구분된다 — 밑줄을 넣지 않는다 */

/* ─── 데모 배너 ─────────────────────────────────────────────
   공용 규칙은 --c-accent-2(탠) 바탕이다. 골격 C 는 사이드바가 이미
   어두운 띠라, 위쪽 띠도 같은 계열로 맞춰야 두 개가 한 틀로 읽힌다.
   ★ 값은 tokens.css 의 --c-demo-bar 가 정한다. 골격 파일은 값을 갖지
     않는다 — 처음에 --c-sb-bg 를 그대로 썼더니 사이드바와 완전히 같은
     색이라 위쪽이 눌렸다(본문과 대비 16.92). 이제 두 띠가 같은 계열이되
     명도가 다르다.
   ★ 폴백으로 --c-sb-bg 를 둔다. 골격 C 를 쓰면서 --c-demo-bar 를 정하지
     않은 데모도 깨지지 않는다. */
.shell > .demo-bar {
  background: var(--c-demo-bar, var(--c-sb-bg));
  color: #fff;
}


/* ═══════════════════════════════════════════════════════════════
   1. 셸 — 사이드바가 왼쪽을 상시 차지한다

   ★ 사이드바를 position:fixed 로 띄우고 본문 열에 padding-left 를 준다.
     grid 2열로 짜면 사이드바가 본문과 함께 스크롤된다 — "고정"이 아니다.
   ★ 본문 열이 화면 높이를 채우도록 flex 로 늘린다. 내용이 짧은
     페이지(문의)에서 푸터가 화면 중간에 뜨는 것을 막는다.
   ═══════════════════════════════════════════════════════════════ */
.shell { min-height: 100svh; display: flex; flex-direction: column; }
.shell > .shell-main { flex: 1 0 auto; }

@media (min-width: 1024px) {
  .shell { padding-left: var(--sb-w); }
}
@media (min-width: 1920px) {
  .shell { padding-left: var(--sb-w-lg); }
}

/* ═══════════════════════════════════════════════════════════════
   2. 사이드바 — 세로 로고 · 메뉴 4 · 하단 저작권
   ═══════════════════════════════════════════════════════════════ */
.sb {
  background: var(--c-sb-bg);
  color: var(--c-sb-fg);
}

@media (min-width: 1024px) {
  .sb {
    position: fixed;
    inset-block: 0;
    left: 0;
    width: var(--sb-w);
    display: flex;
    flex-direction: column;
    padding: var(--sp-5) var(--sp-3);
    border-right: var(--bw) solid var(--c-sb-line);
    z-index: 40;
    /* 메뉴가 길어지면 사이드바 안에서만 스크롤한다 */
    overflow-y: auto;
  }
}
@media (min-width: 1920px) { .sb { width: var(--sb-w-lg); } }

/* ─── 세로 로고 ─────────────────────────────────────────────
   ★ 낱말을 줄로 쌓는다. writing-mode:vertical-rl 로 눕히는 안도 있었지만
     한글은 눕히면 낱자가 세로로 서서 읽는 속도가 눈에 띄게 떨어진다.
     쌓기는 "세로"의 인상을 주면서 가로쓰기의 가독을 지킨다.
   ★ 로고 형태는 데모마다 다를 수 있다. .sb-brand 안의 줄 수와 내용만
     바꾸면 되고 구조는 건드리지 않는다. */
.sb-brand {
  display: block;
  font-family: var(--font-head);
  font-weight: var(--fw-head);
  letter-spacing: var(--ls-head);
  line-height: 1.12;
  color: var(--c-sb-fg);
}
.sb-brand .sbb-l {
  display: block;
  font-size: var(--t-h2);
}
.sb-brand .sbb-en {
  display: block;
  margin-top: var(--sp-2);
  font-family: var(--font-mono);
  font-size: var(--t-eyebrow);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  color: var(--c-sb-muted);
}

/* ─── 메뉴 ─────────────────────────────────────────────────── */
.sb-nav { margin-top: var(--sp-6); display: flex; flex-direction: column; }
.sb-nav a {
  display: block;
  padding-block: var(--sp-2);
  font-size: var(--t-body);
  color: var(--c-sb-muted);
  border-bottom: var(--bw) solid var(--c-sb-line);
  transition: color var(--dur-1) var(--ease-out), padding-left var(--dur-1) var(--ease-out);
}
/* 사이드바 안의 강조(호버·현재 위치·활성 표시)는 흰색이다 — --c-sb-accent */
.sb-nav a:hover { color: var(--c-sb-accent); padding-left: var(--sp-1); }
/* ★ 현재 위치를 색만으로 표시하지 않는다. 어두운 면에서 muted→흰색의
     차이는 밝은 면보다 덜 읽힌다. 왼쪽 선을 함께 세운다. */
.sb-nav a[aria-current="page"] {
  color: var(--c-sb-accent);
  box-shadow: inset 2px 0 0 var(--c-sb-accent);
  padding-left: var(--sp-2);
}

/* ─── 하단 저작권 ───────────────────────────────────────────
   ★ margin-top:auto 로 바닥에 붙인다. position:absolute 로 붙이면
     메뉴가 길어졌을 때 겹친다. */
.sb-foot {
  margin-top: auto;
  padding-top: var(--sp-4);
  font-size: var(--t-caption);
  line-height: var(--lh-body);
  color: var(--c-sb-faint);
}
.sb-foot a { color: var(--c-sb-muted); text-decoration: underline; text-underline-offset: 3px; }
.sb-foot a:hover { color: var(--c-sb-fg); }
.sb-foot .sbf-rule { height: var(--bw); background: var(--c-sb-line); margin-bottom: var(--sp-3); }

/* ═══════════════════════════════════════════════════════════════
   3. 모바일 — 상단 바 + 드로어 (1023 이하)

   ★ 사이드바를 좁히지 않고 방향을 바꾼다. 232px 짜리 세로 띠를 390px
     화면에 남기면 본문이 158px 이 된다 — 그건 좁은 사이드바가 아니라
     못 쓰는 화면이다.
   ═══════════════════════════════════════════════════════════════ */
@media (max-width: 1023px) {
  .sb {
    position: sticky;
    top: 0;
    z-index: 40;
    border-bottom: var(--bw) solid var(--c-sb-line);
  }
  /* ★ 데스크톱에서는 .sb 자신이 padding 을 갖는다. 모바일에서는 바가
       화면 폭을 그대로 쓰므로 안쪽 요소가 좌우 여백을 맡는다 —
       .sb 에 padding 을 주면 sticky 바의 높이 계산이 흔들린다. */
  .sb-in {
    min-height: var(--topbar-h);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-2);
    padding-block: var(--sp-1);
    padding-inline: var(--gutter);
  }
  .sb-nav { padding-inline: var(--gutter); }
  /* 상단 바에서는 로고가 한 줄로 눕는다 — 쌓으면 바가 두 배로 두꺼워진다 */
  .sb-brand { display: flex; align-items: baseline; gap: var(--sp-1); }
  .sb-brand .sbb-l { font-size: var(--t-h4); }
  .sb-brand .sbb-en { margin-top: 0; }

  .sb-nav {
    display: none;
    margin-top: 0;
    padding-bottom: var(--sp-2);
    border-top: var(--bw) solid var(--c-sb-line);
  }
  .sb-nav.open { display: flex; }
  .sb-nav a { border-bottom: var(--bw) solid var(--c-sb-line); }
  .sb-nav a:last-child { border-bottom: 0; }

  /* 사이드바 하단 저작권은 상단 바에 넣지 않는다 — 페이지 푸터가 받는다 */
  .sb-foot { display: none; }

  .sb-burger {
    display: block;
    background: none;
    border: var(--bw) solid var(--c-sb-line);
    color: var(--c-sb-fg);
    width: 40px;
    height: 36px;
    font-size: var(--t-body);
    line-height: 1;
  }
}
@media (min-width: 1024px) {
  .sb-burger { display: none; }
  /* 데스크톱에서는 드로어 상태와 무관하게 항상 펼쳐져 있다 */
  .sb-nav { display: flex; }
}

/* ═══════════════════════════════════════════════════════════════
   4. 격자 — .pgrid · 여백 없이, 비율은 가변

   ★ 셀 비율을 --pg-ar 로 받는다. 원본이 3:2 든 2:3 이든 4:5 든 셀은
     제 비율을 지키고 사진은 object-fit:cover 로 채운다 — 원본 비율이
     섞여도 격자가 어긋나지 않는다. 이것이 이 격자의 재활용 조건이다
     (다음 고객이 어떤 비율로 사진을 줄지 우리가 정하지 못한다).
   ★ gap 이 0 이다. 그래서 셀 사이 구분은 간격이 아니라 아주 옅은 선이
     맡는다 — 같은 톤의 사진 둘이 붙었을 때 경계가 사라지는 것을 막는다.
   ═══════════════════════════════════════════════════════════════ */
.pgrid {
  display: grid;
  grid-template-columns: repeat(var(--pg-cols, 2), minmax(0, 1fr));
  gap: 0;
  --pg-cols: 2;
  /* 셀이 이웃 쪽으로 반 픽셀 물리므로(아래 .pcell) 마지막 열·행이 격자
     밖으로 그만큼 나간다. 여기서 자른다 — 잘리는 것은 사진의 0.5px 이고
     칸 자체는 움직이지 않는다. */
  overflow: hidden;
}
/* 화면 끝까지 붙인다 — 홈의 "여백 없이 꽉 차게" */
.pgrid-bleed { width: 100%; }

.pcell {
  position: relative;
  display: block;
  overflow: hidden;
  background: var(--c-surface);
  aspect-ratio: var(--pg-ar, 3 / 2);
  /* 셀 경계 — 사진끼리 붙었을 때만 보인다 */
  outline: var(--bw) solid var(--c-line);
  outline-offset: calc(-1 * var(--bw));

  /* ─── 서브픽셀 이음매 방지 ───────────────────────────────
     증상: 폭을 조절하다 보면 셀 사이에 얇은 흰 세로선이 보인다.
     원인: 셀 폭이 소수(예: (1281−232)/4 = 262.25px)로 떨어지면 두 이웃의
     **그려지는 상자**가 장치 픽셀에 각각 스냅되면서 사이에 한 줄이 빈다.
     그 자리에 셀 배경(--c-surface, 거의 흰색)이 비쳐 흰 줄로 보인다.

     ★ 좌표로는 안 잡힌다. 320~2560 을 1px 씩 훑어 레이아웃 틈과 반올림
       틈을 쟀는데 2241 폭 전부 0 이었다. 헤드리스 픽셀 검사(dsf 1·1.25·
       1.5·2)에서도 재현되지 않았다 — 일부러 1px 틈을 넣으면 밝기 244 로
       잡히는 검출기인데도 그렇다. 소프트웨어 래스터라이저와 실물
       브라우저의 GPU 합성이 다른 지점이라, 재현 대신 **원인이 성립할 수
       없게** 만든다.

     ★ 칸 폭을 정수로 강제하지 않는다. 그러면 열 수 × 정수 ≠ 컨테이너 폭이
       되어 마지막 열에 나머지가 남는다 — 흰 줄을 없애려다 더 큰 틈을 만든다.
       대신 셀을 이웃 쪽으로 반 픽셀 물린다. 격자 트랙은 그대로이고
       (칸 위치·크기 계산이 바뀌지 않는다) 그려지는 상자만 겹친다.
       겹치면 그 사이에 빈 줄이 생길 수가 없다. */
  margin-right: -0.5px;
  margin-bottom: -0.5px;
}

/* 비율 변형 — 원본이 세로거나 파노라마일 때 셀 자체를 바꾼다 */
.pcell.pc-tall { --pg-ar: 3 / 4; }
.pcell.pc-sq   { --pg-ar: 1 / 1; }
.pcell.pc-pano { --pg-ar: 21 / 9; }
/* 칸 차지 — 강조하고 싶은 컷을 두 칸으로 */
.pcell.pc-w2 { grid-column: span 2; }

/* ★ 두 번째 방어선 — 사진이 셀을 끝까지 덮게 한다.
     정확히 100% 면 사진의 오른쪽·아래 가장자리가 셀 경계와 같은 자리라,
     래스터가 한 줄 모자라면 그 줄에 셀 배경(거의 흰색)이 드러난다.
     1px 크게 그려 두면 남는 쪽이 잘릴 뿐 배경이 드러나지 않는다 —
     .pcell 의 overflow:hidden 이 잘라 준다. 잘리는 것은 사진 1px 이고
     object-fit:cover 라 어차피 원본 일부는 잘리고 있다. */
.pcell > img {
  width: calc(100% + 1px); height: calc(100% + 1px);
  object-fit: cover;
  display: block;
  transition: transform var(--dur-3) var(--ease-out);
}
.pcell > .ph { width: calc(100% + 1px); height: calc(100% + 1px); border-radius: 0; border: none; }
.pcell > .ph > img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* §7-4 확대 상한 */
.pcell:hover > img { transform: scale(1.02); }

/* ─── 셀 위 캡션 ───────────────────────────────────────────
   ★ 사진 위에 글자를 얹으므로 스크림이 필요하다. 아래에서 위로만
     깔아 사진의 위쪽 절반은 그대로 남긴다 — 격자가 주인공이다. */
.pcell .pc-cap {
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  padding: var(--sp-4) var(--sp-3) var(--sp-2);
  color: #fff;
  background: linear-gradient(to top,
              rgba(0, 0, 0, .64) 0%,
              rgba(0, 0, 0, .32) 46%,
              rgba(0, 0, 0, 0) 100%);
  opacity: 0;
  transition: opacity var(--dur-1) var(--ease-out);
}
.pcell:hover .pc-cap,
.pcell:focus-visible .pc-cap { opacity: 1; }
/* ★ 손가락 입력에는 호버가 없다. 항상 보이게 둔다 — 안 그러면 모바일에서
     격자가 "누를 수 있는 것"으로 보이지 않는다. */
@media (pointer: coarse), (max-width: 1023px) {
  .pcell .pc-cap { opacity: 1; }
}
.pcell .pc-t { font-family: var(--font-head); font-size: var(--t-h4); font-weight: var(--fw-head); }
.pcell .pc-m {
  font-family: var(--font-mono);
  font-size: var(--t-eyebrow);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  opacity: .84;
  margin-top: var(--sp-0);
}
.pcell:focus-visible { outline: 2px solid var(--c-accent); outline-offset: -2px; }

/* ─── 열 수 — 폭에 따라 (구조값) ───────────────────────────── */
@media (min-width: 768px)  { .pgrid { --pg-cols: 3; } }
@media (min-width: 1280px) { .pgrid { --pg-cols: 4; } }
@media (min-width: 1920px) { .pgrid { --pg-cols: 5; } }
/* 390 에서 2열이면 셀이 195px 이다. 사진 격자로는 너무 잘아 1열로 내린다 */
@media (max-width: 560px) { .pgrid { --pg-cols: 1; } }

/* ★ 좁은 폭에서는 두 칸짜리를 없앤다.
     2열에서 span 2 는 "한 줄 전체"라 강조가 되지 않고, 앞 줄에 한 칸이
     남으면 자동 배치가 그 칸을 건너뛰어 **격자 한가운데 구멍**이 생긴다.
     여백 없는 격자에서 구멍은 여백보다 나쁘다. */
@media (max-width: 767px) { .pcell.pc-w2 { grid-column: span 1; } }

/* ═══════════════════════════════════════════════════════════════
   5. 분류 줄 — 업종별 보기

   ★ 공용 .chip 은 골격 B(skeleton-b.css)에 있고 여기서는 그 파일을
     불러오지 않는다. 칩은 골격과 무관한 부품이라 여기에 최소한만 둔다.
     세 번째 사용처가 생기면 공용 skeleton.css 로 올린다 — 그 전에
     옮기는 것은 추측이다.
   ═══════════════════════════════════════════════════════════════ */
.pfilters { display: flex; flex-wrap: wrap; gap: var(--sp-1); align-items: center; }
.pchip {
  font-family: var(--font-mono);
  font-size: var(--t-eyebrow);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  color: var(--c-muted);
  background: none;
  border: var(--bw) solid var(--c-line);
  padding: 8px var(--sp-2);
  cursor: pointer;
  transition: color var(--dur-1) var(--ease-out), background var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out);
}
.pchip:hover { color: var(--c-text); background: var(--c-surface); }
.pchip[aria-pressed="true"] {
  color: var(--c-btn-fg);
  background: var(--c-btn-bg);
  border-color: var(--c-btn-bg);
}
.pgrid-empty { padding-block: var(--sp-7); text-align: center; color: var(--c-muted); }

/* ═══════════════════════════════════════════════════════════════
   6. 사례 상세 — 제목 + 스펙 + 사진 세로 나열
   ═══════════════════════════════════════════════════════════════ */
.pj-head { max-width: var(--measure); }
.pj-head .pj-cat {
  font-family: var(--font-mono);
  font-size: var(--t-eyebrow);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  color: var(--c-accent);
}
.pj-head h1 { font-size: var(--t-h1); line-height: var(--lh-tight); margin-top: var(--sp-2); }
.pj-head .lead { margin-top: var(--sp-3); }

/* ─── 스펙 칸 ─────────────────────────────────────────────
   ★ 라벨이 마크업이 아니라 데이터에서 온다 (data/projects.json 의
     specFields). 업종이 바뀌면 그 배열만 갈아 끼운다 —
     주소/면적/설계기간/공사기간 → 클라이언트/연도/역할/분야.
   ★ 칸 수를 4로 못 박지 않는다. repeat(4,1fr) 로 쓰면 항목이 3개일 때
     빈 칸이 남고 5개일 때 줄이 넘친다. --pjs-cols 를 스크립트가 항목
     수로 채운다. */
.pj-specs {
  display: grid;
  grid-template-columns: repeat(var(--pjs-cols, 4), minmax(0, 1fr));
  gap: var(--sp-3) var(--sp-4);
  margin-top: var(--sp-5);
  padding-top: var(--sp-3);
  border-top: var(--bw) solid var(--c-line-2);
}
.pj-specs dt {
  font-family: var(--font-mono);
  font-size: var(--t-eyebrow);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  color: var(--c-faint);
}
.pj-specs dd {
  margin: var(--sp-1) 0 0;
  font-size: var(--t-body);
  line-height: var(--lh-snug);
  color: var(--c-text);
}
@media (max-width: 900px) { .pj-specs { --pjs-cols: 2 !important; } }
@media (max-width: 420px) { .pj-specs { --pjs-cols: 1 !important; gap: var(--sp-2); } }

/* ─── 사진 세로 나열 ───────────────────────────────────────
   ★ 격자가 아니라 한 줄에 한 장이다. 시공 사진은 "무엇을 만들었나"를
     보여 주는 것이라 크게 봐야 한다. 2열로 깔면 각 장이 절반이 된다.
   ★ 원본 비율을 그대로 쓴다(height:auto). 상세에서는 셀을 맞출 이유가
     없고, cover 로 자르면 시공 디테일이 잘린다. */
.pj-shots { margin-top: var(--sp-6); display: flex; flex-direction: column; gap: var(--sp-5); }
.pj-shots figure { margin: 0; }
.pj-shots img { display: block; width: 100%; height: auto; }

/* 세로 컷 — 폭을 제한해 높이를 잡는다.
   ★ 폭만 100% 로 두면 세로 컷(2:3)이 1432px 자리에서 높이 2148px 이 된다.
     한 장이 화면 두 개 반을 차지해 다음 사진이 있다는 것조차 안 보인다.
   ★ 처음에는 `max-height:78svh; width:auto` 로 눌렀는데, 실측에서
     **지연 로딩된 사진의 폭이 0 으로 무너졌다.** width:auto 는 내재 폭에
     기대는데 아직 안 받은 이미지에는 그것이 없다. 첫 장(eager)만 468px 로
     잡히고 나머지 둘이 0 이었다. 그래서 높이가 아니라 폭을 직접 제한한다 —
     레이아웃이 이미지 도착 여부와 무관해진다.
   ★ 520px → 2:3 기준 높이 780px. svh 에 기대지 않으므로 실측값이
     뷰포트 높이에 따라 흔들리지도 않는다(프로필을 정하려면 이게 중요하다). */
.pj-shots img.is-tall { max-width: 520px; margin-inline: auto; }
.pj-shots .ph { border-radius: 0; }
.pj-shots figcaption {
  margin-top: var(--sp-2);
  font-size: var(--t-caption);
  color: var(--c-muted);
}

/* ─── 이전 / 다음 사례 ─────────────────────────────────────── */
.pj-nav {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-3);
  margin-top: var(--sp-7);
  padding-top: var(--sp-3);
  border-top: var(--bw) solid var(--c-line);
}
.pj-nav .pn-next { text-align: right; }
.pj-nav a { display: block; color: var(--c-muted); }
.pj-nav a:hover { color: var(--c-text); }
.pj-nav .pn-l {
  font-family: var(--font-mono);
  font-size: var(--t-eyebrow);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  color: var(--c-faint);
}
.pj-nav .pn-t { font-family: var(--font-head); font-size: var(--t-h3); font-weight: var(--fw-head); margin-top: var(--sp-0); }

/* ═══════════════════════════════════════════════════════════════
   7. 소개 히어로 — 사진 위에 글자

   ★ 공용 .hero-full 을 쓰지 않는다. 그쪽은 헤더가 위에 눕는 골격을
     전제해 100svh 를 기준으로 잡는데, 여기서는 사이드바가 세로를
     이미 다 쓰고 있어 본문 열만 채우면 된다.
   ═══════════════════════════════════════════════════════════════ */
.about-hero {
  position: relative;
  min-height: clamp(360px, 52svh, 560px);
  display: flex;
  align-items: flex-end;
  overflow: hidden;
  background: var(--c-bg-alt);
  border-bottom: var(--bw) solid var(--c-line);
}
.about-hero > .ah-media { position: absolute; inset: 0; }
.about-hero > .ah-media img { width: 100%; height: 100%; object-fit: cover; }
.about-hero > .ah-media .ph { width: 100%; height: 100%; border-radius: 0; border: none; }
.about-hero::after {
  content: '';
  position: absolute; inset: 0;
  pointer-events: none;
  background: linear-gradient(to top,
              rgba(0, 0, 0, .70) 0%,
              rgba(0, 0, 0, .34) 42%,
              rgba(0, 0, 0, .06) 78%);
}
.about-hero .ah-copy { position: relative; z-index: 2; width: 100%; padding-block: var(--sp-6); color: #fff; }
.about-hero h1 { font-size: var(--t-h1); line-height: var(--lh-tight); }
.about-hero .lead { margin-top: var(--sp-3); max-width: var(--measure-tight); color: rgba(255, 255, 255, .90); }
.about-hero .eyebrow { color: rgba(255, 255, 255, .84); }

/* ═══════════════════════════════════════════════════════════════
   8. 서비스 목록 — 소개 페이지
   ═══════════════════════════════════════════════════════════════ */
/* ★ 열 수를 CSS 에 적지 않는다. **실제 항목 수에서 뽑는다.**
     `:nth-child(N):last-child` 는 "N 번째가 마지막" = 정확히 N 개라는 뜻이다.
     항목을 하나 빼거나 더하면 열 수가 알아서 따라온다 — 마크업도 CSS 도
     고칠 자리가 없다.
   ★ :has() 를 못 읽는 브라우저에서는 아래 규칙이 통째로 무시되고
     `--svc-cols: 3` 과 그 아래 폭별 기본값만 남는다. 예전과 같은 화면이다.
   ★ 명세서가 요구하는 범위(3~6건)를 전부 덮는다. 처음에는 "5개 이상은
     3열로 접는다"고 제한을 뒀는데, **근거로 든 '5열이면 제목이 접힌다'가
     실측에서 틀렸다** — 1280px·6열(칸 132px)에서도 제목은 한 줄이다.
     짐작으로 만든 제한이라 걷어냈다. */
.svc {
  display: grid;
  grid-template-columns: repeat(var(--svc-cols, 3), minmax(0, 1fr));
  gap: var(--sp-4);
}
/* ─── 좁은 폭은 **폭**이 정한다 (모바일 우선) ─────────────── */
.svc { --svc-cols: 1; }                              /* ~560 */
@media (min-width: 561px) { .svc { --svc-cols: 2; } } /* 561~900 */

/* ─── 901 이상에서만 **개수**가 정한다 ──────────────────────
   ★ 개수 규칙을 미디어쿼리 안에 넣은 이유가 특정도다.
     `:has()` 의 특정도는 인자 중 가장 센 것을 따른다 —
     `.svc:has(> :nth-child(4):last-child)` 는 (0,3,0) 이라
     `@media { .svc { … } }` (0,1,0) 로는 절대 못 덮는다.
     처음에 미디어쿼리로 덮으려다 **좁은 폭에서도 4열이 그대로 남는**
     것을 실측에서 봤다(561px 에서 칸 107px, 제목 두 줄로 접힘).
     자릿수를 맞춰 싸우는 대신 적용 구간을 나눴다. 읽기도 이쪽이 낫다.
   ★ :has() 를 못 읽는 브라우저는 이 블록이 통째로 무시되고 위의
     폭 기준(2열)만 남는다 — 깨지지 않는다. */
@media (min-width: 901px) {
  .svc { --svc-cols: 3; }
  .svc:has(> :nth-child(1):last-child) { --svc-cols: 1; }
  .svc:has(> :nth-child(2):last-child) { --svc-cols: 2; }
  .svc:has(> :nth-child(3):last-child) { --svc-cols: 3; }
  .svc:has(> :nth-child(4):last-child) { --svc-cols: 4; }
  /* ★ 5개부터는 개수를 따르지 않고 3열에서 멈춘다(위 기본값).
       제목은 6열에서도 한 줄로 버틴다 — 걸리는 것은 **설명 문단**이다.
       같은 75자를 두고 1280px 에서 실측하면
         4열 칸 214px → 4줄   (기준)
         5열 칸 165px → 6줄
         6열 칸 132px → 8줄   (기준의 두 배)
       3열로 접으면 칸이 296px 이 되어 다시 4줄이다.
       "개수 = 열 수"는 칸이 글을 담을 수 있을 때까지만 뜻이 있다.
     ★ 그래서 5·6 규칙을 두지 않는다. 1~4 중 어디에도 안 걸리면
       이 블록 첫 줄의 --svc-cols: 3 이 그대로 남는다 — 7개 이상도 같다. */
}
.svc-item { border-top: var(--bw) solid var(--c-line-2); padding-top: var(--sp-3); }
.svc-item .sv-n {
  font-family: var(--font-mono);
  font-size: var(--t-eyebrow);
  letter-spacing: var(--ls-wide);
  color: var(--c-accent);
}
.svc-item h3 { font-size: var(--t-h3); margin-top: var(--sp-1); }
.svc-item p { color: var(--c-muted); margin-top: var(--sp-2); }

/* ═══════════════════════════════════════════════════════════════
   9. 작은 제목은 산세리프로

   제목 세리프는 h1·h2 와 대형 카피까지다. 18~20px 짜리 작은 제목에서
   한글 세리프는 획이 뭉쳐 읽는 속도가 떨어진다 — 크기가 작을수록
   세리프의 이점(획 대비)이 손해(뭉침)로 바뀐다.

   ★ 이 블록이 파일 **끝**에 있는 이유가 순서다. .pcell .pc-t 와
     .pj-nav .pn-t 가 각각 §4·§6 에서 --font-head 를 지정하는데,
     자릿수가 같아(0,2,0) 앞에 두면 뒤 규칙에 밀린다. 처음에 위쪽에
     뒀다가 두 자리가 그대로 세리프로 남은 것을 실측에서 봤다.
   ★ 범위를 .shell-main 으로 좁혔다. .shell h4 로 두었더니 **푸터 소제목
     까지 산세리프가 되었다** — 그 자리는 원래 모노(.ft h4)다.
     푸터는 .shell 안이지만 .shell-main 밖이다.
   ★ 사이드바 로고(.sb-brand)는 대상이 아니다. 제목이 아니라 워드마크이고,
     이 무드의 인상을 만드는 자리다.
   ★ 굵기는 h3·h4 를 손대지 않는다 — --fw-h3(700)·--fw-h4(600)는
     tokens.css 가 세리프용으로 내린 --fw-head 와 별개라 이미 제 값이다.
   ═══════════════════════════════════════════════════════════════ */
.shell-main h3,
.shell-main h4,
.pcell .pc-t,
.pj-nav .pn-t { font-family: var(--font-body); }

/* .pc-t · .pn-t 는 --fw-head 를 쓰던 자리다. 세리프용으로 400 까지
   내려가 있어, 산세리프로 바뀌면 배경 사진 위에서 너무 얇다.
   라벨성 제목 굵기로 되돌린다. */
.pcell .pc-t,
.pj-nav .pn-t { font-weight: var(--fw-h4); }

/* ═══════════════════════════════════════════════════════════════
   10. 칸이 무엇에 응답하는지 — .pc-act

   격자에는 두 종류의 칸이 있다. 상세 페이지가 있는 칸과 없는 칸.
   생김새가 같으면 **누른 뒤에야** 알 수 있고, 아무 일도 없는 칸은
   고장으로 보인다. 누르기 전에 알려 준다.

   ★ 크게 만들지 않는다. 이 격자의 주인공은 사진이다. 모서리에 작은
     표식 하나로 충분하다 — 상세는 글자, 확대는 아이콘.
   ★ 손가락 입력에는 호버가 없다. 그쪽에서는 항상 보인다.
   ═══════════════════════════════════════════════════════════════ */
.pc-act {
  position: absolute;
  top: var(--sp-2);
  right: var(--sp-2);
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: var(--sp-0);
  padding: 6px var(--sp-1);
  border-radius: var(--radius-pill);
  background: rgba(0, 0, 0, .55);
  color: #fff;
  font-family: var(--font-mono);
  font-size: var(--t-eyebrow);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  line-height: 1;
  opacity: 0;
  transition: opacity var(--dur-1) var(--ease-out);
  pointer-events: none;
}
.pcell:hover .pc-act,
.pcell:focus-visible .pc-act,
.pj-shot:hover .pc-act,
.pj-shot:focus-visible .pc-act { opacity: 1; }
@media (pointer: coarse), (max-width: 1023px) {
  .pc-act { opacity: 1; }
}
.pc-act svg {
  width: 15px; height: 15px;
  fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
}

/* ★ 확대되는 자리는 <button> 이다. 눌러야 하는 것은 눌리는 요소여야
     키보드와 보조기기가 알아본다. 버튼 기본 생김새만 지운다. */
button.pcell,
.pj-shot {
  border: 0;
  padding: 0;
  font: inherit;
  color: inherit;
  text-align: inherit;
  background: none;
  cursor: zoom-in;
  -webkit-appearance: none;
  appearance: none;
}
/* 상세 사진의 버튼은 사진을 그대로 감싼다 — 레이아웃을 바꾸지 않는다 */
.pj-shot { position: relative; display: block; width: 100%; }
/* ★ 세로 컷은 520px 로 묶여 가운데 선다. 버튼이 전폭이면 돋보기 표식만
     저 멀리 오른쪽 끝에 뜬다 — 버튼을 사진 크기로 줄여 붙여 둔다.
     :has() 를 못 읽는 브라우저에서는 표식이 오른쪽에 남을 뿐 동작은 같다. */
.pj-shot:has(> img.is-tall) { width: fit-content; margin-inline: auto; }


/* ═══════════════════════════════════════════════════════════════
   11. 사진 확대 보기 — .lb (lightbox.js 와 한 벌)

   ★ 색 리터럴이 몇 개 있다. 확대 화면의 바탕은 데모의 무드와 무관하게
     거의 검정이어야 사진이 제 색으로 보인다 — 값이 아니라 구조다.
     그래도 바꿀 수 있게 --lb-* 를 먼저 보고 없으면 기본값을 쓴다.
   ═══════════════════════════════════════════════════════════════ */
.lb {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--sp-5) var(--sp-3);
}
.lb[hidden] { display: none; }
.lb-backdrop { position: absolute; inset: 0; background: var(--lb-bg, rgba(0, 0, 0, .92)); }

.lb-fig {
  position: relative;
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-2);
  max-width: min(92vw, 1400px);
}
/* ★ 원본 비율 그대로. contain 이라 어느 쪽도 잘리지 않는다.
     max-height 를 캡션 자리만큼 덜어 둔다 — 안 그러면 세로 사진에서
     캡션이 화면 밖으로 밀린다. */
.lb-img {
  display: block;
  max-width: 100%;
  max-height: calc(88svh - 4rem);
  width: auto;
  height: auto;
  object-fit: contain;
  background: var(--lb-img-bg, rgba(255, 255, 255, .04));
}
.lb-cap {
  color: var(--lb-fg, rgba(255, 255, 255, .88));
  font-size: var(--t-caption);
  text-align: center;
  max-width: var(--measure);
}

.lb-btn {
  position: absolute;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48px; height: 48px;
  border-radius: var(--radius-pill);
  border: var(--bw) solid rgba(255, 255, 255, .22);
  background: rgba(0, 0, 0, .45);
  color: var(--lb-fg, #fff);
  cursor: pointer;
  transition: background var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out);
}
.lb-btn:hover { background: rgba(0, 0, 0, .75); border-color: rgba(255, 255, 255, .5); }
.lb-btn:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.lb-btn svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.lb-btn[hidden] { display: none; }

.lb-x    { top: var(--sp-3); right: var(--sp-3); }
.lb-prev { left: var(--sp-3);  top: 50%; transform: translateY(-50%); }
.lb-next { right: var(--sp-3); top: 50%; transform: translateY(-50%); }

.lb-count {
  position: absolute;
  bottom: var(--sp-3);
  left: 50%;
  transform: translateX(-50%);
  z-index: 2;
  font-family: var(--font-mono);
  font-size: var(--t-eyebrow);
  letter-spacing: var(--ls-wide);
  color: var(--lb-fg, rgba(255, 255, 255, .72));
}

/* 좁은 화면 — 화살표가 사진을 덮지 않게 아래로 내리고 조금 줄인다 */
@media (max-width: 767px) {
  .lb { padding: var(--sp-4) var(--sp-2); }
  .lb-btn { width: 44px; height: 44px; }
  .lb-prev, .lb-next { top: auto; bottom: var(--sp-3); transform: none; }
  .lb-prev { left: var(--sp-3); }
  .lb-next { right: var(--sp-3); }
  .lb-count { bottom: calc(var(--sp-3) + 56px); }
  .lb-img { max-height: calc(82svh - 4rem); }
}

/* ★ 열려 있는 동안 뒤 화면이 따라 스크롤되지 않게 잠근다.
     position:fixed 는 스크롤 위치를 날리므로 lightbox.js 가 top 을
     넣어 두고 닫을 때 되돌린다. */
body.lb-open { position: fixed; width: 100%; overflow: hidden; }

@media (prefers-reduced-motion: reduce) {
  .pcell .pc-act, .lb-btn { transition: none; }
}

/* ═══════════════════════════════════════════════════════════════
   12. 화면에는 없고 문서에는 있는 글자 — .sr-only

   홈처럼 화면이 사진 격자뿐인 자리에도 **문서에는 제목이 있어야 한다.**
   보조기기는 제목으로 페이지를 훑고, 검색엔진도 그것으로 무엇을 다루는
   화면인지 판단한다. 오크 홈은 격자만 남기면서 h1 이 통째로 사라졌다.

   ★ display:none 이나 visibility:hidden 을 쓰지 않는다. 그건 보조기기
     에서도 함께 사라져 아무 문제도 풀지 못한다. 1px 로 줄여 잘라 낸다 —
     읽히기는 하고 보이지는 않는다.
   ★ white-space:nowrap 이 필요하다. 없으면 1px 폭에서 글자가 세로로
     쌓여 일부 브라우저가 레이아웃을 계산하다 스크롤을 만든다.
   ★ 골격 C 에만 두었다. 세 번째 사용처가 생기면 공용 skeleton.css 로
     올린다 — 그 전에 옮기는 것은 추측이다(.pchip 과 같은 기준).
   ═══════════════════════════════════════════════════════════════ */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
