@charset "utf-8";
/* ============================================================================
   더라인성형외과 phpnew4 - main.css   ★ 새 섹션 만들 땐 이 치트시트만 보면 된다 ★

   [철칙] 값을 새로 만들지 않는다. 아래 토큰/클래스에서 "골라 쓴다".
          하드코딩(px·hex) 금지. 애매하면 가장 가까운 토큰으로 흡수.

   ┌ 색상 (7개가 전부) ─────────────────────────────────────────────────────
   │  var(--ink)         #262627  모든 텍스트·제목            ← 기본
   │  var(--dark)        #2E2A26  어두운 섹션/푸터의 "배경"
   │  var(--point)       #E95263  메인 컬러(강조 텍스트·아이콘·활성·hover)
   │  var(--accent)      #E5325B  완전 강조 (아껴 쓸 것)
   │  var(--white)       #fff
   │  var(--gray-dark)   #6a6a6a  보조 텍스트 (글자용 회색)
   │  var(--gray-light)  #E0E0E0  구분선·테두리 (글자에 쓰지 말 것)
   │  var(--point-bg)    연한 핑크 배경  ·  var(--point-soft) 흐린 데코 (--point 파생)
   │  var(--bg-soft)     은은한 회색 - 박스·카드의 면 (--ink 3%)
   │  var(--bg-mute)     한 단계 진한 회색 - 푸터·풀블리드 띠 (--ink 8%)
   └────────────────────────────────────────────────────────────────────────

   ┌ 폰트 (5개 + GNB 예외 1) ───────────────────────────────────────────────
   │  --fs-caption 16 · --fs-body 20 · --fs-sub 30 · --fs-title 42 · --fs-display 80
   │  (예외) --fs-nav 18 = GNB · --fs-event-only 60 = 프로모션 숫자 · --fs-fine 14 = eyebrow·보조문구
   │         ↑ 전용 예외 3개. 정해진 자리 밖에서 쓰지 말 것
   │  (--fs-nav 18 은 GNB depth1 전용)   ※ 제목은 h1~h4 태그만 쓰면 자동 적용
   └────────────────────────────────────────────────────────────────────────

   ┌ 간격 (1920 기준 px) ───────────────────────────────────────────────────
   │  --sp-1  5   --sp-2  10  --sp-3  15  --sp-4  20  --sp-5  30  --sp-6  40
   │  --sp-7  60  --sp-8  80  --sp-9 120  --sp-10 160
   │  --sec-gap 180  ← 섹션과 섹션 사이는 무조건 이거
   └────────────────────────────────────────────────────────────────────────

   ┌ 라운드 ────────────────────────────────────────────────────────────────
   │  --r-sm 5 · --r-md 10 · --r-lg 20(카드 기본) · --r-xl 30 · --r-pill 999
   └────────────────────────────────────────────────────────────────────────

   ┌ 섹션 뼈대 (폭은 이 2개뿐) ─────────────────────────────────────────────
   │  <section class="section"> ─ margin-top: var(--sec-gap)
   │    <div class="container">      max 1400 + 좌우 20  ← 대부분 여기
   │    <div class="container--full"> 풀블리드(마퀴·슬라이더 등 끝까지)
   │      <div class="section__head"><h2>제목</h2><p>부제</p></div>
   │      ... 콘텐츠 ...
   │      <div class="section__foot"><a class="more-link">더보기</a></div>
   └────────────────────────────────────────────────────────────────────────

   반응형: 1920에서 원본과 동일. 이하는 clamp + 브레이크포인트
           1200(GNB→햄버거) / 991.98(주 모바일) / 767.98 / 575.98
   비교 기준: 운영 사이트 https://theline.kr  (DESIGN_SYSTEM 규칙 4)
============================================================================ */

@layer reset, tokens, base, layout, components, templates, templates-type, utilities;

/* ---------------------------------------------------------------- reset -- */
@layer reset {
  *, *::before, *::after { box-sizing: border-box; }
  * { margin: 0; }
  /* (요청 2026-07-17, doctors 갤러리→소개 앵커) sticky 헤더(78, 축소 시 59)가 앵커 목적지를
     덮는다 → 점프 지점을 헤더 높이 + 숨 고를 여백만큼 내린다. 전 페이지 공통(앵커 전부에 이롭다). */
  html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%;
    scroll-padding-top: calc(var(--sp-8) + var(--sp-5)); }
  /* line-height 는 여기서 주지 않는다 - @layer base 의 body 가 --lh-body(1.6) 로 정한다.
     리셋에서 1.5 를 주면 죽은 선언이 되어 "행간이 어디서 정해지는지" 를 흐린다. */
  body { -webkit-font-smoothing: antialiased; }
  img, video { display: block; max-width: 100%; height: auto; }
  input, button, textarea, select { font: inherit; color: inherit; }
  button { background: none; border: 0; cursor: pointer; }
  a { color: inherit; text-decoration: none; }
  ul, ol { list-style: none; padding: 0; }
}

/* --------------------------------------------------------------- tokens -- */
@layer tokens {
  :root {
    /* ══════════════════════════════════════════════════════════════════════
       타이포 5스케일 (2026-07-14 전면 재지정). 값은 "PC(1920) -> 모바일(하한)".
       이름이 곧 쓰임이다 - 새 텍스트를 놓을 때 아래 5개 중 하나를 고른다.

         1) --fs-h2title          42 -> 26  섹션 대제목(h1 · h2). 히어로도 이걸 쓴다
         2) --fs-h2lead           18 -> 16  h2 바로 아래 리드 문장
         3) --fs-content-title    22 -> 18  "제목 + 서브본문" 묶음의 제목(카드 · 박스 · h3)
         4) --fs-content-subtext  16 -> 14  위 제목에 딸린 서브 본문
         5) --fs-content-body     20 -> 15  제목 없이 본문만 있는 자리. 표 내용도 이것

       (삭제) --fs-display(80) : 히어로도 h2title 로 통일 → 대제목은 42 하나뿐이다
       (삭제) --fs-sub(30)     : h3 가 content-title(22) 로 내려와 쓸 자리가 없어졌다
       (삭제) --fs-caption(16) : content-subtext(16) 와 값이 같아 흡수했다
       ══════════════════════════════════════════════════════════════════════ */
    --fs-h2title:         clamp(1.625rem, 2.1875vw, 2.1875rem); /* 26 -> 35 : 700 / 1.3 / -.03em */
    --fs-h2lead:          clamp(1rem, 0.9375vw, 1.125rem);     /* 16 -> 18 : 400 / 1.6 / -.01em */
    --fs-content-title:   clamp(1.125rem, 1.1458vw, 1.375rem); /* 18 -> 22 : 600 / 1.35 / -.01em */
    --fs-content-subtext: clamp(0.875rem, 0.8333vw, 1rem);     /* 14 -> 16 : 400 / 1.6 / 0 */
    --fs-content-body:    clamp(0.9375rem, 1.042vw, 1.25rem);  /* 15 -> 20 : 400 / 1.6 / -.01em */
    /* ⚠️ 예외 1 - 섹션 영문 eyebrow(.tpl-eyebrow) 전용. 다른 텍스트에 쓰지 말 것.
       h2 위에 얹는 영문 라벨이라 본문 스케일과 성격이 다르다(대문자 · 양수 자간).
       5스케일의 최소값(content-subtext 16)보다 작아야 라벨로 읽힌다 → 14 로 따로 뺀다. */
    --fs-eyebrow: calc(var(--fs-content-body) * .7);    /* 14 : eyebrow · 보조 문구 */
    --fs-ref: calc(var(--fs-content-body) * .6);        /* 12 : 참고 논문(cite) 전용 - eyebrow 보다 한 단계 작다 */
    /* ⚠️ 예외 2 - 버튼 라벨(.cta · .btn) 전용. 문장이 아니라 "누르는 것"의 이름이다.
       본문 스케일(content-body 20)을 쓰면 버튼이 문장처럼 커진다 → 16 으로 따로 뺀다. */
    --fs-cta: clamp(0.875rem, 0.8333vw, 1rem);          /* 14 -> 16 : 600 / -.01em */
    /* ⚠️ 예외 3 - 프로모션/이벤트 "가격 숫자" 전용. 일반 텍스트에 쓰지 말 것.
       h2title(42) 은 작고 그렇다고 스케일을 늘릴 자리는 여기뿐이라 예외로 둔다.
       이름에 event-only 를 박아 둔 이유가 그것이다 - 새 섹션에서 이 토큰을 고르면 잘못 고른 것이다. */
    --fs-event-only: clamp(1.625rem, 2.1875vw, 2.1875rem);  /* 26 -> 35 : 프로모션 숫자 - h2title 과 동일 */

    /* ══ UI 치수 - 위 5스케일은 "콘텐츠 본문" 전용이다. 아래는 그것과 별개다. ══
       아이콘(--ico-*) 은 글자가 아니라 그림이다. 모달·상담바 같은 "UI 장치"(--ui-*) 도
       본문 타이포와 리듬이 다르다(작고 촘촘하다). 둘을 5스케일에 억지로 욱여넣으면
       본문이 커지거나 UI 가 헐거워진다 → 스케일을 갈라 둔다.
       ★ 콘텐츠(제목·본문·리드)에는 절대 쓰지 않는다. 쓰고 있으면 잘못 고른 것이다. */
    /* 아이콘 (Phosphor 등) - 그림이므로 텍스트 스케일과 무관하다 */
    --ico-xs: 14px;  --ico-sm: 18px;  --ico-md: 22px;  --ico-lg: 26px;  --ico-xl: 32px;
    /* UI 텍스트 - 딱 2개. 제목 하나, 나머지 하나.
       (요청) 12~24 가 8종류로 흩어져 있었다 → 22 / 13 두 값으로 통일했다.
       UI 는 정보 밀도가 높아 위계가 2단이면 충분하다. 더 늘리지 않는다. */
    --ui-title: 22px;   /* 모달 제목 */
    /* 체크박스 - 상담폼(18)과 하단 상담바(17)가 1px 달랐다 → 18 로 통일 (2026-07-13) */
    --ui-check: 18px;
    --ui-text:  13px;   /* 그 외 UI 텍스트 전부 (뱃지 · 버튼 · 라벨 · 상담바) */

    /* 반투명 면 - 색은 팔레트에서, 투명도만 여기서. rgba 하드코딩을 없앤다 */
    --veil-scrim:  color-mix(in srgb, var(--ink) 45%, transparent);  /* 모바일 메뉴 뒤 */
    --veil-modal:  color-mix(in srgb, var(--ink) 50%, transparent);  /* 모달 뒤 */
    --veil-bar:    color-mix(in srgb, var(--ink) 65%, transparent);  /* 하단 상담바 */
    --veil-line:   color-mix(in srgb, var(--white) 30%, transparent);/* 어두운 면 위 구분선 */
    --veil-track:  color-mix(in srgb, var(--gray-light) 50%, transparent); /* 히어로 진행바 */

    /* ── 섹션 헤드(=[영문 eyebrow] + [H2] + [서브제목]) 는 "하나의 단위" 다.
       줄 간격과 본문까지의 거리를 여기 3개 토큰으로만 정한다.
       어느 페이지의 어떤 헤드를 보더라도 값이 같다 → 하나만 고치면 전 페이지에 반영된다.
       서브제목은 있어도 되고 없어도 된다 - 없으면 H2 가 그 단위의 마지막 줄이 된다.
       헤드 ↔ 본문 거리는 "헤드 블록의 바깥 마진"이라 서브제목 유무와 무관하게 항상 같다. */
    /* (요청 2026-07-14) eyebrow ↔ H2 와 H2 ↔ 리드의 간격이 거꾸로였다(30 / 10).
       eyebrow 는 H2 에 붙는 "라벨"이라 한 덩어리로 읽혀야 하고, 리드는 그 아래 별개 문장이다.
       → 붙일 것은 붙이고(10) 뗄 것은 뗀다(20). 묶음이 [eyebrow+H2] → [리드] 로 읽힌다. */
    --head-gap-title: var(--sp-2);              /* eyebrow ↔ H2   : 10 (붙는 라벨) */
    --head-gap-sub:   var(--sp-4);              /* H2 ↔ 서브제목  : 20 (별개 문장) */
    --head-gap-body:  var(--sp-8);              /* 헤드 ↔ 본문    : 50 -> 80 (★ 예외 없음) */

    /* ── 템플릿 들여쓰기 (요청 2026-07-14) ─────────────────────────────────
       "가로로 긴 것"만 좌우를 좁혀 읽기 폭을 만든다. 카드·갤러리·사진은 대상이 아니다.
       적용 목록(어느 클래스가 어느 값을 쓰는지)은 templates 레이어에 있다.
         --tpl-inset (150) : 11번 구분선 아이콘 행 · 시술 프로세스 4단계 박스
         --tbl-inset (200) : 정의형 2단 표(dt/dd) - 줄이 짧아 더 좁혀도 읽힌다
       좁은 화면(≤1200px)에선 이미 폭이 없다 → 둘 다 0 으로 푼다(아래 반응형). */
    --tpl-inset: 150px;
    --tbl-inset: 200px;

    /* ── 선택 토글(.section__toggle) : 콘텐츠의 "머리" 다. (요청 2026-07-13)
       "모든 쇼츠 영상 · 비포애프터 · SVF 지방흡입, 이식 …" 처럼 콘텐츠를 갈아 끼우는 토글.
       제목의 일부가 아니라 콘텐츠의 시작이므로, 제목과는 공식 여백(80)을 두고
       자기가 제어하는 콘텐츠에는 가깝게(50) 붙인다.
       ★ 폰트 · 항목 간격 · hover · 선택 상태 · 하단 마진을 여기 3개 토큰 + .section__toggle 규칙이
         전부 정한다. 섹션마다 다시 만들지 않는다. */
    --gap-toggle-item: var(--sp-4);                    /* 항목 ↔ 항목   : 20 */
    --gap-toggle-body: clamp(31px, 2.604vw, 50px);     /* 토글 ↔ 콘텐츠 : 50
                                                          (--sp 스케일에 50 이 없어 전용 토큰) */

    /* ── 콘텐츠 ↔ CTA 간격 : CTA "유형"이 값을 정한다. 섹션별 오버라이드 금지. (요청 2026-07-13)
       CTA 는 두 종류뿐이다:
         .more-link : "더보기 +" 텍스트 링크 - 목록의 꼬리라 콘텐츠에 가깝게 붙인다
         .cta       : 토글형(pill) 버튼      - 독립된 행동이라 더 띄워 준다
       ★ 값은 전부 여기 2개 토큰이 정한다. 섹션(.promo · .reviews · .bna …)이 제 값을 갖지 않는다. */
    --gap-cta-more:   var(--sp-6);   /* 콘텐츠 ↔ 더보기 링크 : 40 */
    --gap-cta-button: var(--sp-8);   /* 콘텐츠 ↔ 토글형 버튼 : 80 */

    /* 예외 1개: GNB depth1 전용 (theline.kr 실측 17~18px, 스케일에 없음) */
    --fs-nav:     clamp(0.9375rem, 0.938vw, 1.125rem);  /* 15 -> 18 */

    /* -- 간격: 10스케일 + 섹션. 1920 기준 5/10/15/20/30/40/60/80/120/160/180 */
    --sp-1:  5px;
    --sp-2:  10px;
    --sp-3:  15px;
    --sp-4:  clamp(14px, 1.042vw, 20px);
    --sp-5:  clamp(19px, 1.563vw, 30px);
    --sp-6:  clamp(25px, 2.083vw, 40px);
    --sp-7:  clamp(37px, 3.125vw, 60px);
    --sp-8:  clamp(50px, 4.167vw, 80px);
    --sp-9:  clamp(74px, 6.25vw,  120px);
    --sp-10: clamp(99px, 8.333vw, 160px);
    --sec-gap: clamp(112px, 9.375vw, 180px);   /* 섹션 사이 표준 간격 */

    /* -- 라운드 : 박스·카드·사진은 예외 없이 --r-lg(20). "20px 완전 고정"
       (--r-md 10 · --r-xl 30 은 폐기했다 - 다시 만들지 말 것. 섞이면 박스마다 R 이 달라진다)
       --r-sm 은 폼 입력칸 전용(작은 칸에 20 을 주면 알약이 된다), --r-pill 은 버튼·태그 전용 */
    --r-sm: 5px;  --r-lg: 20px;  --r-pill: 999px;

    /* ═══ 컴포넌트 기본값 - main 이 기준이다. 다른 CSS 는 "기준과 다른 것"만 덮어쓴다 ═══ */

    /* -- CTA 버튼 여백 : 상하 15 · 좌우 25
       25 는 --sp-4(20) 와 --sp-5(30) 사이값이라 --sp-5 에서 파생한다(임의 px 아님).
       본문 CTA · 각도 토글 · 푸터 플로팅 CTA 가 모두 이 값을 본다 - 한쪽만 어긋나지 않게. */
    --cta-pad-block:  var(--sp-3);                  /* 15 */
    --cta-pad-inline: calc(var(--sp-5) * 5 / 6);    /* 25 */

    /* -- 모바일 이벤트 배지(우하단 · .quick-badge-m) : 폭과 바닥에서 띄운 거리.
       배지 위로 펼쳐지는 퀵 메뉴(.quick-side)가 같은 값을 보고 자기 위치를 잡는다
       → 배지를 옮기거나 키우면 메뉴가 따라온다. 두 곳에 같은 숫자를 적지 않는다.
       env(safe-area-inset-bottom) 은 아이폰 홈바에 가리지 않게 하는 여백. */
    --quick-badge-w:   80px;
    --quick-badge-gap: calc(var(--sp-3) * 2 + env(safe-area-inset-bottom, 0px));  /* 15 × 2 = 30 */
    /* 퀵 원 지름 - 알약 안 아이콘과 맨 위로가 전부 이 값을 본다.
       모바일에서 한 단계 줄인다(아래 반응형에서 재정의). */
    --quick-ico: 44px;

    /* -- 리스트 간격 : 배치 형태가 정한다
       --box-gap  (35) : 좌우로 배치되는 박스·사진. 상하좌우 모두 같은 35
                         35 는 --sp-5(30) 과 --sp-6(40) 사이값이라 --sp-5 에서 파생(임의 px 아님)
       --flow-gap (30) : 위에서 아래로 이어지는 "흐름"(체크리스트 · 시술 과정) */
    --box-gap:  calc(var(--sp-5) * 7 / 6);   /* 35 */
    --flow-gap: var(--sp-5);                 /* 30 */

    /* ── About 2단(.tpl-about) : 좌 영상/사진 + 우 설명. 59개 페이지가 이 한 벌을 공유한다.
       ★ 비율·간격을 바꾸려면 여기 네 줄만 고친다 → 전 페이지에 동시 적용된다.

       ★ 눈에 보이는 여백의 기준은 "이미지" 가 아니라 "붉은 데코" 다.
         데코(.tpl-about__deco)가 이미지 밖으로 --about-deco 만큼 비껴 나와 있으므로
         독자가 보는 간격은 [붉은 선 ↔ 글] 이고, 그게 --about-gutter(60) 가 되도록
         column-gap 은 데코 오프셋을 더해서 파생시킨다. 숫자를 직접 적지 않는 이유 =
         화면이 좁아져 데코 오프셋이 줄면 gap 도 같이 줄어야 60 이 유지되기 때문이다. */
    /* 좌 미디어 : 우 텍스트.
       ★ 글줄 폭은 --about-text 가 정한다(고정). 미디어는 남는 폭을 전부 가져간다(1fr).
         글이 길게 늘어지면 읽기 리듬이 깨지므로 글줄을 묶고 미디어를 키우는 쪽을 택했다.
         글줄을 넓히려면 --about-text 만 키운다. */
    --about-text:  400px;
    /* (요청 2026-07-14) 미디어 폭을 29번 「중앙 축 타임라인」의 이미지와 같게 맞춘다.
       29번은 [1fr | 축 104 | 1fr] 에 gap 60 → (1200 - 104 - 120) / 2 = 488.
       15번엔 축이 없으니 그 결과값을 그대로 고정한다. 비율(--about-ratio 16/9)은 원래 같았다
       → 두 템플릿의 이미지가 488 × 275 로 완전히 같아진다.
       글 열은 1fr 로 두어 남는 폭을 가져간다(400 고정이면 우측에 빈 칸이 생긴다). */
    --about-media: 488px;
    --about-cols:  var(--about-media) minmax(0, 1fr);
    --about-deco:   var(--sp-4);  /* 20 : 데코가 이미지 밖으로 비껴 나오는 양 */
    --about-gutter: var(--sp-7);  /* 60 : ★ 독자가 보는 간격 - 붉은 선 ↔ 글 · 좌우 여백 */
    --about-gap:   calc(var(--about-gutter) + var(--about-deco));  /* 미디어 ↔ 텍스트 (파생) */
    /* 미디어 박스의 비율. 영상(16:9)이든 사진이든 이 한 값으로 크기가 같아진다.
       ★ 원본 사진의 비율이 페이지마다 제각각(와이드·정방형)이라 그대로 두면 About 이
         페이지마다 다른 크기로 선다 → 박스를 고정하고 사진은 cover 로 채운다.
       더 큰 미디어를 원하면 4/3 (더 높아짐), 더 납작하게는 2/1 로 바꾼다. */
    --about-ratio: 16 / 9;

    /* -- 박스 내부 : 아이콘은 제목의 라벨이라 붙이고(sm), 제목과 본문은 성격이 달라 벌린다(md).
       상하 여백은 3 : 5 - 아래를 더 비워야 시각적으로 안정된다.
       본문만 좌우로 더 들여써 글자가 박스 외곽선에 붙지 않게 한다. */
    /* (요청) 아이콘 ↔ 제목을 더 붙인다 : 10 → 5. 아이콘은 제목의 라벨이라 붙을수록 한 덩어리다. */
    --box-gap-sm:     var(--sp-1);                   /* 5  : 아이콘 ↔ 제목 */
    --box-gap-md:     var(--sp-5);                   /* 30 : 제목  ↔ 본문 */
    /* (요청 2026-07-13) 사진 ↔ 제목은 제목 ↔ 본문보다 더 벌린다 - 사진은 제목의 라벨이 아니라
       하나의 면이라, 붙으면 카드가 위로 쏠린다. 30 → 40 으로 올려 글 덩어리를 아래로 내린다. */
    --box-gap-photo:  var(--sp-6);                   /* 40 : 사진  ↔ 제목 (.tpl-box--photo 전용) */
    /* 박스 본문 크기 - 자리에 따라 다르다(아래 .tpl-boxes 규칙에서 갈라 준다) */
    /* (요청) 3:5 비율은 버린다. 상하를 각각 따로 정한다.
       내용을 더 아래로 : 상단 40 → 50. 하단은 상단에 묶이지 않고 50 으로 고정한다.
       (50 은 스케일 사이값이라 --sp-5(30) 에서 파생 - 임의 px 아님) */
    --box-pad-top:    calc(var(--sp-5) * 5 / 3);     /* 50 */
    --box-pad-bottom: calc(var(--sp-5) * 5 / 3);     /* 50 */
    --box-text-inset: var(--sp-4);                   /* 20 : 본문 전용 좌우 인셋 */
    /* (요청 2026-07-14) 박스 제목 24 → 22. 카드 폭(≈273)에서 24 는 본문(15)과 덩어리로 뭉쳐
       보였다. 기울기는 1920 기준(22 / 1920 = 1.1458vw), 좁아지면 하한 18. */
    /* (요청 2026-07-14) 박스 본문 18 → 16. 18 은 카드 폭에서 줄당 9~11자로 끊겨 4줄이 됐다.
       16 은 5스케일의 caption 상한과 같은 값이라 스케일을 늘리지 않는다. (16 / 1920 = 0.8333vw), 하한 14.
       전 박스(.tpl-box)가 이 토큰 하나를 공유한다 - 소개·수술정보·특징 모두 같다. */
    /* 14 : 5스케일(16) 아래 "미세" 단계. eyebrow · 보조 문구(단위 · VAT · 경력)가 함께 쓴다.
       예전엔 --fs-eyebrow-only(14) 와 --box-opt-fs(14) 로 토큰이 둘이었다 → 같은 값이라 하나로 합쳤다. */

    /* ══ 굵기(font-weight) - 딱 3개. (2026-07-14 통합)
         400 : 본문 - content-body · content-subtext · h2lead
         600 : 제목 · 강조 - content-title(h3 · h4) · eyebrow · 버튼(--fs-cta) · <strong> · <b>
         700 : 대제목 - h1 · h2 (--fs-h2title)
       ★ 500 · 200 을 새로 쓰지 않는다. 예전엔 500 이 22곳에 흩어져 "본문도 제목도 아닌"
         어중간한 위계를 만들었다(.cta · .promo__num · .locate__tel …) → 전부 600 으로 접었다.
       ⚠️ 단 하나의 예외: 모달 · GNB · 모바일 메뉴 같은 "UI 장치"는 500 을 쓴다.
         이것들은 콘텐츠가 아니라 조작 장치라 --ui-* / --ico-* 처럼 체계가 따로다.
         본문 요소에서 500 이 보이면 잘못 고른 것이다. */

    /* ══ 행간(line-height) - 딱 3개. (2026-07-13 통합)
       예전엔 본문 규격 [--fs-body / 400 / --ink] 이 15곳에 복붙돼 있었고 행간만 1.5·1.6·1.7 로
       제각각이었다. 값에 이름을 붙여 "어느 자리에 무엇을 쓰는지"를 못박는다.
         --lh-tight (1.45) : 보조 문구(옵션·단위·경력) - 작은 글씨라 좁게
         --lh-body  (1.6)  : 본문 기본. 박스 본문 · 체크 항목 · 과정 설명 · 표 - 짧은 덩어리
         --lh-prose (1.7)  : 줄글 문단. 리드문 · About 본문 - 줄이 길어 더 띄운다
       ★ 자리에 맞는 것을 "고른다". 새 값을 만들지 않는다. */
    --lh-title: 1.4;    /* 제목 · 번호 - 짧고 굵은 줄 (h4 · 박스 제목 · 01·02 번호) */
    --lh-tight: 1.45;
    --lh-body:  1.6;
    --lh-prose: 1.7;

    /* ══ 좌우 2단 분할 - 좌 48 : 우 70. (2026-07-13 통합)
       소개 · 수술정보 · 시술과정(sticky) · 의료진 소개/프로필 · 인어주사 6곳이 각자
       minmax(0,48fr) minmax(0,70fr) 를 따로 적고 있었다 → 한 줄로 모은다.
       비율을 바꾸려면 여기만 고친다. */
    --split-cols: minmax(0, 48fr) minmax(0, 70fr);

    /* ══ 사진 비율 - 카드 사진은 4:3, 인물·정사각은 1:1. (2026-07-13 통합) */
    --ratio-photo:  4 / 3;
    --ratio-square: 1 / 1;
    --ratio-portrait: 3 / 4;   /* 세로 컷 - 소개 섹션의 좁은 sticky 사진(.tpl-intro--slim) */
    /* (요청 2026-07-13) 모바일은 카드가 한 줄에 1개라 4:3 사진이 화면을 세로로 다 먹는다.
       → 위아래를 잘라 가로형(16:9)으로 눕힌다. PC 는 4:3 그대로. */
    --ratio-photo-m: 16 / 9;

    /* ══ 카드 hover 확대 - 프로모션 · 시그니처 · 바로가기 · 함께하면 좋은 수술이 같은 동작을 쓴다 */
    --card-zoom: 1.1;

    /* -- 스케일로 만들 수 없는 값은 "이름을 붙여" 여기 둔다. 규칙에서 벗어난 게 아니라,
       출처가 바깥에 있는 값(사진에 박힌 좌표 등)이라 스케일이 설명할 수 없는 경우다.
       CSS 본문에 생짜 숫자를 남기지 않는 것이 핵심 - 여기 없으면 하드코딩이다. */
    --hairline:     1px;    /* 선·테두리 두께. 전 페이지 단 하나 */

    /* -- 스크롤 등장(reveal) : 얼마나 아래에서 올라오고, 얼마나 오래 걸리는가.
       H2 는 섹션보다 더 올라오고 더 느리다 → 섹션이 먼저 뜨고 제목이 뒤따라 오는 리듬. */
    --reveal-rise-h2: var(--sp-6);   /* 40 : H2   */
    --reveal-dur-h2:  .9s;
    /* 메인 B&A 영상의 원본 비율. 소스 파일(pc.mp4 626×690)이 정하는 값이라
       스케일로 만들 수 없다 → 이름을 붙여 여기 둔다. 영상을 갈아끼우면 이 값도 함께 바꾼다. */
    --bna-video-ratio: 626 / 690;
    --container:    1280px; /* 섹션 폭(.container). 좌우 여백은 --sp-6 → 콘텐츠 시작선은 이 둘이 정한다 */
    --read-width:   700px;  /* 리드문 등 "읽기 폭" 상한. 섹션 폭(--container)과 다른 개념 */
    --bna-blur-top: 17px;   /* B&A 블러가 덮어야 할 사진 상단 여백(원본 이미지 기준) */

    /* ══════════ 색상: 이 7개가 전부. 색상 하드코딩 전면 금지 ══════════ */
    /* ── 브랜드 4색 */
    --ink:    #262627;   /* 1. 메인 블랙   - 모든 텍스트·제목               */
    --dark:   #2E2A26;   /* 2. 다크 브라운 - 푸터·어두운 섹션의 "배경"       */
    --point:  #E95263;   /* 3. 메인 컬러   - 포인트(강조 텍스트·아이콘·활성)
                            (#FF6D6A 에서 명도·채도를 눌러 진하게) */
    --accent: #E5325B;   /* 4. 엣지        - 완전 강조 전용 (아껴 쓸 것)    */

    /* ── 중립 3색 (회색은 딱 2개) */
    --white:      #fff;
    --gray-dark:  #6a6a6a;   /* 보조 텍스트 전용 (글자)             */
    --gray-light: #E0E0E0;   /* 구분선·테두리 전용 (글자에는 금지)   */

    /* ── 파생 틴트 (기존 색에서 자동 생성 · 신규 색 아님) */
    --point-bg:   color-mix(in srgb, var(--point) 12%, #fff);  /* 연한 핑크 배경 */
    --point-soft: color-mix(in srgb, var(--point) 30%, #fff);  /* 흐린 숫자·데코 */
    /* 은은한 회색 배경 - 박스·카드의 "면"을 채울 때. --gray-light(#E0E0E0)는
       선 굵기에 맞춘 색이라 면으로 깔면 무겁다. 그래서 --ink 를 3%만 섞어 쓴다.
       ★ 배경 전용. 선·테두리에는 --gray-light, 글자에는 절대 쓰지 않는다. */
    --bg-soft:    color-mix(in srgb, var(--ink) 3%, #fff);     /* ≈ #F8F8F8 - 카드·박스 (작은 면) */
    --bg-mute:    color-mix(in srgb, var(--ink) 8%, #fff);     /* ≈ #EFEFEF - 푸터·띠 (넓은 면) */

  }

  /* ══ 모바일 CTA - 포맷은 딱 하나다 (2026-07-14)
     PC 는 그대로(15/25) 두고, 모바일만 헤더 "상담예약" 규격(5/15)으로 접는다.
     예전엔 모바일에 세 포맷이 공존했다 - 헤더 34px · 본문 .cta 52px · 상담바 버튼.
     본문 CTA 가 헤더보다 18px 나 두꺼워 "같은 버튼"으로 안 읽혔다.
     ★ 여기(토큰)에서 한 번만 바꾼다. 개별 버튼이 자기 padding 을 따로 들고 있으면
       이 한 줄이 안 먹는다 → .header-cta · 상담바 버튼의 자체 padding 을 전부 걷어냈다. */
  @media (max-width: 991.98px) {
    :root {
      --cta-pad-block:  var(--sp-1);   /* 15 -> 5  */
      --cta-pad-inline: var(--sp-3);   /* 25 -> 15 */
    }
  }
}

/* ----------------------------------------------------------------- base -- */
@layer base {
  /* 제목 없이 본문만 있는 자리의 기본값 = --fs-content-body (20 -> 15 / 400 / 1.6 / -.01em).
     표 내용(td · th)도 여기서 상속받는다 - 따로 크기를 주지 않는다. */
  body {
    font-family: 'Pretendard', system-ui, -apple-system, 'Apple SD Gothic Neo', sans-serif;
    font-size: var(--fs-content-body);
    font-weight: 400;
    line-height: var(--lh-body);          /* 1.6 */
    letter-spacing: -.01em;
    color: var(--ink);
    background: var(--white);
    word-break: keep-all;
  }

  /* DESIGN_SYSTEM 규칙 0-2: heading 은 태그 셀렉터 단 하나, class/style 금지.
     h1 · h2 는 같은 스케일(--fs-h2title)을 쓴다 - 대제목은 42 하나뿐이다(display 80 삭제). */
  h1, h2 { font-size: var(--fs-h2title); font-weight: 700; color: var(--ink);
       line-height: 1.3; letter-spacing: -.03em; text-align: center; }
  /* h2 바로 아래 리드 문장 = --fs-h2lead (18 -> 16 / 400 / 1.6 / -.01em).
     위계: eyebrow(14) → h2(42) → 리드(18) → content-title(22) → subtext(16) */
  :is(h1, h2) + p { font-size: var(--fs-h2lead); font-weight: 400; color: var(--ink);
           line-height: var(--lh-body); letter-spacing: -.01em;
           text-align: center; margin-top: var(--sp-2); }
  /* "제목 + 서브본문" 묶음의 제목 = --fs-content-title (22 -> 18 / 600 / 1.35 / -.01em).
     h3 · h4 가 한 벌을 공유한다 - 카드 안이든 밖이든 제목의 성격은 같다. */
  h3, h4 { font-size: var(--fs-content-title); font-weight: 600; color: var(--ink);
       line-height: 1.35; letter-spacing: -.01em; }

  :focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

  @media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
      animation-duration: .01ms !important;
      animation-iteration-count: 1 !important;
      transition-duration: .01ms !important;
      scroll-behavior: auto !important;
    }
  }
}

/* --------------------------------------------------------------- layout -- */
@layer layout {
  /* ===== 섹션 가로폭: 딱 2가지 (DESIGN_SYSTEM 규칙 0-7) =====
     (2) .container       = 좌우 여백(기본·대부분 섹션)   max 1400 + 좌우 패딩
     (1) .container--full = 좌우 100% 풀블리드(마퀴·슬라이더·의료진 등)  화면 끝까지 */
  /* (2026-07-12) 양쪽 여백을 더 줬다: 1400 → 1280, 좌우 패딩 20 → --sp-6(40) */
  .container       { max-width: var(--container); width: 100%; margin-inline: auto; padding-inline: var(--sp-6); }
  .container--full { width: 100%; max-width: none; margin-inline: 0; padding-inline: 0; }
  /* .container--wide 는 헤더/히어로 바 전용. 섹션 콘텐츠에는 사용 금지(위 2종만 사용) */
  .container--wide { max-width: 1920px; width: 100%; margin-inline: auto; padding-inline: var(--sp-6); }

  /* 화면 밖 렌더 스킵(성능) - 시각 결과 동일 */
  .section { content-visibility: auto; contain-intrinsic-size: auto 600px; }

  [role="tabpanel"][hidden] { display: none !important; }
}

/* ----------------------------------------------------------- utilities -- */
@layer utilities {
  .sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
  .view-mobile { display: none !important; }
  @media (max-width: 991.98px) {
    .view-pc     { display: none !important; }
    .view-mobile { display: revert !important; }
  }
}

/* -------------------------------------------------------- components -- */
@layer components {

  /* Reveal-on-scroll (원본 AOS fadeInUp 대응)
     ★ .js 가 붙어야만 감춘다 - 스크립트가 죽으면 아무것도 안 보이는 사고를 막는다(JS 없으면 그냥 보인다). */
  /* (요청 2026-07-14) 섹션 전체(.reveal) 등장 애니메이션은 삭제한다.
     스크롤 애니메이션은 "헤드(eyebrow + H2 + 리드)" 한 곳에만 건다 - 본문·CTA 는 그냥 있는다.
     ★ HTML 의 class="reveal" 은 51개 파일에 342곳 박혀 있어 건드리지 않는다.
       규칙을 여기서 지웠으므로 그 클래스는 아무 일도 하지 않는다(죽은 훅). */

  /* (요청) 헤드는 "하나의 단위"로 등장한다 - eyebrow · H2 · 서브제목이 따로 놀지 않고 함께 올라온다.
     예전에는 h2 에만 애니메이션이 걸려 있어서 eyebrow 와 서브제목만 먼저 떠 있었다.
     섹션(.reveal)보다 조금 더 올라오고 조금 더 느리게 - 제목 무리가 뒤따라 오는 리듬이 된다. */
  .js .section__head, .js .tpl-head { opacity: 0; transform: translateY(var(--reveal-rise-h2));
    transition: opacity var(--reveal-dur-h2) ease, transform var(--reveal-dur-h2) cubic-bezier(.22, 1, .36, 1); }
  .js .section__head.is-visible, .js .tpl-head.is-visible { opacity: 1; transform: none; }

  /* 모션을 줄여달라는 사용자에게는 애니메이션을 걸지 않는다(접근성) */
  @media (prefers-reduced-motion: reduce) {
    .js .section__head, .js .tpl-head { opacity: 1; transform: none; transition: none; }
  }

  .skip-link { position: fixed; top: -60px; left: 1rem; z-index: 2000;
    background: var(--ink); color: var(--white); padding: .6rem 1rem; transition: top .2s; }
  .skip-link:focus { top: 1rem; }

  /* --- 버튼 (원본 CTA 패턴: fs-[23/62/] fw-600 w-[252px]) ---
     ★ 버튼 라벨은 --fs-cta (16 -> 14 / 600 / -.01em) 하나로 관리한다.
       예전엔 .btn 이 크기를 안 줘서 body(20) 를 상속했다 - 버튼이 문장 크기로 커졌다. */
  .btn { display: inline-flex; align-items: center; justify-content: center;
    font-size: var(--fs-cta); font-weight: 600; letter-spacing: -.01em;
    transition: background .3s, color .3s; }
  .btn--rose { width: clamp(164px, 13.802vw, 265px); height: clamp(50px, 4.167vw, 80px);
    background: var(--point); color: var(--white); }
  .btn--rose:hover { background: var(--ink); }

  /* ── 테두리형 CTA (.cta) - 전 페이지 공통 컴포넌트
     page-template.css 에 있던 것을 main.css 로 승격했다(규칙 6: 2개 이상 페이지가 쓰면 main).
     index 상담폼의 .btn--cta 는 이것과 모양만 다르고 역할이 같아 삭제하고 여기로 합쳤다.
     · 고정 width/height 를 두지 않는다 - 크기는 padding 이 정한다(글자가 길어져도 안 깨진다)
     · 테두리는 border 가 아니라 inset box-shadow - border 는 박스를 1px 씩 키운다 */
  .cta { display: inline-flex; align-items: center; justify-content: center;
    padding: var(--cta-pad-block) var(--cta-pad-inline); border-radius: var(--r-pill);
    background: transparent; color: var(--point);
    box-shadow: inset 0 0 0 var(--hairline) var(--point);
    font-size: var(--fs-cta); font-weight: 600; letter-spacing: -.01em;
    transition: background .2s, color .2s; }
  .cta:hover { background: var(--point); color: var(--white); }
  /* (요청 2026-07-14) 본문 CTA 만 모바일에서 상하 1px 씩 키운다(32 → 34).
     GNB 상담예약은 헤더 안에 갇혀 있어 32 가 꽉 차 보이지만, 본문 CTA 는 넓은 여백에
     홀로 놓여 같은 32 여도 작아 보인다. 착시를 보정하는 값이라 토큰이 아니라 여기서만 준다. */
  @media (max-width: 991.98px) {
    .cta { padding-block: calc(var(--cta-pad-block) + 1px); }
  }
  /* (2026-07-12) .bna-toggle(pill) 삭제 - 템플릿 7번 각도 토글이 index 탭과 같은 텍스트 스타일로 통일됐다. */

  /* 더보기 (원본 .board-more-btn) - 우측 정렬 텍스트 링크.
     CTA 와 역할이 다르다: "더보기 +" 는 목록의 연장(우측), CTA 는 행동 유도(중앙 버튼) */
  .more-link { display: inline-flex; align-items: center; gap: .4em;
    font-size: var(--fs-content-body); color: var(--ink);
    border-bottom: 1px solid var(--ink); padding-bottom: .3em; }
  /* hover 는 "마우스가 있는 기기"로 한정한다 (2026-07-17 버그 수정).
     터치 기기는 탭 이후 :hover 가 풀리지 않고 고착돼, 더보기/줄이기가
     한 번 누른 뒤부터 계속 빨간색(디폴트처럼)으로 보였다. */
  @media (hover: hover) {
    .more-link:hover { color: var(--point); border-color: var(--point); }
  }
  /* ── CTA 영역(.section__foot) : "콘텐츠 ↔ CTA" 간격의 유일한 주인 ──
     간격은 CTA 의 "유형"이 정한다. 섹션이 제 값을 갖지 않는다(오버라이드 금지).
       .more-link ("더보기 +" 링크)  → 40  : 목록의 꼬리라 콘텐츠에 붙는다
       .cta       (토글형 pill 버튼) → 80  : 독립된 행동이라 더 띄운다
     새 섹션을 만들어도 CTA 만 넣으면 값이 자동으로 맞는다. */
  .section__foot { text-align: center; }   /* 간격은 세로 리듬이 준다 (40 / 80) */
  .section__foot--right { text-align: right; }

  /* ══════════ 섹션 헤드 = 하나의 단위 (전 페이지 · 전 섹션 공통, 예외 없음) ══════════
       [영문 eyebrow] → [H2] → [서브제목(선택)] → [탭(선택)]
     ★ 이 블록이 사이트의 모든 헤드를 정의한다. 섹션·페이지마다 다시 만들지 않는다.
       .section__head(index) 와 .tpl-head(서브페이지·template) 는 이름만 다른 같은 것이다.
     · 줄 간격  : --head-gap-title(30) / --head-gap-sub(10) / --head-gap-tabs(40)
     · 본문까지 : --head-gap-body(80) - 헤드 "블록"의 바깥 마진.
                  서브제목·탭이 있든 없든 항상 마지막 줄에서 112 다 → 예외를 두지 않는다.
     · 등장     : 이 블록이 통째로 한 번에 올라온다(아래 .js 규칙).
     값을 바꾸려면 위 토큰 4개만 고친다. */
  .section__head, .tpl-head { text-align: center; }   /* 간격은 아래 세로 리듬이 준다 */
  /* 자식 마진을 전부 지우고 여기서만 다시 준다 → 어떤 조합이 와도 간격이 흔들리지 않는다 */
  .section__head > *, .tpl-head > * { margin: 0; }
  .section__head > :is(h1, h2), .tpl-head > :is(h1, h2) { margin-top: var(--head-gap-title); }
  /* 서브제목 - 클래스가 .tpl-lead 든 그냥 <p> 든 완전히 같다.
     ★ 읽기 폭(--read-width 700) 상한을 여기서 준다. 없으면 한 줄이 컨테이너 폭(1200)까지
       퍼져 눈이 줄을 따라가지 못한다(2026-07-12 회귀: .tpl-lead 정의가 지워져 실제로 그랬다).
     크기·색·정렬은 base 의 h2 + p 규칙이 이미 정한다 → 여기서 다시 만들지 않는다. */
  /* ★ --flush(가격 행 · HOT EVENT 띠)는 제외한다.
     거기 <p> 는 "서브제목"이 아니라 가격 값(2,100,000~)이나 배너 카피라서
     크기·정렬이 다르다. 서브제목 규칙에 휩쓸리면 안 된다. */
  /* (요청 2026-07-14) 서브제목은 리드 스케일(--fs-lead 18)이다. body(20) 를 그대로 쓰면
     카드 제목(22) 과 크기가 붙어 위계가 흐려진다. 줄이 길지 않으니 행간도 prose(1.7) → body(1.6). */
  .section__head > :is(h1, h2) + p,
  .tpl-head:not(.tpl-head--flush) > :is(h1, h2) + p {
    font-size: var(--fs-h2lead); font-weight: 400; line-height: var(--lh-body);
    letter-spacing: -.01em; text-align: center; color: var(--ink);
    margin-top: var(--head-gap-sub);
    max-width: var(--read-width); margin-inline: auto; }
  /* 서브제목 안의 <strong> 은 SEO 키워드 마킹용 - 시각 차이를 만들지 않는다(규칙: 제목은 문장 전체가 균일) */
  .section__head > :is(h1, h2) + p strong,
  .tpl-head:not(.tpl-head--flush) > :is(h1, h2) + p strong { color: inherit; font-weight: inherit; }
  .section__head :is(h1, h2) strong, .tpl-head :is(h1, h2) strong { color: inherit; font-weight: inherit; }
  /* .tpl-head--flush : 배너·행 안에 놓인 헤드(가격 행 · HOT EVENT 띠).
     세로 리듬은 "래퍼의 직계 자식"에만 걸리므로 이런 헤드는 애초에 마진을 받지 않는다.
     → 마진 무효화 선언이 필요 없다. 클래스는 서브제목 규칙 제외용으로만 남는다. */

  /* ══════════ 선택 토글 (.section__toggle) - 콘텐츠의 "머리" ══════════
     "모든 쇼츠 영상 · 비포애프터 · SVF 지방흡입, 이식 …" 처럼 콘텐츠를 갈아 끼우는 토글.
     ★ 제목의 일부가 아니라 콘텐츠의 시작이다 → 헤드 밖의 형제 슬롯으로 둔다.
         [헤드] ─80(공식 여백)─ [선택 토글] ─50─ [콘텐츠]
     ★ 폰트 · 항목 간격 · hover · 선택 상태 · 하단 마진을 전부 이 한 곳이 정한다.
       섹션(쇼츠 · 전후사진 · 앞으로 생길 것)마다 다시 만들지 않는다.
     ※ 위 마진은 헤드의 margin-bottom(80)이 잡으므로 여기서 주지 않는다. */
  /* 룩(글자 · 항목 간격 · hover · 선택색)은 여기 한 벌뿐이다.
     .tpl-bna__tabs(카드 안 각도 선택기)도 같은 룩을 쓴다 → 셀렉터에 얹는다.
       (요청) 하단 마진(--gap-toggle-body 50)도 같다 → 토글 ↔ 콘텐츠 거리가 섹션 어디서나 같다.
       남는 차이는 "상태를 담는 속성"뿐이다(aria-selected / .is-on). */
  .section__toggle, .tpl-bna__tabs {
    display: flex; flex-wrap: wrap; justify-content: center;
    gap: var(--gap-toggle-item); }              /* 항목 간 거리 : 20 (아래 간격은 세로 리듬이 준다) */
  /* (2026-07-13) 토글 항목이 "링크"인 경우도 같은 룩을 쓴다 → 셀렉터에 a 를 얹는다.
     같은 시술의 유형이 여러 페이지로 갈라져 있고 그 목록이 GNB 에 없을 때(코성형 6종),
     페이지끼리 서로를 오가는 내비가 필요하다. 전용 컴포넌트를 만들지 않고 이 룩을 그대로 쓴다.
     상태는 button 이 aria-selected(JS), a 는 aria-current="page"(정적 - 현재 페이지). */
  .section__toggle button, .section__toggle a, .tpl-bna__tabs button {
    padding: var(--sp-1) var(--sp-2);
    font-size: var(--fs-content-body); font-weight: 400; color: var(--gray-dark);
    background: none; border: 0; white-space: nowrap; cursor: pointer;
    transition: color .2s; }
  .section__toggle button:hover, .section__toggle a:hover,
  .tpl-bna__tabs button:hover { color: var(--point); }
  /* 선택 상태 = 포인트 컬러 + 볼드.
     상태를 담는 속성이 서로 다르다: 섹션 토글 = aria-selected(JS), 각도 선택기 = .is-on(JS),
     링크 내비 = aria-current="page"(정적) */
  .section__toggle button[aria-selected="true"],
  .section__toggle a[aria-current="page"],
  .tpl-bna__tabs button.is-on { color: var(--point); font-weight: 600; }

  /* ══════════ 섹션 골격 (전 페이지 · 전 섹션 공통, 예외 없음) ══════════
     섹션 <section class="tpl-sec|section">          → 상단 마진 = --sec-gap
       └ 래퍼 <div class="container|container--full"> → 폭 (규칙 7)
           ├ 헤드 .tpl-head / .section__head          → 헤더 + 하단 마진(--head-gap-body 80)
           │                                            ※ 제목 없는 섹션은 헤드 자체를 생략
           ├ 선택 토글 .section__toggle               → 있을 때만. 콘텐츠의 "머리".
           │                                            하단 마진(--gap-toggle-body 50)로 콘텐츠에 붙는다
           ├ 콘텐츠                                    → ★ 자기 위/아래 마진 없음
           │                                            내부 요소끼리만 마진으로 배치
           └ CTA .section__foot                       → 있을 때만. 콘텐츠 ↔ CTA 간격 = 이 요소의 margin-top
                                                        (.more-link 40 / .cta 80 - 유형이 값을 정한다)

     ★ 왜 강제하는가: 콘텐츠가 자기 마진을 들고 있으면 "본문이 끝나는 지점"이 헤드 마진·CTA 마진과
       이중으로 겹쳐서 꼬인다(간격이 두 번 더해지거나, 박스 안에 죽은 공백이 남는다).
       간격의 주인을 하나로 못박는다 → 위는 헤드, 아래는 CTA, 사이는 콘텐츠 내부.
     ★ 마진을 가질 수 있는 것은 헤드 · 토글 · CTA 3개뿐이다. 콘텐츠는 못 가진다. */

  /* ══════════ 섹션 세로 리듬 - 간격은 이 블록이 전부 정한다 ══════════
     ★ 모델 하나 : [간격은 언제나 "뒤 요소의 margin-top"] + [값은 "앞 요소가 무엇이냐"가 정한다]
       그래서 케이스를 나눌 필요가 없다. 토글이 있든 없든, CTA 가 무엇이든 규칙 한 벌로 끝난다.

         앞이 헤드          → 80   (--head-gap-body)     뒤가 토글이든 콘텐츠든 같다
         앞이 선택 토글      →  50  (--gap-toggle-body)
         뒤가 CTA           →  40 (.more-link) / 80 (.cta)   ← CTA 유형이 값을 정한다
         그 외 (콘텐츠끼리)  →   0

     ★ 자기 마진을 갖는 요소가 없다 → 마진이 이중으로 겹치거나 상쇄될 일이 없다.
     ★ 새 슬롯이 생기면 "앞 요소 + *" 한 줄만 추가한다. */

  /* (0) 래퍼 직계 자식은 자기 세로 마진을 갖지 않는다 - 간격의 주인은 아래 규칙뿐이다.
         ※ :is() 로 특이도(0,3,0)를 확보한다 - 안 그러면 컴포넌트 규칙(0,1,0)에 밀린다. */
  :is(.tpl-sec, .section) > :is(.container, .container--full) > * { margin-block: 0; }

  /* (0-b) ★ 컨테이너 직계 이미지 = "통짜 1장" (요청 2026-07-14, svf-liposuction 검수)
     - width 속성이 컨테이너보다 작으면 **왼쪽으로 쏠린다** → margin-inline: auto 로 가운데 세운다.
     - 컨테이너를 꽉 채우면 도해가 지나치게 커 보인다 → 폭 상한을 둔다.
       (잘라내면 라벨이 사라지는 도해라 통짜를 유지하되, 크기만 줄인다) */
  :is(.tpl-sec, .section) > :is(.container, .container--full) > img {
    margin-inline: auto; max-width: min(100%, var(--solo-img-max, 960px)); }
  /* 템플릿 뒤에 통짜 이미지가 이어지면 딱 붙는다(콘텐츠끼리는 0) → 숨을 준다 */
  :is(.tpl-sec, .section) > :is(.container, .container--full) > * + img {
    margin-top: var(--sp-8); }
  /* 반대 방향도 같은 숨 - 통짜 이미지 뒤에 레일이 이어지는 경우 (2026-07-17, about 사회공헌) */
  :is(.tpl-sec, .section) > :is(.container, .container--full) > img + .ub-rail {
    margin-top: var(--sp-8); }
  /* (요청 2026-07-17) 단, 앞이 캡션(CASE A · … )이면 얘기가 다르다 - 캡션은 그 이미지의
     것이므로 붙어 있어야 한 덩어리로 읽힌다. 위 규칙(--sp-8 = 80)은 "남남인 템플릿과
     이미지" 사이의 숨이라 캡션에 쓰면 제목만 붕 뜬다 → 캡션 ↔ 이미지는 15 로 붙인다.
     (해당 패턴은 CASE 캡션 전용이다 - forehead-lift 6 · lower-blepharoplasty 3) */
  :is(.tpl-sec, .section) > :is(.container, .container--full) > .tpl-eyebrow + img {
    margin-top: var(--sp-3);
    /* (요청 2026-07-17) 케이스 사진도 사이트 표준 R 을 따른다 - 섹션 직속 img 에는 R 규칙이
       없어 혼자 각진 모서리였다(다른 사진은 전부 --r-lg). */
    border-radius: var(--r-lg);
    /* (요청 2026-07-17) 케이스 이미지는 원본 크기가 570~640 으로 제각각이라 케이스마다
       폭이 달라 보인다 → 섹션에서 --case-img-w 를 주면 그 폭으로 통일된다.
       기본값 auto = 원본 크기(기존 동작 그대로) - 값을 준 섹션만 바뀐다. */
    width: var(--case-img-w, auto); }
  /* (요청 2026-07-17) 이미지 ↔ 다음 CASE 캡션은 "케이스와 케이스 사이"다 → 캡션 자신의
     margin-top 을 키우면 케이스 묶음(캡션+이미지)이 통째로 떨어져 보인다.
     ★ :has(+ img) 가 핵심 - "앞도 이미지, 뒤도 이미지"인 캡션만 잡는다. 이게 없으면
       이미지 뒤 주의문구(※ …)까지 같이 벌어진다(케이스 사이가 아니므로 대상이 아니다).
     ★ PC 만 50 이다(요청) - 모바일은 기본 간격(--sp-6)을 그대로 둔다. 좁은 화면에서는
       케이스가 이미 세로로 길게 이어져 50 까지 벌릴 이유가 없다. */
  @media (min-width: 992px) {
    :is(.tpl-sec, .section) > :is(.container, .container--full) > img + .tpl-eyebrow:has(+ img) {
      margin-top: 50px; }
  }

  /* (1) 앞이 헤드 → 80 */
  :is(.tpl-sec, .section) > :is(.container, .container--full)
    > :is(.tpl-head, .section__head) + * { margin-top: var(--head-gap-body); }

  /* (2) 앞이 선택 토글 → 50
         ※ .tpl-bna__tabs(카드 안 각도 선택기)는 래퍼 직계가 아니라 카드 안이지만
           "토글 뒤는 50" 이라는 같은 리듬을 따른다 → 같은 줄에 얹는다. */
  :is(.tpl-sec, .section) > :is(.container, .container--full)
    > .section__toggle + *,
  .tpl-bna__tabs + * { margin-top: var(--gap-toggle-body); }

  /* (3) 뒤가 CTA → 유형이 값을 정한다 (섹션이 제 값을 갖지 않는다) */
  :is(.tpl-sec, .section) > :is(.container, .container--full)
    > .section__foot { margin-top: var(--gap-cta-more); }              /* 더보기 링크 : 40 */
  :is(.tpl-sec, .section) > :is(.container, .container--full)
    > .section__foot:has(.cta) { margin-top: var(--gap-cta-button); }  /* 토글형 버튼 : 80 */

  /* 섹션 보조 타이틀(영문 eyebrow) - 전 페이지 공통. 이름은 .tpl-eyebrow 하나다.
     영문 대문자라 자간은 양수(+.08em)가 맞다(한글 제목의 음수 자간과 반대).
     (2026-07-12 별칭 .lp-eyebrow · .mi-eyebrow · .mi-rec-eyebrow 삭제 - 쓰는 페이지가 0 이 됐다) */
  /* (요청 2026-07-12) 크기는 5스케일 최소값(caption 16)까지 낮추고, 굵기는 한 단계 올린다(500→600).
     작지만 또렷하게 - H2 를 가리지 않으면서 섹션의 라벨 역할만 한다. */
  .tpl-eyebrow {
    font-size: var(--fs-eyebrow); font-weight: 600; letter-spacing: .08em;
    text-transform: uppercase; color: var(--point); text-align: center; line-height: 1.5; }

  /* ★★ 문장형 캡션·주의문구의 읽기 폭 (전역, 예외 없음) ─────────────────────
     이 클래스들은 "라벨"이 아니라 "읽는 문장"이다. 폭을 안 막으면 컨테이너를 그대로 받아
     와이드 화면에서 한 줄이 1,200~2,500px 까지 늘어진다 - 눈이 다음 줄 첫 글자를 못 찾는다.
     ⚠️ 특정 섹션에만 걸면 같은 문구가 다른 페이지에서 또 새어 나온다(실제로 consult-fast ·
        real-model · articles-bna 가 그렇게 빠져 있었다). → 클래스 자체에 건다.
     짧은 라벨(예: "RELATED TREATMENTS")은 700 보다 짧으므로 이 상한에 걸리지 않는다. */
  .tpl-eyebrow, .bna-note, .counsel-note, .doctors__cert {
    max-width: var(--read-width); margin-inline: auto; }

  /* (요청 2026-07-14) 섹션 헤드 "밖"의 eyebrow = 템플릿 아래 붙는 캡션·주의문구다.
     헤드의 라벨(빨강·대문자)과 성격이 다르다 → 연한 회색으로 낮추고, 본문에서 떼어 놓는다.
     예) "※ 수술 전후 사진은 개인에 따라…", "지방 흡입 시 SVF와 AD-ECM을 동시에 추출해…" */
  :is(.tpl-sec, .section) > :is(.container, .container--full) > .tpl-eyebrow {
    color: var(--gray-dark); text-transform: none; letter-spacing: normal;
    font-weight: 400; margin-top: var(--sp-6); }

  /* --- 서브페이지 공통: 상단 히어로 배너 (2개 이상 페이지 공유, 원본 sub 상단 배너) --- */
  .sub-hero { position: relative; color: var(--dark); }
  /* 히어로 배너는 표준 1920×600(3.2:1)로 박스를 고정한다. 원본 파일이 다른 비율이어도
     (예: nk-cell-iv 1672×941) object-fit:cover 로 크롭되어 모든 페이지 높이가 같아진다. */
  .sub-hero__bg { display: block; width: 100%; aspect-ratio: 1920 / 600; height: auto; object-fit: cover; }
  /* ⚠️ 히어로 배너는 섹션 헤드가 아니다 - 전용 헤더다.
     사진 위 왼쪽 빈 공간에 얹히는 "배너 카피"라 가운데 정렬하면 인물과 겹친다.
     → 섹션 헤드(.section__head / .tpl-head)와 섞지 않고 여기서 따로 정의한다.
       페이지에 딱 하나뿐이고 다른 섹션과 공유하지 않으므로 예외를 두는 것이 맞다.
     (2026-07-12: 전 H2 통일 작업에서 이 자리만 원래 디자인으로 되돌렸다) */
  /* 카피 시작선 = 섹션 콘텐츠 시작선 (2026-07-13).
     히어로는 풀블리드라 .container 를 못 쓴다 → 같은 식을 좌표로 푼다:
       가운데 정렬된 --container(1280) 의 좌측 여백 + .container 의 좌우 패딩(--sp-6).
     1920 에서 (1920-1280)/2 + 40 = 360 → 아래 섹션들과 같은 x 에서 글자가 시작한다.
     화면이 1280 이하로 좁아지면 clamp 하한(--sp-6)이 받아 .container 와 계속 붙어 간다. */
  .sub-hero__text { position: absolute; top: 50%; transform: translateY(-50%);
    left: clamp(var(--sp-6), calc((100% - var(--container)) / 2 + var(--sp-6)), 50%); }
  .sub-hero__en { font-size: var(--fs-content-title); line-height: clamp(20px, 1.667vw, 32px);
    font-weight: 400; color: inherit; }
  .sub-hero :is(h1, h2) { font-size: var(--fs-h2title); line-height: clamp(37px, 3.108vw, 60px);
    letter-spacing: -.03em; font-weight: 600; color: inherit; text-align: left;
    margin-top: var(--sp-2); }
  /* 행간은 배수로 준다. 예전엔 29px 고정이라 폰트(clamp 15~20)가 줄어도 행간이 안 따라와
     992~1400 구간에서만 비율이 1.93 까지 벌어졌다(PC 1.45 · 모바일 1.45 는 우연히 맞았다). */
  .sub-hero :is(h1, h2) + p { font-size: var(--fs-content-body); line-height: var(--lh-tight); font-weight: 400;
    color: inherit; text-align: left; margin-top: var(--sp-2); }

  /* --- 모바일 배너 (2026-07-13) ---
     원본 배너는 1920×600 이라 390px 폭에서 높이가 122px 로 줄어드는데, 카피는 172px 라
     위아래로 삐져나와 sticky 헤더에 가려졌다. 또 PC 의 left(16.875vw)는 모바일에서
     clamp 하한 201px 이 걸려 화면(390) 절반을 넘어가 카피가 우측으로 밀렸다.
     → 배너 높이를 카피가 들어갈 만큼 확보하고(cover), 인물이 있는 우측을 기준으로 크롭한다.
       카피는 좌측 빈 배경 위로 되돌린다. */
  /* --- 히어로 스크림 (2026-07-13) ---
     배경 사진이 복잡한 페이지(svf-lab 등)는 카피가 사진에 묻혀 안 읽힌다.
     → 카피가 앉는 왼쪽에만 그라디언트를 깔고, 인물이 있는 오른쪽으로 갈수록 투명해진다.
       스크림 색은 글자색을 따라간다. 사진 히어로 61개는 전부 어두운 글자라 흰색 하나면 된다
       (흰 글자는 사진 없는 .sub-hero--plain 뿐이고 걔들은 스크림 대상이 아니다).
       나중에 어두운 사진 위에 흰 글자를 쓰는 히어로가 생기면 --hero-scrim 만 var(--ink) 로 덮는다.
     ⚠️ 끝점을 `transparent` 로 두면 sRGB 보간에서 회색 띠가 생긴다 → color-mix(… 0%) 로 색상을 유지한 채 투명하게 만든다.
     사진이 없는 .sub-hero--plain(컬러밴드)은 :has 로 제외된다. */
  .sub-hero { --hero-scrim: var(--white); --hero-scrim-end: 62%; }
  .sub-hero:has(> .sub-hero__bg)::before {
    content: ""; position: absolute; inset: 0; pointer-events: none;
    background: linear-gradient(90deg,
      color-mix(in srgb, var(--hero-scrim) 85%, transparent) 0%,
      color-mix(in srgb, var(--hero-scrim) 60%, transparent) calc(var(--hero-scrim-end) * .45),
      color-mix(in srgb, var(--hero-scrim)  0%, transparent) var(--hero-scrim-end)); }

  /* 줄간격(2026-07-13): 폰트는 clamp 로 줄어드는데(h2 48→24) line-height 는 PC 용 px 하한
     (h2 37 · 본문 29)에 걸려 그대로 남아 배수가 1.25→1.54, 1.45→1.93 으로 벌어졌다.
     → 모바일에서는 PC 와 같은 "배수"로 고쳐 잡는다(px 하한을 쓰지 않는다). */
  @media (max-width: 991.98px) {
    .sub-hero__bg { height: clamp(200px, 56vw, 260px); object-position: 78% center; }
    /* left 는 손대지 않는다 - 위 clamp 하한(--sp-6)이 곧 .container 의 모바일 좌우 여백이라
       모바일에서도 카피가 아래 섹션과 같은 선에서 시작한다. */
    .sub-hero__text { max-width: 62%; }
    /* 모바일은 카피가 화면 폭의 62% 를 쓰고 사진도 우측 크롭이라, 스크림을 더 오래 끌고 간다. */
    .sub-hero { --hero-scrim-end: 88%; }
    /* ★ 모바일 히어로 타이포 (요청 2026-07-14)
       히어로 h2 가 26/600 이라 바로 아래 섹션 H2(26/600)와 크기·굵기가 똑같았다.
       배너 위 카피와 본문 제목이 같은 무게로 서니 화면이 산만하고 위계가 없다.
       → 히어로는 "작지만 굵게" 간다. 크기는 한 단계 내리고(26→18) 굵기는 올린다(600→700).
         본문 H2(26/600)가 확실히 더 커서, 히어로가 덜 도드라지고 제목 자리를 내준다.
       영문 en 도 18/400 이면 h2 와 같은 크기라 라벨로 안 읽힌다 → eyebrow 규격(14/600)으로. */
    .sub-hero__en { font-size: var(--fs-eyebrow); font-weight: 600; letter-spacing: .08em;
      line-height: 1.1; }
    .sub-hero :is(h1, h2) { font-size: var(--fs-content-title); font-weight: 700;
      line-height: 1.25; margin-top: var(--sp-2); }
    /* 설명은 본문보다 한 단계 작게(15→14) - 카피 덩어리 전체를 가볍게 만든다 */
    .sub-hero :is(h1, h2) + p { font-size: var(--fs-content-subtext); font-weight: 400;
      margin-top: var(--sp-3); }
  }

  /* 로컬 서브내비(.sub-nav) 제거: GNB 드롭다운과 중복 → 페이지 배너 밑 메뉴버튼 금지(규칙 0-8) */

  /* --- 헤더 (원본: bg #fff, 로고 288/모바일243, depth1 17px fw300) --- */
  .site-header { position: sticky; top: 0; z-index: 1000; background: var(--white); }
  /* (요청) 헤더 흰 영역 높이 98 → 78 (20px 축소) */
  /* (요청 2026-07-14) 로고 파일이 길어(313×40) GNB 가 로고에 딱 붙었다(간격 0).
     원본(phpnew3)은 로고 뒤 30px 를 비우고 GNB 를 시작한다 → 헤더 3요소(로고·GNB·유틸)
     사이에 같은 간격을 준다. 간격의 주인은 헤더 한 곳이다. */
  .site-header__inner { display: flex; align-items: center; column-gap: var(--sp-5);
    height: clamp(56px, 4.063vw, 78px); }
  .logo { flex: 0 0 auto; }
  .logo { line-height: 0; }
  /* (2026-07-14) 로고 = assets/img/layout/logo_wide.webp (1200×153 = 가로 7.84배).
     ⚠️ 앞서 쓰던 logo_new.webp(4726×1250)는 가로로 찌그러진 파일이었다(3.78배) → 폐기.
        정상 원본은 phpnew2 의 9796×1250 이고, phpnew3/phpnew2 는 이걸 폭 288(모바일 243)로 쓴다.
     크기의 주인은 "폭"이다: 288/1920 = 15vw · 높이는 비율대로 37. height 는 auto(이미지가 비율을 정한다).
     모바일 하한 180px → 높이 23px 로 모바일 헤더(60px) 안에 수납된다. */
  .logo img { width: clamp(180px, 15vw, 288px); height: auto; }
  @media (max-width: 991.98px) {
    /* (요청 2026-07-13) 모바일 헤더 좌우 여백 축소 : 25 → 15 (--sp-3).
       .container--wide 의 기본 여백(--sp-6)은 모바일에서 하한 25px 로 걸리는데,
       390px 화면에서는 로고와 햄버거를 안쪽으로 너무 밀어 넣어 답답하다.
       ★ 헤더 바(로고 + 햄버거) 에만 적용한다 - 본문 .container 는 그대로다. */
    .site-header__inner { height: 60px; padding-inline: var(--sp-3); }
  }

  /* 원본: GNB는 로고 옆(x360), 유틸이 우측 끝 - margin-left:auto 는 유틸에 */
  /* (요청) GNB는 로고·아이콘 사이 남는 공간의 중앙 정렬 */
  /* min-width:0 - GNB 가 유틸을 밀어내지 않게(가로 스크롤 방지) */
  /* (요청) GNB 는 헤더 흰 영역 높이를 꽉 채운다(align-self: stretch).
     → 밑줄(::after, bottom:0)이 "헤더 흰 영역의 끝선"에 정확히 붙고,
       드롭다운(top:100%)도 헤더 바로 아래에서 열린다. */
  .gnb { display: flex; flex: 1; min-width: 0; justify-content: center; align-self: stretch; }
  .gnb__item { position: relative; display: flex; align-items: center; }
  /* (요청) depth1: 18px(--fs-nav, GNB 전용 예외 토큰) + 굵기 400. 자간 theline.kr 기준 -.05em */
  .gnb__link { display: block; padding: var(--sp-1) var(--sp-4);
    font-size: var(--fs-nav); font-weight: 400; letter-spacing: -.05em;
    color: var(--ink); white-space: nowrap; transition: color .25s; }
  /* (요청) hover 시 depth1 글자색도 포인트 컬러(--point). 강조색(--accent) 아님 */
  /* ⚠️ 열림 조건에 :focus-within 을 쓰지 않는다 (2026-07-17 버그 수정).
     클릭도 포커스를 남기므로, 클릭한 메뉴의 패널이 열린 채 다른 메뉴에 hover 하면
     패널이 2개 겹쳐 보였다. → :has(:focus-visible) 로 좁힌다.
     키보드(Tab) 포커스에만 반응하고, 마우스 클릭 포커스는 무시한다. */
  .gnb__item:hover > .gnb__link,
  .gnb__item:has(:focus-visible) > .gnb__link { color: var(--point); }
  /* 밑줄: 헤더 흰 영역 하단에 붙어 좌우로 펼쳐짐 (링크 좌우 패딩과 동일 폭) */
  .gnb__item::after { content: ""; position: absolute; bottom: 0; left: 50%; right: 50%;
    height: 3px; background: var(--point); transition: left .25s, right .25s; }
  .gnb__item:hover::after, .gnb__item:has(:focus-visible)::after {
    left: var(--sp-4); right: var(--sp-4); }
  /* (요청) phpnew3 서브메뉴: wrap padding 22/30, 각 항목 padding 15px 0 (넉넉한 줄간격) */
  .gnb__panel { position: absolute; top: 100%; left: 50%; transform: translateX(-50%) translateY(6px);
    min-width: max-content; background: var(--white); border-radius: 0 0 var(--r-sm) var(--r-sm);
    box-shadow: 0 .125rem .25rem rgb(0 0 0 / .075);
    padding: var(--sp-4) var(--sp-5); display: grid; gap: 0;
    opacity: 0; visibility: hidden; transition: opacity .25s, transform .25s, visibility .25s;
    text-align: center; }
  .gnb__item:hover .gnb__panel, .gnb__item:has(:focus-visible) .gnb__panel {
    opacity: 1; visibility: visible; transform: translateX(-50%) translateY(0); }
  /* (2026-07-12) 마지막 항목("후기")만 우측 정렬하던 예외를 제거했다.
     GNB 폰트·간격을 줄이기 전에는 중앙정렬 시 패널이 뷰포트를 넘었지만,
     지금은 후기 패널 우측 끝이 1544px(뷰포트 1920) 안쪽이라 넘치지 않는다.
     → 모든 항목이 링크 중심 기준 중앙정렬로 통일된다. */

  /* (요청 2026-07-28) 브레이크포인트 1540 → 1200.
     Injectables 메뉴 숨김으로 GNB 가 10 → 9항목이 되어 필요 폭이 줄었다.
     (이전 1540 근거: 10항목 기준 마지막 항목과 아이콘 간격이 1460 에서 0 이 되는 실측)
     ★ 헤더만 넘긴다. 본문 반응형(991.98)은 건드리지 않는다. */
  @media (max-width: 1199.98px) {
    .gnb.view-pc          { display: none !important; }
    .hamburger.view-mobile { display: inline-flex !important; }
  }

  /* 헤더 CTA(상담예약)는 모바일 전용 - PC 는 하단 상담바가 그 역할을 한다 */
  .header-cta { display: none; }

  /* --- 모바일 헤더 2단 구조 (991.98 이하 전용 · PC 영향 없음) ---
     1단 = 로고 + 햄버거만 / 2단 = 간이 GNB 3개.
     .view-mobile 유틸은 display:revert !important 라 grid 를 덮으므로 쓰지 않고
     .gnb-bar 가 자기 display 를 직접 제어한다. */
  .gnb-bar { display: none; }
  @media (max-width: 991.98px) {
    /* 1단: 블로그·티스토리·언어를 숨겨 로고 + [상담예약] + 햄버거만 남긴다 */
    .util-nav > .util-nav__link:not(.hamburger),
    .util-nav > .lang { display: none; }

    /* 하단 고정 상담바(입력폼)는 모바일에서 화면을 크게 잡아먹는다 → 숨기고,
       그 역할을 헤더의 [상담예약] 버튼이 대신한다(같은 #counsel 로 보낸다). */
    .consult-bar { display: none; }

    /* 헤더 CTA - 외곽선만(면 없음).
       우측 여백은 .util-nav 의 gap 이 담당한다 → margin-right 를 따로 주면
       간격이 두 번 더해져 햄버거가 밀린다. 좌측 여백만 준다.
       ★ 글자는 --fs-cta (14 / 600 / -.01em) - 버튼 라벨은 어디서나 한 벌이다.
         예전엔 calc(--ui-text - 1px) / 700 이라 다른 버튼과 크기·굵기가 모두 튀었다. */
    .header-cta { display: inline-flex; align-items: center; justify-content: center;
      margin-left: var(--sp-3); margin-right: 0;
      padding: var(--cta-pad-block) var(--cta-pad-inline);   /* 모바일 토큰 = 5/15 */
      /* 테두리는 border 가 아니라 inset box-shadow - border 는 박스를 1px 씩 키운다.
         예전엔 여기만 border 라 본문 .cta(32px) 보다 2px 두꺼웠다(34px). */
      box-shadow: inset 0 0 0 var(--hairline) var(--point); border-radius: var(--r-pill);
      color: var(--point); background: transparent;
      font-size: var(--fs-cta); font-weight: 600; letter-spacing: -.01em; white-space: nowrap; }
    .header-cta:active { background: var(--point); color: var(--white); }
    /* (margin-left:auto 는 아래 기본 정의로 올렸다 - 992~1539 구간에서도 필요하다) */

    .site-header__inner { border-bottom: var(--hairline) solid var(--gray-light); }

    .gnb-bar { display: grid; grid-template-columns: repeat(3, 1fr);
      border-bottom: var(--hairline) solid var(--gray-light); background: var(--white); }
    /* 높이는 패딩으로 정한다(하드코딩 금지) - caption + --sp-3 상하 = 약 46px 터치타겟 */
    .gnb-bar a { display: flex; align-items: center; justify-content: center;
      padding-block: var(--sp-3); color: var(--ink);
      font-size: var(--fs-content-subtext); font-weight: 500; letter-spacing: -.03em;
      white-space: nowrap; transition: color .2s; }
    .gnb-bar a[aria-current="page"] { color: var(--point); font-weight: 600; }
  }
  /* (요청) 서브메뉴 색을 '약간 진한' 회색(--gray-2)으로 - 너무 연한 문제 해소 */
  .gnb__panel a { font-size: var(--fs-content-subtext); font-weight: 400; color: var(--gray-dark);
    white-space: nowrap; transition: color .2s; padding: var(--sp-3) 0; line-height: 1.64; }
  .gnb__panel a:hover { color: var(--point); }

  /* 우측 유틸 (원본: blog/tstory 이미지 20px 원형, globe/user Phosphor 20px) - 세로 중앙 정렬, 간격 확대 */
  /* (요청) 아이콘 20 → 22px, 아이콘 사이 간격 20 → 40px (--sp-4 → --sp-6) */
  /* (요청 2026-07-14) 우측 아이콘 4개 사이 간격 40 → 30 (--sp-6 → --sp-5).
     스케일 위의 값이라 임의 px 을 박지 않는다.
     ★ margin-left:auto 는 여기(기본 정의)에 둔다. PC 는 .gnb(flex:1) 가 유틸을 우측으로 밀지만,
       GNB 를 숨긴 992~1539 구간에는 미는 주체가 없어 아이콘이 로고 옆에 붙어 버린다.
       모바일 전용으로 두면 그 중간 구간이 비어 있게 된다. (2026-07-14) */
  .util-nav { display: flex; align-items: center; gap: var(--sp-5); flex: 0 0 auto;
    margin-left: auto; }
  /* ⚠️ 모바일 gap 은 반드시 "이 기본 정의 뒤"에 와야 한다.
     미디어쿼리는 특이도를 올려주지 않으므로, 위쪽(539·601줄)에 써 두면
     이 줄(--sp-6 = 25)이 소스 순서로 이겨서 죽은 규칙이 된다.
     모바일 util-nav 에는 [상담예약]과 햄버거 둘뿐이라 좁혀도 안전하다. (2026-07-13) */
  @media (max-width: 991.98px) { .util-nav { gap: var(--sp-2); } }   /* 10 */
  .util-nav__link { display: inline-flex; align-items: center; justify-content: center;
    height: 22px; line-height: 1; color: var(--ink); font-size: var(--ico-md); }
  .util-nav__img { width: 22px; height: 22px; border-radius: 50%; }
  /* padding:0 - <button> 의 UA 기본 패딩(1px 6px)이 남아 있으면 아이콘이 안쪽으로 6px 더
     들어가, 좌측 로고(컨테이너 패딩 25)보다 우측 여백이 넓어 보인다. 좌우를 맞춘다. */
  .hamburger { font-size: var(--ico-lg); height: auto; padding: 0; }
  .lang { position: relative; display: inline-flex; align-items: center; }
  .lang summary { list-style: none; cursor: pointer; font-size: var(--ico-md); line-height: 1;
    display: inline-flex; align-items: center; justify-content: center; height: 20px; }
  .lang summary::-webkit-details-marker { display: none; }
  /* (요청) 지구본 아이콘 "바로 아래", 아이콘 기준 가로 중앙 정렬.
     right:0 은 우측 끝 정렬이라 아이콘 중심과 어긋났다 → left:50% + translateX(-50%). */
  .lang__menu { position: absolute; top: 130%; left: 50%; right: auto;
    transform: translateX(-50%); background: var(--white);
    box-shadow: 0 .5rem 1rem rgb(0 0 0 / .15); padding: .5rem 0; min-width: 90px; z-index: 10; }
  /* 아이콘 하단(49) ~ 메뉴 상단(55) 사이 6px 이 .lang 바깥이라, 마우스가 그 틈을 지나는 순간
     mouseleave 가 떠서 메뉴가 닫혔다(아래로 내려가다 사라지는 증상).
     → 메뉴에 투명한 "다리"를 붙여 틈을 .lang 안쪽으로 흡수한다. 보이지는 않는다. */
  .lang__menu::before { content: ""; position: absolute; left: 0; right: 0;
    top: -10px; height: 10px; }
  .lang__menu a { display: block; padding: .4rem 1rem; font-size: var(--ui-text); text-align: center; }
  .lang__menu a:hover { color: var(--point); }

  /* --- 모바일 메뉴 (원본 오프캔버스: 헤더 #5A5252, 로고 흰반전) --- */
  /* 메뉴 면 전체는 --bg-soft(박스 배경과 같은 연회색). 상단 헤더(--dark)만 예외.
     서브메뉴는 배경을 따로 주지 않아 이 면을 그대로 물려받는다. */
  .mobile-menu { position: fixed; top: 0; bottom: 0; right: 0; width: min(86vw, 360px);
    background: var(--bg-soft); z-index: 1200; transform: translateX(100%); transition: transform .35s ease;
    display: flex; flex-direction: column; overflow-y: auto; }
  .mobile-menu[hidden] { display: flex; }
  .mobile-menu.is-open { transform: none; }
  .mobile-menu__head { display: flex; align-items: center; justify-content: space-between;
    padding: 1.2rem 1.4rem; background: var(--dark); color: var(--white); }
  /* 좌측 로고 - 헤더(--dark)의 흰 글씨를 물려받는다. 크기만 세운다. */
  .mobile-menu__logo { font-size: var(--fs-content-body); font-weight: 600;
    letter-spacing: -.02em; }
  /* 메뉴 목록 - 남는 높이를 먹어 SNS 묶음을 면 아래로 밀어낸다 */
  .mobile-menu__nav { flex: 1 0 auto; }
  /* 우측 묶음 - 로그인(PC 유틸의 ph-user 를 그대로 가져옴) + 닫기 */
  .mobile-menu__util { display: flex; align-items: center; gap: var(--sp-4); }
  .mobile-menu__link,
  .mobile-menu__close { display: inline-flex; align-items: center; justify-content: center;
    color: var(--white); font-size: var(--ico-md); }
  .mobile-menu details { border-bottom: 1px solid var(--gray-light); }
  .mobile-menu summary { padding: 1rem 1.4rem; font-weight: 500; cursor: pointer;
    display: flex; justify-content: space-between; align-items: center; list-style: none; }
  .mobile-menu summary::-webkit-details-marker { display: none; }
  .mobile-menu summary::after { content: "\e13a"; font-family: "Phosphor"; font-size: var(--ico-sm); color: var(--gray-dark); transition: transform .2s; }
  /* 닫힘 ">" → 열림 "v"(아래). 180deg 는 "<"(왼쪽)이 되어 아코디언 관례에 어긋난다 */
  .mobile-menu details[open] summary::after { transform: rotate(90deg); }
  /* 서브 링크는 손가락으로 누른다 - 텍스트 높이(약 21px)만으로는 오터치가 난다.
     gap 대신 링크 자체에 상하 패딩을 줘 터치 타겟을 약 51px 로 키운다(권장 44px↑).
     간격이 아니라 "누를 수 있는 면"이 넓어지는 것이라 인접 항목을 잘못 눌러도 경계가 명확하다. */
  /* 좌측은 summary(1.4rem) 보다 한 단계 더 들여써서 상위-하위 계층이 눈에 보이게 한다 */
  .mobile-menu__sub { padding: 0 1.4rem var(--sp-2) calc(1.4rem + var(--sp-5));
    display: grid; gap: 0; }
  .mobile-menu__sub a { display: block; padding-block: var(--sp-3);
    font-size: var(--ui-text); color: var(--gray-dark); }
  .mobile-menu__sub a:active { color: var(--point); }
  /* 메뉴 하단 SNS·예약 바로가기 - 3×2. 아이콘은 PC(퀵사이드·푸터)에서 쓰던 것 그대로.
     원본 크기가 브랜드 70px / 예약 30px 로 제각각이라 --ico-xl 로 통일한다. */
  .mobile-menu__sns { display: grid; grid-template-columns: repeat(3, 1fr);
    gap: var(--sp-5) var(--sp-2); padding: var(--sp-6) 1.4rem var(--sp-8);
    border-top: var(--hairline) solid var(--gray-light); }
  .mobile-menu__sns a { display: flex; flex-direction: column; align-items: center;
    gap: var(--sp-2); color: var(--gray-dark); font-size: var(--ui-text); text-align: center; }
  .mobile-menu__sns img { width: var(--ico-xl); height: var(--ico-xl); object-fit: contain; }
  .mobile-menu__sns a:active { color: var(--point); }

  .scrim { position: fixed; inset: 0; background: var(--veil-scrim); z-index: 1100; }
  .scrim[hidden] { display: none; }

  /* --- 우측 세로 퀵 = 알약(pill) 5개 + 맨 위로 ---------------------------
     한 칸 = [라벨][원형 아이콘]. 흰 면이라 선을 두르지 않고 그림자로 띄운다
     (.ua-card 와 같은 공식). 마지막 전화 칸만 포인트 색을 채워 "행동"을 구분한다.
     PC : 화면 우측 세로 중앙에 항상 떠 있다.
     모바일 : 접어 두고, 우하단 이벤트 배지를 누르면 그 위로 펼친다(아래 반응형).
     ※ 원 지름은 --quick-ico 하나가 정한다 - 알약 아이콘과 맨 위로가 한 벌이다. */
  .quick-side { position: fixed; right: clamp(27px, 2.292vw, 44px); top: 50%;
    transform: translateY(-50%); z-index: 9001;
    display: flex; flex-direction: column; align-items: flex-end; gap: var(--sp-4); }
  /* 폭은 글자가 정한다(고정 폭 없음) - 라벨은 오른쪽에 붙어 아이콘과 나란히 끝난다.
     컨테이너가 align-items:flex-end 라 길이가 달라도 오른쪽 끝은 한 줄로 맞는다. */
  .quick-side__item { display: flex; align-items: center;
    gap: var(--sp-3); width: max-content;
    padding: var(--sp-1) var(--sp-1) var(--sp-1) var(--sp-4);
    border-radius: var(--r-pill); background: var(--white); color: var(--ink);
    box-shadow: 0 var(--sp-1) var(--sp-4) color-mix(in srgb, var(--ink) 12%, transparent);
    transition: transform .2s ease, box-shadow .2s ease; }
  .quick-side__item:hover { transform: translateX(calc(var(--sp-1) * -1));
    box-shadow: 0 var(--sp-2) var(--sp-5) color-mix(in srgb, var(--ink) 18%, transparent); }
  .quick-side__label { display: flex; flex-direction: column; align-items: flex-end; gap: 3px;
    font-size: var(--fs-cta); font-weight: 600; letter-spacing: -.03em;
    white-space: nowrap; text-align: right; }
  .quick-side__id { display: none; font-size: var(--fs-eyebrow); font-weight: 500; letter-spacing: -.02em;
    color: var(--gray-dark); }
  /* (요청) 원은 연한 포인트 면 + 붉은 선 아이콘. 포인트를 꽉 채우면 톤이 너무 강했다. */
  .quick-side__ico { flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
    width: var(--quick-ico); height: var(--quick-ico); border-radius: 50%;
    background: var(--point-bg); color: var(--point); font-size: var(--ico-md); }
  /* 전화 - 목록의 마지막 한 칸만 면을 깔아 구분한다(글자도 포인트색).
     그 안의 원은 반대로 흰 면이라 알약 위에서 도드라진다. */
  .quick-side__item--tel { background: var(--point-bg); color: var(--point); }
  .quick-side__item--tel .quick-side__ico { background: var(--white); color: var(--point); }
  /* 맨 위로 - 알약 안의 원형 아이콘(.quick-side__ico)을 그대로 덧입는다.
     지름·색·아이콘 크기를 따로 갖지 않는다 → 목록의 원과 한 벌로 보인다.
     ★ 알약은 원 둘레에 --sp-1 만큼 흰 여백을 두르고 있다(padding). 화살표는 알약 없이
       원만 놓이므로 같은 값을 바깥 여백으로 줘야 [원 ↔ 원] 세로 간격과 오른쪽 끝이 맞는다.
       세로: gap(15) + 알약 아래여백(5) + 여기 위여백(5) = 25 = 알약끼리의 원 간격.
       가로: 알약 오른쪽 여백(5) = 여기 오른쪽 여백(5) → 원 중심이 한 줄로 선다. */
  /* (요청) 화면 맨 위에서는 나오지 않고 스크롤이 시작되면 나타난다.
     맨 위에서 "맨 위로" 는 할 일이 없다 - .is-on 은 main.ts 가 스크롤 위치를 보고 붙인다.
     자리는 늘 차지한 채(visibility) 보였다 안 보였다 하므로 위 알약들이 밀리지 않는다. */
  .quick-side__top { margin: var(--sp-1) var(--sp-1) 0 0;
    opacity: 0; visibility: hidden;
    transition: opacity .25s ease, visibility .25s; }
  .quick-side__top.is-on { opacity: 1; visibility: visible; }

  /* --- 좌하단 배지 (원본 quick_left: bottom 100 left 70, bounce 1.6s) --- */
  /* (요청) 좌측 이벤트 플로팅 = ".container 좌측 여백(거터)"의 정중앙에 배치.
     거터 폭 = (100vw - 컨테이너폭)/2 + 컨테이너 좌우 패딩(20)
     박스를 그 거터 폭에 딱 맞추고 grid(justify-items:center)로 "내용만" 가운데 정렬한다.
     ※ transform 은 bounce 애니메이션이 쓰고 있어 translateX(-50%) 로는 중앙정렬 불가. */
  .quick-badge { position: fixed; bottom: 100px; left: 0; z-index: 999;
    width: max(96px, calc((100vw - min(1400px, 100vw)) / 2 + 20px));
    display: grid; gap: .5rem; justify-items: center;
    animation: quick_bounce 1.6s infinite; transform-origin: center bottom; }
  /* 거터가 좁아지면 내용도 같이 줄어 밖으로 새지 않게 (100% = 거터 폭) */
  .quick-badge__crown { max-width: min(150px, 100%); }
  .quick-badge a img { width: 75px; max-width: 100%; }
  @keyframes quick_bounce {
    0%,20%,53%,80%,100% { transform: translate3d(0,0,0); }
    40%,43% { transform: translate3d(0,-30px,0); }
    70% { transform: translate3d(0,-15px,0); }
    90% { transform: translate3d(0,-4px,0); }
  }

  /* --- 히어로 (원본: h-700, aspect 36.9%, 활성 슬라이드 scale 확대) --- */
  .hero { position: relative; overflow: clip; background: var(--ink); }
  .hero__viewport { position: relative; aspect-ratio: 1920 / 708.5; }
  @media (max-width: 991.98px) { .hero__viewport { aspect-ratio: 640 / 720; } } /* 원본 모바일 배너 비율 */
  /* ⚠️ (2026-07-21 버그수정) opacity:0 은 클릭을 막지 않는다.
     슬라이드가 전부 겹쳐 쌓여 있으므로, 그대로 두면 DOM 맨 뒤 슬라이드의 <a> 가
     화면 전체를 덮어 어떤 배너를 눌러도 마지막 배너의 링크로 가 버린다.
     → 보이지 않는 슬라이드는 클릭 대상에서 뺀다. */
  .hero__slide { position: absolute; inset: 0; opacity: 0; transition: opacity 1.5s ease;
    pointer-events: none; }
  .hero__slide.is-active { opacity: 1; pointer-events: auto; }
  .hero__slide img, .hero__slide video { width: 100%; height: 100%; object-fit: cover; }
  /* (요청 4) 롤링 배너 확대 효과 미적용 */
  .hero__slide a { position: absolute; inset: 0; }
  /* 원본: 네비 전체가 중앙 클러스터(x567~1352), 바 600px, 화살표는 바 우측 */
  .hero__nav { position: absolute; bottom: clamp(37px, 3.125vw, 60px); left: 50%;
    transform: translateX(-50%); width: max-content; padding: 0;
    display: flex; align-items: center; gap: var(--sp-4); color: var(--white); }
  .hero__count { display: flex; align-items: center; gap: .8rem;
    font-size: var(--fs-content-body); font-weight: 600; }
  .hero__bar { width: clamp(372px, 31.25vw, 600px); height: 3px; background: var(--veil-track); display: block; }
  @media (max-width: 991.98px) { .hero__bar { width: clamp(135px, 15.625vw, 300px); } }
  .hero__bar em { display: block; height: 100%; width: 0; background: var(--white); }
  .hero__ctrl { display: flex; gap: .5rem; }
  .hero__ctrl button { color: var(--gray-dark); font-size: var(--ico-md); width: 40px; height: 40px;
    display: inline-flex; align-items: center; justify-content: center; }
  .hero__ctrl button:hover { color: var(--white); }

  /* --- 통계 sec-anniv (원본: max-w 950, gap 60, border-bottom #111) --- */
  /* (요청) 숫자 셀 2개를 각각 더 좁게, 둘 사이는 더 벌린다.
       전체 폭 950 → 900, 셀 사이 gap 60 → --sp-9(120)
       → 셀(=밑줄) 길이가 줄고 가운데가 비어 두 지표가 확실히 분리된다. */
  .stats { margin-top: var(--sec-gap); }
  /* 폭·위 마진은 골격이 정한다(규칙 7·섹션 골격) → 여기선 배치만.
     max-width:900 은 제3의 폭이라 삭제, margin-top 은 헤드(80)가 이미 잡는다. */
  .stats__grid { display: flex; justify-content: center; gap: var(--sp-9); }
  /* 통계 근거 문구 (2012~2026 수술 통계 기준) - 카운터 아래 옅게 */
  .stats__note { margin-top: var(--sp-4); text-align: center;
    font-size: var(--fs-eyebrow); color: var(--gray-dark); letter-spacing: normal; }
  /* 모바일: 셀을 위아래로 세로 스택 (각 셀 border-bottom 이 구분선) */
  @media (max-width: 991.98px) {
    .stats__grid { flex-direction: column; gap: 0; padding-inline: 12px; }
    .stat-cell, .stat-cell:first-child { flex: none; }
  }
  .stat-cell { flex: 1; padding: var(--sp-6) 0; border-bottom: 1px solid var(--ink);
    display: flex; justify-content: space-between; align-items: center; }
  .stat-cell:first-child { flex: .8; }
  .stat-label { font-size: var(--fs-content-body); font-weight: 400; line-height: 1.35; color: var(--ink); }
  /* (요청) 숫자는 포인트 컬러. 자간은 H2 와 동일한 -.02em (한글·숫자 제목 공통 자간) */
  .stat-num { font-size: var(--fs-h2title); font-weight: 600; letter-spacing: -.02em;
    line-height: 1; font-variant-numeric: tabular-nums; color: var(--point); }
  .stat-unit { font-size: var(--fs-content-body); font-weight: 400; margin-left: 6px; color: var(--ink); }

  /* --- 마퀴 (원본 swiper 연속 흐름 재현: speed 10000 ≒ 등속) --- */
  .marquee { overflow: clip; }
  .marquee__track { display: flex; width: max-content;
    animation: marquee var(--marquee-dur, 60s) linear infinite; }
  .marquee:hover .marquee__track { animation-play-state: paused; }
  @keyframes marquee { to { transform: translateX(-50%); } }
  /* (요청) 모바일에서는 자동 스크롤을 멈추고 손으로 좌우 스와이프해서 넘긴다. */
  @media (max-width: 991.98px) {
    .marquee { overflow-x: auto; overflow-y: hidden; scroll-snap-type: x proximity;
      -webkit-overflow-scrolling: touch; scrollbar-width: none; }
    .marquee::-webkit-scrollbar { display: none; }
    .marquee__track { animation: none; }
    .marquee__track > * { scroll-snap-align: start; }
  }

  /* --- 프로모션 sec-2 (원본: 슬라이드 400, 패딩 0 27, 숫자 80 로즈) --- */
  .promo { margin-top: var(--sec-gap); }
  .promo__card { width: calc(clamp(248px, 20.833vw, 400px) + clamp(33px, 2.812vw, 54px)); padding: 0 var(--sp-5); }
  .promo__card figure { overflow: hidden; border-radius: var(--r-lg); } /* (요청 5) R값 */
  .promo__card img { width: 100%; aspect-ratio: 1; object-fit: cover;
    transform: scale(1); transition: transform .8s ease; transform-origin: center; }
  .promo__card:hover img { transform: scale(var(--card-zoom)); }
  /* (요청) 사진 ↔ 카테고리(윗줄) 는 벌리고, 카테고리 ↔ 제품명 은 붙인다
     → 두 줄이 한 덩어리로 읽히고, 사진과는 확실히 분리된다.
       사진 ↔ 윗줄  : 20 → 30 (--sp-4 → --sp-5)
       윗줄 ↔ 아랫줄 : 10 → 3  (--sp-1(5) 에서 파생. 최소 간격보다 더 붙여야 한 덩어리로 읽힌다) */
  /* (요청) 큰 제목(제품명)과 숫자의 "글자 바닥선"을 맞춘다.
     flex-end 는 "박스" 바닥만 맞춘다. line-height: 1 이어도 글자 아래에는 폰트의 descent 여백이
     남고, 그 여백은 폰트 크기에 비례한다 → 60px 숫자가 30px 제목보다 더 많이 떠 보인다.
     → last baseline 으로 두 글자의 실제 baseline 을 맞춘다(왼쪽 블록의 마지막 줄 = 제품명). */
  .promo__meta { display: flex; align-items: last baseline; justify-content: space-between;
    margin-top: var(--sp-5); gap: var(--sp-2); }
  /* (요청 6) 텍스트 영역이 줄고 숫자는 밀리지 않게: 텍스트 min-width 0 축소, 숫자 고정 */
  .promo__meta > div { min-width: 0; flex: 1 1 auto; }
  /* (요청) 카테고리(윗줄) 스타일 재배정 - 제품명의 "라벨"이므로 작고 연하게 (weight 200 은 너무 얇았다) */
  .promo__meta small { display: block; font-size: var(--fs-content-subtext); font-weight: 400;
    color: var(--gray-dark);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  /* (요청) 제품명 - 한 단계 확대(--fs-body 20 → --fs-sub 30). 볼드는 600 유지 */
  .promo__meta strong { display: block; margin-top: calc(var(--sp-1) * 8 / 5);   /* (요청) 3 → 8 */
    font-size: var(--fs-content-title); font-weight: 600; line-height: 1;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  /* (요청) 숫자 - title(45) 은 작고 display(80) 은 과했다 → 60.
     이 자리 하나 때문에 스케일을 6칸으로 늘리지 않고, "여기 전용" 예외 토큰으로 둔다.
     ★ --fs-event-only 는 이 프로모션 숫자에서만 쓴다. 다른 곳에서 쓰면 안 된다. */
  /* (요청) 카드 ↔ "프로모션 더보기" CTA 여백 : 40 → 60 → 80 (조금 더 내린다) */
  .promo__num { flex: 0 0 auto; font-size: var(--fs-event-only); letter-spacing: -.03em;
    color: var(--point); font-weight: 600; line-height: 1; }

  /* --- 시그니처 sec-4 (원본: 400×540, 패딩 0 28, 텍스트 #111) --- */
  .signature { margin-top: var(--sec-gap); }
  .sig__card { width: calc(clamp(248px, 20.833vw, 400px) + clamp(35px, 2.917vw, 56px)); padding: 0 var(--sp-5); }
  .sig__no { display: flex; align-items: center; gap: .8rem; font-weight: 400;
    font-size: var(--fs-content-body); color: var(--ink); margin-bottom: var(--sp-3); }
  .sig__no::after { content: ""; flex: 1; height: 1px; background: var(--ink); }
  .sig__card figure { position: relative; overflow: hidden; border-radius: var(--r-lg); } /* (요청 5) R값 */
  .sig__card img { width: 100%; height: clamp(335px, 28.125vw, 540px); object-fit: cover;
    transform: scale(1); transition: transform .8s ease; }
  .sig__card:hover img { transform: scale(var(--card-zoom)); }
  .sig__cap { position: absolute; bottom: clamp(40px, 3.385vw, 65px); left: 0; right: 0;
    text-align: center; color: var(--ink); }
  .sig__cap small { display: block; font-size: var(--fs-content-body); font-weight: 400;
    letter-spacing: .5em; text-indent: .5em; }
  .sig__cap strong { display: block; margin-top: var(--sp-2);
    font-size: var(--fs-content-title); font-weight: 600; }

  /* --- 상담폼 sec-3 --- */
  /* (요청) 라벨 줄 / 입력창 줄이 따로 노는 구조를 버리고, [라벨 + 입력창] 을 한 덩어리로 묶은
     "작은 섹션" 6개로 나눈다.
       · 6개 섹션 폭 동일 (1fr × 6)  · 섹션 간 간격 30px (--sp-5)  · 폭은 .container 가 잡는다
       · 라벨과 입력창은 같은 왼쪽 선에 맞춘다(좌측 정렬)
     하단은 [동의 체크 → CTA] 를 세로로 쌓아 가운데 정렬한다. */
  .counsel { margin-top: var(--sec-gap); }
  /* (요청) 순서 = 이름 · 휴대폰 · 키 · 체중 · 희망수술 · 담당의
     폭  = 키/체중만 120px 고정, 나머지 4개가 남는 폭을 똑같이 나눠 갖는다 */
  .counsel__form {
    display: grid; grid-template-columns: 1fr 1fr 120px 120px 1fr 1fr;
    gap: var(--sp-5); }
  @media (max-width: 991.98px) { .counsel__form { grid-template-columns: repeat(2, 1fr); } }

  /* 빠른 상담 - 사진 첨부(최대 4장) 업로더. 기존 .field 패널 안에 들어간다(토큰만 사용). */
  .counsel__form > .field--photo,
  .counsel__form > .field--wide { grid-column: 1 / -1; }
  /* (요청 2026-07-18) 리얼모델 - 전신사진 : 동영상 = 3 : 1 한 줄. 모바일은 세로로 쌓는다. */
  .rm-media-row { grid-column: 1 / -1; display: grid; grid-template-columns: 3fr 1fr; gap: var(--sp-5); }
  @media (max-width: 767.98px) { .rm-media-row { grid-template-columns: 1fr; } }
  /* 상담내용 입력란 - .field 언더라인 스타일과 동일하게. 반반 행이라 높이를 키우고 칸을 채운다. */
  .field textarea { width: 100%; min-width: 0; border: 0; background: transparent; padding: 0;
    font: inherit; font-size: var(--fs-content-subtext); color: var(--ink); line-height: 1.5;
    resize: vertical; min-height: 120px; flex: 1 1 auto; }
  .field textarea::placeholder { color: var(--gray-dark); }
  .field textarea:focus { outline: none; }
  .photo-up__grid { display: flex; flex-wrap: wrap; gap: var(--sp-3);
    list-style: none; margin: 0; padding: 0; }
  /* 박스 4칸 - 왼쪽 '사진 추가' 뒤로 썸네일이 오른쪽에 쌓인다. 반폭을 4칸이 꽉 채운다. */
  .photo-up { height: 100%; }
  .photo-up__grid > li { width: calc((100% - 3 * var(--sp-3)) / 4); aspect-ratio: 4 / 3; }
  /* 상담방법·연락시간·수술경험·예약희망일 4개를 데스크톱에서 한 줄에 (span 1·2·2·1) */
  @media (min-width: 992px) {
    .counsel__form > .field--sp1 { grid-column: span 1; }
    .counsel__form > .field--sp2 { grid-column: span 2; }
    /* 데스크톱 반반(6칸 중 3칸). 모바일에선 이 클래스 규칙이 없어 2개/줄로 흐른다 */
    .counsel__form > .field--dh { grid-column: span 3; }
  }
  /* 예약 희망일 - 년/월/일 콤보박스 3개를 한 줄에 */
  .date-combos { display: flex; gap: var(--sp-2); }
  .date-combos select { flex: 1 1 0; min-width: 0; }

  /* 빠른 상담 - 폼 위 바로 연락 채널(아이콘 버튼). 폼과의 간격을 넉넉히 둔다.
     ⚠️ 컨테이너 직속 자식은 위 593줄 규칙이 margin-block:0 으로 덮으므로 특이도를 올려 되살린다. */
  .quick-contact { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--sp-5); }
  /* 3영역 구분: [헤더] - [아이콘] - [폼]. 아이콘↔폼 사이를 넓게 벌리고(영역 분리),
     안내문구는 폼 영역 소속이라 폼에 바짝 붙인다. */
  .counsel .container > .quick-contact { margin-top: var(--sp-7); margin-bottom: 70px; }
  /* 폼 위 한 줄 안내문구 - 폼 영역 소속(폼에 붙임) */
  .counsel-note { text-align: center; color: var(--gray-dark); font-size: var(--fs-content-subtext); line-height: 1.5; }
  .counsel .container > .counsel-note { margin-bottom: 20px; }
  .quick-contact__ch { display: flex; flex-direction: column; align-items: center;
    gap: var(--sp-2); text-decoration: none; color: var(--ink); }
  .quick-contact__ico { display: grid; place-items: center;
    width: clamp(38px, 3.8vw, 48px); aspect-ratio: 1; border-radius: var(--r-pill);
    background: var(--bg-soft); color: var(--point); font-size: clamp(18px, 1.9vw, 24px);
    line-height: 1; transition: background .15s; }
  .quick-contact__ch:hover .quick-contact__ico { background: var(--gray-light); }
  .quick-contact__label { font-size: var(--fs-content-subtext); font-weight: 500; }
  /* (요청) 채널 아이디(위챗·라인 아이디 · 왓츠앱 번호)는 모바일에서만 노출한다.
     PC 는 클릭하면 QR 로 연결되므로 화면에 아이디/번호를 띄우지 않는다. */
  .quick-contact__id { display: none; }
  @media (max-width: 991.98px) {
    .quick-contact__id { display: block; margin-top: 2px;
      font-size: var(--fs-eyebrow); font-weight: 400; color: var(--gray-dark); }
  }
  /* (요청) 좁은 화면(휴대폰)에서는 채널을 한 줄에 3개씩(3+2)으로 - 5개가 4+1 로 눌려 좁아지는 것 방지 */
  @media (max-width: 640px) {
    .quick-contact__ch { flex: 0 0 calc((100% - 2 * var(--sp-5)) / 3); }
  }
  .photo-up__thumb { position: relative; width: 100%; height: 100%; overflow: hidden;
    border-radius: var(--r-sm); border: var(--hairline) solid var(--gray-light); background: var(--white); }
  .photo-up__thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
  .photo-up__del { position: absolute; top: 3px; right: 3px; width: 20px; height: 20px;
    display: grid; place-items: center; padding: 0; border: 0; cursor: pointer; line-height: 1;
    border-radius: var(--r-pill); background: var(--point); color: var(--white); font-size: 12px; }
  .photo-up__add { width: 100%; height: 100%; display: flex; flex-direction: column;
    align-items: center; justify-content: center; gap: var(--sp-1); cursor: pointer;
    border: var(--hairline) dashed var(--gray-light); border-radius: var(--r-sm);
    background: var(--white); color: var(--gray-dark); }
  .photo-up__add:hover { border-color: var(--point); color: var(--point); }
  .photo-up__add i { font-size: 20px; }
  .photo-up__add span { font-size: var(--fs-content-subtext); }
  /* 동영상 첨부 - 사진 추가와 같은 대시 + 박스(요청 2026-07-18). 영상은 미리보기가 안 되니
     업로드되면 파일명으로 바뀐다(JS). 박스는 사진 칸과 같은 4:3 비율. */
  /* 사진 칸(1/4 폭 셀)과 같은 크기가 되도록 - 동영상 필드가 사진의 1/3 폭이라 그 안에서 76%. */
  /* 동영상 업로드도 전신사진과 동일한 박스 그리드 템플릿 사용.
     동영상은 1장뿐 → 데스크톱(좁은 1fr 컬럼)에선 박스를 사진 박스 크기로 채우고,
     모바일(스택·전폭)에선 사진 박스와 동일한 1/4 크기로 둔다. */
  @media (min-width: 768px) {
    .video-up .photo-up__grid > .photo-up__add-cell { width: 100%; max-width: 220px; }
  }
  .video-up .photo-up__add span { max-width: 100%; padding: 0 var(--sp-3); text-align: center; overflow-wrap: anywhere; }
  .video-up .photo-up__add.is-filled { border-style: solid; border-color: var(--point); color: var(--ink); }
  /* 셀카 후기 작성 - 별점 선택기(요청 2026-07-18, 바비톡 느낌). 채운 별은 selfie-star 와 같은 fill 폰트. */
  .star-rate { display: flex; align-items: center; flex-wrap: wrap; gap: var(--sp-2); }
  .star-rate__btn { border: 0; background: none; padding: 0; cursor: pointer; line-height: 1;
    font-size: 40px; color: var(--gray-light); transition: color .1s; }
  .star-rate__btn i { display: block; }
  .star-rate__btn.is-on { color: var(--point); }
  /* !important 가 없으면 phosphor.css 의 `.ph { font-family:"Phosphor" !important }` 에 덮여
     선택한 별도 빈 별로 그려진다. 특정도만으로는 !important 를 못 이긴다. */
  .star-rate__btn.is-on i { font-family: "Phosphor-Fill-Star", "Phosphor" !important; }
  .star-rate__txt { margin-left: var(--sp-2); font-size: var(--fs-content-subtext); color: var(--gray-dark); font-weight: 600; }
  @media (max-width: 575.98px) {
    /* (요청) 모바일도 2개/줄. 글 작성(textarea)·사진첨부·날짜 콤보·미디어만 전폭 */
    .counsel__form { grid-template-columns: 1fr 1fr; }
    .counsel__form > .field { grid-column: auto; }
    .counsel__form > .field--wide,
    .counsel__form > .field--photo,
    .counsel__form > .rm-media-row,
    .counsel__form > .field:has(textarea) { grid-column: 1 / -1; }
    /* 예약 희망일(년/월/일 콤보)은 절반 폭이라 좁으니 필드 여백·콤보 여백을 줄이고
       년(2026)은 폭을 더 줘서 잘리지 않게 한다 */
    .field--date { padding-inline: var(--sp-2); }
    .date-combos { gap: var(--sp-1); }
    .date-combos select { padding-inline: 0; font-size: var(--fs-eyebrow); }
    .date-combos select:first-child { flex-grow: 1.7; }
    /* 사진/동영상 추가 박스 - 모바일에선 글자·아이콘을 더 작게, 좌우 패딩 제거(줄바꿈 방지) */
    .photo-up__add span { font-size: var(--fs-eyebrow); }
    .photo-up__add i { font-size: 16px; }
    .video-up .photo-up__add span { padding-inline: 0; }
  }

  /* 한 덩어리 = 작은 섹션. 배경 면(--bg-soft)으로 묶어야 라벨이 입력창의 것임이 보인다.
     면을 줬으니 테두리는 없다(면 = --bg-soft / 선 = --gray-light 원칙). */
  .field { display: flex; flex-direction: column; align-items: stretch; gap: var(--sp-2);
    min-width: 0; padding: var(--sp-3) var(--sp-4);
    background: var(--bg-soft); border-radius: var(--r-lg); }
  /* (요청) 라벨 - 진한 색(--ink) + 한 단계 크게(caption 16 → body 20) + 볼드
     (요청) 입력값·placeholder - 라벨보다 한 단계 작게(body 20 → caption 16), placeholder 는 연한 회색
     6개 필드(input · select · 희망수술 버튼)가 전부 같은 크기·색을 쓴다 */
  .field label { font-size: var(--fs-content-body); font-weight: 600; color: var(--ink);
    text-align: left; }
  /* (요청) 필수 항목(이름 · 휴대폰)은 라벨 옆에 * 만 붙인다("필수" 글자는 쓰지 않는다).
     HTML 에 표식을 박지 않고, required 가 붙은 입력창을 가진 라벨에만 자동으로 붙인다
     → 나중에 필수 항목이 바뀌어도 CSS 를 안 고쳐도 된다.
     스크린리더는 input 의 required 로 필수 여부를 이미 안다 → * 는 장식이라 읽지 않게 둔다. */
  .field label:has(+ input:required)::after,
  .field label:has(+ select:required)::after,
  .field--photo:has(input:required) > label::after,
  .star-field:has(input[required]) > label::after { content: "*";
    margin-left: .15em; color: var(--point); font-weight: 600; }
  .field input, .field select, .field .field__pick { width: 100%; min-width: 0;
    height: clamp(26px, 2.083vw, 40px); border: 0; background: transparent;
    font-size: var(--fs-content-subtext); color: var(--ink); padding: 0; border-radius: 0; }
  .field input::placeholder { color: var(--gray-dark); }
  .field input:focus, .field select:focus { outline: none; }
  .field input:valid:not(:placeholder-shown) { color: var(--ink); }
  /* select · 희망수술 버튼도 "미선택 = 연한 회색, 선택됨 = 진한 색" 으로 placeholder 와 동일하게
     (.field .field__pick 이 위에서 --ink 를 잡으므로 같은 특이도로 다시 덮는다) */
  .field select { color: var(--gray-dark); }
  .field select:has(option:checked:not([value=""])) { color: var(--ink); }
  .field .field__pick { color: var(--gray-dark); }
  .field .field__pick.is-filled { color: var(--ink); }

  /* 하단: 동의 → CTA 세로 스택, 가운데 정렬 */
  /* (요청) 폼(입력칸) ↔ 동의 문구 여백을 더 준다 : 20(--sp-4) → 40(--sp-6)
     동의 ↔ CTA 는 30(--sp-5) 유지 - 동의와 CTA 는 한 덩어리로 붙어 있어야 한다. */
  .counsel__foot { grid-column: 1 / -1; display: flex; flex-direction: column;
    align-items: center; gap: var(--sp-5); margin-top: var(--sp-6); }
  /* 동의 2개 - 마진 줄이고(간격 sp-2) 체크박스 시작점을 왼쪽으로 맞춘다(요청 2026-07-18).
     블록은 foot 이 가운데로 두되, 안쪽 라벨은 왼쪽 정렬이라 체크박스가 같은 x 에서 시작한다. */
  .counsel__agrees { display: flex; flex-direction: column; align-items: flex-start; gap: var(--sp-2); }
  .agree { font-size: var(--fs-content-subtext); color: var(--ink); font-weight: 400;
    display: flex; align-items: center; gap: .5rem; }
  .agree input { width: var(--ui-check); height: var(--ui-check); accent-color: var(--point); }
  /* (요청 7) 희망수술 선택 버튼 - select 처럼 보이도록 */
  .field__pick { width: 100%; min-width: 0;
    height: clamp(26px, 2.083vw, 40px); border: 0;
    background: transparent; font-size: var(--fs-content-subtext); text-align: left; color: var(--gray-dark);
    padding: 0; display: flex; align-items: center; justify-content: space-between;
    gap: var(--sp-1); overflow: hidden; }
  /* 라벨 텍스트: 폼 밖으로 절대 넘치지 않게 말줄임 (JS 가 축약해도 최후 안전장치) */
  .field__pick__txt { min-width: 0; flex: 1 1 auto;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .field__pick::after { content: "\e136"; font-family: "Phosphor"; font-size: var(--ico-xs);
    color: var(--gray-dark); flex: 0 0 auto; }
  .field__pick.is-filled { color: var(--ink); }

  /* --- 희망수술 모달 (phpnew3 상담희망부위 구조 재현) --- */
  .op-modal { position: fixed; inset: 0; z-index: 2000; background: var(--veil-modal);
    display: flex; align-items: center; justify-content: center; padding: 20px; }
  .op-modal[hidden] { display: none; }
  .op-modal__box { background: var(--white); border-radius: var(--r-lg); width: min(760px, 100%);
    max-height: 85vh; display: flex; flex-direction: column; padding: var(--sp-5); }
  .op-modal__head { display: flex; align-items: center; justify-content: space-between; }
  .op-modal__head h3 { font-size: var(--ui-title); font-weight: 500; }
  .op-modal__close { font-size: var(--ico-md); color: var(--ink); }
  /* 헤더 밑 작은 안내문 (재수술 중복 선택) */
  .op-modal__note { margin-top: 6px; font-size: var(--ui-text); font-weight: 400; line-height: var(--lh-title); color: var(--gray-dark); }
  /* 현재 대분류 표시 (소분류 진입 시에만 노출). 복귀는 하단 "뒤로가기" 버튼이 담당.
     → "상담 희망 부위 ›" 반복 표기 폐지 (제목과 중복이라 제거) */
  /* (요청) [제목영역] ↔ [선택박스 영역] 사이 여백 확대: 18 → 34 */
  .op-navi { display: flex; align-items: center; flex-wrap: wrap; gap: var(--sp-2);
    margin-top: 34px; font-size: var(--ui-text); font-weight: 500; color: var(--point); }
  .op-navi:empty { display: none; }
  /* 카테고리 뱃지 (대분류/소분류 공용) - 남는 세로공간을 채우며 스크롤 */
  .op-cate-list { display: flex; flex-wrap: wrap; align-content: flex-start; gap: 10px;
    margin-top: calc(var(--sp-6) * 17 / 20); flex: 1 1 auto; min-height: 0; overflow-y: auto; }
  /* 대분류명이 떠 있을 땐(소분류 화면) 그 바로 아래이므로 간격을 좁힌다 */
  .op-navi:not(:empty) + .op-cate-list { margin-top: var(--sp-3); }
  /* (요청) 뱃지는 무조건 1줄. 데이터에 박힌 <br> 도 무력화 →
     긴 항목은 그만큼 넓어지고, 그 줄에 들어가는 박스 수가 자연히 줄어든다. */
  .op-cate-item { padding: 11px 18px; font-size: var(--ui-text); line-height: 1.3; text-align: center;
    border: 1px solid var(--gray-light); border-radius: 999px; background: var(--white); color: var(--gray-dark);
    cursor: pointer; transition: all .15s;
    white-space: nowrap; max-width: 100%; }
  .op-cate-item br { display: none; }
  .op-cate-item:hover { border-color: var(--point); color: var(--point); }
  /* (요청) [선택박스 영역] ↔ [나의 선택 희망 부위] 사이 여백 확대: 22 → 40 */
  .op-picked-label { margin-top: 40px; font-size: var(--ui-text); font-weight: 500; color: var(--gray-dark); }
  /* 선택한 항목 칩 (클릭 시 삭제) - 칩도 1줄 유지 */
  .op-selected { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-top: 10px; min-height: 40px; }
  .cate-added { display: inline-flex; align-items: center; gap: 6px; padding: 8px 12px;
    background: var(--ink); color: var(--white); border-radius: var(--r-lg); font-size: var(--ui-text); cursor: pointer;
    white-space: nowrap; max-width: 100%; }
  .cate-added br { display: none; }
  .cate-added::after { content: "\00d7"; font-size: var(--ico-xs); }
  /* 하단 버튼: [뒤로가기] [초기화] [선택완료] - 뒤로가기는 소분류 화면에서만 노출 */
  .op-modal__foot { display: flex; gap: 10px; margin-top: 22px; }
  .op-btn-back, .op-btn-reset { height: 49px; width: 106px; font-size: var(--ui-text); font-weight: 500;
    border-radius: var(--r-lg); background: var(--gray-light); color: var(--ink);
    display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-1);
    flex: 0 0 auto; transition: background .2s, color .2s; }
  .op-btn-back[hidden] { display: none; }
  .op-btn-back:hover, .op-btn-reset:hover { background: var(--point); color: var(--white); }
  .op-btn-done { flex: 1; height: 49px; font-size: var(--ui-text); font-weight: 500;
    border-radius: var(--r-lg); background: var(--ink); color: var(--white); }

  /* --- Shorts sec-5 --- */
  /* (요청) BEFORE&AFTER 섹션과 같은 구성으로 통일 - 전부 가운데 정렬로
       [제목 .section__head] → [선택 토글 .section__toggle] → [영상 3개 + 양옆 화살표 .shorts__viewport]
     ★ 새 CSS 를 만들지 않았다. 좌우 2단 레이아웃(.shorts__layout · .shorts__left)과
       세로 밑줄탭만 지우고 나머지는 전부 기존 규칙을 그대로 쓴다.
       - 토글  : 공통 .section__toggle 슬롯을 그대로 쓴다(전용 정의 없음)
       - 화살표: .shorts__nav (.tpl-carousel__nav 와 공용)
       - 3개 노출: .short__card 의 flex-basis 가 이미 1/3 이다 */
  .shorts { margin-top: var(--sec-gap); }
  /* (요청) 영상 ↔ 영상 = 30px (--sp-5) */
  .shorts__slider { display: flex; gap: var(--sp-5); overflow-x: auto;
    scroll-snap-type: x mandatory; padding-bottom: 1rem; scrollbar-width: thin; }
  /* 한 화면에 3개 노출 (좌우 화살표로 이전/다음). 3장 + 간격 2개 = 100% */
  .short__card { flex: 0 0 calc((100% - var(--sp-5) * 2) / 3); scroll-snap-align: start; position: relative; }
  @media (max-width: 991.98px) { .short__card { flex: 0 0 100%; } }  /* 모바일: 한 번에 1개 */
  .short__card img.short__thumb { width: 100%; aspect-ratio: 252 / 458; object-fit: cover;
    border-radius: var(--r-lg); } /* (요청 5) R값 */
  .short__card img.short__play { position: absolute; top: 50%; left: 50%;
    transform: translate(-50%, -50%); width: clamp(50px, 4.219vw, 81px); height: auto; }
  /* 슬라이더 하단 더보기는 .section__foot.section__foot--right 로 통일 (전용 클래스 폐지) */
  /* 캐러셀 좌우 화살표: 영상과 겹치지 않게 좌우에 전용 영역 배정 (flex 컬럼)
     화살표-영상 사이 마진을 조금 더(1.5→3.4). gap 은 뷰포트 안쪽으로만 벌어지므로
     화살표는 여전히 container 안쪽 끝에 위치 → 섹션 좌우 여백선(padding 20)을 넘지 않음 */
  /* (요청) 화살표 ↔ 영상 = 50px. --sp-6(40) 과 --sp-7(60) 사이값이라 --sp-7 에서 파생(임의 px 아님) */
  .shorts__viewport { display: flex; align-items: center; justify-content: center;
    gap: calc(var(--sp-7) * 5 / 6); }
  .shorts__slider { flex: 1 1 0; min-width: 0; }
  /* 캐러셀 화살표 버튼: shorts · reviews · 템플릿 순환 캐러셀이 공유 (규칙 6 - 공용 승격)
     (요청) 모양을 template 기준으로 통일한다 - 면을 채우지 않고 "테두리 + 화살표"에만 포인트 컬러.
       흰 배경 + 회색 드롭섀도(하드코딩 rgba) 를 걷어내고, .cta 와 같은 방식으로
       inset box-shadow 링을 쓴다(border 를 쓰면 버튼이 1px 씩 커진다).
     hover 는 그대로 - 포인트로 채워지고 화살표가 흰색이 된다. */
  .shorts__nav, .reviews__nav, .tpl-carousel__nav { flex: 0 0 auto; width: clamp(31px, 2.604vw, 50px); height: clamp(31px, 2.604vw, 50px);
    border-radius: 50%; display: flex; align-items: center; justify-content: center;
    background: transparent; box-shadow: inset 0 0 0 var(--hairline) var(--point);
    color: var(--point); font-size: var(--fs-content-body); transition: background .2s, color .2s; cursor: pointer; }
  .shorts__nav:hover, .reviews__nav:hover, .tpl-carousel__nav:hover { background: var(--point); color: var(--white); }
  @media (max-width: 991.98px) {
    .shorts__nav, .reviews__nav, .tpl-carousel__nav { width: 34px; height: 34px; font-size: var(--ico-sm); }
  }

  /* --- Study sec-6 (원본: 메인 850 16:9, 리스트 h480, 썸네일 193×109) --- */
  .study { margin-top: var(--sec-gap); }
  /* (요청) 영상을 줄이고, 그만큼을 목록에 준다.
       영상   850 → 700 (16:9 → 높이 394)
       목록   310 → 460 (남는 폭 전부)
     목록 높이는 영상 높이(394)와 같게 잡아 두 컬럼의 아래선이 맞는다.
     한 항목 = 썸네일 107 + 위아래 여백 40 + 구분선 1 = 148 → 394 / 148 ≒ 2.6 개가 보인다
     (= "2개 반". 아래가 잘려 보여야 더 있다는 게 읽힌다). */
  /* (요청) 영상 ↔ 우측 목록 간격 = 60 (--sp-7). 템플릿의 좌우 분리 섹션과 같은 계열 */
  .study__layout { display: grid; grid-template-columns: clamp(434px, 36.458vw, 700px) 1fr;
    gap: var(--sp-7); }
  @media (max-width: 991.98px) { .study__layout { grid-template-columns: 1fr; } }
  .study__main { aspect-ratio: 16 / 9; }
  .study__main iframe { width: 100%; height: 100%; border: 0; }
  .study__list { height: clamp(244px, 20.521vw, 394px); overflow-y: scroll; padding-right: .5rem;
    scrollbar-width: thin; scrollbar-color: var(--gray-dark) var(--gray-light); }
  /* (요청) 썸네일 ↔ 제목 간격 = 30 (--sp-5) */
  .study__item { display: grid; grid-template-columns: clamp(118px, 9.896vw, 190px) 1fr;
    gap: var(--sp-5); cursor: pointer; padding-block: var(--sp-4);
    border-top: 1px solid var(--gray-light); align-items: center; }
  .study__item:first-child { border-top: 0; }
  .study__item img { width: 100%; height: clamp(66px, 5.573vw, 107px); object-fit: cover;
    border-radius: var(--r-lg); } /* (요청 5) R값 */
  /* (요청) 제목은 딱 2줄까지만 보이고 넘치면 "…" 로 자른다.
     자르는 일은 CSS 가 한다 - 데이터(_prerender.js)에는 전체 제목이 들어 있다. */
  /* word-break: keep-all - 한글은 기본값(normal)이면 단어 한가운데서도 줄이 끊긴다.
     keep-all 이면 띄어쓰기 단위로만 끊어져 읽기 흐름이 살아난다(한국어 표준 조판).
     overflow-wrap: anywhere 는 안전장치 - 띄어쓰기 없는 긴 덩어리가 칸을 넘지 않게 한다. */
  .study__item b { font-size: var(--fs-content-body); font-weight: 600; line-height: var(--lh-title);
    word-break: keep-all; overflow-wrap: anywhere;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
    overflow: hidden; text-overflow: ellipsis; }
  .study__item.is-active b { color: var(--point); }

  /* --- 의료진 sec-7 (재개편) -----------------------------------------------
     (요청) 어두운 배경은 그대로. 컨테이너 안에서
       [중앙 헤드(eyebrow + H2)] → [좌우 2분할: 원장 2명]
       각 원장 = 사진 → 이름 → 핵심 문구 여러 줄 → "전체 이력 보기" CTA
     ★ 헤드(.section__head) · 버튼(.cta) 은 다른 섹션 것을 그대로 쓴다 - 새로 만들지 않는다.
       어두운 면 위에서만 필요한 색 델타(H2 흰색)만 둔다. */
  /* 배경은 사진이 아니라 진한 회색 면이다 (--ink · 사용자 지시 2026-07-15).
     사진을 깔면 그 위의 의료진 사진·수치가 배경과 뒤엉켜 읽히지 않는다 - 45(HOT EVENT 띠)와
     같은 검정 면을 써서 글과 사진만 남긴다. 팔레트 7색 안이다.
     ⚠️ --gray-dark(#6a6a6a)는 "보조 텍스트 전용(글자)" 이라 면에 쓰지 않는다. */
  /* 면에 노이즈를 얹는다 (사용자 지시). 넓은 검정 면은 그냥 두면 인쇄물처럼 평평하다.
     ★ 이미지 파일을 만들지 않는다 - SVG feTurbulence 를 data URI 로 심어 CSS 안에 가둔다.
       (외부 파일이 늘면 관리 지점이 늘고, 앞서 phpnew3 를 참조하던 배경처럼 경로가 깨진다)

     ★ 두 겹이다. 한 겹으로는 단조로움이 안 풀린다:
       ① 고운 필름 그레인 - 면의 살결. SVG 타일(160px).
       ② 넓은 밝기 얼룩  - 면이 고르게 지저분한 게 아니라 "자연스럽게 흔들리게" 만든다.

     ★ ②는 "타일을 깔지 않는다". 두 방법 모두 실패했다:
        - 큰 SVG 타일(600px) : `stitchTiles` 를 줘도 **이음새가 격자선으로** 보였다(저주파라 경계 불연속이 눈에 잡힌다).
        - radial-gradient    : 결국 원이라 **원형 경계**가 보였다. 개수를 늘려도 원은 원이다.
        → **저주파 SVG 한 장을 `background-size: cover` 로 늘려 덮는다.** `no-repeat` 라 반복이 없고,
          늘어나면서 뭉개져 원도 격자도 없는 **유기적인 얼룩**이 된다. 5옥타브가 큰 덩어리부터 잔결까지 겹친다.

     ⚠️ feTurbulence 는 RGB 를 따로 흔들어 **색 얼룩(녹색·갈색기)** 을 만든다.
        → `feColorMatrix saturate 0` 로 채도를 죽여 무채색으로 만든다. 팔레트를 더럽히지 않는다.

     background-size / -repeat 는 **레이어 순서대로** 짝지어 읽힌다 - 그레인은 타일 반복, 얼룩은 한 장 cover. */
  .doctors { margin-top: var(--sec-gap);
    padding-block: var(--sp-9);
    /* ★ 바탕은 --ink 를 어둡게 깐다. 흰 노이즈가 평균 밝기를 **+25 올리기** 때문에(실측),
       --ink 를 그대로 깔면 최종 면이 (63,63,63) 으로 떠 지정된 진한 회색이 아니게 된다.
       → 노이즈가 올릴 만큼 미리 내려 두면 **최종 면이 --ink(38,38,39) 에 앉는다.**
       팔레트 토큰에서 파생시킨 값이라(color-mix) 새 색을 만든 게 아니다 - --bg-soft 와 같은 방식이다. */
    background-color: color-mix(in srgb, var(--ink) 40%, #000);
    background-image:
      url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23g)' opacity='0.2'/%3E%3C/svg%3E"),
      url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='500' height='400'%3E%3Cfilter id='c'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.009' numOctaves='5' seed='7'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='500' height='400' filter='url(%23c)' opacity='0.16'/%3E%3C/svg%3E");
    background-size: 160px 160px, cover;
    background-repeat: repeat, no-repeat;
    /* ⚠️ 밝기 - 노이즈는 흰 rect 라 얹을수록 면이 밝아진다(--ink 가 중간 회색으로 뜬다).
       `background-blend-mode: overlay` 로 밝기를 보존해 봤지만, **어두운 면에서는 overlay 가 눌려
       노이즈가 통째로 안 보였다**(실측). → 블렌드를 걷고 **노이즈를 옅게** 잡는 쪽으로 갔다.
       얼룩 .16 · 그레인 .2 - 이 선이 "--ink 가 유지되면서 질감이 보이는" 지점이다. */
    color: var(--white); }
  .doctors h2 { color: var(--white); }   /* 어두운 면 위 - 기본 --ink 로는 안 보인다 */

  /* (요청) H2 아래 신뢰 3단. 간격·크기는 template 규칙을 그대로 따른다.
       1) 규모   : .tpl-lead (H2 와 --sp-3) - 숫자를 키워 먼저 읽히게
       2) 만족도 : 한 줄에 나열, 구분선으로 끊는다
       3) 인증   : caption 크기로 눌러 둔다 - 근거이지 주장이 아니다
     색은 쓰지 않는다 - 크기·굵기·투명도로만 위계를 만든다(이 섹션의 규칙). */
  /* 크기 오버라이드는 두지 않는다 - base .tpl-lead 가 이미 sub(30) 이라 충분히 크다.
     (예전엔 body*1.2=24 로 키웠지만, 리드가 sub 로 올라가면서 이 값은 오히려 축소가 된다) */
  .doctors .tpl-lead { color: var(--white); font-weight: 600; word-break: keep-all; }
  .doctors__stats { margin-top: var(--sp-4);
    display: flex; flex-wrap: wrap; justify-content: center; align-items: center;
    gap: var(--sp-2) var(--sp-4); }
  .doctors__stats li { position: relative; display: flex; align-items: baseline; gap: .4em;
    font-size: var(--fs-content-body); font-weight: 400; opacity: .85; white-space: nowrap; }
  /* 항목 사이 세로 구분선 - 줄바꿈된 첫 항목에는 붙지 않게 ::before 위치를 gap 안으로 */
  .doctors__stats li + li::before { content: ""; position: absolute;
    left: calc(var(--sp-4) / -2); top: .25em; bottom: .25em;
    width: var(--hairline); background: var(--veil-line); }
  .doctors__stats b { font-weight: 600; }
  /* (요청 2026-07-14) 인증 문구는 "체형 수술 8만례" 와 한 폰트 그룹이다.
     둘 다 h2 아래에서 병원의 규모·자격을 말하는 리드 문장이라 크기·굵기·색이 같아야 한다.
     → .doctors .tpl-lead 와 같은 벌을 쓴다(--fs-h2lead / 600 / 흰색). 자리도 stats 위로 올렸다.
       예전엔 stats 아래에서 subtext(16) / opacity .6 으로 흐릿하게 깔려 별개 요소처럼 보였다. */
  .doctors .tpl-lead,
  .doctors__cert { color: var(--white); font-weight: 600; word-break: keep-all; }
  .doctors__cert { margin-top: var(--sp-2); font-size: var(--fs-h2lead);
    line-height: var(--lh-body); }
  /* 설문 출처 - 체계에서 가장 작은 글씨(--fs-eyebrow 14)에 연한 회색. 만족도 수치의 각주다. */
  .doctors__note { margin-top: var(--sp-3); font-size: var(--fs-eyebrow);
    font-weight: 400; line-height: var(--lh-tight); color: var(--gray-light);
    opacity: .85; word-break: keep-all; }

  .doctors__grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--sp-7); }
  @media (max-width: 767.98px) { .doctors__grid { grid-template-columns: minmax(0, 1fr); } }

  /* 한 명 = 세로 스택. 사진 아래 텍스트가 이어지고 CTA 로 닫는다.
     CTA 는 카드 높이가 달라도 아래선이 맞도록 margin-top: auto 로 바닥에 붙인다. */
  .doctor { display: flex; flex-direction: column; align-items: center; text-align: center; }
  /* 사진: 배경이 투명(누끼)이라 자를 면이 없다 → (요청) radius 제거 */
  .doctor__photo { width: 100%; aspect-ratio: var(--ratio-square); object-fit: cover; object-position: top center; }

  /* (요청) 이름·설명에 포인트 컬러를 쓰지 않는다 - 어두운 면 위에서는 흰 글자 하나로 간다.
     위계는 색이 아니라 "크기 · 굵기 · 투명도"로만 만든다.
       이름     30 / 600 / 100%   ← 누구인가
       한 줄 정체성 24 / 600 / 100%   ← 연차 + 수치 (신뢰의 핵심)
       철학     20 / 400 / 85%    ← 본인의 말
       권위·수치 16 / 400 / 70%   ← 검증 가능한 사실 */
  .doctor__name { margin-top: var(--sp-5); font-size: var(--fs-content-title); font-weight: 600;
    color: var(--white); }
  .doctor__name span { margin-left: .4em; font-size: var(--fs-content-body); font-weight: 400;
    opacity: .7; }

  /* 한 줄 정체성 - "제목 + 서브본문" 묶음의 제목이다 → --fs-content-title(22).
     (2026-07-14) 예전엔 body×1.2 = 24 라는 5스케일 밖의 값이었다. 파생이라도 스케일 밖이면
     체계를 새는 구멍이 된다 → 토큰을 그대로 쓴다. */
  .doctor__tagline { margin-top: var(--sp-3); font-size: var(--fs-content-title);
    font-weight: 600; line-height: 1.35; letter-spacing: -.01em; word-break: keep-all; }

  /* 철학 한 줄 - 인용이므로 위아래 여백을 주고 살짝 눌러 둔다 */
  .doctor__quote { margin-top: var(--sp-4); padding-top: var(--sp-4);
    border-top: var(--hairline) solid rgb(255 255 255 / .2);
    font-size: var(--fs-content-body); font-weight: 400; line-height: var(--lh-body);
    opacity: .85; word-break: keep-all; }

  .doctor__points { margin-top: var(--sp-4); display: grid; gap: var(--sp-1); }
  .doctor__points li { font-size: var(--fs-content-subtext); font-weight: 400; line-height: var(--lh-body);
    opacity: .7; word-break: keep-all; }   /* 한글은 어절 단위로만 끊는다 */
  .doctor .cta { margin-top: var(--sp-6); }

  /* --- 후기 sec-8 : template 6번(실제 후기 사진)과 완전 동일한 컴포넌트 ---------
     (요청) index 도 template 6번과 똑같이 간다 → 클래스·CSS 를 그대로 공유한다(규칙 6 승격).
       · 캐러셀 · 화살표 · 그라디언트 · 닉네임 캡션 전부 없음
       · 카드 = 한 사람 (전 · 후 · 전 · 후 4장) → .container 안에 한 줄로 다 들어온다
       · 사진 폭 1fr → 컨테이너가 좁아지면 4장이 함께 줄어든다(넘치지 않는다)
       · 원본 비율 그대로 - aspect-ratio 를 강제하지 않고 object-fit 도 걸지 않는다
       · 사진 사이 간격 = --box-gap(35), 사람 사이 = --sp-8(80)
     섹션 배경(연한 핑크 면)은 index 고유라 그대로 둔다 - 그 외는 전부 template 과 같다. */
  .reviews { margin-top: 0; margin-bottom: var(--sp-9);
    padding: var(--sp-10) 0;
    background: var(--point-bg) center / cover no-repeat;
    background-image: url("https://storage.googleapis.com/best-stem-cell-lipo-gangnam/theline-reviews-section-bg.webp"); }

  /* ── template 6번(후기) 컴포넌트 : template.html 이 쓴다 (규칙 6 승격) ── */
  .tpl-review__list { display: grid; gap: var(--sp-8); }   /* 사람과 사람 사이 */
  .tpl-review__imgs { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: var(--box-gap); align-items: start; }
  @media (max-width: 991.98px) {
    .tpl-review__imgs { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  }

  /* ── index 후기 캐러셀 : 쇼츠와 "같은 규칙"을 쓴다 ──
       화살표 ↔ 사진 = 50px (--sp-7 × 5/6)  ← .shorts__viewport 와 동일한 식
       사진 ↔ 사진   = 30px (--sp-5)
       한 화면 4장  → 사진 = (100% - 간격 3개) / 4  = 한 사람의 [전·후·전·후] 한 세트
     사진이 작아진 만큼 4장이 화살표 안쪽에 여유 있게 들어온다. */
  .reviews__viewport { display: flex; align-items: center; justify-content: center;
    gap: calc(var(--sp-7) * 5 / 6); }
  .reviews__slider { flex: 1 1 0; min-width: 0; display: flex; gap: var(--sp-5);
    overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: none; }
  .reviews__slider::-webkit-scrollbar { display: none; }
  .review__photo { flex: 0 0 calc((100% - var(--sp-5) * 3) / 4); scroll-snap-align: start; }
  @media (max-width: 991.98px) { .review__photo { flex: 0 0 calc((100% - var(--sp-5)) / 2); } }
  /* (요청 2026-07-22) 폰에서 한 장만 보이면 전후 비교가 안 된다 → 두 장을 함께 세운다.
     칸이 좁아진 만큼 사진 사이 간격만 한 단계 줄인다(--sp-5 → --sp-3). */
  @media (max-width: 575.98px) {
    /* (요청 2026-07-22) 폰은 화살표를 사진 옆이 아니라 **아래**로 내린다.
       옆에 두면 좌우로 폭을 먹어 사진이 작아진다 → 사진이 한 줄을 통째로 쓰고,
       화살표는 그 아래 가운데에 나란히 선다. 순서는 [사진] → [화살표] → [후기 더보기].
       화살표는 CTA 보다 사진 쪽에 붙인다(사진과 20 · CTA 와는 .section__foot 의 80). */
    .reviews__viewport {
      display: grid;
      grid-template-columns: auto auto;
      grid-template-areas: "slider slider" "prev next";
      justify-content: center;
      gap: var(--sp-4) var(--sp-3);
    }
    .reviews__slider { grid-area: slider; gap: var(--sp-3); }
    /* 첫 행(사진)이 두 열을 다 쓰므로 열 폭이 슬라이더의 절반씩이다 →
       그대로 두면 화살표가 좌우 끝으로 벌어진다. 가운데로 모아 붙인다. */
    .reviews__nav--prev { grid-area: prev; justify-self: end; }
    .reviews__nav--next { grid-area: next; justify-self: start; }
    .review__photo { flex: 0 0 calc((100% - var(--sp-3)) / 2); }
  }

  /* 사진 한 장의 모양(라운드 · 전/후 캡션)은 template 6번과 완전히 같다 - 한 규칙으로 공유한다 */
  /* ★ 비율 고정(425:567 = 원본 후기 썸네일 규격). 이게 없으면:
       슬라이더가 flex(align-items:stretch) 라 figure 는 "제일 큰 카드" 높이로 늘어나는데
       img 는 height:auto(원본 비율) 라 figure 안쪽, 사진 밑에 죽은 공백이 남는다.
       → 본문 박스가 사진보다 커져서 "본문 ↔ CTA 20px" 이 눈에는 80px+ 로 보였다.
       본문은 자기 콘텐츠에 딱 맞아야 한다(본문 자체엔 위아래 마진 0, 간격은 CTA 마진이 잡는다). */
  .tpl-review__imgs figure, .review__photo { position: relative;
    aspect-ratio: 425 / 567; border-radius: var(--r-lg); overflow: hidden; }
  .tpl-review__imgs img, .review__photo img {
    width: 100%; height: 100%; object-fit: cover; display: block; }
  /* 전/후 배지("수술 전" · "3개월 후")는 사진 위에 얹는 라벨이지 본문이 아니다.
     (요청) 본문 body(20) → 한 스케일 아래 caption(16).
     index 후기 캐러셀(.review__photo)과 서브페이지 후기(.tpl-review__imgs)가 이 한 줄을 공유하므로
     여기만 고치면 전 페이지에 동시 적용된다. */
  /* (요청 2026-07-14) 캡션 한 단계 축소: content-subtext(16) → eyebrow(14).
     사진 위에 얹힌 라벨이라 작아도 읽힌다. 사진을 덜 가린다. */
  .tpl-review__imgs figcaption, .review__photo figcaption { position: absolute; left: 0; top: 0;
    padding: var(--sp-1) var(--sp-3); font-size: var(--fs-eyebrow); font-weight: 600;
    color: var(--white); background: var(--ink); border-bottom-right-radius: var(--r-lg); }
  .tpl-review__imgs .is-after figcaption,
  .review__photo.is-after figcaption { background: var(--point); }

  /* --- BEFORE&AFTER sec-9 (원본: 탭 pill #E0D5CF, 비디오 627, 그리드 3col) --- */
  .bna { margin-top: var(--sec-gap); }
  /* 폭: 공통 .container(1400·변형2) 사용. 이전 1280 특례는 섹션 폭 2종 통일로 제거 */
  /* (요청) 탭 위아래 여백 40 → 30 : 제목 ~ 탭 ~ 콘텐츠를 조금씩 당겨 붙인다 */
  /* (요청) 섹션 탭 = 텍스트 (토글 pill 아님). BEFORE&AFTER · TheLINE Shorts 가 완전히 같은 스타일.
       선택   : 포인트 컬러 + 볼드(600)
       비선택 : 회색(--gray-dark) + 볼드 없음(400)
     ※ 템플릿 7번의 "정면/후면/측면"은 성격이 다른 UI(각도 선택)라 pill 토글(.cta + .bna-toggle)을 유지한다. */
  /* (요청) 템플릿 7번의 각도 토글(정면/후면/측면)도 index 의 탭과 "같은 스타일"을 쓴다.
     pill(.cta + .bna-toggle) 을 버리고 텍스트 탭으로 통일 → 규칙 한 벌을 셋이 공유한다.
       활성 표시는 마크업이 서로 다르다(index = aria-selected, template = .is-on) → 둘 다 받는다. */
  /* 좌:우 비율 grid → 컨테이너 축소 시 비디오도 함께 축소
     (요청) 좌측 영상 ↔ 우측 사진영역 간격 = 60px = --sp-7 (기존 20 --sp-4) */
  /* (요청) 영상을 자르지 않는다 - 원본 비율 그대로.
     이전에는 영상이 object-fit: cover 로 "사진 2행"의 높이를 채웠다. 영상(626×690)은 세로형인데
     칸은 280 폭에 444 높이라 세로로 늘어난 만큼 좌우가 잘려 나갔다.

     그래서 반대로 푼다 - 영상은 원비율(--bna-video-ratio)로 두고, 컬럼 비율을 그 높이에 맞춘다.
       영상 높이  = L × 690/626
       그리드 높이 = 사진 2행 + 행간 (사진은 425×204 가로형)
     (요청) 영역을 키운다 - 컨테이너 폭(1280)은 표준이라 못 늘린다. 대신 간격을 줄여
     그만큼을 영상·사진에 돌린다. 여백이 곧 콘텐츠 크기의 재원이다.
       영상 ↔ 사진 = 60(--sp-7)  ·  사진 ↔ 사진 = 30(--sp-5)     [100 · 60 에서 축소]
     이 간격에서 두 식을 같게 두고 풀면 L : R = 356 : 784 → 좌우 높이가 392px 로 맞는다.
     간격을 바꾸면 이 비율도 다시 풀어야 한다(간격이 컬럼 폭을 먹기 때문).
     전후사진은 before|after 가 좌우로 붙어 있어 애초에 크롭 금지다(원비율 유지). */
  .bna__layout { display: grid; grid-template-columns: minmax(0, 356fr) minmax(0, 784fr);
    gap: var(--sp-7); align-items: start; }
  @media (max-width: 991.98px) { .bna__layout { grid-template-columns: 1fr; } }
  .bna__video video { display: block; width: 100%; height: auto;
    aspect-ratio: var(--bna-video-ratio); object-fit: contain;
    border-radius: var(--r-lg); }
  /* (요청) 3열 최대 9장 → 2열 2행, 최대 4장.
     (요청) 사진 ↔ 사진 = 30(--sp-5). 상하좌우 같은 값이라 gap 하나로 끝난다.
     간격이 생겼으니 칸을 나누던 세로 구분선(border-right)은 뺀다 - 선과 여백을 같이 쓰지 않는다. */
  .bna__grid { display: grid; grid-template-columns: repeat(2, 1fr); align-content: start;
    gap: var(--sp-5); }
  .bna__cell { border-right: 0; }

  /* ── (요청 2026-07-22) 왼쪽 영상과 오른쪽 전후 카드의 높이를 맞춘다 ─────────────
     이 섹션의 오른쪽은 전후사진 목록과 같은 와이프 카드(.bna-wipe)를 쓴다. 그런데 그 카드는
     자기 비율(490:492)로 높이가 정해져 영상(626:690)보다 20px 남짓 짧았다.
     → 컬럼을 stretch 로 두고 카드가 영상 높이를 그대로 채우게 한다.
     ⚠️ 높이가 비율에서 풀리므로 이미지도 함께 손봐야 한다:
        원래 규칙은 width·height 를 둘 다 계산해 넣어 카드가 490:492 일 때만 원본 비율이 맞는다.
        카드가 세로로 길어지면 사진이 늘어나 버리므로 height 를 auto 로 돌려 비율을 지킨다.
     크롭 배분은 원래 의도대로 위는 조금(4%)·아래는 더 많이 잘라, 사진 아래 [Before/After] 띠와
     문구가 살아 남는다. ★ 이 섹션(.bna__layout) 안으로만 한정한다 - 다른 페이지의 39 는 그대로. */
  .bna__layout { align-items: stretch; }
  .bna__layout .bna-wipe { height: 100%; }
  .bna__layout .bna-wipe > div { height: 100%; }
  .bna__layout .bna-wipe__box { height: 100%; }
  .bna__layout .bna-shot { aspect-ratio: auto; height: 100%; }
  .bna__layout .bna-shot img { height: auto; }
  /* 모바일은 1단이라 영상과 카드가 위아래로 서고 stretch 가 의미 없다 → 원래 비율로 되돌린다 */
  @media (max-width: 991.98px) {
    .bna__layout .bna-wipe, .bna__layout .bna-wipe > div,
    .bna__layout .bna-wipe__box { height: auto; }
    .bna__layout .bna-shot--b { aspect-ratio: 490 / 492; }
    .bna__layout .bna-shot--a { aspect-ratio: 490 / 492; }
    .bna__layout .bna-shot img { height: calc(100% * 600 / 492); }
  }
  .bna__cell figure { position: relative; overflow: hidden; }
  .bna__cell img { width: 100%; height: auto; } /* 원본: 가로형 전후사진 원비율 */
  .bna__cell figure::before { content: ""; position: absolute; top: 0; bottom: 0; left: 0; right: 50%;
    backdrop-filter: blur(5px); -webkit-backdrop-filter: blur(5px); z-index: 1; }
  /* (요청) 사진 하단 캡션 삭제 - 사진 4장만 꽉 채운다.
     img 의 alt 에는 시술명이 그대로 남아 SEO 손실은 없다. */

  /* --- 바로가기 sec-10 (원본: 837/594/466 카드, hover scale 1.1 .6s) --- */
  .shortcuts { margin-top: var(--sec-gap); }
  .shortcuts__grid { display: flex; flex-wrap: wrap; justify-content: center;
    gap: var(--sp-5); }
  .shortcut { position: relative; overflow: hidden; display: block; color: var(--white);
    border-radius: var(--r-lg); } /* (요청 5) R값 */
  .shortcut img.shortcut__bg { width: 100%; height: 100%; object-fit: cover;
    transition: transform .6s ease; }
  .shortcut:hover img.shortcut__bg { transform: scale(var(--card-zoom)); }
  /* (요청) 이 섹션도 .container 안으로 넣는다(기존 .container--full → .container).
     그래서 카드의 고정 px 폭(837/594/466)을 버리고 "컨테이너 폭의 비율"로 바꾼다.
       1행 = 837 : 594  (합 1431, 사이 간격 1개)
       2행 = 466 × 3    (사이 간격 2개)
     간격은 위·아래·좌우 모두 --sp-5(30) 하나로 통일 → gap 이 그 값을 정한다.
     높이는 aspect-ratio 가 원본 비율 그대로 잡는다(1행 466 높이, 2행 정사각). */
  .shortcut--w837 { width: calc((100% - var(--sp-5)) * 837 / 1431);
    height: auto; aspect-ratio: 837 / 466; }
  .shortcut--w594 { width: calc((100% - var(--sp-5)) * 594 / 1431);
    height: auto; aspect-ratio: 594 / 466; }
  .shortcut--w466 { width: calc((100% - var(--sp-5) * 2) / 3);
    height: auto; aspect-ratio: 1; }
  /* 모바일은 전 카드가 1열로 쌓인다 → 비율도 하나로 통일한다(837/466).
     예전엔 w466 만 aspect-ratio:1(정사각)이라, 같은 1열인데 Q&A · 비공개 상담 카드만
     높이가 유독 높았다(2026-07-14 요청). */
  @media (max-width: 991.98px) {
    .shortcut--w837, .shortcut--w594, .shortcut--w466 {
      width: 100%; height: auto; aspect-ratio: 837 / 466; }
  }
  /* 캡션은 카드 좌측, 세로는 "제목의 첫 줄이 카드 정중앙에서 시작"한다.
     (2026-07-14) bottom 기준으로 잡으면 캡션 높이(제목 줄 수 · CTA)에 따라 시작점이 흔들린다
     - 제목이 2줄인 카드와 1줄인 카드의 첫 줄이 서로 다른 선에 섰다.
     → top:50% 로 시작점을 못박는다. 카드 크기가 달라져도 제목은 늘 한가운데서 시작한다. */
  .shortcut__cap { position: absolute; z-index: 1;
    left: clamp(20px, 2.604vw, 50px);
    top: 50%; bottom: auto; }
  .shortcut__cap strong { display: block; font-size: var(--fs-content-title); font-weight: 600; }
  /* 사진 위 CTA - 비포애프터 블러의 "로그인" 버튼과 같은 벌이다.
     .cta 가 크기·굵기·라운드를 정하고, 여기서는 사진 위라 흰색으로만 뒤집는다.
     제목 ↔ CTA 간격도 카드에 비례한다(모바일 카드가 작아 30 은 과했다). */
  .shortcut__cap .cta--onphoto { margin-top: clamp(12px, 1.563vw, 30px);
    color: var(--white); box-shadow: inset 0 0 0 var(--hairline) var(--white); }
  .shortcut:hover .cta--onphoto { background: var(--white); color: var(--ink); }
  .shortcut__logo { position: absolute; top: 50%; left: 50%; transform: translate(-50%,-50%);
    width: clamp(121px, 10.156vw, 195px); height: clamp(56px, 4.688vw, 90px); object-fit: contain; z-index: 1; }
  /* (요청) 하단 배너(10_7)는 좌우 여백 없는 100% 풀폭 */
  /* (요청) 이벤트 띠 위/아래 흰 영역을 같게 만든다.
       아래(띠 ~ 푸터1) : 120 → 110 (10px 축소)   ← .locate margin-top
       위  (카드 ~ 띠)  : 30  → 110 (동일 확보)
     110 은 --sp-9(120) 에서 파생한다(임의 px 아님). 둘이 같은 식을 쓰므로 한쪽만 바뀌지 않는다. */
  .shortcuts__banner { display: block; margin-top: calc(var(--sp-9) * 11 / 12); width: 100%; }
  .shortcuts__banner img { width: 100%; }

  /* --- 오시는길 ("푸터1") - phpnew3 원본값 그대로 (전화 48/500, 본문 20, SNS 60, 지도 880×441) --- */
  .locate { margin-top: calc(var(--sp-9) * 11 / 12); }   /* 120 → 110 : 띠 위쪽 여백과 동일 */
  /* (요청) 지도를 줄이고 남는 폭을 왼쪽 텍스트에 준다.
     지도 880 → 660 (@1920) → 좌측 정보영역 280 → 500 으로 넓어져 주소·진료시간이 안 접힌다. */
  /* (요청) 지도 높이 = 좌측 정보영역 높이. align-items: stretch 로 두면
     그리드 행 높이(=더 큰 쪽인 좌측 정보)를 지도가 그대로 채운다 → 고정 height 불필요 */
  .locate .container { display: grid; grid-template-columns: 1fr clamp(410px, 34.375vw, 660px);
    gap: var(--sp-6); align-items: stretch; }
  @media (max-width: 991.98px) { .locate .container { grid-template-columns: 1fr; } }
  .locate__tel { font-size: var(--fs-h2title); color: var(--point); font-weight: 600; letter-spacing: -.05em; }
  .locate__addr { margin-block: var(--sp-4); font-size: var(--fs-content-body); font-weight: 400; letter-spacing: -.05em; color: var(--ink); }
  .locate__hours { display: grid; gap: .5rem; margin-bottom: var(--sp-5); }
  .locate__hours div { display: flex; gap: 1rem; font-size: var(--fs-content-body); font-weight: 400; }
  .locate__hours dt { min-width: 90px; font-weight: 400; }
  .locate__maps { display: flex; flex-wrap: wrap; gap: var(--sp-5);
    margin-bottom: var(--sp-5); }
  .locate__maps a { display: inline-flex; align-items: center; gap: var(--sp-2);
    font-size: var(--fs-content-body); font-weight: 400; color: var(--ink); transition: color .2s; }
  .locate__maps a:hover { color: var(--point); }
  .locate__maps img { width: 20px; }
  /* SNS: 브랜드 컬러가 기본. hover 로 색이 켜지는 연출은 쓰지 않는다 (2026-07-13)
     - 회색으로 깔아두면 "비활성" 처럼 읽혀 클릭 대상으로 인지되지 않는다. */
  .locate__sns { display: flex; gap: var(--sp-3); }
  .locate__sns img { width: clamp(37px, 3.125vw, 60px); }
  .locate__map { height: auto; }   /* 좌측 정보영역과 같은 높이로 늘어난다(stretch) */
  .locate__map iframe { width: 100%; height: 100%; border: 0; }
  /* 모바일은 1컬럼이라 "맞출 상대"가 없다 → 고정 높이로 되돌린다.
     ★ 이 규칙은 반드시 위 height:auto '뒤'에 와야 한다(같은 특이도 → 뒤가 이긴다). */
  @media (max-width: 991.98px) { .locate__map { height: clamp(205px, 40vw, 331px); } }

  /* --- 푸터 (원본: 흰 로고 156, 카피 #E0E0E0) - (요청 16) 크게 축소 --- */
  /* --- 푸터2 (이용약관) - phpnew3 원본값 (로고 156, 본문 20/500/-.05em, 카피 #E0E0E0) --- */
  /* 하단 padding 만 상담바(푸터플로팅) 높이를 커버하도록 유지 → 카피 안 가림 */
  /* (요청) 푸터2 를 다크 브라운 → 연한 회색으로. 볼드도 뺀다.
     배경이 밝아졌으니 글자는 --gray-dark, 로고는 흰색본(logo_white) → 기본본(logo_new)으로 교체했다. */
  .site-footer { background: var(--bg-mute); color: var(--gray-dark);
    margin-top: var(--sp-8);
    padding: var(--sp-6) 0 var(--sp-9); }
  /* (요청) 로고를 "서울 강남구" 첫 줄과 시작 라인 맞춤 → 상단 정렬 */
  .site-footer__inner { display: grid; grid-template-columns: auto 1fr;
    gap: var(--sp-10); align-items: start; }
  /* 본문 첫 줄(line-height 30 / 폰트 20)의 여백만큼 로고를 내려 광학적 정렬 */
  .site-footer__brand { padding-top: calc((var(--sp-5) - 1em) / 2); }
  @media (max-width: 767.98px) { .site-footer__inner { grid-template-columns: 1fr; gap: 1.2rem; } }
  /* (2026-07-14) 푸터2 로고도 정상 비율 파일(logo_wide.webp 7.84배)로 교체.
     (요청 2026-07-14) 156 → 200 으로 키운다. 비율(7.84)대로 높이는 26 이 된다.
     좁은 화면 하한도 120 → 150 으로 함께 올린다 - 모바일에서 로고만 유독 작아 보였다. */
  .site-footer__brand img { width: clamp(180px, 12.5vw, 240px); height: auto; }
  .site-footer__links { display: flex; gap: var(--sp-4); margin-bottom: var(--sp-3); }
  .site-footer__links a { font-size: var(--fs-content-subtext); font-weight: 400; color: var(--gray-dark); }
  .site-footer__links a:hover { color: var(--point); }
  /* (요청) 폰트 한 단계 축소 (--fs-body 20 → --fs-caption 16), 볼드 전부 해제(400) */
  .site-footer__info p { font-size: var(--fs-content-subtext); line-height: 1.9;
    letter-spacing: -.05em; font-weight: 400; }
  .copyright { color: var(--gray-dark); margin-top: var(--sp-4); }

  /* --- 하단 고정 상담바(푸터플로팅) - 3섹션 [폼3 : 동의1 : 버튼1], 본문 여백(container) --- */
  .consult-bar { position: fixed; bottom: 0; left: 0; right: 0; z-index: 1039;
    background: var(--veil-bar); }
  /* (요청) 배경 박스 높이 조금 키움 : padding ↑ */
  .consult-bar__inner { display: flex; align-items: center; gap: var(--sp-4);
    padding-block: var(--sp-2); }
  /* (1) 폼 영역 - 남는 공간을 흡수. min-width:0 이 없으면 min-content(약 716px)에서
     더 못 줄어들어 좁은 화면에서 "개인정보 동의"를 짓눌러 2줄로 만든다. */
  .consult-bar__fields { flex: 1 1 auto; min-width: 0; display: flex; gap: var(--sp-2); }
  /* (요청) 폼 입력칸 height 만 조금 축소 (44 → 38) */
  .consult-bar__fields input { flex: 1; min-width: 0; height: clamp(24px, 1.979vw, 38px);
    border: 0; border-radius: var(--r-sm); padding: 0 .8rem; background: var(--white);
    font-size: var(--fs-content-subtext); }
  /* (요청) 상담희망 부위 = 희망수술 모달 트리거. 다른 입력칸과 똑같이 보이게 */
  .consult-bar__fields .field__pick { flex: 1; min-width: 0;
    height: clamp(24px, 1.979vw, 38px); border: 0; border-bottom: 0;
    border-radius: var(--r-sm); padding: 0 .8rem; background: var(--white);
    font-size: var(--fs-content-subtext); color: var(--gray-dark);
    overflow: hidden; white-space: nowrap; }
  .consult-bar__fields .field__pick.is-filled { color: var(--ink); }
  /* (요청) 칸 폭을 2쌍으로 통일 - [이름 = 연락처] 짧게 / [상담 희망 부위 = 메모] 넓게 */
  .consult-bar__fields input[name="name"],
  .consult-bar__fields input[name="phone"] { flex: 1; }     /* 이름 = 연락처 */
  .consult-bar__fields .field__pick,
  .consult-bar__fields input[name="memo"]  { flex: 1.7; }   /* 희망부위 = 메모 */
  /* (2) 개인정보 동의 - 내용 폭만 차지하고 절대 줄바꿈하지 않는다 */
  .agree--light { flex: 0 0 auto; white-space: nowrap;
    color: var(--white); display: flex; align-items: center; gap: .4rem;
    font-size: var(--fs-content-subtext); line-height: 1.3; }
  .agree--light input { flex: 0 0 auto; width: var(--ui-check); height: var(--ui-check); accent-color: var(--point); }
  /* (3) CTA 버튼 = 원형(pill)
     (요청) 여백을 본문 CTA(.cta) 와 통일 - 고정 width/height 를 버리고 여백이 크기를 정한다.
     색은 .btn--rose 가 정한다(포인트 배경 + 흰 글자) - 여기서 건드리지 않는다. */
  /* 상담바 버튼 - 바 높이가 낮아 박스만 줄인다. 여백 15/25 → 10/20 (--sp-2 / --sp-4).
     ★ 글자는 .btn 이 준 --fs-cta(16/600) 를 그대로 쓴다 - 버튼 라벨은 어디서나 한 벌이다.
       예전엔 여기만 caption(16)/700 이라 다른 버튼과 굵기가 튀었다. */
  /* 상담바 버튼 - 바 높이가 낮아 PC 에서만 한 단계 좁힌다(10/20).
     모바일은 :root 의 모바일 토큰(5/15)이 그대로 내려온다 → 여기서 덮지 않는다.
     ★ width/height 는 auto - .btn--rose 의 고정 크기(clamp 164~265 × 50~80)를 푼다. */
  .consult-bar .btn--rose { flex: 0 0 auto; width: auto; height: auto;
    padding: var(--sp-2) var(--sp-4);
    border-radius: var(--r-pill); }
  @media (max-width: 991.98px) {
    .consult-bar .btn--rose { padding: var(--cta-pad-block) var(--cta-pad-inline); }
  }
  /* 모바일: 체크박스 1줄, 필드 랩 */
  @media (max-width: 991.98px) {
    .consult-bar__inner { flex-wrap: wrap; gap: 6px; padding: 8px 10px; }
    .consult-bar__fields { flex: 1 1 100%; flex-wrap: wrap; gap: var(--sp-1); }
    .consult-bar__fields input { flex: 1 1 45%; height: 32px; font-size: var(--ui-text); }
    .agree--light { flex: 1 1 auto; order: 3; font-size: var(--ui-text); }
    /* 여백은 토큰(--cta-pad-*)이 clamp 로 알아서 줄어든다 → 여기서 다시 덮지 않는다.
       글자도 마찬가지 - --fs-cta 가 모바일에서 14 로 내려간다. --ui-text(13) 로 덮으면
       버튼 라벨만 다른 버튼보다 1px 작아진다(2026-07-14 제거). */
    .consult-bar .btn--rose { flex: 0 0 auto; }
  }

  /* 모바일 전용 이벤트 배지.
     원본은 top:77% 였다 - 화면 높이의 "비율"이라 해상도마다 바닥과의 거리가 달라진다
     (844 화면에선 바닥 114px 위, 작은 화면에선 74px 위). 하단 상담바를 없앴으니
     bottom 기준으로 바꿔 어느 해상도에서든 항상 바닥에서 같은 만큼 띄운다.
     env(safe-area-inset-bottom) 은 아이폰 홈바에 가리지 않게 하는 여백. (2026-07-13) */
  /* ★ 배지 = 모바일 퀵 메뉴의 여닫이 버튼이다(이벤트 페이지 링크가 아니다).
     이벤트로 가는 길은 퀵 메뉴 안 "이달의 이벤트" 칸이 맡는다. */
  /* (요청) 모바일 배지는 움직이지 않는다 - 누르는 버튼이라 흔들리면 겨냥이 어긋난다.
     PC 좌하단 배지(.quick-badge)의 quick_bounce 는 그대로 둔다(링크라 성격이 다르다). */
  .quick-badge-m { position: fixed; top: auto;
    bottom: var(--quick-badge-gap);
    right: var(--sp-2); z-index: 999; width: var(--quick-badge-w); }
  /* (요청) 열려 있어도 배지는 인물 이미지 그대로다 - 닫기(×) 표시를 얹지 않는다.
     닫는 방법은 배지를 다시 누르거나 · 메뉴 밖을 누르거나 · ESC 세 가지다. */
  .quick-badge-m__btn { display: block; width: 100%; padding: 0; }

  /* --- 모바일 퀵 메뉴 : 배지 위로 펼친다 ---------------------------------
     평소엔 접혀 있고(배지 클릭 → .is-open), 배지 바로 위에서 위로 쌓인다.
     세로 위치는 "배지가 바닥에서 띄운 만큼 + 배지 높이(폭 × 이미지 비율 200:270)" 다
     → 배지 토큰(--quick-badge-w/gap)만 고치면 메뉴가 따라온다. */
  @media (max-width: 991.98px) {
    :root { --quick-ico: 36px; }
    .quick-side { top: auto; transform: none; right: var(--sp-2);
      bottom: calc(var(--quick-badge-gap) + var(--quick-badge-w) * 1.35 + var(--sp-3));
      gap: var(--sp-2);
      opacity: 0; visibility: hidden; translate: 0 var(--sp-4);
      transition: opacity .25s ease, translate .25s ease, visibility .25s; }
    .quick-side.is-open { opacity: 1; visibility: visible; translate: 0 0; }
    .quick-side__item { padding-left: var(--sp-3); }
    .quick-side__label { font-size: var(--ui-text); }
    .quick-side__id { display: block; }
    .quick-side__ico { font-size: var(--ico-sm); }
    /* "맨 위로" 는 PC 전용 - 모바일은 메뉴가 바닥에 붙어 있어 자리를 뺏는다 */
    .quick-side__top { display: none; }
  }

  /* ==========================================================================
     ★ 섹션 컴포넌트 (tpl-*) - template.html 이 SSOT   [2026-07-12 page-template.css 에서 승격]

     서브페이지의 섹션은 전부 이 컴포넌트로 만든다. 페이지마다 새로 짜지 않는다.
       .tpl-head/.tpl-eyebrow/.tpl-lead  섹션 헤드      (eyebrow → H2 → 리드문)
       .tpl-boxes/.tpl-box               3구획 박스      (아이콘 / 제목 / 본문)
       .tpl-box--photo                   사진 박스       (아이콘 자리에 사진)
       .tpl-about                        영상·사진 + 글 2단
       .tpl-intro                        소개            (좌 sticky 사진 + 01~05)
       .tpl-info                         수술/시술 정보  (사진 + 박스 6개)
       .tpl-check                        체크리스트      (사진 + 한 줄 항목)
       .tpl-process                      시술 과정       (스텝 + 사진, 5스텝↑ sticky)
       .tpl-review                       실제 후기 사진  (전·후·전·후 4장)
       .tpl-carousel/.tpl-bna            전후사진        (순환 캐러셀 + 각도 토글 + 블러)
       .sub-hero--plain                  사진 없는 히어로 (.sub-hero 변형)

     그 페이지에만 있는 것(lp- · qk- · doc- · bi- · mi-)은 page-template.css 에 둔다.
     2개 이상 페이지가 같은 걸 쓰기 시작하면 여기로 승격하고 예외에서 지운다.
  ========================================================================== */


  /* ══════════════════════════════════════════════ 섹션 셸
     간격 토큰(--box-gap 35 · --flow-gap 30)은 main.css :root 에 있다 → 여기서 만들지 않는다. */
  .tpl-sec { margin-top: var(--sec-gap); }
  .tpl-sec--first { margin-top: var(--sp-8); }

  /* ══════════════════════════════════════════════ 섹션 헤드 (전 섹션 동일)
     lipo-abdomen 의 INTRODUCTION 스타일이 기준. 섹션마다 색을 바꾸지 않는다.
       eyebrow(.tpl-eyebrow) · 헤드 여백(.tpl-head) · H2 는 전부 main.css 로 승격했다.
       → 여기서 다시 선언하지 않는다(중복 금지). 간격 델타만 둔다. */
  /* (요청) 헤드 간격 델타
       영문 eyebrow ↔ 한글 H2 : 10 → 15  (아주 조금만)
       제목영역 ↔ 본문 섹션   : 96 → 112 (조금 더) */
  /* 헤드 여백(80) · eyebrow↔H2(15) · strong 색상은 main.css 가 정한다 → 중복 선언하지 않는다. */
  /* (요청) 리드 문장 폭 = 700px (1096 → 700). 섹션 폭이 아니라 "읽기 폭" 상한이라
     .container 2종 규칙과 무관하다. 좁은 화면에선 컨테이너가 먼저 폭을 잡는다. */
  /* .tpl-lead 는 main.css 로 승격했다(index 도 쓴다) → 여기서 중복 선언하지 않는다. */

  /* ══════════════════════════════════════════════ 박스 3구획 (공통 컴포넌트)
     아이콘 영역 / 제목 영역 / 텍스트 영역을 고정 높이 행으로 잡는다.
     → 내용 길이가 달라도 같은 줄의 박스끼리 아이콘·제목·본문이 같은 y 에 온다.
     → 구획 사이 구분선은 긋지 않는다(여백으로만 나눔).
     특징 · 추천 · 수술 정보 세 섹션이 전부 이 컴포넌트 하나를 쓴다. */
  /* (요청) 좌우 분리 섹션의 좌↔우 컬럼 간격 = 70px (풀사이즈 기준).
     70 은 --sp-7(60) 과 --sp-8(80) 사이값이라 --sp-7 에서 파생한다(임의 px 아님).
     소개 · 수술 정보 · 체크리스트 · 시술 과정 4개 섹션이 모두 이 값을 쓴다. */
  .tpl-intro, .tpl-info, .tpl-check, .tpl-process {
    --tpl-col-gap: calc(var(--sp-7) * 7 / 6); }   /* 60 → 70 */

  /* 간격 토큰(--box-gap · --flow-gap)은 .tpl-sec 에서 선언한다 → 여기서 다시 안 만든다.
     행 높이는 auto - 1fr 로 모든 행을 같은 높이로 묶으면 짧은 박스에 빈 공간이 크게 남아
     "본문 끝 ~ 박스 하단 = 5" 비율이 시각적으로 깨진다. 같은 행 안에서는 여전히 높이가 같다. */
  /* (요청) 시술 특징(섹션 3) 박스의 본문은 한 단계 작다 (--fs-body 20 → --fs-caption 16).
     거기 본문은 "설명 문장"이라 길고, 수술 정보(섹션 2)의 본문은 "값"이라 짧다(3시간 전후 · 수면마취).
     → 같은 컴포넌트지만 자리에 따라 크기를 가른다. HTML 은 건드리지 않는다:
       .tpl-info 안 = 수술 정보(값)   / .tpl-info 밖 = 시술 특징(설명) */
  /* (요청) 시술 특징 박스는 수술 정보 박스와 "완전히 같은" 제목·본문 스타일을 쓴다.
     → 자리마다 크기를 가르던 오버라이드를 전부 지웠다. 값은 :root 기본값 하나뿐이다
       (제목 --box-title-fs 24 / 본문 --fs-body 20 / 인셋 --box-text-inset 20).
     같은 컴포넌트는 어디에 놓이든 같아 보여야 한다. */
  /* grid 가 아니라 flex 다. grid 는 마지막 줄이 항상 왼쪽으로 쏠려
     5개(3+2)·7개(4+3)처럼 딱 안 떨어지면 오른쪽이 휑하게 빈다.
     flex + justify-content:center 면 남는 줄이 가운데로 모인다.
     폭 계산은 grid 와 똑같다 → 딱 떨어지는 3·4·2열은 시각 결과가 완전히 동일하다. */
  .tpl-boxes { display: flex; flex-wrap: wrap; justify-content: center;
    gap: var(--box-gap); }
  .tpl-boxes > * { flex: 0 1 calc((100% - (var(--cols, 3) - 1) * var(--box-gap)) / var(--cols, 3));
    min-width: 0; }

  /* ★ 카테고리 묶음 (2026-07-13) - 박스가 많으면 원본처럼 "그룹"으로 나눈다.
     예: 줄기세포 연구소 22개 = 체형/안면성형/항노화·웰빙/피부치료/모발/Private 6개 Center.
     한 줄에 22개를 쏟으면 의미가 사라진다. 그룹 제목(h3)이 계층을 되살린다. */
  .tpl-group + .tpl-group { margin-top: var(--sp-8); }
  .tpl-group > h3 { text-align: left; font-size: var(--fs-content-title); font-weight: 600;
    color: var(--ink); letter-spacing: -.02em; margin-bottom: var(--sp-5);
    padding-bottom: var(--sp-3); border-bottom: var(--hairline) solid var(--gray-light); }

  /* ★ 열 수는 "박스 개수"가 정한다 (2026-07-13) - 페이지마다 style="--cols:N" 을 찍지 않는다.
     6개를 4열로 두면 4+2 로 갈라져 마지막 줄이 반쯤 빈다 → 3+3 이 맞다.
     아래 규칙이 기본값이고, 정말 다르게 가야 하는 자리에서만 인라인 --cols 로 덮는다.
     기본은 3열이다(3개·5개는 여기서 처리된다).
     남는 줄은 위 flex 가 가운데로 모아주므로, 5개(3+2)·7개(4+3)도 어색하지 않다.

     ⚠️ 2026-07-13 수정: 아래 두 줄("기본은 3열이다…" · "남는 줄은…")이 주석 밖에 생짜 텍스트로
        새어나와 있었다. 파서가 그걸 셀렉터로 읽고 다음 '{' 까지 삼켜서 바로 아래
        "2개 → --cols: 2" 규칙이 통째로 죽어 있었다(4·6·7·8·9·10 은 살아 있었다).
        → 주석 안으로 되돌렸다. 이제 2개짜리 자동 규칙이 산다. */
  .tpl-boxes:has(> :nth-child(2):last-child)  { --cols: 2; }   /* 2개  → 한 줄   */
  .tpl-boxes:has(> :nth-child(4):last-child)  { --cols: 4; }   /* 4개  → 한 줄   */
  /* (요청 2026-07-14) 5개도 한 줄이다. 기본 3열로 두면 3+2 로 끊겨 마지막 줄이 허전하다.
     칸이 좁아지지만 값 타일(수술시간 · 마취방법 …)은 짧아서 들어간다. */
  .tpl-boxes:has(> :nth-child(5):last-child)  { --cols: 5; }   /* 5개  → 한 줄   */
  .tpl-boxes:has(> :nth-child(6):last-child)  { --cols: 3; }   /* 6개  → 3+3    */
  .tpl-boxes:has(> :nth-child(7):last-child)  { --cols: 4; }   /* 7개  → 4+3    */
  .tpl-boxes:has(> :nth-child(8):last-child)  { --cols: 4; }   /* 8개  → 4×2    */
  .tpl-boxes:has(> :nth-child(9):last-child)  { --cols: 3; }   /* 9개  → 3×3    */
  .tpl-boxes:has(> :nth-child(10):last-child) { --cols: 2; }   /* 10개 → 쌍 5행 */

  /* (요청 2026-07-13) ★ 글 박스 특별 규칙 - 본문 폭을 좌우 10 씩 더 좁힌다 (인셋 20 → 30).
     훅은 마크업에 이미 있는 의미 구분을 쓴다:
       <div class="tpl-box">     = 값 타일 (수술시간 · 마취방법 …) - 짧은 값이라 인셋 20 그대로
       <article class="tpl-box"> = 글 박스 (특징 · 만족도 · POINT · 특별함) - 문장이 들어간다
     문장이 박스 폭 끝까지 붙으면 줄 끝을 눈이 못 따라간다 → 글 박스만 읽기 폭을 좁힌다.
     인셋 토큰만 덮으므로 글자 체계(18/400)는 다른 박스와 그대로 공유된다. */
  .tpl-boxes:has(> article.tpl-box) { --box-text-inset: var(--sp-5); }   /* 20 → 30 */
  /* 박스 내부 기본값(--box-gap-sm/md · --box-pad-top/bottom · --box-text-inset ·
     --box-title-fs · --fs-fine)은 전부 main.css :root 에 있다 → 여기서 만들지 않는다.
     이 파일에는 "main 기본값과 다른 것"만 둔다(아래 소개 박스 delta). */

  /* 3구획 전부 "고정 높이" → 본문이 길든 짧든 아이콘·제목·본문의 시작 위치가 절대 안 움직인다.
     본문 행은 "본문 2줄"을 기준으로 잡는다 → 박스 높이가 전부 같아진다.
     (2줄을 넘는 내용은 행이 늘어나되, 그건 글이 규칙을 어긴 것이다 - 2줄 이내로 쓸 것) */
  .tpl-box { display: grid;
    grid-template-rows: var(--tpl-row-icon) var(--tpl-row-title) minmax(var(--tpl-row-text), auto);
    row-gap: 0; justify-items: center; text-align: center;
    /* (요청) 배경 = 은은한 회색(--bg-soft), 외곽선 제거
       (요청) R 값은 옆 이미지와 동일하게 --r-lg(20) - 카드 기본값 */
    background: var(--bg-soft); border: 0; border-radius: var(--r-lg);
    padding: var(--box-pad-top) var(--sp-4) var(--box-pad-bottom);
    /* 구획 높이 - 이 3구획 그리드는 특징 박스만의 구조라 여기서 계산한다.
       제목 행은 "제목 + 위 여백"까지 품는다(그래야 3구획 위치가 계속 고정). */
    --tpl-row-icon:  clamp(40px, 3.1vw, 60px);
    /* 제목 행 = 2줄 고정. 영문 제목은 길어 2줄로 넘어가는 경우가 많다 → 1줄로 잡으면 카드마다
       제목 줄 수가 달라 본문 윗줄이 어긋난다(요청 2026-07). 2줄로 고정하고 제목을 위쪽 정렬하면
       붉은 제목·본문 모두 카드 전체에서 윗줄이 맞는다. */
    --tpl-row-title: calc(var(--fs-content-title) * 1.4 * 2 + var(--box-gap-sm));
    /* 본문 행 = [제목과의 여백] + [본문 2줄]. 이 값이 박스 높이를 결정한다 */
    --tpl-row-text:  calc(var(--box-gap-md) + var(--fs-content-body) * 1.6 * 2); }

  /* 1구획 - 아이콘 */
  .tpl-box__icon { display: grid; place-items: center;
    font-size: calc(var(--fs-content-title) * 1.2); color: var(--point); line-height: 1; }
  /* 이미지 아이콘(로고·마크)은 행 높이에 딱 맞춘다 (2026-07-17, about 인증 로고).
     max-height:100% 는 HTML width/height 속성이 준 고유 크기를 못 눌러 행을 넘쳐
     아래 제목·본문 위로 겹쳤다 → 행과 같은 값(--tpl-row-icon)으로 높이를 고정한다. */
  .tpl-box__icon img { height: var(--tpl-row-icon); max-width: 100%; width: auto;
    object-fit: contain; }
  /* 2구획 - 제목 : 아이콘과 "가깝게"(sm) */
  /* 박스 제목은 h3 가 기본이지만, 그룹(.tpl-group)으로 묶이면 그룹 제목이 h3 가 되고
     박스 제목은 h4 로 한 단계 내려간다(h 계층 유지). 스타일은 한 벌을 공유한다. */
  .tpl-box :is(h3, h4) { align-self: start; margin-top: var(--box-gap-sm);
    font-size: var(--fs-content-title); font-weight: 600; color: var(--point);
    line-height: 1.35; letter-spacing: -.01em; }
  /* 3구획 - 텍스트 : 제목과는 그보다 "조금 더"(md)
     (요청) 본문만 좌우를 더 들여쓴다 - 글자가 박스 외곽선에 붙지 않게.
     아이콘·제목은 그대로 두고 본문에만 --box-text-inset 를 더한다
     (박스 좌우 패딩 20 + 인셋 20 = 본문 기준 40) */
  /* (요청 2026-07-13) 박스 본문 20 -> 18(--box-text-fs). 제목 24 와의 차가 벌어져 위계가 또렷해진다.
     전 박스(수술정보 · 특징 · 소개)가 이 한 줄을 공유한다. */
  /* 박스 본문 글자 체계 = 전 박스 공유 (수술정보 · 특징 · 소개).
     크기 18(--box-text-fs) / 굵기 400 / 행간 1.6 / 색 --ink 를 여기 한 곳에서만 정한다.
     배치(정렬 · 여백)는 각 박스가 자기 규칙에서 덮는다. */
  /* 제목에 딸린 서브 본문 = --fs-content-subtext (16 -> 14 / 400 / 1.6 / 자간 0).
     ★ 자간만 body(-.01em) 를 되돌린다 - 작은 글씨는 조이면 뭉쳐 읽힌다. */
  .tpl-box p, .tpl-intro__item p {
    font-size: var(--fs-content-subtext); font-weight: 400; line-height: var(--lh-body);
    letter-spacing: normal; color: var(--ink); }
  .tpl-box p { align-self: start; margin-top: var(--box-gap-md);
    padding-inline: var(--box-text-inset); }
  /* (요청) 보조 문구 - 괄호를 쓰지 않는다. 대신 폰트 2단계 축소 + 연한 색으로 위계를 만든다 */
  .tpl-box__opt { display: block; margin-top: var(--sp-1);
    font-size: var(--fs-eyebrow); color: var(--gray-dark); line-height: var(--lh-tight); }
  /* 박스에 번호(01·02…)는 달지 않는다 - 순서가 의미 없는 나열이라 장식일 뿐이다.
     순서가 의미 있는 곳(소개 카드 · 시술 과정)에서만 번호를 쓴다. */

  /* ── 모바일 배치 규칙 (요청)
     ⚠️ .tpl-boxes 는 grid 가 아니라 flex 다(위 참조). 열 수는 자식의 flex-basis 가 정한다.
        그래서 여기서도 grid-template-columns 가 아니라 flex-basis 를 덮어야 한다.
        (예전 규칙이 grid-template-columns 였고 그래서 모바일 배치가 통째로 죽어 있었다 -
         PC 의 4·5열이 그대로 유지돼 카드가 뭉개졌다.)
     열 수를 정하는 --cols 는 HTML 인라인 style 이라 CSS 로 덮을 수 없다 → flex-basis 를 직접 쓴다.

       ① 박스는 한 줄에 최대 2개
       ② 사진이 있는 박스(.tpl-box--photo)는 사진이 작아지면 못 읽는다 → 1개
       ③ 글이 많은 박스(PC 에서 2열로 세운 = 설명형)도 1개
     ★ 배치는 여기서만 정한다. 페이지가 제 값을 갖지 않는다. */
  @media (max-width: 991.98px) {
    /* ① 한 줄에 2개 */
    .tpl-boxes > * { flex-basis: calc((100% - var(--box-gap)) / 2); }
    /* ② 사진 박스 · ③ 설명형(2열) 은 1개 */
    .tpl-boxes:has(.tpl-box--photo) > *,
    .tpl-boxes[style*="--cols:2"] > *,
    .tpl-boxes[style*="--cols:1"] > * { flex-basis: 100%; }
    /* (요청 2026-07-13) 모바일 박스 상하 여백을 한 단계 줄인다.
       모바일은 박스가 한 줄에 1~2개라 세로로 길게 쌓인다. PC 여백(상 50 / 하 50, 사진↔제목 40)을
       그대로 두면 카드마다 빈 띠가 생겨 스크롤만 길어진다.
       ★ 값을 토큰에서 덮으므로 규칙이 여기 한 곳에 있다 - 박스 종류(아이콘 · 사진 · 설명형)와
         제목 행 높이(--tpl-row-title 은 --box-gap-photo 에서 파생)가 전부 따라온다. */
    .tpl-box { --box-pad-top: var(--sp-5); --box-pad-bottom: var(--sp-5);    /* 31.7 → 19 */
      --box-gap-md: var(--sp-4); }                                          /* 제목↔본문 19 → 14 */
    .tpl-box--photo { --box-gap-photo: var(--sp-5); }                        /* 사진↔제목 25 → 19 */
  }
  @media (max-width: 575.98px) {
    .tpl-boxes > * { flex-basis: 100%; }
    /* (요청 2026-07-14) 5개짜리 값 타일은 좁은 화면에서도 **한 줄에 2개**를 유지한다.
       (짧은 값이라 1개씩 쌓으면 스크롤만 길어진다. 5개 = 2+2+1, 마지막 칸은 가운데)
       (요청 2026-07-17) 6개짜리 로고 타일(about 인증·협력병원)도 같은 이유로 2개씩.
       ★ (영문판 2026-07-23) 예전엔 이 줄을 [style*="--cols:6"] 로 집었다. PC 가 6열에서
         3열 2줄로 바뀌면서 그 셀렉터가 헛돌아 모바일이 1열로 떨어졌다.
         "자식이 6개" 로 집으면 본문이 긴 6개짜리 카드(forehead-lift·svf-hair 등 5곳)까지
         2열로 끌려 들어간다 → 그 블록만 갖는 인라인 토큰(--box-gap-sm)으로 집는다. */
    .tpl-boxes:has(> :nth-child(5):last-child) > *,
    .tpl-boxes[style*="--box-gap-sm"] > * {
      flex-basis: calc((100% - var(--box-gap)) / 2); }
  }

  /* ══════════════════════════════════════════════ 1) 소개 - 좌 sticky 이미지 + 우 번호 리스트 */
  .tpl-intro { display: grid; grid-template-columns: var(--split-cols);
    column-gap: var(--tpl-col-gap); align-items: start; justify-content: center; }
  /* 좌측 블록을 sticky 로 두면 스크롤 끝에서 블록 하단(=CTA 끝선)이 마지막 박스와 정렬된다 */
  .tpl-intro__aside { position: sticky; top: var(--sp-6); align-self: start; }
  /* 사진은 1:1 로 자른다 (2026-07-14 요청). 원본 비율을 그대로 쓰면 세로컷이 리스트만큼
     길어져 sticky 가 붙잡을 여백이 없다 - 높이를 줄여야 실제로 따라 붙는다. */
  .tpl-intro__aside img { width: 100%; display: block; border-radius: var(--r-lg);
    aspect-ratio: var(--ratio-square); object-fit: cover; }
  /* ── 예외 : 글자가 박힌 도해 (.tpl-intro--fit) ─────────────────────────────
     (요청 2026-07-14, svf-hair) 1:1 cover 슬롯은 가로 도해의 **좌우를 잘라** 라벨을 지워 버린다.
     → 원본 비율 그대로 둔다. **폭은 그대로(칸을 꽉 채움)이고 높이가 줄어든다** = 이미지가 작아진다.
     .tpl-boxes--fit(02) 과 같은 취지의 modifier 다. */
  .tpl-intro--fit .tpl-intro__aside img { aspect-ratio: auto; object-fit: contain; }
  /* CTA: 이미지 폭을 꽉 채우지 않고 안쪽으로 살짝 들어오게(=이미지보다 작게),
     색도 먹색이 아니라 포인트 컬러로 눌러 이미지가 주인공이 되게 한다. */
  /* CTA 의 "모양"(테두리 pill · 색 · 여백 · hover)은 main.css 의 .cta 가 정의한다.
     index 상담폼의 .btn--cta 도 같은 것이어서 삭제하고 여기로 통합했다 → 여기서 중복 선언하지 않는다.
     소개 섹션의 "배치 델타"만 둔다: 이미지 아래 가운데, 이미지보다 살짝 좁게. */
  /* ★ 이 델타는 "소개 섹션의 이미지 아래 CTA" 전용이다.
     예전에는 셀렉터가 그냥 .cta 여서 전역 CTA 에 margin(위 40 · 좌우 auto)이 붙었고,
       · 상담폼 CTA 가 동의 문구에서 40px 밀려났고
       · 토글 줄(flex)에서는 좌우 auto 마진이 남는 공간을 먹어 gap 20 이 116 으로 벌어졌다.
     → 소개 섹션 안으로 스코프를 좁힌다. */
  .tpl-intro__aside .cta { display: flex; width: fit-content; max-width: 84%;
    margin: var(--sp-6) auto 0; }
  /* (요청 2026-07-13) 소개 섹션의 "좁은 사진" 변형 - CTA 없이 사진만 sticky 로 붙는 경우.
     원본이 세로로 긴 장식 컷(예: 세포 이미지 448×788)이면 사진 칸이 섹션을 지배한다.
     → ① 사진 칸을 좁혀 카드 폭을 더 준다(48:70 → 32:86)
       ② 사진은 위아래를 잘라(cover) 세로 컷 비율(--ratio-portrait)로 높이를 줄인다.
     텍스트가 들어 있는 도해에는 쓰지 않는다(잘리면 정보가 사라진다 → .tpl-boxes--fit 쪽을 쓴다). */
  .tpl-intro--slim { --split-cols: minmax(0, 32fr) minmax(0, 86fr); }
  .tpl-intro--slim .tpl-intro__aside img { aspect-ratio: var(--ratio-portrait); object-fit: cover; }
  /* ── 데코 테두리 (요청 2026-07-17, svf-lab 지정서) ────────────────────────────
     "병원이 가장 어필하고 싶은" 사진에 붉은 테두리를 비껴 깔아 시선을 잡는다.
     ★ 장치를 새로 만들지 않는다 - .tpl-about__deco(02 블록)를 그대로 가져다 쓴다.
       여기서 하는 일은 데코가 설 "자리"를 aside 안에 만드는 것뿐이다.
       처방은 .tpl-about__media 와 같다 : 데코를 박스 밖으로 내보내면 그려지지 않는다
       → aside 가 우·하로 --about-deco 만큼 패딩을 갖고, 사진은 그 안쪽에 선다.
     ★ aside 는 이미 position: sticky 라 absolute 데코의 기준 박스가 된다(모바일은 아래 참고). */
  .tpl-intro__aside:has(.tpl-about__deco) {
    padding: 0 var(--about-deco) var(--about-deco) 0; }
  /* z-index 1 : 사진이 데코 "위"에 선다 (데코를 z-index:-1 로 뒤로 보내지 않는다 - 02 주석 참고) */
  .tpl-intro__aside:has(.tpl-about__deco) > img { position: relative; z-index: 1; }
  /* (요청) 우측 박스 사이 간격 35px 고정 = --box-gap */
  .tpl-intro__list { display: grid; gap: var(--box-gap); }
  /* 소개 카드는 [번호 | 제목+본문] 가로 구성이지만, 세로 여백 비례(상 3 : 하 5)는 박스와 공유 */
  .tpl-intro__item { display: grid; grid-template-columns: auto minmax(0, 1fr);
    column-gap: var(--sp-5); align-items: start; text-align: left;
    /* (요청) 배경 = 은은한 회색(--bg-soft), 외곽선 제거
       (요청) R 값은 옆 이미지와 동일하게 --r-lg(20) - 카드 기본값 */
    background: var(--bg-soft); border: 0; border-radius: var(--r-lg);
    padding: var(--box-pad-top) var(--sp-6) var(--box-pad-bottom);
    /* ★ main 기본값과 다른 것만 여기서 덮는다 (의도된 delta - 다른 박스에는 적용하지 않는다)
         제목 ↔ 본문 : 30 → 15  한 덩어리로 읽히게 바짝 붙인다
         상하 패딩   : 30:50 → 28:35  박스 높이를 내용에 맡기고 여백을 줄인다
       모두 --sp-5(30) 에서 파생한다(임의 px 아님). 글자 체계는 main 기본값 그대로. */
    --box-gap-md:     var(--sp-3);                          /* 30 → 15 */
    --box-pad-top:    calc(var(--sp-5) * 14 / 15);          /* 30 → 28 */
    --box-pad-bottom: calc(var(--box-pad-top) * 5 / 4); }   /* 50 → 35 */
  .tpl-num { font-size: var(--fs-content-title); font-weight: 700; line-height: var(--lh-title); color: var(--point);
    font-variant-numeric: tabular-nums; }
  .tpl-intro__item h3 { font-size: var(--fs-content-title); font-weight: 600; color: var(--point); line-height: var(--lh-title); }
  .tpl-intro__item h3 strong { color: inherit; font-weight: inherit; }
  /* 제목 ↔ 본문은 박스와 동일하게 md (조금 더 벌린다)
     (요청) 가로로 긴 박스는 본문이 우측 끝까지 붙으면 읽기 힘들다 → 우측 여백을 더 준다.
     (요청) 80 → 30% 축소(56) → 다시 15 축소 = 40(--sp-6).  박스 우측 패딩(40) + 40 = 총 80
     ※ 글자 체계(크기 18 / 굵기 400 / 행간 / 색)는 위 .tpl-box p 와 "한 셀렉터로 공유"한다
       → 아래에서는 이 박스에만 필요한 여백(margin-top · padding-right)만 덮는다. */
  .tpl-intro__item p { margin-top: var(--box-gap-md); padding-right: var(--sp-6); }
  @media (max-width: 991.98px) { .tpl-intro__item p { padding-right: 0; } }

  @media (max-width: 991.98px) {
    .tpl-intro { grid-template-columns: minmax(0, 1fr); row-gap: var(--sp-6); }
    .tpl-intro__aside { position: static; }
    /* 데코가 있으면 기준 박스는 남겨야 한다 - sticky 만 풀고 relative 로 내린다.
       static 이 되면 데코가 조상(.tpl-sec)을 기준으로 잡아 섹션 전체에 붉은 테두리가 그려진다.
       자리(패딩)는 반납한다 - 데코도 inset:0 으로 사진에 겹쳐진다(.tpl-about__deco 모바일과 동일). */
    .tpl-intro__aside:has(.tpl-about__deco) { position: relative; padding: 0; }
    /* ★ 모바일에선 사진을 가로로 눕혀 크롭한다 (2026-07-14 요청).
       aside 는 원본 비율을 그대로 쓰므로, 세로컷이 오면 한 화면을 통째로 먹는다. */
    .tpl-intro__aside img {
      aspect-ratio: var(--ratio-photo-m); object-fit: cover; }
    /* 도해는 여기서도 자르지 않는다 - 잘리면 라벨이 사라진다 */
    .tpl-intro--fit .tpl-intro__aside img { aspect-ratio: auto; object-fit: contain; }
  }

  /* ══════════════════════════════════════════════ 2) 수술 정보 - 좌 이미지 + 우 박스 6개
     이미지 높이는 "박스 전체 높이"가 정한다. img 를 absolute 로 띄워 이미지가 행 높이에
     끼어들지 못하게 하고, 정해진 높이를 cover 로 채운다 → 상·하단이 정확히 맞는다. */
  .tpl-info { display: grid; grid-template-columns: var(--split-cols);
    column-gap: var(--tpl-col-gap); align-items: stretch; justify-content: center; }
  .tpl-info__img { position: relative; border-radius: var(--r-lg); overflow: hidden; }
  .tpl-info__img img { position: absolute; inset: 0; display: block;
    width: 100%; height: 100%; object-fit: cover; object-position: center; }

  @media (max-width: 991.98px) {
    .tpl-info { grid-template-columns: minmax(0, 1fr); row-gap: var(--sp-6); }
    /* 1열로 쌓이면 기준이 될 박스 높이가 없으므로 이미지는 원본 비율로 되돌린다 */
    .tpl-info__img { position: static; }
    .tpl-info__img img { position: static; height: auto; }
  }

  /* ══════════════════════════════════════════════ 5) 이런 경우 - 이미지 + 체크 리스트
     체크는 "한 줄짜리 항목"이라 3구획을 적용하지 않는다.
     이미지 높이는 우측 체크 리스트 전체 높이가 정한다(수술 정보와 같은 원칙). */
  .tpl-check { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
    column-gap: var(--tpl-col-gap); align-items: stretch; }
  .tpl-check__img { position: relative; border-radius: var(--r-lg); overflow: hidden; }
  .tpl-check__img img { position: absolute; inset: 0; display: block;
    width: 100%; height: 100%; object-fit: cover; object-position: center; }
  /* (요청) 세로로 이어지는 흐름 → --flow-gap (30) */
  .tpl-check__list { display: grid; gap: var(--flow-gap); }
  /* ★★ (요청) "1줄짜리 가로 박스" 셸 - 체크리스트(4)와 시술 과정(5)은 같은 박스다.
     크기 · 배경 · R · 간격을 여기 한 벌로만 정의한다. 각자 따로 두면 한쪽만 고치게 된다.
       박스 좌우 ↔ 아이콘  : --sp-6 (40)   ← padding-inline
       아이콘 ↔ 제목        : --sp-5 (30)   ← gap
       제목   ↔ 구분선      : --sp-5 (30)   ← gap
       구분선 ↔ 본문        : --sp-5 (30)   ← .tpl-process__desc padding-left
     배경 = --bg-soft(연한 회색) · R = --r-lg(20) 전역 통일값 */
  .tpl-check__list li, .tpl-process__step {
    display: flex; align-items: center; gap: var(--sp-5);
    border-radius: var(--r-lg); padding: var(--sp-5) var(--sp-6);
    background: var(--bg-soft); }

  /* 아이콘 자리는 두 박스가 같은 크기를 쓴다 - 이 칸이 박스 높이를 정하므로 어긋나면 안 된다.
     칸 크기만 공유하고, 안을 어떻게 채우는지는 각자 다르다(아래) */
  .tpl-check__ico, .tpl-process__ico { flex: 0 0 auto;
    width: clamp(20px, 1.667vw, 32px); height: clamp(20px, 1.667vw, 32px);
    display: grid; place-items: center; color: var(--point); }
  /* 체크리스트 - 연한 분홍 원 + 얇은 링 안에 체크 */
  .tpl-check__ico { border-radius: 50%; background: var(--point-bg); font-size: var(--fs-content-body);
    box-shadow: inset 0 0 0 var(--hairline) color-mix(in srgb, var(--point) 35%, var(--white)); }
  /* (요청) 시술 과정 - 원(배경·테두리) 없이 글리프만. 대신 글리프를 키운다.
     칸 크기는 그대로라 박스 높이는 체크리스트와 계속 같다 */
  .tpl-process__ico { background: none; box-shadow: none; font-size: var(--fs-content-title); }
  /* ★ (요청 2026-07-14) 사진(.tpl-check__img) 없이 리스트만 쓰는 경우 - 항목이 컨테이너 전폭으로
     늘어나 한 줄이 지나치게 길고 오른쪽이 텅 빈다. 원래 이 리스트는 5:6 격자의 오른쪽 칸(6)에
     들어가도록 설계된 것이다.
     → 사진 없이 단독으로 쓸 땐 2열 카드 격자로 접고, 항목을 [제목 + 설명] 두 단으로 세운다.
       .tpl-check(사진 + 리스트 2단) 안에서는 종전대로 1열을 유지한다. */
  .tpl-check__list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .tpl-check .tpl-check__list { grid-template-columns: minmax(0, 1fr); }
  /* 카드가 되면 [체크 아이콘 | 제목 + 설명] 두 단이다 → 아이콘을 제목 줄에 맞춰 위로 올린다 */
  .tpl-check__list li { align-items: start; }
  .tpl-check__list h3 + p { margin-top: var(--box-gap-md); }
  /* (요청 2026-08-01, svf-skin-inner) 추천 대상을 Inner · Premium 두 그룹으로 좌우 분리한다.
     ★ 두 그룹이 같은 행(row)을 공유하도록 subgrid 를 쓴다 - 같은 줄의 좌·우 카드가 높이가 같고,
       제목 높이(2줄 예약)로 본문 시작선까지 맞는다. (라벨 1행 + 카드 3행) */
  .inner-target { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-template-rows: auto repeat(3, auto); gap: var(--flow-gap) var(--box-gap); }
  .inner-target__group { display: grid; grid-row: 1 / -1; grid-template-rows: subgrid; }
  /* ul 을 없는 셈 치고 그 안의 카드(li)를 그룹 subgrid 의 행에 직접 태운다 */
  .inner-target__group .tpl-check__list { display: contents; }
  .inner-target__label { text-align: center; margin: 0;
    font-size: var(--fs-content-title); font-weight: 600; color: var(--point); letter-spacing: -.01em; }
  /* 카드 제목을 2줄로 예약 - 좌·우 카드의 제목 높이와 본문 시작선을 맞춘다(라벨 h3 는 제외) */
  .inner-target .tpl-check__list h3 { min-height: calc(var(--fs-content-title) * 1.35 * 2); }

  @media (max-width: 991.98px) {
    .tpl-check { grid-template-columns: minmax(0, 1fr); row-gap: var(--sp-6); }
    .tpl-check__img { position: static; }
    .tpl-check__img img { position: static; height: auto; }
    /* 모바일 : subgrid 를 풀고 그룹을 세로로 쌓는다(Inner 그룹 → Premium 그룹) */
    .inner-target { grid-template-columns: minmax(0, 1fr); grid-template-rows: none; row-gap: var(--sp-7); }
    .inner-target__group { grid-row: auto; grid-template-rows: none; gap: var(--flow-gap); }
    .inner-target__group .tpl-check__list { display: grid; gap: var(--flow-gap); }
    .inner-target .tpl-check__list h3 { min-height: 0; }
  }
  /* 좁은 화면에선 2열이 오히려 갑갑하다 → 1열로 되돌린다 */
  @media (max-width: 767.98px) {
    .tpl-check__list { grid-template-columns: minmax(0, 1fr); }
  }

  /* ══════════════════════════════════════════════ 5) 시술 과정 - 스텝 + 이미지
     스텝 4개까지는 이미지와 나란히(1:1, 이미지 높이 = 스텝 전체 높이).
     스텝이 4개를 넘어가면 리스트가 이미지보다 훨씬 길어지므로 소개 섹션과 같은
     sticky 방식(.tpl-process--sticky)으로 전환한다 → 이미지 고정 + 스텝만 흐른다. */
  .tpl-process { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    column-gap: var(--tpl-col-gap); align-items: stretch; }
  /* (요청) 세로로 이어지는 흐름 → --flow-gap (30). sticky 변형도 같은 값이라 따로 안 덮는다 */
  .tpl-process__steps { display: flex; flex-direction: column; gap: var(--flow-gap); }

  /* ── 예외 : 이미지를 자르지 않는 변형 (.tpl-process--fit) ───────────────────
     (요청 2026-07-17, facelift-deep-plane) 기본형은 1:1 균등 칸에 이미지를 cover 로
     늘여 채운다 → 원본이 작거나 가로세로가 다르면 크게 잘린다.
     → 열은 sticky 변형과 같은 좌 48 : 우 70(--split-cols)으로 좁히고,
       이미지는 원본 비율 그대로 전부 보여준다(자르지 않는다).
     .tpl-intro--fit(21) · .tpl-boxes--fit(02) 과 같은 취지의 modifier 다. */
  .tpl-process--fit { grid-template-columns: var(--split-cols); align-items: start; }
  .tpl-process--fit .tpl-process__img { position: static; aspect-ratio: auto; }
  .tpl-process--fit .tpl-process__img img {
    position: static; width: 100%; height: auto; object-fit: contain; }

  /* ── sticky 변형 (스텝 5개 이상) : 소개 섹션과 동일한 좌 48 : 우 70 + 좌측 고정 ── */
  .tpl-process--sticky { grid-template-columns: var(--split-cols);
    align-items: start; justify-content: center; }
  /* 스텝은 자연 높이로. (늘어나면 리스트가 이미지 높이에 맞춰 커지고
     → 스크롤 여지가 없어 sticky 가 발동하지 않는다)
     padding 은 덮지 않는다 - 박스 크기는 체크리스트와 같은 한 벌을 그대로 쓴다 */
  .tpl-process--sticky .tpl-process__step { flex: 0 0 auto; }
  /* 좌측 이미지가 sticky. 리스트가 이미지보다 길어야 이미지가 고정된 채 스텝만 흐른다.
     소개 섹션과 같은 원리 - 끝까지 스크롤하면 이미지 하단이 마지막 스텝과 정렬된다. */
  /* 이미지는 스텝 리스트보다 "짧아야" 고정될 여지가 생긴다(길면 같이 밀린다).
     스텝이 늘수록 리스트가 길어지므로 sticky 효과도 그만큼 커진다. */
  .tpl-process--sticky .tpl-process__img { order: -1;
    position: sticky; top: var(--sp-6); align-self: start;
    height: auto; aspect-ratio: var(--ratio-square); max-height: 72vh; }
  .tpl-process--sticky .tpl-process__img img { position: absolute; inset: 0; height: 100%; }
  /* 박스 셸(크기·배경·R·간격)은 체크리스트와 공유한다 → 위 "1줄짜리 가로 박스" 참조.
     여기서는 시술 과정에만 있는 요소(제목 · 구분선 · 본문)만 정의한다.
     (요청) 번호(01·02…) 삭제 · 자연 배출(활성 스텝) 강조 제거 - 전 스텝이 같은 회색 */
  /* 제목 폭을 고정한다 - 라벨 길이가 제각각이면(시술 전 · 마취 · SVF 도포)
     구분선이 스텝마다 다른 위치에 서서 세로로 안 맞는다
     ★ (영문판 2026-07-23) 6em → 13em. 한글 라벨은 6em 안에 들어갔지만 영문은 그 두 배다
       (최장 "Anatomical understanding" 24자, 사이트 전체 127개 중 다수가 12자 초과).
       nowrap 이라 넘친 만큼 칸이 제 폭을 넘어서고, 그 결과 구분선이 행마다 다른 자리에 섰다
       (사용자 검수: STEP 1·2·3 의 세로선이 어긋남). 최장 라벨이 들어가는 폭으로 올린다. */
  .tpl-process__label { flex: 0 0 13em;
    font-size: var(--fs-content-body); font-weight: 600; color: var(--point); white-space: nowrap; }
  .tpl-process__desc { flex: 1; min-width: 0;
    font-size: var(--fs-content-subtext); font-weight: 400; line-height: var(--lh-body); color: var(--ink);
    border-left: var(--hairline) solid var(--gray-light); padding-left: var(--sp-5); }
  /* 이미지 높이는 스텝 전체 높이에 맞춘다(수술 정보와 같은 원칙) */
  .tpl-process__img { position: relative; border-radius: var(--r-lg); overflow: hidden; }
  .tpl-process__img img { position: absolute; inset: 0; display: block;
    width: 100%; height: 100%; object-fit: cover; }

  /* (요청 2026-07-14) 모바일 사진 높이 - 4:5 세로컷은 1열이 되면 화면을 세로로 크게 먹는다
     (실측 340×425 @390). → 4:3 으로 눕혀 조금 납작하게. 사진만 있는 박스(.tpl-box--photo)와
     같은 기준(--ratio-photo)을 쓴다 - 모바일에서 사진이 눕는 규격은 하나로 통일한다. */
  @media (max-width: 991.98px) {
    .tpl-process, .tpl-process--sticky { grid-template-columns: minmax(0, 1fr); row-gap: var(--sp-6); }
    .tpl-process__img, .tpl-process--sticky .tpl-process__img { position: static; aspect-ratio: auto; }
    .tpl-process__img img, .tpl-process--sticky .tpl-process__img img {
      position: static; height: auto; aspect-ratio: var(--ratio-photo); }
  }

  /* ★ (요청 2026-07-14) 모바일 스텝 - 좌우를 3:7 로 고정한다.
     [아이콘][라벨][본문] 을 한 줄로 늘어놓으면 라벨(6em)이 폭을 먹어 본문이 한 줄에 서너 글자만
     들어간다. → 좌측을 [아이콘 ⏎ 라벨] 세로 2단으로 접는다.
     ★ 좌열을 auto 로 두면 라벨 글자 수에 따라 칸이 55~90px 로 들쭉날쭉해지고("노화 관리" vs
       "탄력·주름 관리"), 스텝마다 본문 시작선이 어긋난다.
       → 3fr : 7fr 로 못박아 좌우 영역을 확실히 분리한다. 어느 스텝이든 본문이 같은 선에서 시작한다. */
  @media (max-width: 767.98px) {
    .tpl-process__step {
      display: grid;
      /* ⚠️ minmax(0, …) 가 없으면 fr 은 min-content 아래로 못 내려간다.
         라벨이 긴 스텝("SVF 시술 전후")에서 좌열이 3fr(83) 을 넘어 86 까지 밀려,
         스텝마다 본문 시작선이 147/150/148 로 어긋났다 → 0 을 하한으로 못박아 비율을 강제한다.
         라벨은 필요하면 줄을 바꾼다. */
      grid-template-columns: minmax(0, 3fr) minmax(0, 7fr);
      /* (요청 2026-07-14) 아이콘 ↔ 라벨 간격 10 → 5. 둘은 한 덩어리로 읽혀야 한다.
         세로는 좌우 모두 중앙 - align-content 로 두 행 묶음 자체를 스텝 높이 중앙에 세우고,
         align-items 로 각 칸의 내용도 중앙에 둔다. */
      column-gap: var(--sp-4); row-gap: var(--sp-1);
      align-items: center; align-content: center; }
    /* ⚠️ 본문(desc)이 두 행을 걸치므로 그 높이가 두 행으로 나뉘어 들어간다.
       아이콘·라벨을 각 행의 start 에 두면 서로 멀찍이 떨어지고 위로 쏠린다.
       → 아이콘은 1행 **끝**, 라벨은 2행 **처음**에 붙인다. 둘이 행 경계에서 만나
         row-gap(5)만큼만 떨어진다. */
    .tpl-process__ico   { grid-area: 1 / 1; justify-self: center; align-self: end; }
    .tpl-process__label { grid-area: 2 / 1; flex: none; justify-self: center; align-self: start;
      /* the desktop rule pins white-space:nowrap for the 13em column; on the narrow mobile column
         that makes long labels ("Anatomical understanding", "Session duration") spill out — let
         them wrap by word instead. (2026-08-03) */
      white-space: normal; word-break: keep-all; overflow-wrap: break-word;
      text-align: center; }
    /* 본문은 좌측 2단 전체 높이를 타고 내려간다 → 구분선이 스텝 높이만큼 이어진다.
       글이 짧아 두 행보다 낮을 땐 세로 중앙에 선다(좌측 묶음과 눈높이가 맞는다). */
    .tpl-process__desc  { grid-area: 1 / 2 / 3 / 3; align-self: center; }
  }

  /* ══════════════════════════════════════════════ 순환 캐러셀 (공통 컴포넌트)
     후기 · B&A 가 이 하나를 같이 쓴다.
     좌에서 우로 흐르다 끝나지 않고 순환한다(첫 장 ← 이전 → 마지막 장). 이동은 page-template.js.
     양옆 마스크로 다음/이전 장이 살짝 비쳐 "더 있다"는 게 읽히게 한다. */
  .tpl-carousel { display: flex; align-items: center; justify-content: center;
    gap: var(--sp-4); max-width: clamp(806px, 67.708vw, 1300px); margin-inline: auto; }
  /* 현재 사진은 좌·우 어느 쪽으로 넘겨도 "항상 화면 중앙"에 온다.
     좌우 패딩을 (트랙 폭 - 슬라이드 폭)/2 로 주면 첫 장·마지막 장도 중앙까지 올라온다.
     여기에 scroll-snap-align:center 가 붙어 스냅 지점이 곧 중앙이 된다. */
  /* (요청) 좌우 페이드(mask-image 그라디언트) 삭제 - 사진이 가장자리에서 흐려지지 않는다 */
  .tpl-carousel__track { flex: 1 1 0; min-width: 0; display: flex;
    overflow-x: auto; scrollbar-width: none; scroll-snap-type: x mandatory;
    cursor: grab; padding-block: var(--sp-3);
    padding-inline: calc((100% - var(--slide-w)) / 2); }
  .tpl-carousel__track::-webkit-scrollbar { display: none; }
  .tpl-carousel__track > * { scroll-snap-align: center; flex: 0 0 auto; width: var(--slide-w); }
  /* 화살표 버튼(.tpl-carousel__nav)의 크기·모양·색은 main.css 의 .shorts__nav / .reviews__nav 와
     한 몸이다 → 전부 거기서 정의한다(규칙 6). 여기서 덮을 것이 없다. */

  /* ── 6) 실제 후기 사진 : 카드 = 한 사람(전 · 후 · 전 · 후 4장) ──
     (요청) 캐러셀·화살표 없음 - 4장이 .container 안에 한 줄로 다 들어온다.
            사진 폭은 1fr 이므로 컨테이너가 좁아지면 4장이 함께 줄어든다(넘치지 않는다).
     (요청) 원본 비율 그대로 - aspect-ratio 를 강제하지 않고 object-fit 도 걸지 않는다.
            사진을 자르지 않으므로 4장의 세로 길이가 서로 다르면 아래가 들쭉날쭉해진다(위쪽 정렬).
     (요청) 사진 사이 간격 = --box-gap (35) - 박스 그리드와 같은 값
     (요청) 닉네임 캡션(.tpl-review__cap) 삭제 */
  /* 후기 컴포넌트(.tpl-review__*)는 main.css 로 승격했다 - index 도 똑같이 쓴다(규칙 6).
     → 여기서 중복 선언하지 않는다. */

  /* ── 9) 전후사진 : 의료법상 블러 + 로그인 안내 필수, 하단 경고 문구 필수 ── */
  /* 사진 사이 마진은 기준(--sp-4) 대비 -30% (후기보다 더 붙인다) */
  /* (요청) 옆 사진 미리보기(peek) 삭제 - 슬라이드가 트랙 폭을 꽉 채운다(--slide-w: 100%).
     그러면 .tpl-carousel__track 의 padding-inline 도 0 이 되어 좌우 여백이 사라진다.
     한 번에 한 장만 보이고, 넘김은 화살표(또는 드래그)로만. 순환(롤링)은 그대로 유지.
     (요청) 좌우 그라디언트도 삭제 → .tpl-carousel__track 에서 mask-image 를 뺐다 */
  /* (요청) 제목 ↔ 토글 간격만 줄인다. .tpl-head 의 112 는 전 섹션 공통이라 건드리지 않고,
  /* 헤드 ↔ 본문 거리는 --head-gap-body 토큰 하나가 정한다 - 이 섹션도 예외가 아니다. */
  /* (요청) 사진 크기 축소 - 캐러셀 폭을 0.9 배로 눌렀다(1300 → 1170).
     슬라이드가 트랙 폭 100% 라 캐러셀이 좁아지면 사진도 같이 줄고, 화살표도 안쪽으로 따라 들어온다. */
  .tpl-sec--bna .tpl-carousel { max-width: clamp(725px, 60.938vw, 1170px); }
  .tpl-bna__track { --slide-w: 100%; gap: 0; padding-block: 0; }
  /* padding-bottom(30) 은 옛 각도 탭이 사진 "아래에 걸쳐" 있던 자리였다.
     탭을 사진 위로 옮겼으므로 이제 빈 공간일 뿐 - 없앤다. */
  .tpl-bna__slide { padding-bottom: 0; }
  .tpl-bna__photo { position: relative; }

  /* (요청) 각도 토글 = CTA 템플릿(.cta) 그대로. 이미지 "위"에 한 줄, 중앙 정렬.
     토글 1개면 가운데 한 개, 3개면 서로 35px(--box-gap) 씩 벌어진다.
     .cta 에 박힌 margin(위 40 · 좌우 auto)은 이 줄 안에서 필요 없으므로 0 으로 되돌린다. */
  /* 토글의 모양 · 간격 · 활성색 · 하단 마진(50)은 전부 .section__toggle 공용 규칙이 정한다.
     → 여기 델타 없음. (구 margin-block 델타 삭제 - 섹션8 토글과 값이 갈렸었다) */
  .tpl-bna__frame { border-radius: var(--r-lg); overflow: hidden; }
  /* 한 사람(슬라이드) 안에 각도별 사진이 여러 장 겹쳐 있다. 선택된 각도 한 장만 보인다.
     SSR 원칙상 전부 HTML 에 있어야 하므로 지우지 않고 감춘다(규칙: JS 렌더 금지). */
  .tpl-bna__frame img { width: 100%; height: auto; display: none; object-fit: cover; }
  .tpl-bna__frame img.is-on { display: block; }
  /* 블러 + 로그인 안내: phpnew3 원본(lp-bna) 스펙 기준.
     (요청) 원본 크기로는 사진의 좌측·하단이 20px 씩 덜 덮였다 → 폭·높이에 20 씩 더한다.
     우측(left:50% + translateX(-100%))과 상단(top:17px)은 고정이라
     폭을 키우면 "왼쪽으로", 높이를 키우면 "아래로" 자란다 - 딱 맞던 두 변은 그대로 있다. */
  /* (요청) 라운드는 전역 카드값 --r-lg(20). 단 "왼쪽 두 모서리만" 둥글린다.
     블러의 오른쪽 변은 사진 정중앙(Before | After 분할선)이라 거기까지 둥글리면
     그 자리에 Before 사진이 삼각형으로 새어 나온다(의료법상 노출 금지).
     왼쪽 변·위아래 모서리는 사진 자체의 라운드 박스와 맞닿으므로 20 이 정확히 맞는다. */
  .tpl-bna__blur { position: absolute; z-index: 100; left: 50%; transform: translateX(-100%);
    top: var(--bna-blur-top);
    width:  calc(clamp(249px, 20.938vw, 402px) + 20px);
    height: calc(clamp(239px, 20.104vw, 386px) + 20px);
    border-radius: var(--r-lg) 0 0 var(--r-lg);
    /* (요청) 안내 문구 아래에 로그인 CTA - 세로로 쌓아 가운데 정렬 */
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: var(--sp-4);
    backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); }
  .tpl-bna__blur p { text-align: center; color: var(--white);
    font-size: var(--fs-content-body); line-height: 1.5; }
  /* (요청) 로그인은 CTA 템플릿(.cta)을 그대로 쓴다 - 새 버튼을 만들지 않는다.
     다만 블러(사진 위)라 포인트 컬러 테두리는 배경에 묻힌다 → 이 안에서만 흰색으로 반전한다.
     크기·여백·라운드는 .cta 그대로라 다른 CTA 와 어긋나지 않는다. */
  .tpl-bna__blur .cta { margin: 0; max-width: none;
    color: var(--white); box-shadow: inset 0 0 0 var(--hairline) var(--white); }
  /* (요청) 클릭 영역 = 블러 전체. 버튼만이 아니라 모자이크 어디를 눌러도 로그인으로 간다.
     링크에 투명 오버레이(::after)를 씌워 블러 박스를 통째로 덮는다 - 마크업은 그대로 둔다.
     블러가 이미 position:absolute 라 그 자체가 기준 박스가 된다.
     오버레이도 링크의 일부라, 블러 어디에 올려도 아래 :hover 가 함께 발동한다. */
  .tpl-bna__blur { cursor: pointer; }
  .tpl-bna__blur .cta::after { content: ""; position: absolute; inset: 0; }
  .tpl-bna__blur .cta:hover { background: var(--white); color: var(--ink); }
  /* (옛 .tpl-bna__login = 블러 하단에 꽉 찬 먹색 바. .cta 로 교체해 삭제했다) */
  /* (사진 아래 붙어 있던 각도 탭 .tpl-bna__tab 은 삭제 - 위 .tpl-bna__tabs 토글그룹으로 옮겼다) */
  /* 주의 문구(법적 고지) - 사진과 CTA 사이에 놓이는 "콘텐츠"다.
     섹션 골격상 CTA 간격의 주인은 .section__foot 이므로 여기서는 위 간격만 갖는다.
     (구 .tpl-bna__foot 래퍼 삭제 - CTA 를 .section__foot 으로 넘겼다)
     ★ --fs-caption 을 쓰는 곳은 여기 하나뿐이다(주의 문구 전용).
     본문·서브제목·캡션 등 다른 어디에도 caption 을 쓰지 않는다 → 최소 --fs-body. */
  .tpl-bna__note { margin-top: var(--sp-3); text-align: center;
    font-size: var(--fs-content-subtext); font-weight: 400; line-height: 1.5;
    color: var(--gray-dark); }

  @media (max-width: 991.98px) {
    .tpl-carousel { max-width: 100%; }
    /* 후기 사진 4장은 좁은 화면에서 2열로 접는다(1fr 로 계속 줄이면 너무 작아진다) */
    .tpl-review__imgs { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    /* 각도 토글이 3개면 한 줄에 다 못 들어온다 → flex-wrap 으로 접히고 간격만 줄인다 */
    .tpl-bna__tabs { gap: var(--sp-3); }
  }
  /* ══════════════════════════════════════ 1) 히어로 - 사진 없는 컬러 밴드
     사진이 있는 페이지는 main.css 의 .sub-hero 를 그대로 쓴다.
     보톡스 · 미니 지방흡입은 원본에 배너 사진이 없어 포인트 컬러 밴드로 대신한다.
     .sub-hero 가 position:relative + 절대배치 텍스트라, 여기서는 "높이"만 만들어 준다. */
  .sub-hero--plain { min-height: clamp(279px, 23.438vw, 450px); background: var(--point); }
  .sub-hero--plain .sub-hero__text,
  .sub-hero--plain .sub-hero__en,
  .sub-hero--plain :is(h1, h2),
  .sub-hero--plain :is(h1, h2) + p { color: var(--white); }
  @media (max-width: 991.98px) {
    .sub-hero--plain { min-height: clamp(202px, 23.438vw, 450px); }
  }

  /* ══════════════════════════════════════ About - 영상/사진 + 설명 2단 (.tpl-about)
     제목은 위에 .tpl-head(eyebrow + H2) 로 따로 선다 → 여기는 "본문 2단"만 담당한다.
     ★ 비율(--about-cols)과 간격(--about-gap)은 :root 가 정한다 - 여기서 숫자를 쓰지 않는다.
       59개 페이지가 이 한 벌을 공유하므로 :root 한 줄만 고치면 전부 바뀐다. */
  /* 좌우에도 같은 60(--about-gutter) 을 준다 → [60] 미디어 [붉은 선+60] 본문(400) [60]
     ★ 좌우 여백은 --about-gutter, 가운데만 --about-gap(= gutter + 데코) 이다.
       가운데만 데코가 끼어들기 때문이다. 둘을 같은 값으로 묶으면 좌우가 함께 벌어져
       미디어가 그만큼 쪼그라든다.
     이 섹션만의 여백이다(다른 tpl-* 는 .container 여백을 그대로 쓴다). */
  .tpl-about {
    display: grid; grid-template-columns: var(--about-cols);
    column-gap: var(--about-gutter); padding-inline: var(--about-gutter);
    align-items: center; }
  /* ★ 데코가 있는 About 만 gap 을 넓힌다(80개 중 40개). 영상형처럼 데코가 없는 About 은
     이미지 끝이 곧 눈에 보이는 끝이라 60 이 맞다 → :has() 로 CSS 가 스스로 판정한다.
     (일괄로 넓히면 데코 없는 쪽이 20 만큼 헐거워진다) */
  .tpl-about:has(.tpl-about__deco) { column-gap: var(--about-gap); }
  /* ★ 데코가 들어설 자리를 "박스 안"에 만든다 (2026-07-14 버그 수정).
     예전엔 데코를 미디어 밖으로 비껴 내보냈는데(transform 또는 음수 inset), 그러면
     **밖으로 나간 부분이 그려지지 않아 아래쪽 선이 사라졌다**(overflow: visible 인데도 잘렸다.
     프로브를 z-index 99 로 띄워도 미디어 밖에서는 안 그려지는 것을 확인했다).
     → 미디어 자신이 우·하로 --about-deco 만큼 패딩을 갖는다.
       사진은 그 안쪽(content box)에 서고, 데코는 그 패딩까지 채운다 → 둘이 어긋나 보이되
       **데코가 미디어 박스 안**이라 잘릴 일이 없다. 보이는 결과는 종전과 같다. */
  /* ★ 패딩은 영상형에도 똑같이 준다. 데코가 있든 없든 미디어 박스가 같은 크기여야
     "어느 페이지에서나 미디어 크기가 같다"는 규칙이 지켜진다(사진만 20 작아지면 어긋난다). */
  .tpl-about__media { position: relative;
    padding: 0 var(--about-deco) var(--about-deco) 0; }
  /* 영상도 사진도 같은 박스(--about-ratio)에 담긴다 → 어느 페이지에서나 미디어 크기가 같다.
     iframe 은 자기 높이가 없고, 사진은 원본 비율이 제각각이라 둘 다 박스가 크기를 정해야 한다. */
  .tpl-about__media .ratio { position: relative; width: 100%; aspect-ratio: var(--about-ratio);
    border-radius: var(--r-lg); overflow: hidden; }
  .tpl-about__media iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
  /* z-index 1 : 사진이 데코 "위"에 선다. 데코를 z-index:-1 로 뒤로 보내면 안 된다(아래 참고) */
  .tpl-about__media > img { width: 100%; height: 100%; display: block;
    aspect-ratio: var(--about-ratio); object-fit: cover;
    border-radius: var(--r-lg); position: relative; z-index: 1; }
  /* 사진 뒤로 살짝 비껴 깔리는 데코 테두리.
     ★ 오프셋은 --about-deco 다. --about-gap 이 이 값을 더해서 파생되므로
       여기를 바꾸면 미디어 ↔ 텍스트 간격이 따라 움직여 [붉은 선 ↔ 글] 은 60 으로 유지된다. */
  /* 데코는 미디어의 "우하단으로 --about-deco 만큼 밀린 사각형" 이다.
     ★ 미디어 밖으로 내보내지 않는다(위 .tpl-about__media 주석 참고 - 밖은 그려지지 않는다).
       미디어가 우·하로 패딩을 갖고 있으므로, 데코를 [좌상 +deco / 우하 0] 에 붙이면
       사진과 딱 --about-deco 만큼 어긋난 자리에 선다. inset 은 padding box 기준이다. */
  .tpl-about__deco { position: absolute; z-index: 0;
    inset: var(--about-deco) 0 0 var(--about-deco);
    border: var(--sp-1) solid var(--point-bg); border-radius: var(--r-lg); }
  /* 본문은 어디서든 --fs-body(20) · 400 · --ink (템플릿 공통 룰) */
  .tpl-about__body p { font-size: var(--fs-content-body); font-weight: 400; line-height: var(--lh-prose);
    color: var(--ink); text-align: left; }
  .tpl-about__body p + p { margin-top: var(--sp-4); }
  .tpl-about__body p strong { font-weight: 600; color: var(--ink); }
  @media (max-width: 991.98px) {
    /* 1열로 떨어지면 좌우 60 여백은 불필요하다(.container 가 이미 여백을 준다) */
    .tpl-about { grid-template-columns: minmax(0, 1fr); row-gap: var(--sp-6);
      padding-inline: 0; }
    /* 모바일에선 데코를 겹치지 않게 - 패딩과 오프셋을 함께 푼다(둘은 한 벌이다) */
    .tpl-about__media { padding: 0; }
    .tpl-about__deco { inset: 0; }
  }

  /* ══════════════════════════════════════ 1) 사진 박스 (tpl-box 변형)
     tpl-box 의 3구획(아이콘 / 제목 / 텍스트) 중 1구획을 사진으로 바꾼 것이다.
     제목·본문 규격(--box-title-fs · --fs-body)과 배경(--bg-soft) · R(--r-lg) 은
     tpl-box 를 그대로 물려받는다 → 다른 박스와 나란히 놓아도 어긋나지 않는다.
     사진이 박스 위쪽을 꽉 채우므로 상단 패딩만 걷어낸다. */
  /* 사진 행은 max-content, 본문 행은 1fr - 이 순서가 중요하다.
     같은 줄의 박스는 높이가 서로 같아지는데(그리드 stretch), 그 남는 높이를 어느 행이 먹느냐가
     사진의 아래 여백을 정한다. 사진 행을 auto 로 두면 본문이 짧은 카드일수록 사진 칸이 늘어나
     사진과 제목 사이가 벌어지고 제목 줄이 카드마다 어긋난다.
     → 사진은 자기 높이만(max-content), 남는 높이는 본문 행(1fr)이 받는다. */
  .tpl-box--photo { position: relative;
    grid-template-rows: max-content var(--tpl-row-title) minmax(var(--tpl-row-text), 1fr);
    padding: 0 0 var(--box-pad-bottom); overflow: hidden; }
  .tpl-box--photo .tpl-box__photo { width: 100%; }
  .tpl-box--photo .tpl-box__photo img { width: 100%; height: auto; display: block;
    aspect-ratio: var(--ratio-photo); object-fit: cover; }
  /* 사진 ↔ 제목은 아이콘보다 더 벌린다 (사진은 제목의 라벨이 아니라 하나의 면이다).
     ⚠️ h3 는 align-self:end 라 "제목 행 높이" 안에 갇힌다. 행 높이가 아이콘 기준
        (+--box-gap-sm 5) 이면 margin-top 을 줘도 실제 여백이 그만큼 안 나온다.
        → 행 높이와 margin-top 을 같은 값(--box-gap-photo)으로 맞춰야 여백이 살아난다. (2026-07-13) */
  .tpl-box--photo { --tpl-row-title: calc(var(--fs-content-title) * 1.4 + var(--box-gap-photo)); }
  .tpl-box--photo :is(h3, h4) { margin-top: var(--box-gap-photo); padding-inline: var(--sp-4); }

  /* ★ 사진만 있는 박스 (2026-07-14 사용자 지시) - 제목·본문 없이 사진 한 면이 곧 카드다.
     위 3행 격자(사진 / 제목 / 본문)를 그대로 두면 텍스트가 없어도 제목 행·본문 행이
     자리를 지켜 사진 아래가 텅 빈다 → 행을 하나로 접고 패딩을 걷어낸다.
     사진은 4:3 을 버리고 카드 높이를 꽉 채운다(옆 아이콘 박스가 정한 높이에 맞춘다).
     자식이 사진 하나뿐인 것을 :has 로 스스로 안다 - 마크업에 클래스를 더하지 않는다. */
  .tpl-box--photo:has(> .tpl-box__photo:only-child) {
    grid-template-rows: 1fr; padding: 0; }
  .tpl-box--photo:has(> .tpl-box__photo:only-child) .tpl-box__photo { height: 100%; }
  .tpl-box--photo:has(> .tpl-box__photo:only-child) .tpl-box__photo img {
    height: 100%; aspect-ratio: auto; object-fit: cover; }
  /* 모바일은 사진 박스가 한 줄에 1개다 - 옆 박스가 없으니 카드 높이를 정해 줄 것도 없어
     사진이 원본 비율(세로컷)로 서서 화면을 세로로 크게 먹는다 (실측 340×374 @390).
     → 4:3 으로 눕혀 조금 납작하게 (사용자 지시 2026-07-14). 글이 딸린 사진 박스가
     16:9(--ratio-photo-m)까지 눕는 것보다는 덜 눕힌다 - 여기는 사진이 곧 카드다. */
  @media (max-width: 991.98px) {
    .tpl-box--photo:has(> .tpl-box__photo:only-child) .tpl-box__photo img {
      height: auto; aspect-ratio: var(--ratio-photo); }
  }
  /* (요청 2026-07-13) 본문 글줄 폭을 좌우 5(--sp-1)씩 더 좁힌다 - 사진 폭에 눌려 글이 외곽에 붙는다 */
  .tpl-box--photo p { padding-inline: calc(var(--sp-4) + var(--box-text-inset) + var(--sp-1)); }
  /* 해부 일러스트(절개 부위 · 보형물 위치)는 잘리면 정보가 사라진다 → 통째로 넣고(contain)
     남는 자리는 흰 면으로 채운다. 실사진은 기본값(cover) 그대로 꽉 채운다.
     (2026-07-13 breast-implant 의 .bi-card 를 흡수하면서 승격 - 그 페이지 전용 카드였다) */
  .tpl-boxes--fit .tpl-box--photo .tpl-box__photo { background: var(--white); }
  .tpl-boxes--fit .tpl-box--photo .tpl-box__photo img { object-fit: contain; }
  /* (요청 2026-07-15) --square : 원본이 1:1 인 도해용. 슬롯(4:3)에 1:1 을 contain 하면
     좌우 25%가 흰 여백으로 남고 그림만 작아진다(박스 583 → 그림 437).
     박스 폭을 줄여도 슬롯이 박스 기준이라 그림도 같이 줄어 여백 비율은 그대로다
     → 해법은 슬롯을 이미지와 같은 1:1 로 맞추는 것뿐이다. 그래야 "박스 폭 = 이미지 폭"이 된다.
     모바일에서도 --fit 이 4:3 을 강제하므로 거기서도 1:1 을 지켜 준다. */
  .tpl-boxes--fit.tpl-boxes--square .tpl-box--photo .tpl-box__photo img { aspect-ratio: 1 / 1; }
  /* (요청 2026-07-17) --natural : 원본이 1:1 도 4:3 도 아닌 도해용(예: 250×280 = 0.893).
     --square 와 같은 처방이되, 고정 비율을 못박지 않고 원본 비율에 맡긴다(aspect-ratio:auto).
     슬롯이 곧 이미지가 되므로 "박스 폭 = 이미지 폭"이 되고 좌우 흰 여백이 사라진다.
     .tpl-intro--fit(21) 이 aspect-ratio:auto 를 쓰는 것과 같은 방식이다. */
  .tpl-boxes--fit.tpl-boxes--natural .tpl-box--photo .tpl-box__photo img { aspect-ratio: auto; }
  /* (요청 2026-07-17) --narrow : 도해 카드가 넓으면 회색 면만 커지고 그림은 그대로다.
     → 칸 폭을 340 으로 못박고(--cols 계산을 쓰지 않으므로 개수와 무관하다),
       박스 사이는 60 으로 벌린다. --sp-7 이 1920 에서 정확히 60 이다(생짜 60px 을 박지 않는다
       - .gal-stagger 와 같은 처방). 남는 자리는 .tpl-boxes 의 justify-content:center 가 나눈다.
     ★ 모바일은 건드리지 않는다 - 거기선 한 줄에 1~2개라 폭을 묶으면 화면이 남는다. */
  .tpl-boxes--narrow { gap: var(--sp-7); }
  .tpl-boxes--narrow > * { flex: 0 0 var(--tpl-narrow-w, 340px); }
  /* (요청 2026-07-13) 모바일은 사진 박스가 한 줄에 1개라 4:3 사진이 화면을 세로로 다 먹는다
     → 위아래를 잘라 가로형으로 눕힌다(object-fit:cover 라 가운데가 남는다). PC 는 4:3 유지.
     단, --fit(해부 도해)은 잘라내기가 아니라 통째로 보여주는 카드다. 비율을 눕히면 그림만
     작아지고 얻는 게 없다 → 4:3 을 그대로 둔다. */
  @media (max-width: 991.98px) {
    .tpl-box--photo .tpl-box__photo img { aspect-ratio: var(--ratio-photo-m); }
    .tpl-boxes--fit .tpl-box--photo .tpl-box__photo img { aspect-ratio: var(--ratio-photo); }
    .tpl-boxes--fit.tpl-boxes--square .tpl-box--photo .tpl-box__photo img { aspect-ratio: 1 / 1; }
    .tpl-boxes--fit.tpl-boxes--natural .tpl-box--photo .tpl-box__photo img { aspect-ratio: auto; }
    /* 모바일은 폭 고정을 푼다 - 아래 배치 규칙(사진 박스는 한 줄에 1개)이 주인이다 */
    .tpl-boxes--narrow > * { flex-basis: auto; }
  }
  /* 번호는 순서가 의미 있을 때(POINT)만. 사진 좌상단에 올린다 */
  .tpl-box--photo .tpl-num { position: absolute; top: var(--sp-4); left: var(--sp-4); z-index: 1;
    width: var(--sp-6); height: var(--sp-6); border-radius: 50%;
    display: grid; place-items: center;
    background: var(--dark); color: var(--white);
    font-size: var(--fs-content-subtext); font-weight: 600; line-height: 1; }


  /* ══════════════════════════════════════ 카드 전체를 덮는 링크 (.stretched)
     (2026-07-13 통합) 예전엔 `.lp-best__card a.stretched` 와 `.note-card .stretched` 로
     같은 것이 두 벌 있었고, 그래서 다른 카드(.tpl-box 등)에서는 쓸 수가 없었다.
     → 스코프를 없앤 단일 규칙 하나로 합친다. 부모가 position:relative 이기만 하면 어디서든 쓴다. */
  .stretched { position: absolute; inset: 0; z-index: 1; border-radius: var(--r-lg); }

  /* ══════════════════════════════════════════════════════════════════════
     시술 페이지 공용 밴드 (lp-*) - page-template.css 에서 승격 (2026-07-13)
     EVENT 비용 · 함께 하면 좋은 수술 · HOT EVENT. **27개 페이지**가 공유한다
     → "페이지 예외"가 아니라 공통 컴포넌트다 (DESIGN_SYSTEM 규칙 5).
  ══════════════════════════════════════════════════════════════════════ */
  /* ══════════════════════════════════════ 3) EVENT 비용 (다크 밴드 - 구조 유지)
     다크 밴드는 자체 제목을 갖는 예외 구역이다(CONVERSION_RULES 4).
     구조·색은 원본 그대로 두고, 폰트·간격만 토큰으로 통일했다. */
  .lp-price { background: var(--dark); color: var(--white);
    border-radius: var(--r-lg); padding: var(--sp-7); }
  .lp-price__row { display: flex; align-items: center; flex-wrap: wrap;
    column-gap: var(--sp-8); row-gap: var(--sp-6); }
  /* (요청) H2 통일 - 크기·자간·정렬 오버라이드 삭제. 색만 상속시킨다. */
  .lp-price h2 { color: inherit; }
  .lp-price h2 + p { font-size: var(--fs-h2title); color: inherit; font-weight: 600;
    text-align: left; margin-top: var(--sp-3); line-height: 1.3; }
  /* (2026-07-13) .lp-price--text · .lp-price__sub 삭제 - 쓰는 페이지가 0 이었다(죽은 CSS).
     금액 자리에 문장이 들어오는 페이지가 생기면 그때 되살린다. */
  .lp-price__checks { display: flex; flex-direction: column; row-gap: var(--sp-4); }
  .lp-price__check { display: flex; align-items: center; gap: var(--sp-5); }
  /* 아이콘은 Phosphor 로 통일 (원본 인라인 SVG 는 색이 하드코딩돼 있었다) */
  .lp-price__check i { flex: 0 0 auto; font-size: var(--fs-content-title); color: var(--point); line-height: 1; }
  .lp-price__check p { font-size: var(--fs-content-body); font-weight: 400; }

  /* ══════════════════════════════════════ 4) 함께 하면 좋은 수술 (프로모션 카드)
     카드 = 면(--bg-soft) + --r-lg. 면을 줬으니 테두리는 없다(면/선 원칙). */
  .lp-best__cards { display: grid; grid-template-columns: repeat(var(--cols, 3), minmax(0, 1fr));
    gap: var(--box-gap); }
  .lp-best__card { position: relative; display: flex; flex-direction: column;
    align-items: center; text-align: center;
    background: var(--bg-soft); border-radius: var(--r-lg);
    padding: var(--box-pad-top) var(--sp-5) var(--sp-5); }
  .lp-best__num { font-size: var(--fs-content-title); font-weight: 700; color: var(--point);
    line-height: var(--lh-title); font-variant-numeric: tabular-nums; }
  .lp-best__card h3 { margin-top: var(--box-gap-sm);
    font-size: var(--fs-content-title); font-weight: 600; color: var(--point); line-height: var(--lh-title); }
  .lp-best__imgwrap { width: 100%; aspect-ratio: var(--ratio-square); margin-top: var(--box-gap-md);
    overflow: hidden; border-radius: var(--r-lg); }
  .lp-best__imgwrap img { width: 100%; height: 100%; object-fit: cover;
    transform: scale(1); transition: transform .8s ease; }
  .lp-best__card:hover .lp-best__imgwrap img { transform: scale(var(--card-zoom)); }
  .lp-best__meta { display: flex; justify-content: space-between; align-items: baseline;
    width: 100%; margin-top: var(--sp-4);
    border-top: var(--hairline) solid var(--gray-light); padding-top: var(--sp-3); }
  /* 가격 = [숫자] + [단위]. 예전엔 "239m~" 라고 붙여 써서 m 이 무슨 뜻인지 읽히지 않았다.
     숫자는 한 단계 키워(body 20 → sub 30) 카드에서 제일 먼저 눈에 들어오게 하고,
     단위는 거기서 두 단계 낮춰(--fs-fine 14) 볼드를 빼면 "239 만원~" 으로 자연히 읽힌다.
     단위는 값의 일부라 색은 --ink 그대로 둔다(--gray-dark 는 단서·주석용). */
  .lp-best__price { font-size: var(--fs-content-title); font-weight: 600; color: var(--ink);
    line-height: 1; }
  .lp-best__unit { margin-left: var(--sp-1);
    font-size: var(--fs-eyebrow); font-weight: 400; color: var(--ink); }
  /* 부가 정보(단서)는 괄호 대신 크기·색으로 위계를 만든다 (템플릿 공통 룰) */
  .lp-best__vat { font-size: var(--fs-eyebrow); font-weight: 400; color: var(--gray-dark); }
  @media (max-width: 991.98px) { .lp-best__cards { grid-template-columns: minmax(0, 1fr); } }

  /* ══════════════════════════════════════ 5) HOT EVENT 띠 (다크 밴드 - 구조 유지)
     골격: section > .container--full > .lp-hot__strip > .container.lp-hot__inner
       - 화면 끝까지 뻗는 건 래퍼(.container--full)가 한다 → 100vw 해킹 삭제.
       - 안쪽 폭은 표준 .container 가 잡는다 → max-width:1280 하드코딩 삭제(규칙 7: 제3의 폭 금지). */
  .lp-hot__strip {
    background: linear-gradient(139deg, var(--ink) 0%, var(--ink) 77%, var(--accent) 77%, var(--accent) 100%);
    padding-block: var(--sp-5); }
  .lp-hot__inner { color: var(--white);
    display: flex; justify-content: space-between; align-items: center;
    flex-wrap: wrap; gap: var(--sp-5); }
  /* (요청) H2 통일 - 크기·자간·정렬 오버라이드 삭제. 색만 상속시킨다. */
  .lp-hot h2 { color: inherit; }
  .lp-hot h2 span { color: var(--accent); }
  .lp-hot h2 + p { font-size: var(--fs-content-title); color: inherit; text-align: left;
    margin-top: var(--sp-2); line-height: 1.35; }
  /* 다크 밴드 위에서는 포인트 테두리 CTA 가 묻힌다 → 이 안에서만 흰색으로 반전한다.
     크기·여백·라운드는 .cta 그대로라 다른 CTA 와 어긋나지 않는다. */
  .lp-hot .cta { flex: 0 0 auto; margin: 0; max-width: none;
    color: var(--white); box-shadow: inset 0 0 0 var(--hairline) var(--white); }
  .lp-hot .cta:hover { background: var(--white); color: var(--ink); }

}

/* ============================================================================
   TEMPLATES - 콘텐츠 컴포넌트 (구 all_template.css)
   갤러리(gal-*) · 항목나열(ub-*) · 소개(ua-*) · 전후사진(bna-*) · 정보(ti-*)

   components 레이어보다 뒤에 선다 - 통합 전 all_template.css 가 레이어 밖에서
   갖던 우선순위를 그대로 보존한다. :where() 로 특이도 0 인 타이포 규격이
   components 의 개별 룰을 이겨야 하기 때문에 레이어 순서로만 성립한다.
   ============================================================================ */
@layer templates {

/* ★★ 템플릿 들여쓰기 (요청 2026-07-14 · 대상 축소) ═══════════════════════════
   좌우 100px 들여쓰기는 **11번 「구분선 아이콘 행」(.ub-row) 형태에만** 적용한다.
   이 안은 아이콘·제목·본문이 가로로 길게 늘어선 "표"라, 컨테이너를 꽉 채우면
   한 줄이 너무 길어져 눈이 줄을 따라가지 못한다 → 좌우를 좁혀 읽기 폭을 만든다.

   나머지 템플릿(카드 격자 · 갤러리 · 타임라인 · 레일 · 전후사진 …)은 들여쓰지 않는다.
   그 안들은 사진·카드가 주인공이라 크게 보여야 한다(2026-07-14 전체 해제).
   ※ 되살리려면 아래 :is() 목록에 클래스 이름만 다시 넣으면 된다. */
/* ⚠️ .tpl-process__steps 는 두 가지 자리에 쓰인다 - 들여쓰기 대상은 앞의 것 하나뿐이다.
     1) .container 바로 아래 단독 (ECM 프로세스 등) : 폭 1200 을 통으로 쓴다 → 들여쓴다
     2) .tpl-process 2열 그리드 안 (사진 460 + 스텝 670) : 이미 좁은 칼럼이다 → 건드리면 안 된다
        (실제로 일괄 적용했더니 670 → 370 으로 뭉개졌다. 2026-07-14) */
:is(.ub-row,                                        /* 11번 구분선 아이콘 행 - 가로로 긴 표 */
    .tpl-process__steps:not(.tpl-process *),        /* 시술 프로세스 4단계 박스 (단독 배치만) */
    .gal-list)                                      /* 10번 매거진 리스트 - 좌우 150 (요청 2026-07-14) */
{
  margin-inline: var(--tpl-inset);
}

/* 정의형 2단 표(dt/dd) - 200. 항목명·값이 짧아 150 보다 더 좁혀도 읽힌다.
   ⚠️ 여기도 두 자리에 쓰인다: .ti-spec 2열 그리드(사진 + 표) 안의 것은 이미 664px 이라 제외한다. */
.ti-spec__list:not(.ti-spec *) {
  margin-inline: var(--tbl-inset);
}

@media (max-width: 1200px) {
  /* 좁은 화면은 이미 폭이 없다 → 들여쓰기를 푼다 */
  :root { --tpl-inset: 0px; --tbl-inset: 0px; }
}

/* ══════════════════ 항목 나열 (ub-*) - 구 template-boxes.css */
@charset "utf-8";
/* ============================================================================

.ub-case { margin-top: var(--sp-10); }
.ub-case:first-of-type { margin-top: 0; }

/* 시안 라벨 - 갤러리에서 안을 구분하기 위한 장치. 운영 섹션 헤더가 아니다 */
.ub-head { margin-bottom: var(--sp-7); padding-bottom: var(--sp-4);
  border-bottom: var(--hairline) solid var(--gray-light); }

/* 좌우 화살표 - 도트 대신 쓰는 유일한 이동 장치 (rail 이 공유) */
/* (요청 2026-07-15) 평상시엔 회색 테두리 + 먹색 화살표라 배경에 묻혀 "누를 것"으로 안 읽혔다.
   → 포인트 컬러를 **배경이 아니라 외곽선과 화살표**에 준다. 배경은 흰 면 그대로 두어
   카드 위에서 떠 보이게 한다. 채움(배경 point + 흰 화살표)은 hover 로 미룬다
   - .cta(테두리 point → hover 시 채움)와 같은 위계다. */
.ub-arrow { display: inline-grid; place-items: center;
  width: var(--ub-arrow-size); height: var(--ub-arrow-size);
  --ub-arrow-size: clamp(40px, 3.125vw, 52px);
  border: var(--hairline) solid var(--point); border-radius: var(--r-pill);
  background: var(--white); color: var(--point); font-size: var(--ico-md);
  transition: background .25s, color .25s, border-color .25s; }
.ub-arrow:hover { background: var(--point); border-color: var(--point); color: var(--white); }

/* 공통 - 카드 안 제목/본문 규격. main.css 의 .tpl-box 규격을 그대로 따른다 */

/* 보조 태그(핵심 문구) - 본문보다 작게, 회색으로. 괄호 대신 위계를 만든다 */
.ub-tag { display: inline-block; font-size: var(--fs-eyebrow); font-weight: 600;
  color: var(--point); letter-spacing: .01em; line-height: var(--lh-tight); }
.ub-tag--pill { padding: var(--sp-1) var(--sp-3); border-radius: var(--r-pill);
  background: var(--point-bg); }

.ub-txt { font-weight: 400;
  color: var(--ink); }

/* ══════════════════════════════════════ 1. 가로 스크롤 스냅 레일 (.ub-rail) ══ */
.ub-rail__track { display: flex; gap: var(--box-gap); overflow-x: auto;
  scroll-snap-type: x mandatory; scroll-behavior: smooth;
  padding-bottom: var(--sp-3); scrollbar-width: none; }
.ub-rail__track::-webkit-scrollbar { display: none; }

.ub-rail__card { flex: 0 0 clamp(250px, 24vw, 320px); scroll-snap-align: start;
  border-radius: var(--r-lg); background: var(--bg-soft); overflow: hidden; }
.ub-rail__ph { aspect-ratio: var(--ratio-photo); overflow: hidden; }
.ub-rail__ph img { width: 100%; height: 100%; object-fit: cover;
  transition: transform .5s; }
.ub-rail__card:hover .ub-rail__ph img { transform: scale(var(--card-zoom)); }
.ub-rail__body { padding: var(--sp-5); display: grid; gap: var(--sp-3); }
/* (요청 2026-07-27) 태그(.ub-tag)가 카드마다 1~2줄로 달라 그 아래 제목·본문 시작 높이가
   어긋나던 것을 막는다 - 태그에 2줄 높이를 예약하면 1줄짜리 카드도 제목이 같은 선에서 시작한다.
   opt-in : 필요한 rail 컨테이너에만 붙인다(다른 ub-rail 26곳은 그대로). */
.ub-rail--tagfix .ub-rail__body .ub-tag { min-height: calc(var(--fs-eyebrow) * var(--lh-tight) * 2); }
.ub-rail__nav { display: flex; justify-content: flex-end; gap: var(--sp-2);
  margin-top: var(--sp-5); }

/* (요청 2026-07-14) 카드가 3개 이하면 한 줄에 다 들어간다 - 스크롤할 것이 없다.
   → 트랙을 **가운데로 모으고 좌우 화살표를 감춘다.** (누를 데가 없는 버튼은 두지 않는다)
   항목 수는 :has 로 스스로 안다 - 마크업에 클래스를 더하지 않는다.
   ⚠️ 모바일(≤991.98px)은 카드가 화면 폭의 78% 라 3개여도 넘친다 → 규칙을 적용하지 않는다. */
@media (min-width: 992px) {
  .ub-rail:not(:has(.ub-rail__card:nth-child(4))) .ub-rail__track { justify-content: center; }
  .ub-rail:not(:has(.ub-rail__card:nth-child(4))) .ub-rail__nav { display: none; }
}

/* ═════════════════════════════════════════ 3. 세로 타임라인 (.ub-time) ══ */
/* 세로 타임라인 (2026-07-14 요청)
   · 글이 짧으면 오른쪽이 통째로 비어 보인다 → 컨테이너 바깥 여백만큼(100%) 안쪽으로 밀어 중앙으로 모은다.
     뷰포트가 좁아 바깥 여백이 없으면 max() 가 0 을 골라 그대로 둔다.
   · 노드를 잇던 세로 축(::before)은 삭제한다. 마지막 노드 아래로 선이 삐져나와 지저분했다. */
.ub-time { --ub-node: clamp(46px, 3.4vw, 60px);
  /* ⚠️ (2026-07-21 버그수정) 패딩에 상한 --container/4(320) 를 씌운다.
     이 요소는 이미 .container **안**에 있는데 아래 계산은 뷰포트 기준 바깥 여백을 한 번 더
     안쪽으로 깎는다 → 화면이 넓을수록 컨테이너는 1280 에 멈추고 패딩만 자라 본문이 사라졌다
     (2200px 에서 본문 180px · 2560px 에서 0px).
     ★ 상한 320 은 뷰포트 1920 일 때의 값과 정확히 같다 → **1920 까지는 기존 그림 그대로**이고
       그 위로만 320 에서 멈춘다. 상한을 --sp-8 같은 작은 여백으로 두면 내용이 넓어지면서
       왼쪽으로 쏠려 보인다(짧은 글의 오른쪽이 비는 원래 문제로 되돌아간다). */
  --ub-inset: min(calc(var(--container) / 4),
                  max(0px, calc((100vw - var(--container)) / 2)));
  position: relative; display: grid; gap: var(--sp-7);
  padding-inline: var(--ub-inset); }

.ub-time__item { position: relative; display: grid;
  grid-template-columns: var(--ub-node) minmax(0, 1fr);
  align-items: start; gap: var(--sp-6); }
.ub-time__node { position: relative; display: grid; place-items: center;
  width: var(--ub-node); height: var(--ub-node); border-radius: var(--r-pill);
  background: var(--point-bg); color: var(--point); font-size: var(--ico-md); }
.ub-time__item:first-child .ub-time__node,
.ub-time__item:last-child .ub-time__node { background: var(--point); color: var(--white); }

.ub-time__body { display: grid; gap: var(--sp-2); padding-bottom: var(--sp-2); }
.ub-time__step { font-size: var(--fs-eyebrow); font-weight: 600; color: var(--point);
  letter-spacing: .1em; line-height: var(--lh-tight); }
.ub-time__body h3 { color: var(--ink); }

/* ════════════════════════════════════════════════ 5. 탭 전환 (.ub-tab) ══ */
.ub-tab__list { display: flex; flex-wrap: wrap; gap: var(--gap-toggle-item);
  justify-content: center; margin-bottom: var(--gap-toggle-body);
  border-bottom: var(--hairline) solid var(--gray-light); }
.ub-tab__list button { padding: var(--sp-3) var(--sp-4);
 font-weight: 400; color: var(--gray-dark);
  border-bottom: calc(var(--hairline) * 2) solid transparent;
  transition: color .25s, border-color .25s; }
.ub-tab__list button:hover { color: var(--point); }
.ub-tab__list button[aria-selected="true"] { color: var(--point); font-weight: 600;
  border-bottom-color: var(--point); }

.ub-tab__panel[hidden] { display: none; }
.ub-tab__panel { display: grid; grid-template-columns: var(--split-cols);
  align-items: center; gap: var(--sp-8); }
.ub-tab__ph { border-radius: var(--r-lg); overflow: hidden;
  aspect-ratio: var(--ratio-photo); }
.ub-tab__ph img { width: 100%; height: 100%; object-fit: cover; }
.ub-tab__body { display: grid; gap: var(--sp-4); justify-items: start; }
.ub-tab__body h3 { color: var(--ink); }
.ub-tab__body .ub-txt { line-height: var(--lh-prose); }

/* 숫자는 "배경" 이다 - 글 뒤에 흐리게 깔린다 */

/* ══════════════════════════ 7. 겹친 사진 오버레이 카드 (.ub-ov) ══ */
.ub-ov { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--box-gap); }
/* (요청 2026-07-14) 5장이면 **한 줄에 5열**로 세운다. 기본 3열이면 3+2 로 끊겨 마지막 줄이 허전하다.
   카드가 좁아지지만(3열 390 → 5열 222) 단계 도해라 작아도 읽힌다. 항목 수는 :has 가 스스로 안다. */
.ub-ov:not(.ub-ov--circle):has(.ub-ov__card:nth-child(5):last-child) {
  grid-template-columns: repeat(5, minmax(0, 1fr)); }
/* (요청 2026-07-14) 5열 카드는 **오버레이를 쓰지 않는다.**
   정사각 사진 위에 글을 얹으면 캡션이 도해를 절반이나 덮는다.
   → 같은 페이지 위쪽 33(.ub-rail__card, Surgery Steps)과 **똑같은 골격**으로 세운다:
     [사진 4:3] 위 · [태그 → 제목 → 본문] 아래, 회색 카드.
   ※ .ub-ov--circle(원형 카드)은 제 규칙이 따로 있으므로 제외한다. */
.ub-ov--flat .ub-ov__card,
/* ★ (2026-07-17) 행을 auto auto 로 두면 카드가 같은 높이로 늘어날 때 남는 공간이
   align-content:stretch 로 두 행에 절반씩 나뉜다. 본문이 짧은 카드(예: 2단계)는 남는 공간이
   많아 사진 행이 더 커지고 캡션이 아래로 밀려 제목 줄이 어긋난다.
   → 사진 행은 내용 크기(auto), 남는 공간은 캡션 행(1fr)이 전부 먹게 해 캡션 시작점을 통일한다. */
.ub-ov:not(.ub-ov--circle):has(.ub-ov__card:nth-child(5):last-child) .ub-ov__card {
  aspect-ratio: auto; display: grid; grid-template-rows: auto 1fr;
  background: var(--bg-soft); cursor: default; }
/* (요청 2026-07-17) 비율은 그대로 두되 잘림 기준을 위로 - 도해라 윗부분(배꼽·복부 라인)이
   중요하고 아래(다리 쪽)는 잘려도 된다. object-position 기본값 50% 50%(가운데)를 top 으로. */
.ub-ov:not(.ub-ov--circle):has(.ub-ov__card:nth-child(5):last-child) .ub-ov__card img {
  height: auto; aspect-ratio: var(--ratio-photo); object-fit: cover;
  object-position: top; }
.ub-ov:not(.ub-ov--circle):has(.ub-ov__card:nth-child(5):last-child) .ub-ov__card:hover img {
  transform: none; }
/* 캡션은 사진 "아래" - 절대배치·그라디언트를 푼다 (33 의 .ub-rail__body 와 같은 패딩) */
.ub-ov:not(.ub-ov--circle):has(.ub-ov__card:nth-child(5):last-child) .ub-ov__veil {
  position: static; background: none; padding: var(--sp-5); }
.ub-ov:not(.ub-ov--circle):has(.ub-ov__card:nth-child(5):last-child) .ub-ov__veil h3 { color: var(--ink); }
.ub-ov:not(.ub-ov--circle):has(.ub-ov__card:nth-child(5):last-child) .ub-ov__veil .ub-tag { color: var(--point); }
.ub-ov:not(.ub-ov--circle):has(.ub-ov__card:nth-child(5):last-child) .ub-ov__more > p { color: var(--gray-dark); }
/* 본문은 항상 펼쳐 둔다 - 33 처럼 hover 로 여닫지 않는다 */
.ub-ov:not(.ub-ov--circle):has(.ub-ov__card:nth-child(5):last-child) .ub-ov__more {
  grid-template-rows: 1fr; opacity: 1; }
.ub-ov__card { position: relative; overflow: hidden; border-radius: var(--r-lg);
  aspect-ratio: var(--ratio-square); isolation: isolate; }
.ub-ov__card img { width: 100%; height: 100%; object-fit: cover;
  transition: transform .6s; }
.ub-ov__card:hover img { transform: scale(var(--card-zoom)); }
/* 사진 위에 잉크 그라디언트를 덮고 글자를 얹는다 */
.ub-ov__veil { position: absolute; inset: 0; display: grid; align-content: end;
  gap: var(--sp-2); padding: var(--sp-5);
  background: linear-gradient(to top,
    color-mix(in srgb, var(--ink) 88%, transparent) 0%,
    color-mix(in srgb, var(--ink) 55%, transparent) 40%,
    transparent 78%); }
.ub-ov__veil i { color: var(--white); font-size: var(--ico-lg); line-height: 1; }
.ub-ov__veil h3 { color: var(--white); }
.ub-ov__veil .ub-tag { color: var(--point-soft); }
/* 접힌 본문 - 높이를 grid fr 로 여닫는다(수치를 쓰지 않는 열림 애니메이션) */
/* ── 예외 : 원형 이미지 카드 (.ub-ov--circle) ────────────────────────────────
   (요청 2026-07-14, svf-hair) 사진 자체가 흰 바탕 위의 **원**이다. 오버레이 카드로 쓰지 않는다.
   PC  : 한 줄에 **5개**. [원 + 그 아래 중앙 정렬 캡션(title · subtext)]. 그라디언트를 쓰지 않는다.
   모바일 : 다시 오버레이로 돌아가되 **원이 다 보이도록** 크기를 줄이고 **정중앙에 흰 글씨**를 얹는다.
   ⚠️ 배치(align-content 등)는 여기서 못 준다 - templates-type 의 `.ub-ov__veil`(align-content: end)이
     레이어 우선순위로 이긴다. 배치는 그 레이어에 적어 둔다(아래 "06 예외 : 원형 이미지 카드"). */
.ub-ov--circle { grid-template-columns: repeat(5, minmax(0, 1fr)); }
/* 카드는 [사진][캡션] 2행이다 - 정사각 고정을 풀어 캡션이 사진 아래에 붙게 한다 */
/* (2026-07-17) 행은 auto 1fr - gal-timeline·5장 포맷과 같은 이유(stretch 분배로 캡션이 밀림) */
.ub-ov--circle .ub-ov__card {
  aspect-ratio: auto; overflow: visible; border-radius: 0;
  display: grid; grid-template-rows: auto 1fr; cursor: default; }
/* 사진은 원 전체가 보이도록 정사각으로 두고 원형으로 깎는다 (cover 로 잘리지 않게) */
.ub-ov--circle .ub-ov__card img {
  height: auto; aspect-ratio: var(--ratio-square); border-radius: 50%; }
.ub-ov--circle .ub-ov__card:hover img { transform: none; }
/* 캡션은 사진 "아래" - 절대배치·그라디언트를 모두 푼다 */
.ub-ov--circle .ub-ov__veil {
  position: static; background: none; }
.ub-ov--circle .ub-ov__veil h3       { color: var(--ink); }
.ub-ov--circle .ub-ov__veil .ub-tag  { color: var(--point); }
.ub-ov--circle .ub-ov__more > p      { color: var(--gray-dark); }
/* 설명(subtext)은 항상 펼쳐 둔다 - hover 로 여닫지 않는다 */
.ub-ov--circle .ub-ov__more { grid-template-rows: 1fr; opacity: 1; }

.ub-ov__more { display: grid; grid-template-rows: 0fr; opacity: 0;
  transition: grid-template-rows .45s, opacity .35s; }
.ub-ov__more > p { overflow: hidden; color: var(--white); font-size: var(--fs-eyebrow);
 }
.ub-ov__card:hover .ub-ov__more,
.ub-ov__card:focus-within .ub-ov__more { grid-template-rows: 1fr; opacity: 1; }

/* ═══════════════════════════════════════════════ 8. 비교표 (.ub-tbl) ══ */
.ub-tbl { overflow-x: auto; border-radius: var(--r-lg); background: var(--bg-soft); }
.ub-tbl table { width: 100%; border-collapse: collapse; min-width: var(--read-width); }
.ub-tbl th, .ub-tbl td { text-align: left; padding: var(--sp-5) var(--sp-6);
  border-bottom: var(--hairline) solid var(--gray-light);
 color: var(--ink);
  vertical-align: middle; }
.ub-tbl thead th { background: var(--point); color: var(--white); font-weight: 600;
  font-size: var(--fs-eyebrow); letter-spacing: .06em; border-bottom: 0; }
.ub-tbl tbody tr:last-child :is(th, td) { border-bottom: 0; }
.ub-tbl tbody tr:hover :is(th, td) { background: var(--point-bg); }
/* (요청 2026-07-14) 비교 항목 왼쪽의 아이콘은 쓰지 않는다 - 표는 글자만으로 읽힌다.
   마크업에서 <i> 를 넣지 말 것. 아이콘이 사라졌으므로 flex·gap 도 필요 없다. */
.ub-tbl__key { display: block; font-weight: 600; color: var(--ink);
  white-space: nowrap; }
.ub-tbl__val { font-weight: 600; color: var(--point); white-space: nowrap; }

/* ★ (요청 2026-07-14) 모바일에선 표를 쓰지 않는다.
   좁은 화면에서 4열 표는 가로 스크롤에 갇혀 머리행(옵션명)이 화면 밖으로 나가고 한 열만 잘려 보인다.
   → 행(=비교 항목) 하나를 카드 하나로 접고, 각 값 위에 옵션명을 빨간 라벨로 얹는다.
     옵션명은 td 의 data-label 에서 가져온다(마크업에 반드시 넣는다 - 없으면 값만 나열되어 못 읽는다). */
@media (max-width: 767.98px) {
  .ub-tbl { overflow-x: visible; background: none; border-radius: 0; }
  .ub-tbl table { display: block; min-width: 0; }
  .ub-tbl thead { display: none; }                 /* 머리행은 각 값의 라벨로 흡수된다 */
  .ub-tbl tbody { display: grid; gap: var(--flow-gap); }
  .ub-tbl tbody tr { display: block;
    background: var(--bg-soft); border-radius: var(--r-lg);
    padding: var(--sp-5) var(--sp-6); }
  .ub-tbl tbody tr:hover :is(th, td) { background: none; }
  /* 비교 항목(개념·핵심 작용…)이 카드 제목 */
  .ub-tbl tbody th[scope="row"] { display: block; padding: 0 0 var(--sp-4);
    border-bottom: var(--hairline) solid var(--gray-light); }
  .ub-tbl tbody th[scope="row"] .ub-tbl__key { white-space: normal;
    font-size: var(--fs-content-title); }
  /* 옵션별 값 - 라벨(빨강 eyebrow) → 값(subtext) */
  .ub-tbl tbody td { display: block; padding: var(--sp-4) 0 0; border-bottom: 0;
    font-size: var(--fs-content-subtext); line-height: var(--lh-body); }
  .ub-tbl tbody td::before { content: attr(data-label); display: block;
    margin-bottom: var(--sp-1);
    color: var(--point); font-size: var(--fs-eyebrow); font-weight: 600;
    letter-spacing: .06em; }
}

/* ══════════════════════════════ 10. 히어로 1장 + 위성 항목 (.ub-hero) ══ */
.ub-hero { display: grid; grid-template-columns: var(--split-cols);
  gap: var(--sp-8); align-items: stretch; }
/* (요청 2026-07-14) PC 에선 min-height 를 두지 않는다.
   min-height(432@1440)가 옆 항목 목록보다 커서 사진만 아래로 삐져나왔다.
   → align-items: stretch 에 맡기면 사진 높이가 **옆 박스 묶음의 높이와 정확히 같아진다.**
   (모바일은 세로로 스택되어 기댈 높이가 없다 → 아래 반응형에서 min-height 를 준다) */
.ub-hero__main { position: relative; border-radius: var(--r-lg); overflow: hidden;
  isolation: isolate; }
.ub-hero__main img { position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover; }
.ub-hero__cap { position: relative; z-index: 1; display: grid; align-content: end;
  gap: var(--sp-3); height: 100%; padding: var(--sp-6);
  background: linear-gradient(to top,
    color-mix(in srgb, var(--ink) 90%, transparent) 0%,
    color-mix(in srgb, var(--ink) 45%, transparent) 45%,
    transparent 80%); }
.ub-hero__cap h3 { color: var(--white); font-size: var(--fs-content-title); }
.ub-hero__cap .ub-txt { color: var(--white); }
.ub-hero__cap .ub-tag { color: var(--point-soft); }

.ub-hero__list { display: grid; gap: var(--sp-3); align-content: start; }
.ub-hero__item { display: grid; grid-template-columns: var(--ico-xl) minmax(0, 1fr);
  gap: var(--sp-4); align-items: center;
  padding: var(--sp-4) var(--sp-5); border-radius: var(--r-lg);
  background: var(--bg-soft); transition: background .25s, transform .25s; }
.ub-hero__item:hover { background: var(--point-bg); }
.ub-hero__item > i { color: var(--point); font-size: var(--ico-xl); line-height: 1; }
.ub-hero__item h3 { color: var(--ink); font-weight: 600; }
.ub-hero__item .ub-tag { color: var(--gray-dark); font-weight: 400; }

/* ════════════════════════════ 11. 아이콘 인라인 리스트 (.ub-row) ══ */
/* 좌우 들여쓰기(100)는 templates 레이어 첫머리의 **공통 규칙(--tpl-inset)** 이 준다.
   여기서 margin-inline 을 따로 주지 않는다.
   ★ 열은 .ub-row 가 정의하고 각 행(li)은 subgrid 로 그 열을 공유한다.
   행마다 grid 를 따로 두면 max-content 인 제목 열이 행별로 달라져 열 정렬이 무너진다.
   subgrid 라야 "가장 긴 제목" 하나로 전 행의 제목 열이 함께 정해진다. */
/* 구분선의 주인은 "행"(.ub-row__item) 하나다. 컨테이너(.ub-row)에 border-top 을 주면
   그 선만 padding-inline(30) 바깥에 그려져 혼자 60px 더 길어진다(2026-07-14 검수).
   → 맨 위 선도 첫 행이 그린다. 모든 선의 길이가 같아진다. */
.ub-row {
  display: grid; padding-inline: var(--sp-5);   /* 10 → 30 (요청 2026-07-14) */
  /* 열은 딱 4개 - [아이콘 | 제목 | 빨강 태그 | 본문]. 자식도 4개다.
     (2026-07-14) 예전엔 뒤에 빈 2fr 열이 하나 더 있어, 본문 오른쪽에 60px 이 유령처럼 남았다
     → 우측 여백이 30 이 아니라 90 이 됐다. 여백의 주인은 padding-inline(30) 하나다. */
  grid-template-columns: calc(var(--ico-xl) + var(--sp-3))
    max-content minmax(0, 5fr) minmax(0, 12fr); }
/* 열 폭도 함께 조인다: 제목·태그는 짧고 본문만 길다 → 4:3:8 에서 3:15 로 (사용자 검수).
   ★ (영문판 2026-07-23) 빨강 열을 3fr → 5fr 로 넓혔다. 3fr 이면 열이 약 100px 이라
     한글 태그("재생 · 보습")는 한 줄로 서지만 영문("Matrix-bound factors")은 3~6줄로 접힌다.
     열이 하나뿐인 표라 비율을 고치는 것이 유일한 전역 해법이다 - 페이지별 예외를 만들면 갈라진다.
   (요청 2026-07-14) 열 간격(gap)은 0 이다 - 세 텍스트 열은 오직 비율로만 나뉜다.
   ① 아이콘과 제목이 붙으면 못 읽는다 → 아이콘 열 자체를 [아이콘 + 여백] 폭으로 잡아
      아이콘 "뒤에만" 간격이 생기게 한다. 텍스트 열 사이는 여전히 0 이다.
   ② 제목 열만 fr 경쟁에서 뺀다(max-content). 3fr 로 두면 fr 이 남는 폭을 다 가져가 열이 최소값에
      묶이고, 긴 제목("개인정보·사진 처리")이 열을 넘쳐 빨간 태그에 달라붙는다.
      폭은 아래 h3 가 정한다 - min-width(136) 으로 짧은 제목의 칸을 지키고, 긴 제목은 제 폭만큼 밀어낸다.
   ③ 끝에 여백 트랙(2fr)을 둔다. 검정 본문이 오른쪽 구분선까지 꽉 차지 않게. */
/* (요청 2026-07-14) 행의 양쪽 끝에 30px 여백 - 아이콘 왼쪽 · 마지막 서브텍스트 오른쪽.
   ⚠️ 여백의 주인은 부모(.ub-row)다. 행(subgrid)에 padding 을 주면 트랙이 부모와 어긋난다
      → 부모의 padding-inline 을 10(--sp-2) → 30(--sp-5) 으로 올린다. 구분선도 함께 들어온다. */
.ub-row__item { position: relative; display: grid; align-items: center;
  grid-template-columns: subgrid; grid-column: 1 / -1;
  gap: 0; padding-block: var(--sp-6);
  transition: background .25s, padding-left .25s; }
/* 구분선은 border 가 아니라 ::after 로 그린다.
   border 는 행의 box 안에 갇혀서 콘텐츠와 같은 폭(840)이 된다 → 선이 짧아 여백이 안 보인다.
   ::after 를 부모 padding(30) 만큼 좌우로 내밀면 선이 컨테이너 끝까지(900) 간다
   → 글자만 안으로 들어간 "마진"으로 읽힌다. subgrid 는 건드리지 않는다. (2026-07-14) */
.ub-row__item::after { content: ""; position: absolute; bottom: 0;
  left: calc(var(--sp-5) * -1); right: calc(var(--sp-5) * -1);
  border-bottom: var(--hairline) solid var(--gray-light); }
/* 맨 위 선도 같은 길이로 - 첫 행이 그린다 */
.ub-row__item:first-child::before { content: ""; position: absolute; top: 0;
  left: calc(var(--sp-5) * -1); right: calc(var(--sp-5) * -1);
  border-top: var(--hairline) solid var(--gray-light); }
/* ── 표 변형(.ub-row--tagwide / --spread) 삭제 (영문판 2026-07-23) ────────────
   한글 기준으로 만든 두 예외였다. tagwide 는 빨강 열을 max-content 로 빼 한 줄로 세웠는데,
   subgrid 라 "가장 긴 태그" 하나가 전 행의 열 폭을 정한다 → 영문에서 긴 태그가 하나만 있어도
   열이 통째로 벌어지고 제목과 태그 사이에 큰 빈칸이 생겼다(사용자 검수: "컬럼 간격 깨짐").
   spread 는 반대로 본문이 짧을 때만 맞는 비율이었다.
   → 표는 .ub-row 하나로 통일한다. 폭 문제는 예외가 아니라 기본 비율(5:12)로 푼다.
   같은 표가 페이지마다 다르게 보이는 것이 가장 큰 문제였다. */

/* hover 회색면도 구분선과 같은 폭이어야 한다 - 선은 컨테이너 끝까지 가는데 면만 콘텐츠 폭(840)
   에서 끊기면, 면이 선보다 좁아 안쪽에 뜬 것처럼 보인다.
   background 는 행의 box(840) 를 넘지 못한다 → box-shadow 로 좌우 padding(30) 만큼 같은 색을
   덧대 900 까지 늘린다. subgrid·레이아웃은 그대로다. (2026-07-14) */
.ub-row__item:hover { background: var(--bg-soft);
  box-shadow: calc(var(--sp-5) * -1) 0 0 var(--bg-soft),
                   var(--sp-5)       0 0 var(--bg-soft); }
.ub-row__item > i { color: var(--point); font-size: var(--ico-xl); line-height: 1; }
/* 제목 열의 폭은 h3 가 정한다(위 max-content 트랙).
   min-width 로 짧은 제목의 칸을 지키고, padding-right 로 빨간 태그와의 최소 간격을 만든다.
   스택되는 ≤1200 에선 아래 반응형에서 푼다. */
.ub-row__item h3 { color: var(--ink); white-space: nowrap;
  min-width: 136px; padding-right: var(--sp-4); }
/* (요청 2026-07-14) 검은 본문(.ub-txt)을 빨간 태그(.ub-tag)에서 20px 떼어 놓는다.
   열 간격(gap)은 0 이라 두 글자가 바짝 붙어 한 덩어리로 읽혔다.
   ★ gap 을 올리지 않는다 - gap 은 모든 열 사이에 걸려 제목·태그 간격까지 벌어진다.
     본문 열 "안쪽"에 padding 을 줘야 이 경계 하나만 벌어진다. 열 폭(15fr)은 그대로다.
     스택되는 ≤1200 에선 아래 반응형에서 푼다(세로로 쌓이면 옆에 태그가 없다). */
.ub-row__item .ub-txt { padding-left: var(--sp-4); }
.ub-row__item .ub-txt { color: var(--gray-dark); }

/* ══════════════════════════════════ 12. 가로 확장 패널 (.ub-exp) ══ */
.ub-exp { display: flex; gap: var(--sp-3);
  height: clamp(360px, 30vw, 460px); }
/* display:grid - 캡션이 패널 높이만큼 늘어나야 글이 아래에 붙는다
   (세로 스택으로 눕는 모바일에서 캡션이 위로 떠 버리는 것을 막는다) */
.ub-exp__item { position: relative; display: grid; flex: 1 1 0; min-width: 0;
  isolation: isolate; border-radius: var(--r-lg); overflow: hidden; cursor: pointer;
  transition: flex-grow .45s ease; }
.ub-exp__item:hover, .ub-exp__item:focus-within { flex-grow: 2.8; }
.ub-exp__item img { position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover; }
.ub-exp__cap { position: relative; z-index: 1; display: grid; align-content: end;
  gap: var(--sp-2); height: 100%;
  /* 상 sp-5 · 우 sp-4 · 하 sp-6 · 좌 sp-3 (좌측 여백만 한 단계 더 줄임) */
  padding: var(--sp-5) var(--sp-4) var(--sp-6) var(--sp-3);
  background: linear-gradient(to top,
    color-mix(in srgb, var(--ink) 90%, transparent) 0%,
    color-mix(in srgb, var(--ink) 40%, transparent) 55%,
    transparent 85%); }
.ub-exp__cap i { color: var(--white); font-size: var(--ico-lg); line-height: 1; }
/* 접힌 띠는 폭이 좁다 - 제목을 줄바꿈시켜 잘리지 않게 한다 */
.ub-exp__cap h3 { color: var(--white); font-weight: 600;
  word-break: keep-all; }
/* ★ 제목 줄 수(1줄 vs 2줄)에 따라 아이콘이 위아래로 널뛰던 문제 (2026-07-14).
   cap 이 align-content:end 라 아래에서부터 쌓이기 때문이다.
   제목칸 높이를 고정해 아이콘 위치를 통일한다.
   ★ (2026-07-16) 접힘/펼침 모두 같은 높이 유지(호버 시 min-height 해제 규칙 제거)
     → 제목칸 높이가 변하지 않아 아이콘·제목이 서로 널뛰지 않는다.
     예약은 3줄 - 한 카드를 펼치면 옆 카드가 좁아지며 긴 제목(예: 멀티셀 프락셀 CO2)이
     3줄까지 늘어나므로, 2줄로 줄이면 그 카드 아이콘만 위로 올라가 정렬이 깨진다. */
.ub-exp__cap h3 {
  display: flex; align-items: flex-start;
  margin-top: var(--box-gap-sm);                      /* 아이콘 ↔ 제목 */
  min-height: calc(var(--fs-content-title) * 1.35 * 3);
  transition: min-height .35s ease;
}
/* ★ (2026-07-16) 카드가 커질 때 이모지 height 고정:
   펼치면 제목칸을 "본문 2줄 높이만큼" 줄이고(min-height -= 본문높이), 그 자리에 본문이
   딱 그 높이로 열린다. 줄어드는 양 = 열리는 양 이라 이모지 아래 총높이가 3줄로 항상 일정
   → 이모지·제목이 위로 안 올라온다. 두 애니메이션 duration(.35s)을 맞춰 널뜀도 없다. */
.ub-exp__item:hover .ub-exp__cap h3,
.ub-exp__item:focus-within .ub-exp__cap h3 {
  min-height: calc(var(--fs-content-title) * 1.35 * 3 - var(--fs-eyebrow) * var(--lh-body) * 2);
}
/* 본문(서브텍스트)은 제목 아래(정상 순서). 접힘: 높이 0(자리 안 차지) → 이모지·제목이 카드
   하단에 낮게 내려가 정렬됨(통일은 위 h3 3줄 예약). 펼침: 딱 본문 2줄 높이로 열리는데,
   위 h3 축소량과 정확히 같아 이모지는 그 자리에 고정된다.
   (이 컴포넌트는 svf-scar·svf-hair·svf-lab·svf-360·forehead-lift·breast-implant·
    bodylift-abdomen 등 여러 페이지가 공유한다.) */
.ub-exp__more { overflow: hidden; height: 0; opacity: 0;
  transition: height .35s ease, opacity .3s ease; }
.ub-exp__more > p { overflow: hidden; color: var(--white); font-size: var(--fs-eyebrow);
 }
.ub-exp__item:hover .ub-exp__more,
.ub-exp__item:focus-within .ub-exp__more {
  height: calc(var(--fs-eyebrow) * var(--lh-body) * 2); opacity: 1; }
/* (요청) .ub-exp--3line 갤러리(예: hip-implant): 제목·아이콘은 고정하되 본문을 2줄이 아닌 3줄로 연다.
   아이콘 고정을 위해 제목칸 예약 = "제목 1줄 + 본문 3줄", 펼치면 제목칸을 본문 3줄만큼 줄여 그 자리에
   본문 3줄이 열린다(줄어드는 양 = 열리는 양이라 아이콘이 안 움직인다). 기본 갤러리(2줄)는 그대로. */
.ub-exp--3line .ub-exp__cap h3 {
  min-height: calc(var(--fs-content-title) * 1.35 + var(--fs-eyebrow) * var(--lh-body) * 3); }
.ub-exp--3line .ub-exp__item:hover .ub-exp__cap h3,
.ub-exp--3line .ub-exp__item:focus-within .ub-exp__cap h3 {
  min-height: calc(var(--fs-content-title) * 1.35); }
.ub-exp--3line .ub-exp__item:hover .ub-exp__more,
.ub-exp--3line .ub-exp__item:focus-within .ub-exp__more {
  height: calc(var(--fs-eyebrow) * var(--lh-body) * 3); }
/* (요청 2026-07-26) .ub-exp--fit : 본문이 길어 2줄로 못 줄이는 갤러리(svf-lab·svf-scar).
   펼치면 본문을 "내용 전체 높이"로 열어 절대 잘리지 않게 한다. 카드 높이가 넉넉하고 캡션이
   아래 정렬이라, 본문이 제목 위로 채워지며 아이콘·제목이 그만큼 위로 오른다(활성 카드만).
   제목칸 예약(3줄)은 접힘 상태 아이콘 정렬용이므로 유지하고, 펼침 때만 자연 높이로 푼다. */
.ub-exp--fit .ub-exp__item:hover .ub-exp__cap h3,
.ub-exp--fit .ub-exp__item:focus-within .ub-exp__cap h3 {
  min-height: 0; }
.ub-exp--fit .ub-exp__item:hover .ub-exp__more,
.ub-exp--fit .ub-exp__item:focus-within .ub-exp__more {
  height: auto; }

/* ══════════════════════════════════════════════════════ 반응형 ══ */
@media (max-width: 1200px) {
  /* 2열로 스택되면 행이 이미 좁다 → subgrid 를 푼다 (들여쓰기는 --tpl-inset 이 0 이 된다) */
  .ub-row { display: block; padding-inline: 0; }
  .ub-row__item { grid-column: auto; padding: var(--sp-6) var(--sp-2); }
  /* [아이콘 | 제목] 한 줄, 그 아래 2열에 빨강(ub-tag) → 검정(ub-txt) 서브텍스트가 쌓인다.
     (요청 2026-07-14) 세로 리듬은 row-gap 이 아니라 margin 이 잡는다 - row-gap 을 두면
     아래 templates-type 의 margin 과 더해져 빨강↔검정이 두 배로 벌어진다. */
  /* 스택 상태에선 아이콘 열이 제목·본문 바로 옆에 붙으므로 열 간격이 필요하다 (PC 는 0) */
  .ub-row__item { grid-template-columns: var(--ico-xl) minmax(0, 1fr);
    gap: 0 var(--sp-5); align-items: start; }
  /* 세로로 쌓이면 제목 옆에 빨간 태그가 오지 않는다 → 폭 제약을 전부 푼다 */
  .ub-row__item h3 { white-space: normal; min-width: 0; padding-right: 0; }
  /* 본문도 마찬가지 - 스택되면 빨간 태그가 옆이 아니라 "위"에 온다 → 왼쪽 20px 은 필요 없다 */
  .ub-row__item .ub-txt { padding-left: 0; }
  /* (요청 2026-07-14) 아이콘(32)과 제목(18×1.35)은 높이가 달라 start 로 두면 윗선이 어긋난다.
     첫 행 안에서 둘 다 세로 중앙에 세워 눈높이를 맞춘다. */
  .ub-row__item > i,
  .ub-row__item h3 { align-self: center; }
  .ub-row__item .ub-tag,
  .ub-row__item .ub-txt { grid-column: 2; }
}

@media (max-width: 991.98px) {
  .ub-ov { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* ★ (요청 2026-07-17) 5장짜리도 모바일에선 한 줄에 2개.
     위 .ub-ov 규칙(특이도 0,1,0)만으로는 안 된다 - PC 의 5열 규칙이 :has() 때문에 (0,4,0) 이라
     미디어쿼리 안에서도 그대로 이겨 폰에서 50px 짜리 5열이 된다. → 같은 특이도로 다시 덮는다. */
  .ub-ov:not(.ub-ov--circle):has(.ub-ov__card:nth-child(5):last-child) {
    grid-template-columns: repeat(2, minmax(0, 1fr)); }

  /* ★ (요청 2026-07-14) 원형 카드는 모바일에서 **다시 오버레이**로 돌아간다.
     원이 다 보이도록 정사각을 유지하고, 글자는 **원 정중앙에 흰색**으로 얹는다.
     (사진 아래 캡션 방식은 좁은 폭에서 원이 작아지고 글이 흩어져 읽기 나쁘다) */
  .ub-ov--circle { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ub-ov--circle .ub-ov__card {
    display: block; position: relative; aspect-ratio: var(--ratio-square); }
  .ub-ov--circle .ub-ov__card img {
    width: 100%; height: 100%; object-fit: cover; }
  /* 흰 글씨가 밝은 사진 위에서 묻히지 않도록 **어두운 반투명 단색**을 원 모양으로 덮는다
     (그라디언트가 아니다 - 원 밖 흰 여백에 띠가 생기지 않게 border-radius 를 원에 맞춘다) */
  .ub-ov--circle .ub-ov__veil {
    position: absolute; inset: 0; align-content: center; padding: var(--sp-4);
    border-radius: 50%;
    background: color-mix(in srgb, var(--ink) 52%, transparent); }
  .ub-ov--circle .ub-ov__veil h3,
  .ub-ov--circle .ub-ov__veil .ub-tag,
  .ub-ov--circle .ub-ov__more > p { color: var(--white); }

  /* sticky 인덱스는 좁은 화면에서 고정을 풀고 위로 눕힌다 */

  /* ★ (요청 2026-07-14) 히어로는 모바일에서 1단이다 - 사진 먼저, 그다음 항목 목록.
     split-cols(2열)를 그대로 두면 좁은 폭을 반으로 갈라 캡션도 항목도 글자 두세 개씩 끊긴다.
     DOM 순서가 [main → list] 라 1열로 접기만 하면 사진이 먼저 온다. */
  .ub-hero { grid-template-columns: minmax(0, 1fr); gap: var(--sp-6); }
  .ub-hero__main { min-height: clamp(260px, 44vw, 360px); }

  /* ★ (요청 2026-07-14) 항목 박스는 [아이콘 | 제목+내용] 2단으로 가르지 않는다.
     좁은 폭에서 텍스트 칸이 반토막 나 제목도 내용도 끊긴다.
     → **[아이콘 + 제목] 한 줄, 그 아래 내용** 으로 세운다. 11(.ub-row__item) 모바일과 같은 골격이다.
     내용은 제목과 같은 열(2)에서 시작한다 - 아이콘 아래로 파고들지 않는다. */
  .ub-hero__item { grid-template-columns: var(--ico-xl) minmax(0, 1fr);
    gap: 0 var(--sp-5); align-items: start; }
  .ub-hero__item > div { display: contents; }
  /* 아이콘과 제목은 같은 줄에서 눈높이를 맞춘다 (11 과 동일) */
  .ub-hero__item > i,
  .ub-hero__item h3 { align-self: center; }
  .ub-hero__item h3 { grid-column: 2; }
  /* ⚠️ 제목↔내용 간격은 여기서 못 준다 - templates-type 레이어의 `h3 + p` 공통 규칙(--box-gap-md)이
     레이어 우선순위로 이긴다. 그 레이어에 같이 적어 둔다(아래 "10 : 히어로 위성 항목"). */
  .ub-hero__item .ub-tag { grid-column: 2; }

  /* 가로 확장 패널 → 세로 스택 (전부 펼친 상태) */
  .ub-exp { flex-direction: column; height: auto; gap: var(--sp-4); }
  .ub-exp__item { flex: 0 0 auto; min-height: clamp(200px, 40vw, 280px); }
  .ub-exp__more { height: auto; opacity: 1; }
  /* 세로로 쌓이면 카드가 저마다 한 줄을 차지하므로 아이콘 높이를 맞출 이유가 없다.
     본문도 항상 펼쳐져 있으니 제목칸 3줄 고정을 풀어야 제목 바로 아래 본문이 붙는다. */
  .ub-exp__cap h3 { min-height: 0; }
  /* ★ 모바일 버그 수정 (2026-07-26): 카드를 터치하면 :focus-within(및 일부 기기의 :hover)이
     데스크톱용 고정 높이를 걸어 제목칸이 줄고 본문이 2줄로 잘렸다. 세로 스택에서는 항상
     펼친 상태이므로 그 규칙들을 auto 로 되돌린다(--3line·--fit 변형도 여기서 함께 풀린다). */
  .ub-exp__item:hover .ub-exp__cap h3,
  .ub-exp__item:focus-within .ub-exp__cap h3 { min-height: 0; }
  .ub-exp__item:hover .ub-exp__more,
  .ub-exp__item:focus-within .ub-exp__more { height: auto; }

  /* 오버레이 카드도 본문을 항상 보여준다 (hover 가 없는 환경) */
  .ub-ov__more { grid-template-rows: 1fr; opacity: 1; }

}

@media (max-width: 767.98px) {

  .ub-time__item { gap: var(--sp-4); }
  .ub-tab__list { justify-content: flex-start; overflow-x: auto;
    flex-wrap: nowrap; scrollbar-width: none; }
  .ub-tab__list::-webkit-scrollbar { display: none; }
  .ub-tab__list button { white-space: nowrap; }
}

@media (max-width: 575.98px) {
  .ub-ov { grid-template-columns: minmax(0, 1fr); }
  .ub-ov__card { aspect-ratio: var(--ratio-photo); }
  /* 원형 카드는 예외다 - 4:3 으로 되돌리면 원이 상하로 잘린다 → **정사각**을 지킨다.
     (요청 2026-07-16) 폰에서도 한 줄에 **2개**. 원이 작아지므로(지름 ~165) 원 안에는
     긴 설명(.ub-ov__more)을 넣지 않고 **제목만** 정중앙에 얹는다(아래 규칙). */
  .ub-ov--circle { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ub-ov--circle .ub-ov__card {
    aspect-ratio: var(--ratio-square); width: 100%; }
  /* 작은 원 안에서 넘치지 않게 태그·설명은 감추고 제목만 남긴다 */
  .ub-ov--circle .ub-ov__veil .ub-tag,
  .ub-ov--circle .ub-ov__more { display: none; }
  .ub-rail__card { flex: 0 0 78%; }
  /* row-gap 은 0 을 유지한다 (위 1200 블록 주석 참조) - 열 간격만 좁힌다 */
  .ub-row__item { gap: 0 var(--sp-4); padding: var(--sp-5) 0; }
}

/* ══════════════════ 소개 (ua-*) - 구 template-about.css */
/* ═══════════════════════════════════════════════════════════════════════════
   template-about.css  —  "미디어 + 글 2단"(.tpl-about) 대체 UI 12안 전용

   ★ 시안 갤러리(template-about.html) 만 이 파일을 링크한다.
     운영 페이지(index.html · 서브 72개)는 이 파일을 읽지 않는다 → 기존 화면 영향 0.

   ★ 값은 전부 main.css :root 토큰에서만 가져온다.
     생짜 px·rem·em 금지(_build/lint_css.py) · #hex 금지 · --wv 금지.
     비율(aspect-ratio)·열 수(fr)·투명도(%)는 스케일의 대상이 아니라 그대로 쓴다.

   ★ 접두사는 ua- (UI Draft) 하나. 변형마다 ua-<이름> 을 덧붙인다.
     .ua = 12안이 공유하는 본문 규격(문단 · 강조 · 사진틀).
   ═══════════════════════════════════════════════════════════════════════════ */

/* main.css 는 @layer 로 감싸여 있다. 여기는 레이어 밖 → 항상 우선한다(재정의 걱정 없음). */

/* ───────────────────────────────────────────────────────── 갤러리 껍데기 (시안 라벨) */

/* ───────────────────────────────────────────────────── 12안 공용 본문 규격
   ★ :where() 로 감싸 특이도를 0 으로 만든다.
     그냥 `.ua p` 로 쓰면 특이도가 (0,1,1) 이라 아래의 한 클래스짜리 규칙
     (.ua-stat__n · .ua-time__node …)을 전부 이겨 버린다
     → 숫자 타일이 본문 크기로, 흰 캡션이 검은 글씨로 깨진다. 실제로 그렇게 깨졌었다. */
:where(.ua p) {
  font-weight: 400;
  color: var(--ink);
  line-height: var(--lh-prose);
}
.ua strong { font-weight: 600; }

/* 사진틀 - 비율만 갈아 끼운다. 사진은 cover 로 채워 어느 안에서도 크기가 흔들리지 않는다. */
.ua-ph {
  position: relative;
  overflow: hidden;
  border-radius: var(--r-lg);
  background: var(--bg-soft);
}
.ua-ph img { width: 100%; height: 100%; object-fit: cover; }

.ua-ph--wide  { aspect-ratio: 16 / 9; }
.ua-ph--cine  { aspect-ratio: 21 / 9; }
.ua-ph--photo { aspect-ratio: var(--ratio-photo); }
.ua-ph--sq    { aspect-ratio: var(--ratio-square); }
.ua-ph--port  { aspect-ratio: var(--ratio-portrait); }
.ua-ph--fill  { height: 100%; }

/* 흰 카드 - 사진 위로 떠오르는 글 상자(03 · 10). 면 위의 면이라 선을 두르지 않고 그림자로 띄운다. */
.ua-card {
  background: var(--white);
  border-radius: var(--r-lg);
  box-shadow: 0 var(--sp-2) var(--sp-6) color-mix(in srgb, var(--ink) 12%, transparent);
}

/* ═════════════════════════════════════════════ 01. 풀블리드 배경 + 글 오버레이 */
.ua-bleed {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  min-height: calc(var(--sp-10) * 3.5);
  display: grid;
  align-items: center;
}
.ua-bleed__bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: -2;
}
.ua-bleed::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(100deg,
    var(--veil-bar) 0%, var(--veil-bar) 42%, transparent 82%);
}
.ua-bleed__panel {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding: var(--sp-9) var(--sp-6);
}
.ua-bleed__inner { max-width: var(--read-width); }
.ua-bleed__kicker {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  margin-bottom: var(--sp-5);
  font-size: var(--fs-eyebrow);
  line-height: var(--lh-tight);
  color: var(--white);
  padding: var(--sp-1) var(--sp-4);
  border-radius: var(--r-pill);
  background: var(--point);
}
.ua-bleed p { color: var(--white); }
.ua-bleed p + p { margin-top: var(--sp-4); }

/* ═════════════════════════════════════════ 03. 사진 위 캡션 카드(오버랩) */
.ua-cap__figure { position: relative; }
.ua-cap__card {
  position: relative;
  z-index: 1;
  margin-top: calc(var(--sp-9) * -1);
  margin-inline: var(--sp-9);
  padding: var(--sp-7);
}
.ua-cap__title {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin-bottom: var(--sp-5);
  font-weight: 600;
  color: var(--ink);
}
.ua-cap__title i { font-size: var(--ico-md); color: var(--point); }
.ua-cap__card p + p { margin-top: var(--sp-4); }
.ua-cap__foot {
  max-width: var(--read-width);
  margin: var(--sp-7) auto 0;
  text-align: center;
  color: var(--gray-dark);
}

/* ═════════════════════════════════════════ 04. 대형 인용문(pull quote) 중심 */

/* ═════════════════════════════════════════ 05. 비대칭 사진 콜라주 3장 */
/* __a 는 4:3 으로 세운다 - 16:9 로 눕히면 옆의 세로컷(__b)보다 한참 짧아져 아래에 큰 구멍이 뚫린다 */

/* ═════════════════════════════════════ 06. 세로 스크롤 스토리(sticky · 사진 교체) */
.ua-story {
  display: grid;
  grid-template-columns: var(--split-cols);
  gap: var(--about-gap);
  align-items: start;
}
.ua-story__stage {
  position: sticky;
  top: var(--sp-8);
  aspect-ratio: var(--ratio-photo);
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--bg-soft);
}
.ua-story__shot {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity .6s ease;
}
.ua-story__shot.is-on { opacity: 1; }

.ua-story__step {
  min-height: calc(var(--sp-10) * 2);
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding-left: var(--sp-5);
  border-left: var(--hairline) solid var(--gray-light);
  opacity: .35;
  transition: opacity .4s ease, border-color .4s ease;
}
.ua-story__step.is-on { opacity: 1; border-left-color: var(--point); }
.ua-story__no {
  margin-bottom: var(--sp-3);
  font-weight: 600;
  color: var(--point);
}

/* ═════════════════════════════════════════ 07. 통계 수치 타일(1994 · 8만 · 6배) */
.ua-stat { display: grid; }
.ua-stat__tiles {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--hairline);                       /* 선을 긋지 않고 배경색이 새어 나와 칸이 갈린다 */
  margin: calc(var(--sp-8) * -1) var(--sp-8) 0;
  padding: 0;
  background: var(--gray-light);
  border-radius: var(--r-lg);
  overflow: hidden;
}
.ua-stat__tile {
  background: var(--white);
  padding: var(--sp-7) var(--sp-5);
  text-align: center;
}
.ua-stat__n {
  font-size: var(--fs-h2title);
  font-weight: 600;
  color: var(--point);
}
.ua-stat__n span { font-size: var(--fs-content-title); }
.ua-stat__k {
  margin-top: var(--sp-2);
  font-size: var(--fs-eyebrow);
  line-height: var(--lh-tight);
  color: var(--gray-dark);
}
.ua-stat__body {
  margin-top: var(--sp-8);
  column-count: 3;
  column-gap: var(--sp-8);
}
.ua-stat__body p { break-inside: avoid; }
.ua-stat__body p + p { margin-top: var(--sp-4); }

/* ═════════════════════════════════════════ 09. 타임라인(연혁형) */
.ua-time { display: grid; row-gap: var(--sp-6); position: relative; }
.ua-time::before {                                   /* 가운데 세로 축 */
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: var(--hairline);
  background: var(--gray-light);
}
.ua-time__item {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  gap: var(--sp-7);
  align-items: center;
}
/* 사진은 16:9 로 눕힌다. 4:3 이면 한 항목이 화면을 통째로 먹어 축(가운데 선)이 끊겨 보인다.
   (2026-07-14 요청) 항목 간격은 --sp-6, 글줄 폭은 20px 좁힌다. */
.ua-time__media.ua-ph { aspect-ratio: var(--ratio-photo-m); }
/* ── 예외 : 글자·라벨이 박힌 도해 (.ua-ph--fit) ─────────────────────────────
   (요청 2026-07-17, location 지하철 약도) 16:9 cover 는 지도 도해의 상하를 잘라
   랜드마크 라벨을 지워 버린다 → 원본 비율 그대로 둔다.
   .tpl-boxes--fit · .tpl-intro--fit 과 같은 취지의 modifier 다. */
.ua-time__media.ua-ph--fit { aspect-ratio: auto; }
.ua-ph--fit img { height: auto; object-fit: contain; }
.ua-time__txt { max-width: calc(100% - 20px); }
.ua-time__item:not(.ua-time__item--flip) .ua-time__txt { margin-right: auto; }
.ua-time__item--flip .ua-time__txt { margin-left: auto; }
.ua-time__node {
  position: relative;
  z-index: 1;
  display: grid;
  place-items: center;
  width: calc(var(--sp-8) * 1.3);
  height: calc(var(--sp-8) * 1.3);
  border-radius: 50%;
  background: var(--point);
  color: var(--white);
  font-size: var(--fs-eyebrow);
  font-weight: 600;
  line-height: var(--lh-tight);
}
.ua-time__txt p + p { margin-top: var(--sp-4); }
.ua-time__cue {
  margin-bottom: var(--sp-3);
  font-weight: 600;
  color: var(--ink);
}
/* 짝수 항목은 좌우를 뒤집어 축을 사이에 두고 번갈아 선다 */
.ua-time__item--flip .ua-time__media { order: 3; }
.ua-time__item--flip .ua-time__node  { order: 2; }
.ua-time__item--flip .ua-time__txt   { order: 1; text-align: right; }

/* ═════════════════════════════════════════ 10. 카드 사진 + 글 오프셋 겹침 */
.ua-offset {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  align-items: center;
}
.ua-offset__media { grid-area: 1 / 1 / 2 / 9; }
.ua-offset__text {
  grid-area: 1 / 7 / 2 / 13;
  z-index: 1;
  margin-top: var(--sp-9);
  padding: var(--sp-8);
}
.ua-offset__tag {
  display: inline-block;
  margin-bottom: var(--sp-5);
  padding: var(--sp-1) var(--sp-4);
  border-radius: var(--r-pill);
  background: var(--point-bg);
  color: var(--point);
  font-size: var(--fs-eyebrow);
  font-weight: 600;
  line-height: var(--lh-tight);
}
.ua-offset__text p + p { margin-top: var(--sp-4); }

/* ═════════════════════════════════════════ 11. 3분할 그리드(동일 높이 3열) */

/* ═════════════════════════════════════════ 12. 사진 마스크(원형 · 비대칭 라운드) */
.ua-mask {
  display: grid;
  grid-template-columns: var(--split-cols);
  gap: var(--about-gap);
  align-items: center;
}
.ua-mask__art {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  align-items: center;
}
.ua-mask__blob {
  grid-area: 1 / 1 / 2 / 6;
  aspect-ratio: var(--ratio-photo);
  overflow: hidden;
  /* 비대칭 라운드 - 대각선 두 모서리만 크게 깎는다. 값은 토큰 파생이라 생짜 숫자가 아니다. */
  border-radius: calc(var(--sp-9) * 1.2) var(--r-lg) calc(var(--sp-9) * 1.2) var(--r-lg);
}
.ua-mask__circle {
  grid-area: 1 / 4 / 2 / 7;
  align-self: end;
  z-index: 1;
  aspect-ratio: var(--ratio-square);
  overflow: hidden;
  border-radius: 50%;
  border: var(--sp-2) solid var(--white);
  margin-bottom: calc(var(--sp-8) * -1);
}
.ua-mask__blob img,
.ua-mask__circle img { width: 100%; height: 100%; object-fit: cover; }
.ua-mask__body p + p { margin-top: var(--sp-4); }
.ua-mask__body i {
  display: block;
  margin-bottom: var(--sp-5);
  font-size: var(--ico-xl);
  color: var(--point);
}

/* ═══════════════════════════════════════════════════════════════════════════
   반응형 - 브레이크포인트는 991.98 / 767.98 두 개만 쓴다(DESIGN_SYSTEM 규칙).
   ═══════════════════════════════════════════════════════════════════════════ */
@media (max-width: 991.98px) {
  .ua-case { margin-block: var(--sp-9); }

  /* 01 - 좁은 화면에선 가로 그라디언트로 글이 안 읽힌다 → 면을 통째로 덮는다 */
  .ua-bleed::after { background: var(--veil-bar); }
  .ua-bleed__panel { padding-block: var(--sp-8); }

  /* 03 - 카드가 사진을 파고드는 폭을 줄인다 */
  .ua-cap__card {
    margin-top: calc(var(--sp-6) * -1);
    margin-inline: var(--sp-4);
    padding: var(--sp-6);
  }

  /* 06 - sticky 해제. 사진은 글 위에 눕고 스크롤에 맞춰 계속 교체된다 */
  .ua-story { grid-template-columns: 1fr; gap: var(--sp-6); }
  .ua-story__stage { position: relative; top: auto; }
  .ua-story__step { min-height: 0; padding-block: var(--sp-5); }

  /* 07 - 타일 3열은 390px 에서 숫자가 깨진다 → 1열로 세운다 */
  .ua-stat__tiles {
    grid-template-columns: 1fr;
    margin-inline: var(--sp-4);
    margin-top: calc(var(--sp-6) * -1);
  }
  .ua-stat__tile { padding: var(--sp-5); }
  .ua-stat__body { column-count: 1; margin-top: var(--sp-6); }

  /* 08 - 21:9 는 모바일에서 너무 납작하다 → 16:9 로 */

  /* 09 - 가운데 축을 왼쪽으로 옮기고 전부 좌측 정렬.
     ★ 노드는 좁혀도 "1994" 4글자가 들어가야 한다 - --sp-6(25) 로 줄이면 글자가 원 밖으로 삐져나온다.
       원 지름을 --sp-8 기준으로 잡고 축(::before)을 그 절반 위치에 맞춘다. */
  .ua-time::before { left: calc(var(--sp-8) * .55); }
  .ua-time__item {
    grid-template-columns: calc(var(--sp-8) * 1.1) 1fr;
    gap: var(--sp-4);
    row-gap: var(--sp-4);
  }
  .ua-time__node {
    grid-area: 1 / 1 / 2 / 2;
    align-self: start;
    width: calc(var(--sp-8) * 1.1);
    height: calc(var(--sp-8) * 1.1);
    font-size: var(--ui-text);
  }
  .ua-time__media { grid-area: 1 / 2 / 2 / 3; }
  .ua-time__txt   { grid-area: 2 / 2 / 3 / 3; }
  .ua-time__item--flip .ua-time__media,
  .ua-time__item--flip .ua-time__node,
  .ua-time__item--flip .ua-time__txt { order: 0; }
  .ua-time__item--flip .ua-time__txt { text-align: left; }

  /* 10 - 겹침을 풀고 카드만 살짝 물린다 */
  .ua-offset { grid-template-columns: 1fr; }
  .ua-offset__media { grid-area: auto; }
  .ua-offset__text {
    grid-area: auto;
    margin-top: calc(var(--sp-6) * -1);
    margin-inline: var(--sp-4);
    padding: var(--sp-6);
  }

  /* 11 - 3열 → 1열. 사진 2장은 나란히 남겨 리듬을 지킨다 */

  /* 12 - 마스크 2장이 겹치면 좁은 화면에서 얼굴이 가려진다 → 나란히 */
  .ua-mask { grid-template-columns: 1fr; gap: var(--sp-6); }
  .ua-mask__blob {
    grid-area: 1 / 1 / 2 / 5;
    border-radius: calc(var(--sp-9) * .8) var(--r-lg) calc(var(--sp-9) * .8) var(--r-lg);
  }
  .ua-mask__circle {
    grid-area: 1 / 4 / 2 / 7;
    margin-bottom: calc(var(--sp-6) * -1);
    border-width: var(--sp-1);
  }
}

@media (max-width: 767.98px) {
  .ua-bleed { min-height: calc(var(--sp-10) * 2.6); }
}

/* ── UI 이름표 (2026-07-13) - 4개 갤러리가 같은 배지를 쓴다. 코드는 48개가 서로 겹치지 않는다. */

/* ══════════════════ 전후사진 (bna-*) - 구 template-bna.css */
@charset "utf-8";
/* ============================================================================
   template-bna.css — 전후사진(B&A) UI 대체 디자인 12안 전용
   ----------------------------------------------------------------------------
   · template-bna.html 에서만 쓴다. 기존 페이지(72개)는 이 파일을 링크하지 않는다.
   · main.css 토큰만 쓴다(색·폰트·간격·라운드). hex·생짜 px 금지.
   · 새 수치가 필요하면 아래 :root 에서 기존 토큰으로부터 파생시킨다.
     (main.css 는 수정 금지이므로 새 이름은 여기서 붙인다 — 전부 --bna-* 접두)

   ── 원본 에셋 기하 (bna 이미지 197장 전수 실측, 전부 1250×600 동일 레이아웃) ──
     · 카드 영역      x 112‥1148 (폭 1036) · y 20‥512 (높이 492)
     · Before/After 분할선   x = 626
     · 가운데 흰 원형 화살표  x 598‥650  ← 반쪽 크롭 시 "반달 자국"이 남는다
     · 하단 라벨 띠(Before / After N개월차)  y 449‥512  ← 에셋에 이미 박혀 있다
     · 맨 아래 브랜드 로고 띠  y 520‥                    ← 카드 크롭에서 제외된다

   ⇒ 반쪽 크롭은 원형 화살표를 피해서 자른다
        BEFORE  x 112‥598  (폭 486)
        AFTER   x 654‥1148 (폭 494)
      두 쪽을 겹치는 시안(01·02·09)은 공칭 폭 490 으로 통일한다(오차 0.8%, 무시 가능).
      하단 라벨 띠는 그대로 살린다 → Before·After 라벨을 새로 만들지 않는다.
   ========================================================================== */

:root {
  /* 원형 화살표 버튼 · 와이프 손잡이 지름 */
  --bna-nav:    calc(var(--sp-6) + var(--sp-2));
  --bna-handle: calc(var(--sp-6) + var(--sp-3));
  /* 1~2px 급 얇은 선 (--sp-1 = 5px 에서 파생) */
  --bna-hair:   calc(var(--sp-1) * 0.4);
  /* 썸네일 스트립 한 칸 폭 */
  --bna-thumb:  var(--sp-9);
  /* 가로 스크롤·마퀴 카드 폭 */
  --bna-card:   calc(var(--sp-10) * 2.4);
  /* 그리드 최소 칼럼 폭 */
  --bna-col:    calc(var(--sp-10) * 2);
}

/* ══════════════════════════════════════════════════════════════════════════
   갤러리 크롬 (시안 라벨) — 실제 페이지에는 들어가지 않는다
   ══════════════════════════════════════════════════════════════════════════ */

/* ══════════════════════════════════════════════════════════════════════════
   공통 1 — 크롭 유틸 (.bna-shot)
   원본 합성 이미지에서 필요한 부분만 잘라 보여 준다. 이미지 파일은 원본 그대로.
   ══════════════════════════════════════════════════════════════════════════ */
.bna-shot {
  position: relative;
  overflow: hidden;
  border-radius: var(--r-lg);
  background: var(--bg-soft);
}
.bna-shot img {
  position: absolute;
  max-width: none;                       /* main.css 리셋(max-width:100%) 무력화 — 필수 */
  height: calc(100% * 600 / 492);        /* 카드 높이 492 기준으로 원본을 확대 */
  top: calc(-100% * 20 / 492);           /* 카드 상단 y=20 만큼 끌어올린다 */
}
/* 카드 전체(Before+After 한 장) */
.bna-shot--full { aspect-ratio: 1036 / 492; }
.bna-shot--full img {
  width: calc(100% * 1250 / 1036);
  left: calc(-100% * 112 / 1036);
}
/* Before 반쪽 (원형 화살표 앞에서 자른다) */
.bna-shot--b { aspect-ratio: 490 / 492; }
.bna-shot--b img {
  width: calc(100% * 1250 / 490);
  left: calc(-100% * 112 / 490);
}
/* After 반쪽 (원형 화살표 뒤에서 자른다) */
.bna-shot--a { aspect-ratio: 490 / 492; }
.bna-shot--a img {
  width: calc(100% * 1250 / 490);
  left: calc(-100% * 654 / 490);
}

/* ══════════════════════════════════════════════════════════════════════════
   공통 2 — 주의 문구 · 케이스 라벨 · 원형 화살표 · 탭
   ══════════════════════════════════════════════════════════════════════════ */
.bna-note {
  font-size: var(--fs-eyebrow);
  line-height: 1.6;
  color: var(--gray-dark);
  margin-top: var(--sp-5);
}
.bna-cap {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  font-size: var(--fs-eyebrow);
  font-weight: 700;
  letter-spacing: .04em;
  color: var(--point);
  margin-bottom: var(--sp-2);
}
.bna-cap span {
  font-weight: 400;
  color: var(--gray-dark);
}

/* 원형 좌우 화살표 (도트 인디케이터 금지 → 화살표·탭·썸네일만 쓴다) */
.bna-nav {
  display: grid;
  place-items: center;
  width: var(--bna-nav);
  height: var(--bna-nav);
  border-radius: 999px;
  border: 1px solid var(--gray-light);
  background: var(--white);
  color: var(--ink);
  font-size: var(--ico-sm);
  transition: background .2s ease, color .2s ease, border-color .2s ease;
}
.bna-nav:hover { background: var(--point); border-color: var(--point); color: var(--white); }
.bna-nav:disabled { opacity: .35; cursor: default; }
.bna-nav:disabled:hover { background: var(--white); border-color: var(--gray-light); color: var(--ink); }

/* 탭 (각도 · 케이스 전환) */

/* ══════════════════════════════════════════════════════════════════════════
   01 — bna-wipe : 드래그 와이프
   ══════════════════════════════════════════════════════════════════════════ */
.bna-wipe {
  display: grid;
  /* 열 수는 인라인 토큰으로만 조절한다(style="--cols:2"). 지정이 없으면 기존 그대로 3열. */
  grid-template-columns: repeat(var(--cols, 3), 1fr);
  /* (요청 2026-07-14) 사진 사이 간격 30 → 60. --sp-7 이 1920 에서 정확히 60 이다
     (좁아지면 37 까지 함께 줄어든다). 생짜 60px 을 박지 않는다. */
  gap: var(--sp-7);
}
/* CASE 캡션은 쓰지 않는다 (요청 2026-07-14).
   ★ HTML 에서도 지웠지만 규칙을 여기 남긴다 - 이 템플릿을 새 페이지에 복사해 붙일 때
     캡션이 딸려 와도 자동으로 안 보인다. "한 곳만 고치면 전 페이지 반영"의 안전망이다. */
.bna-wipe .bna-cap { display: none; }
/* 39 의 하단 주의 문구는 가운데 정렬한다 (요청 2026-07-15).
   3열 격자 아래에 한 줄로 서는 캡션이라 왼쪽에 붙으면 격자 축과 어긋나 떠 보인다.
   ★ 39 스코프로 한정한다(`.bna-wipe ~`) - .bna-note 는 08·35 등 다른 bna 템플릿도 쓰는
     공통 클래스라, 클래스 자체에 주면 안 건드려도 될 템플릿까지 함께 바뀐다.
   이 템플릿을 쓰는 모든 페이지·시안에 함께 걸린다. */
.bna-wipe ~ .bna-note { text-align: center; }
/* 모바일은 1단 - 3열을 유지하면 사진이 89px 까지 쪼그라들어 전후 비교가 불가능하다.
   이 템플릿을 쓰는 모든 섹션에 함께 걸린다. (요청 2026-07-14) */
@media (max-width: 991.98px) {
  .bna-wipe { grid-template-columns: 1fr; }
}
/* 리스트 분류 필터(전후사진·블로그) - 토글 바로 아래 본문 폭(760) 구분선 + 우측 끝 작은 드롭다운
   (요청 2026-07-18). 구분선은 카드 영역(.rel-cite, 760)과 폭·정렬이 같다. 기존 토큰만 사용. */
/* 구분선 폭·드롭다운 위치/크기를 전 리스트 페이지에서 블로그 기준(1000)으로 통일(요청 2026-07-18).
   전후사진·셀카(사진 760)에서도 구분선은 1000 으로 같게 간다. */
.bna-filter { display: flex; justify-content: flex-end; align-items: center;
  max-width: 1000px; margin: var(--sp-2) auto var(--sp-6);   /* 구분선 위 여백 +10px */
  border-top: 1px solid var(--gray-light); padding-top: var(--sp-4); }
.bna-filter__pick { display: flex; align-items: center; gap: var(--sp-3); }
.bna-filter label { font-size: var(--fs-content-subtext); font-weight: 600; color: var(--gray-dark); }
/* 최대한 작게 - 낮은 높이(세로 sp-1) + 작은 글씨(eyebrow). 커스텀 캐럿은 오른쪽에서 sp-3 만큼 띄운다. */
.bna-filter select { appearance: none; -webkit-appearance: none;
  padding: var(--sp-1) var(--sp-6) var(--sp-1) var(--sp-3); border-radius: var(--r-pill);
  border: 1px solid var(--gray-light); color: var(--ink);
  background: var(--white) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='7' viewBox='0 0 12 8' fill='none' stroke='%23888888' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5'/%3E%3C/svg%3E") no-repeat right var(--sp-3) center;
  font-size: var(--fs-eyebrow); font-weight: 600; cursor: pointer; }
.bna-filter select:hover, .bna-filter select:focus { border-color: var(--point); outline: none; }
/* 셀카후기 - '내 후기 작성하기' 진입 버튼(요청 2026-07-18). 드롭다운(select)과 같은 크기·모양이되
   외곽선·글씨는 포인트색(외곽 유지). 왼쪽 끝, 드롭다운은 오른쪽 끝(:has 로 space-between). */
.bna-filter__write { padding: var(--sp-1) var(--sp-3); border-radius: var(--r-pill);
  border: 1px solid var(--point); color: var(--point); background: var(--white);
  font-size: var(--fs-eyebrow); font-weight: 600; white-space: nowrap; cursor: pointer;
  transition: background .15s, color .15s; }
.bna-filter__write:hover { background: var(--point); color: var(--white); }
.bna-filter:has(.bna-filter__write) { justify-content: space-between; }
/* 셀카 후기 작성 페이지 - 구분선 위(토글)는 리스트와 동일, 아래만 폼.
   구분선(.bna-filter)은 셀카 리스트와 동일하게 1000(base 유지), 본문(폼)은 셀카 카드와 동일하게 850. */
.review-write__body { max-width: 850px; margin-inline: auto; margin-top: var(--sp-6); }
/* 셀카 후기 작성 - 줄별 래퍼(모바일에서도 대부분 1줄 2개 유지, 후기 내용만 1줄 1개).
   .field 인라인 span 대신 래퍼로 열을 잡아 counsel__form 의 모바일 스택 규칙에 영향받지 않게 한다. */
.review-row { grid-column: 1 / -1; display: grid; gap: var(--sp-5); }
/* grid 칸이 내용(넓은 select 등) 때문에 자기 몫보다 커져 옆 칸을 침범하지 않도록 축소 허용. */
.review-row > * { min-width: 0; }
.review-row select, .review-row input { max-width: 100%; }
.review-row--half, .review-row--photo { grid-template-columns: 1fr 1fr; }   /* 만족도·시술부위 / Before·After = 1줄 2개 */
.review-row--3-1 { grid-template-columns: 3fr 1fr; }                          /* 제목 75% : 닉네임 25% */
/* 사진 추가 박스는 빠른 상담(consult-fast)과 동일 크기(≈133×99). 본문이 850이라 1/4 셀은 작아지므로 고정 폭으로 맞춘다. */
.review-write .photo-up__grid > li { width: 133px; max-width: 100%; }
@media (max-width: 575.98px) {
  /* 모바일 - 열을 그대로 두되 간격을 줄이고, 별점은 좁은 반칸에 맞게 축소(넘침 방지). */
  .review-row { gap: var(--sp-3); }
  .review-write .star-rate { gap: 3px; }
  .review-write .star-rate__btn { font-size: clamp(15px, 4.4vw, 28px); }   /* 반칸에 별 5개 한 줄로 (줄바꿈 방지) */
  .review-write .photo-up__grid > li { width: 100%; }        /* 반칸 안에서 사진 추가 박스는 칸 폭에 맞춘다 */
}
.bna-wipe__box {
  --wipe: 50%;
  position: relative;
  aspect-ratio: 490 / 492;
  border-radius: var(--r-lg);
  overflow: hidden;
  touch-action: none;                    /* 터치 드래그가 스크롤로 새지 않게 */
  cursor: ew-resize;
  user-select: none;
}
.bna-wipe__box .bna-shot {
  position: absolute;
  inset: 0;
  border-radius: 0;
}
.bna-wipe__box .bna-shot--a { clip-path: inset(0 0 0 var(--wipe)); }
/* (요청 2026-07-15) 모자이크 오버레이 - 36(.tpl-bna__blur)과 같은 blur(10px) 를 쓰되
   ① Before 쪽(좌측)만 덮는다. 덮는 폭을 --wipe 에 묶었으므로 손잡이를 끌어도 경계가
      함께 움직여, 드래그로 Before 원본이 새어 나오지 않는다(의료법상 노출 금지).
   ② 36 과 달리 로그인 게이트가 아니다 → pointer-events:none 으로 드래그를 막지 않는다.
   레이어 순서(DOM 순서 그대로): 사진(.bna-shot) → 모자이크(.bna-wipe__mask) → 손잡이(.bna-wipe__handle) */
/* (요청 2026-07-15) 39 의 CTA 는 사진에 더 붙인다 : 1920 기준 80 → 40.
   ★ .section__foot 에 margin 을 직접 박지 않는다. 간격의 주인은 여전히 main.css 의 CTA 규칙이고,
     여기서는 그 규칙이 읽는 변수만 이 섹션 안에서 갈아 끼운다(--sp-6 = 1920 에서 40).
     → 실제 페이지(.section > .container)와 시안(.at-body > .container)이 서로 다른 셀렉터로
       CTA 간격을 잡고 있어도, 둘 다 같은 변수를 읽으므로 한쪽만 어긋날 수 없다.
   39 를 쓰는 모든 페이지·시안에 함께 걸린다. */
:is(.container, .container--full):has(> .bna-wipe) { --gap-cta-button: var(--sp-6); }
.bna-wipe__mask {
  position: absolute;
  inset: 0;
  clip-path: inset(0 calc(100% - var(--wipe)) 0 0);
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  pointer-events: none;
}
/* 안내 문구는 "가려진 폭"의 한가운데 선다. 마스크가 clip-path 로 잘리므로 박스 정중앙에 두면
   문구의 오른쪽 절반이 잘려 나간다 → 좌측 영역(0 ~ --wipe)의 중점 calc(var(--wipe)/2) 에 못박는다.
   손잡이를 끌면 문구도 함께 따라 움직이고, 0% 로 밀면 마스크와 함께 사라진다.
   클릭은 받지 않는다(로그인은 섹션 하단 CTA 하나로 모은다) - 드래그를 막지 않기 위함. */
.bna-wipe__mask p {
  position: absolute;
  top: 50%;
  left: calc(var(--wipe) / 2);
  transform: translate(-50%, -50%);
  display: grid;
  justify-items: center;
  gap: var(--sp-2);
  width: max-content;
  max-width: 90%;
  text-align: center;
  color: var(--white);
  font-size: var(--fs-content-subtext);
  line-height: 1.5;
  text-shadow: 0 1px 6px color-mix(in srgb, var(--ink) 45%, transparent);
}
.bna-wipe__mask i { font-size: var(--ico-md); }
/* Once logged in (html.is-authed) the static before/after masks are removed. Same approach as
   front-kr: the .bna-wipe__mask markup is hard-coded on many treatment pages and can't read React
   auth state, so AuthBodyClass toggles a class on <html> and this rule unlocks them all at once. */
html.is-authed .bna-wipe__mask { display: none; }
.bna-wipe__handle {
  position: absolute;
  top: 0;
  bottom: 0;
  left: var(--wipe);
  width: var(--bna-hair);
  background: var(--white);
  transform: translateX(-50%);
  display: grid;
  place-items: center;
}
/* 원(핸들 손잡이)은 선(2px) 위에 "얹히는" 것이지 선 안에 담기는 것이 아니다.
   예전엔 부모(.bna-wipe__handle)가 width:2px 인 grid 이고 원이 45px 라, 아이템이 트랙보다
   22배 넓어 place-items:center 가 먹지 않고 왼쪽 기준으로 깔려 오른쪽으로 21.5px 삐져나왔다.
   → 부모를 기준으로 절대 배치해 가로·세로 모두 정중앙에 못박는다. (2026-07-14) */
.bna-wipe__handle i {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: var(--bna-handle);
  height: var(--bna-handle);
  border-radius: 999px;
  background: var(--white);
  color: var(--ink);
  font-size: var(--ico-md);
  display: grid;
  place-items: center;
  box-shadow: 0 2px 10px color-mix(in srgb, var(--ink) 30%, transparent);
}
.bna-wipe__handle:focus-visible { outline: none; }
.bna-wipe__handle:focus-visible i { outline: 2px solid var(--point); outline-offset: 2px; }

/* ══════════════════════════════════════════════════════════════════════════
   02 — bna-fade : 호버(터치 시 탭)하면 After 가 겹쳐 떠오른다
   ══════════════════════════════════════════════════════════════════════════ */
.bna-fade {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--sp-5);
}
.bna-fade__card {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 490 / 492;
  border-radius: var(--r-lg);
  overflow: hidden;
  text-align: left;
}
.bna-fade__card .bna-shot {
  position: absolute;
  inset: 0;
  border-radius: 0;
}
.bna-fade__card .bna-shot--a {
  opacity: 0;
  transition: opacity .45s ease;
}
.bna-fade__card:hover .bna-shot--a,
.bna-fade__card:focus-visible .bna-shot--a,
.bna-fade__card.is-on .bna-shot--a { opacity: 1; }

.bna-fade__hint {
  position: absolute;
  left: var(--sp-3);
  top: var(--sp-3);
  z-index: 1;
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  padding: var(--sp-1) var(--sp-3);
  border-radius: 999px;
  background: color-mix(in srgb, var(--ink) 55%, transparent);
  color: var(--white);
  font-size: var(--fs-eyebrow);
  transition: opacity .3s ease;
}
.bna-fade__card:hover .bna-fade__hint,
.bna-fade__card.is-on .bna-fade__hint { opacity: 0; }

/* ══════════════════════════════════════════════════════════════════════════
   05 — bna-grid : 전·후 쌍이 카드로 나열되는 갤러리
   ══════════════════════════════════════════════════════════════════════════ */
.bna-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(var(--bna-col), 100%), 1fr));
  gap: var(--sp-5);
}
.bna-grid__card {
  padding: var(--sp-4);
  border-radius: var(--r-lg);
  border: 1px solid var(--gray-light);
  background: var(--white);
  transition: border-color .2s ease, transform .2s ease;
}
.bna-grid__card:hover {
  border-color: var(--point);
  transform: translateY(-4px);
}
.bna-grid__meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-2);
  margin-top: var(--sp-3);
  font-size: var(--fs-eyebrow);
  color: var(--gray-dark);
}

/* ══════════════════════════════════════════════════════════════════════════
   07 — bna-film : 썸네일 스트립 + 대형 뷰
   ══════════════════════════════════════════════════════════════════════════ */
.bna-film {
  display: grid;
  grid-template-columns: var(--bna-thumb) 1fr;
  gap: var(--sp-4);
  align-items: start;
}
.bna-film__strip {
  display: grid;
  gap: var(--sp-2);
}
.bna-film__thumb {
  display: block;
  width: 100%;
  padding: 0;
  border-radius: var(--r-sm);
  overflow: hidden;
  border: 2px solid transparent;
  opacity: .55;
  transition: opacity .2s ease, border-color .2s ease;
}
.bna-film__thumb .bna-shot { border-radius: 0; }
.bna-film__thumb:hover { opacity: 1; }
.bna-film__thumb.is-on {
  opacity: 1;
  border-color: var(--point);
}
.bna-film__stage .bna-shot { width: 100%; }
.bna-film__cap {
  margin-top: var(--sp-3);
  font-size: var(--fs-eyebrow);
  color: var(--gray-dark);
}

/* ══════════════════════════════════════════════════════════════════════════
   11 — bna-marquee : 카드가 끊김 없이 흐른다 (호버 시 정지)
   ══════════════════════════════════════════════════════════════════════════ */
.bna-marquee {
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, var(--ink) 8%, var(--ink) 92%, transparent);
  mask-image: linear-gradient(90deg, transparent, var(--ink) 8%, var(--ink) 92%, transparent);
}
.bna-marquee__track {
  display: flex;
  gap: var(--sp-4);
  width: max-content;
  animation: bna-flow 40s linear infinite;
}
.bna-marquee:hover .bna-marquee__track,
.bna-marquee:focus-within .bna-marquee__track { animation-play-state: paused; }
.bna-marquee__item {
  flex: 0 0 auto;
  width: var(--bna-card);
}
.bna-marquee__item .bna-shot { width: 100%; }
@keyframes bna-flow {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}
@media (prefers-reduced-motion: reduce) {
  .bna-marquee__track { animation: none; }
  .bna-marquee { overflow-x: auto; }
}

/* ══════════════════════════════════════════════════════════════════════════
   12 — bna-lightbox : 썸네일 그리드 → 클릭 시 확대 모달
   ══════════════════════════════════════════════════════════════════════════ */
.bna-lightbox {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(var(--bna-col), 100%), 1fr));
  gap: var(--sp-4);
}
.bna-lightbox__cell {
  position: relative;
  display: block;
  width: 100%;
  border-radius: var(--r-lg);
  overflow: hidden;
}
.bna-lightbox__cell .bna-shot { border-radius: 0; }
.bna-lightbox__zoom {
  position: absolute;
  right: var(--sp-3);
  bottom: var(--sp-3);
  display: grid;
  place-items: center;
  width: var(--bna-nav);
  height: var(--bna-nav);
  border-radius: 999px;
  background: color-mix(in srgb, var(--ink) 55%, transparent);
  color: var(--white);
  font-size: var(--ico-sm);
  opacity: 0;
  transition: opacity .2s ease;
}
.bna-lightbox__cell:hover .bna-lightbox__zoom,
.bna-lightbox__cell:focus-visible .bna-lightbox__zoom { opacity: 1; }

/* 모달 */
.bna-lb {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: none;
  place-items: center;
  padding: var(--sp-5);
  background: var(--veil-modal);
}
.bna-lb.is-on { display: grid; }
.bna-lb__inner {
  position: relative;
  width: 100%;
  max-width: 1100px;
}
.bna-lb__inner .bna-shot { width: 100%; }
.bna-lb__cap {
  margin-top: var(--sp-3);
  text-align: center;
  font-size: var(--fs-eyebrow);
  color: var(--white);
}
.bna-lb__close {
  position: absolute;
  right: 0;
  bottom: 100%;
  margin-bottom: var(--sp-2);
}
.bna-lb__prev,
.bna-lb__next {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
}
.bna-lb__prev { right: 100%; margin-right: var(--sp-3); }
.bna-lb__next { left: 100%; margin-left: var(--sp-3); }

/* ══════════════════════════════════════════════════════════════════════════
   모바일 (390px 대응)
   ══════════════════════════════════════════════════════════════════════════ */
@media (max-width: 768px) {

  /* 각도 탭 3열 → 1열 */

  /* 좌우 비교는 모바일에서도 좌우를 유지한다(비교가 목적) — 화살표만 뺀다 */

  /* 썸네일 스트립을 아래로 내려 가로로 눕힌다 */
  .bna-film { grid-template-columns: 1fr; }
  .bna-film__strip {
    grid-auto-flow: column;
    grid-auto-columns: var(--bna-thumb);
    overflow-x: auto;
    order: 2;
  }
  .bna-film__stage { order: 1; }

  /* 아코디언 3각도 → 가로 스크롤 */

  /* 라이트박스 좌우 버튼을 이미지 안쪽으로 */
  .bna-lb__prev { right: auto; left: var(--sp-2); margin-right: 0; }
  .bna-lb__next { left: auto; right: var(--sp-2); margin-left: 0; }
}

/* ── UI 이름표 (2026-07-13) - 4개 갤러리가 같은 배지를 쓴다. 코드는 48개가 서로 겹치지 않는다. */

/* ══════════════════ 수술정보 (ti-*) - 구 template-info.css */
/* ============================================================================
   template-info.css - "수술 정보"(.tpl-info) 대체 UI 12안  [시안 갤러리 전용]

   ★ 이 파일은 template-info.html 만 링크한다. 실 페이지(72개)는 링크하지 않는다.
   ★ main.css / page-template.css 는 손대지 않았다. 여기 있는 것은 전부 신규 클래스다.
   ★ 접두사는 ti- (template-info) 하나뿐이다. 기존 tpl-* 와 절대 겹치지 않는다.

   값 규칙 (DESIGN_SYSTEM · _build/lint_css.py)
     · 색   : 팔레트 토큰만 (--ink --dark --point --accent --white --gray-dark
              --gray-light --point-bg --point-soft --bg-soft --bg-mute). hex 금지.
     · 폰트 : --fs-caption/body/sub/title/display · --fs-fine · --box-title-fs · --box-text-fs
     · 간격 : --sp-1 ~ --sp-10 · --box-gap · --flow-gap
     · 라운드: --r-lg (박스·사진 공통 20) · --r-pill (알약)
     · padding/margin/gap/font-size/border-radius/width/height/inset 에 생짜 px 금지
       → var() · calc() · clamp() 로만 쓴다.
   ========================================================================== */

/* ══════════════════════════════════════════════ 0) 갤러리 크롬 (시안 라벨)
   시안을 구분하는 라벨 줄. 실제 컴포넌트가 아니라 "시안 갤러리"의 뼈대다. */
.ti-note { margin-top: var(--sp-2); font-size: var(--fs-content-subtext); color: var(--gray-dark);
 }

/* ── 공통 사진 셸 ─────────────────────────────────────────────────
   ① .ti-photo : 옆 칸(정보) 높이에 맞춰 늘어나는 컬럼 사진. 모바일에서는 원본 비율로 되돌린다.
   ② .ti-band  : 가로로 눕는 배너 사진. 비율 고정이라 모바일에서도 absolute 를 유지한다. */
.ti-photo { position: relative; border-radius: var(--r-lg); overflow: hidden; }
.ti-photo img { position: absolute; inset: 0; display: block;
  width: 100%; height: 100%; object-fit: cover; object-position: center; }
/* ★ img 를 absolute 로 띄우면 figure 에 높이를 줄 것이 없다.
   옆 칸이 늘려 주는 자리(align-items: stretch)에서는 그걸로 충분하지만,
   start · center 로 세우는 자리(04 · 08 · 11)에서는 figure 가 0 으로 접힌다
   → 그 자리에서만 비율로 높이를 준다. */
.ti-photo--ar { aspect-ratio: var(--ratio-square); }
.ti-band { position: relative; border-radius: var(--r-lg); overflow: hidden;
  aspect-ratio: 21 / 9; }
.ti-band img { position: absolute; inset: 0; display: block;
  width: 100%; height: 100%; object-fit: cover; object-position: center 42%; }
@media (max-width: 991.98px) {
  .ti-photo { position: static; }
  .ti-photo img { position: static; height: auto; }
  .ti-band { aspect-ratio: var(--ratio-photo-m); }
}

/* ══════════════════════════════════════════════ 01) 스펙 표 (.ti-spec)
   카드를 전부 없애고 "키 : 값" 2열 정의형 표로만 세운다. 구분선이 유일한 장치다. */
.ti-spec { display: grid; grid-template-columns: var(--split-cols);
  column-gap: var(--ti-col-gap); align-items: stretch; }
/* ⚠️ 여기에 margin 을 선언하지 않는다. templates 레이어가 components 레이어를 이기므로
   `<dl>` 을 헤드 바로 뒤에 놓았을 때 헤드↔본문 여백(--head-gap-body 80)까지 지워 버렸다.
   dl 의 브라우저 기본 마진은 이미 @layer reset 의 `* { margin: 0 }` 이 지운다.
   세로 마진의 주인은 섹션 리듬 규칙, 좌우 마진의 주인은 --tpl-inset 공통 규칙이다. */
.ti-spec__list { display: grid; align-content: center;
  border-top: var(--hairline) solid var(--ink); }
.ti-spec__row { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  column-gap: var(--sp-5); align-items: baseline;
  padding-block: var(--sp-5);
  border-bottom: var(--hairline) solid var(--gray-light); }
.ti-spec__k { display: flex; align-items: center; gap: var(--sp-2);
 font-weight: 600; color: var(--gray-dark); }
.ti-spec__k i { font-size: var(--ico-md); color: var(--point); }
.ti-spec__v { margin: 0; font-weight: 600;
  color: var(--ink); }
.ti-spec__opt { display: block; margin-top: var(--sp-1);
  font-size: var(--fs-eyebrow); font-weight: 400; color: var(--gray-dark); line-height: var(--lh-tight); }
@media (max-width: 991.98px) {
  .ti-spec { grid-template-columns: minmax(0, 1fr); row-gap: var(--sp-6); }
  /* (요청 2026-07-14) 좁은 화면에선 키/값이 세로로 쌓인다 → 왼쪽에 붙여 두면 표가 아니라
     흘러내린 목록으로 보인다. 가운데로 세워 "표" 로 읽히게 한다. */
  .ti-spec__row { grid-template-columns: minmax(0, 1fr); row-gap: var(--sp-2);
    justify-items: center; text-align: center; }
  .ti-spec__k { justify-content: center; }
}

/* ══════════════════════════════════════════════ 02) 사진 위 핀 (.ti-pin)
   사진이 면 전체를 차지하고, 정보는 사진 위에 핀(라벨)으로 얹힌다.
   모바일에서는 핀이 절대배치를 버리고 사진 아래 리스트로 흘러내린다(내용 중복 없음). */
/* (요청 2026-07-14) 사진을 컨테이너 안쪽으로 좌우 100px 들여 줄인다.
   핀이 사진 밖으로 나가지 않으면서도 사진 끝에 딱 붙지 않으려면 사진에 여유가 있어야 한다. */
.ti-pin { position: relative; margin-inline: 100px; }
@media (max-width: 1200px) { .ti-pin { margin-inline: 0; } }
.ti-pin__fig { position: relative; border-radius: var(--r-lg); overflow: hidden;
  aspect-ratio: var(--ratio-photo-m); }
.ti-pin__fig img { position: absolute; inset: 0; display: block;
  width: 100%; height: 100%; object-fit: cover; object-position: center 38%; }
.ti-pin__list { position: absolute; inset: 0; margin: 0; padding: 0; list-style: none; }

/* ── 핀 배치 (요청 2026-07-14) ─────────────────────────────────────────────
   예전엔 좌표를 HTML 인라인(--px/--py)에 박아 뒀다. 20/80 · 19/81 · 20/84 처럼 좌우가
   자로 잰 듯 대칭이라 기계적으로 보였고, 페이지마다 손으로 고쳐야 했다(15개 파일 73곳).
   → 좌표를 CSS 로 걷어 올리고 nth-child 로 "흩뿌린" 자리를 준다. HTML 은 개수만 정하면 된다.

   세 가지 제약을 동시에 만족시킨다:
     ① 핵심 요소 회피 : 좌측 핀은 사진 왼쪽에, 우측 핀은 오른쪽에만 붙는다 → 한가운데는 늘 빈다
     ② 사진 끝과 여유 : ★ 핀 폭은 글자 수에 따라 다르다(nowrap). 중심 기준(translate -50%)으로
                        놓으면 긴 핀이 사진 밖으로 41px 까지 삐져나갔다(svf-hair 검수).
                        → 좌측 핀은 "왼쪽 끝"을, 우측 핀은 "오른쪽 끝"을 좌표에 맞춘다.
                          폭이 얼마든 사진 안에 들어오고, 가장자리에서 8% 씩 떨어진다.
     ③ 개수 대응     : 3~6개 어느 쪽이든 고르게 흩어지도록 "1,2,3번이 이미 삼각형"이 되게
                        순서를 짰다. 4개면 사각, 5·6개면 좌우 중단이 채워진다.
   ★ 좌표를 살짝 어긋나게(8/12/7, 24/19/79) 두어 대칭 티를 없앴다 - 자로 잰 듯하면 랜덤해 보이지 않는다. */
.ti-pin__item { position: absolute;
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-2) var(--sp-4);
  border-radius: var(--r-pill); white-space: nowrap;
  background: color-mix(in srgb, var(--white) 92%, transparent);
  box-shadow: 0 6px 20px color-mix(in srgb, var(--ink) 20%, transparent); }
/* ★ 좌표는 PC 전용이다 (min-width). 모바일에서는 핀이 사진 위가 아니라 아래 리스트로 내려간다.
   ⚠️ 예전엔 이 규칙들을 미디어쿼리 밖에 뒀다가 사고가 났다. :nth-child(0,2,0) 가 모바일 규칙의
      .ti-pin__item(0,1,0) 보다 특이도가 높아, position:static 인데도 transform 이 살아남았다
      → 짝수 핀이 translate(-340px) 로 화면 밖으로 날아가고, 홀수 핀은 위로 올라가 사진과 겹쳤다.
      "모바일에서 사진 아래 여백이 사라지고 박스가 다 안 보인다"의 정체가 이것이다. (2026-07-14) */
@media (min-width: 992px) {
  /* 홀수 = 좌측(왼쪽 끝을 좌표에 맞춘다) · 짝수 = 우측(오른쪽 끝을 맞춘다) */
  .ti-pin__item:nth-child(odd)  { transform: translate(0, -50%); }
  .ti-pin__item:nth-child(even) { transform: translate(-100%, -50%); }
  .ti-pin__item:nth-child(1) { left:  8%; top: 24%; }   /* 좌상 */
  .ti-pin__item:nth-child(2) { left: 92%; top: 19%; }   /* 우상 */
  /* ★ (영문판 2026-07-23) 3·4 의 세로 간격을 4% → 14% 로 벌린다.
     3 은 좌측 기준, 4 는 우측 기준으로 뻗는데 영문 라벨이 길어 둘이 화면 가운데서 만난다
     (실측: svf-hair·svf-nose-contracture·svf-private-product 에서 최대 49px 겹침).
     좌표를 벌리는 것이 전역 해법이다 - 페이지마다 글자를 깎으면 또 다른 페이지에서 터진다. */
  .ti-pin__item:nth-child(3) { left: 12%; top: 72%; }   /* 좌하 - 3개만 있어도 삼각 분산 */
  .ti-pin__item:nth-child(4) { left: 88%; top: 86%; }   /* 우하 - 4개면 사각 분산 */
  .ti-pin__item:nth-child(5) { left:  7%; top: 52%; }   /* 좌중 */
  .ti-pin__item:nth-child(6) { left: 93%; top: 48%; }   /* 우중 */
  .ti-pin__item:nth-child(7) { left: 14%; top: 13%; }   /* 예비 - 7개 이상 */
  .ti-pin__item:nth-child(8) { left: 86%; top: 88%; }
}
.ti-pin__no { flex: 0 0 auto; display: grid; place-items: center;
  width: clamp(20px, 1.458vw, 28px); height: clamp(20px, 1.458vw, 28px);
  border-radius: 50%; background: var(--point); color: var(--white);
  font-size: var(--fs-eyebrow); font-weight: 700; line-height: 1; }
.ti-pin__k { font-size: var(--fs-eyebrow); color: var(--gray-dark); }
.ti-pin__v { font-weight: 600; color: var(--ink); }
.ti-pin__opt { font-size: var(--fs-eyebrow); font-weight: 400; color: var(--point); }
@media (max-width: 991.98px) {
  .ti-pin__fig { aspect-ratio: var(--ratio-photo); }
  .ti-pin__list { position: static; display: grid; gap: var(--sp-3);
    margin-top: var(--sp-5); }
  .ti-pin__item { position: static; transform: none; white-space: normal;
    box-shadow: none; background: var(--bg-soft);
    padding: var(--sp-3) var(--sp-4); }
}

/* ══════════════════════════════════════════════ 03) 가로 타임라인 (.ti-rail)
   사진은 위로 눕히고, 정보는 "수술 → 회복 → 복귀" 시간축 위의 노드가 된다.
   모바일에서는 축이 세로로 선다. */
.ti-rail { --ti-node: clamp(44px, 3.646vw, 70px); }
.ti-rail__track { position: relative; margin-top: var(--sp-8);
  display: grid; grid-template-columns: repeat(6, minmax(0, 1fr));
  column-gap: var(--sp-4); }
.ti-rail__track::before { content: ''; position: absolute;
  left: 0; right: 0; top: calc(var(--ti-node) / 2);
  height: var(--hairline); background: var(--gray-light); }
.ti-rail__step { position: relative; display: grid; justify-items: center;
  row-gap: var(--sp-4); text-align: center; }
.ti-rail__txt { display: block; }
.ti-rail__k, .ti-rail__v { display: block; }
.ti-rail__node { display: grid; place-items: center;
  width: var(--ti-node); height: var(--ti-node); border-radius: 50%;
  background: var(--white); color: var(--point); font-size: var(--ico-lg); line-height: 1;
  box-shadow: inset 0 0 0 var(--hairline) var(--gray-light); }
.ti-rail__step--now .ti-rail__node { background: var(--point); color: var(--white);
  box-shadow: 0 0 0 var(--sp-1) var(--point-bg); }
.ti-rail__k { font-size: var(--fs-eyebrow); color: var(--gray-dark); }
.ti-rail__v { margin-top: var(--sp-1); font-weight: 600;
  color: var(--ink); }
.ti-rail__opt { display: block; margin-top: var(--sp-1);
  font-size: var(--fs-eyebrow); font-weight: 400; color: var(--gray-dark); }
@media (max-width: 767.98px) {
  .ti-rail__track { grid-template-columns: minmax(0, 1fr); row-gap: var(--sp-5); }
  .ti-rail__track::before { top: 0; bottom: 0; right: auto;
    left: calc(var(--ti-node) / 2); width: var(--hairline); height: auto; }
  .ti-rail__step { grid-template-columns: auto minmax(0, 1fr);
    justify-items: start; text-align: left;
    column-gap: var(--sp-4); row-gap: 0; align-items: center; }
}

/* ══════════════════════════════════════════════ 04) 원형 다이얼 타일 (.ti-dial)
   수치가 링 한가운데에 들어앉는다. 숫자가 없는 항목(마취·절개)은 아이콘이 그 자리를 대신한다.
   ※ 링의 채움(--sweep)은 리듬을 주는 장식이다. 비율을 읽는 게이지가 아니다. */
.ti-dial { display: grid; grid-template-columns: var(--split-cols);
  column-gap: var(--ti-col-gap); align-items: center; }
.ti-dial__grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--box-gap); }
.ti-dial__tile { display: grid; justify-items: center; row-gap: var(--sp-3); text-align: center; }
.ti-dial__ring { --ti-ring: clamp(86px, 6.771vw, 130px);
  position: relative; display: grid; place-items: center;
  width: var(--ti-ring); height: var(--ti-ring); border-radius: 50%;
  background: conic-gradient(from -90deg,
    var(--point) 0 var(--sweep, 100%), var(--point-bg) var(--sweep, 100%) 100%); }
.ti-dial__ring::after { content: ''; position: absolute; inset: var(--sp-2);
  border-radius: 50%; background: var(--white); }
.ti-dial__c { position: relative; z-index: 1; display: grid; justify-items: center; }
.ti-dial__num { font-size: var(--fs-h2title); font-weight: 700; color: var(--point);
  line-height: 1; font-variant-numeric: tabular-nums; }
.ti-dial__c i { font-size: var(--ico-xl); color: var(--point); line-height: 1; }
.ti-dial__k { font-weight: 600; color: var(--ink);
 }
.ti-dial__v { font-size: var(--fs-eyebrow); color: var(--gray-dark); line-height: var(--lh-tight); }
@media (max-width: 991.98px) {
  .ti-dial { grid-template-columns: minmax(0, 1fr); row-gap: var(--sp-6); }
}
@media (max-width: 575.98px) {
  .ti-dial__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 991.98px) {
}

@media (max-width: 991.98px) {
}
@media (max-width: 575.98px) {
}

@media (max-width: 991.98px) {
}

@media (max-width: 991.98px) {
}

/* 오른쪽 글은 컨테이너 안쪽 선까지만 온다 - 화면이 넓어도 글이 끝까지 흘러가지 않게 */
@media (max-width: 991.98px) {
}

@media (max-width: 991.98px) {
}

@media (max-width: 991.98px) {
}

/* ══════════════════════════════════════════════ 12) 인포그래픽 카드 (.ti-hero)
   사진이 배경으로 깔리고 수치가 전면에 선다. 숫자(--fs-display)가 주인공,
   항목명은 숫자의 캡션으로 내려간다. 숫자가 없는 항목은 값 문장이 그 자리를 대신한다. */
.ti-hero { position: relative; overflow: hidden; border-radius: var(--r-lg);
  background: var(--dark); }
.ti-hero__fig { position: absolute; inset: 0; margin: 0; }
.ti-hero__fig img { display: block; width: 100%; height: 100%;
  object-fit: cover; object-position: center 30%; }
.ti-hero__fig::after { content: ''; position: absolute; inset: 0;
  background: color-mix(in srgb, var(--dark) 74%, transparent); }
.ti-hero__inner { position: relative; padding: var(--sp-9) var(--sp-8); }
.ti-hero__grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--sp-8) var(--sp-6); }
/* 값의 줄 수가 달라도(1줄 · 2줄) 항목명 캡션의 윗선이 한 줄로 맞도록 아래로 밀어붙인다 */
.ti-hero__cell { display: flex; flex-direction: column; justify-content: space-between;
  text-align: center; }
.ti-hero__num { display: block; font-size: var(--fs-h2title); font-weight: 700;
  color: var(--white); line-height: 1; letter-spacing: -.02em;
  font-variant-numeric: tabular-nums; }
.ti-hero__num em { font-style: normal; margin-left: var(--sp-1);
  font-size: var(--fs-content-title); font-weight: 600;
  color: color-mix(in srgb, var(--white) 78%, transparent); }
.ti-hero__txt { display: block; font-size: var(--fs-h2title); font-weight: 700;
  color: var(--white); letter-spacing: -.02em; }
.ti-hero__k { display: block; margin-top: var(--sp-4);
  padding-top: var(--sp-3);
  border-top: var(--hairline) solid color-mix(in srgb, var(--white) 30%, transparent);
  font-size: var(--fs-content-subtext); font-weight: 600;
  color: color-mix(in srgb, var(--white) 80%, transparent); }
.ti-hero__opt { display: block; margin-top: var(--sp-1); font-size: var(--fs-eyebrow);
  color: color-mix(in srgb, var(--white) 60%, transparent); }
@media (max-width: 991.98px) {
  .ti-hero__inner { padding: var(--sp-8) var(--sp-6); }
  .ti-hero__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-7) var(--sp-5); }
}
@media (max-width: 575.98px) {
  .ti-hero__grid { grid-template-columns: minmax(0, 1fr); }
}

/* ── UI 이름표 (2026-07-13) - 4개 갤러리가 같은 배지를 쓴다. 코드는 48개가 서로 겹치지 않는다. */

/* ══════════════════ 기존 변형 (gal-*) - 구 template.css */
@charset "utf-8";
/* ============================================================================
   template.css — 「사진 + 제목 + 설명」 × 4 로 만들 수 있는 UI 16종
   ----------------------------------------------------------------------------
   ★ 카탈로그 전용이다. template.html 에서만 읽는다.
     채택된 한 벌만 main.css 로 승격하고 여기서는 지운다.
     (CSS 3개 상시 운용 금지 규칙을 어기지 않기 위한 대기실이다)

   왜 : 4장짜리 사진+글 묶음이 전부 .tpl-box--photo 격자 하나로만 나온다.
        같은 에셋으로 리듬을 바꿀 선택지를 늘린다.

   규칙 : 값은 전부 main.css 토큰에서 온다. 생짜 px · hex 금지.
   접두어 : .gal-
   제외 : 캐러셀 · 탭 전환 (2026-07-13 사용자 지시)
   ========================================================================== */

/* ── 16종 공통 ─────────────────────────────────────────────────────────── */
/* 이름표. 카탈로그에는 섹션 헤더(eyebrow·H2·리드문)도 CTA 도 두지 않는다 →
   어느 안인지 알아볼 한 줄만 얹는다. 본문 UI 를 나란히 비교하는 것이 이 문서의 일이다. */

/* ★ height 는 aspect-ratio 가 정한다 - height:100% 를 주면 부모 행 높이를 되받아
   비율이 무시되고 칸마다 사진 높이가 어긋난다(타임라인·격자에서 아래끝이 안 맞는다). */
.gal-pic {
  display: block; width: 100%; height: auto;
  aspect-ratio: var(--ratio-photo); object-fit: cover;
  border-radius: var(--r-lg);
}
.gal-title { font-weight: 600; color: var(--ink);
  line-height: var(--lh-tight); }
.gal-desc  { font-weight: 400; color: var(--gray-dark);
 }
/* 사진 위에 글을 얹는 안들이 공유하는 장치.
   바닥을 짙게(--veil-bar) 깔고 위로 길게 풀어야 밝은 사진에서도 흰 글씨가 산다. */
.gal-cap {
  position: absolute; inset: auto 0 0 0;
  padding: var(--sp-8) var(--sp-5) var(--sp-5);
  display: grid; gap: var(--sp-2);
  background: linear-gradient(to top,
    var(--veil-bar) 0%, var(--veil-scrim) 55%, transparent 100%);
}
.gal-cap .gal-title, .gal-cap .gal-desc { color: var(--white); }
/* 사진 위 좌상단 라벨(번호·구분). 여러 안이 함께 쓴다. */
.gal-tag {
  position: absolute; top: var(--sp-4); left: var(--sp-4);
  padding: var(--sp-1) var(--sp-3); border-radius: var(--r-pill);
  background: var(--point); color: var(--white);
  font-size: var(--fs-eyebrow); font-weight: 600; letter-spacing: .06em;
}

/* ══════════════════ B) 지그재그 2단 (.gal-zigzag)
   .tpl-about 를 4번 반복하되 짝수만 좌우를 뒤집는다.
   마크업 순서(사진 → 글)는 그대로 두고 order 로 시각만 반전 → 읽기 순서가 유지된다. */
/* 블록 사이 간격도 29번과 같게 - 29번(.ua-time)은 row-gap --sp-6(40)이다.
   예전엔 --sp-9(120) 라 이미지끼리 세 배나 벌어져 있었다. (요청 2026-07-14) */
.gal-zigzag { display: grid; row-gap: var(--sp-6); }
/* 짝수 블록은 좌우 반전 - 글 열이 앞, 미디어(488)가 뒤로 간다 */
.gal-zigzag > .tpl-about:nth-child(even) {
  grid-template-columns: minmax(0, 1fr) var(--about-media); }
.gal-zigzag > .tpl-about:nth-child(even) .tpl-about__media { order: 2; }
.gal-zigzag > .tpl-about:nth-child(even) .tpl-about__body  { order: 1; }
/* 데코도 뒤집는다 - 사진이 오른쪽에 서면 데코는 왼쪽 아래로 비껴야 대칭이 맞는다.
   패딩도 함께 뒤집어야 한다(패딩이 데코의 자리를 만든다 - 위 버그 수정 참고). */
.gal-zigzag > .tpl-about:nth-child(even) .tpl-about__media {
  padding: 0 0 var(--about-deco) var(--about-deco); }
.gal-zigzag > .tpl-about:nth-child(even) .tpl-about__deco {
  inset: var(--about-deco) var(--about-deco) 0 0; }
@media (max-width: 991.98px) {
  .gal-zigzag { row-gap: var(--sp-7); }
  .gal-zigzag > .tpl-about:nth-child(even) { grid-template-columns: minmax(0, 1fr); }
  .gal-zigzag > .tpl-about:nth-child(even) .tpl-about__media,
  .gal-zigzag > .tpl-about:nth-child(even) .tpl-about__body { order: 0; }
}

/* ══════════════════ C) 2×2 오버레이 (.gal-quad)
   4장을 정사각에 가깝게 네 칸으로 나누고 글을 얹는다.
   4개가 대등할 때 가장 균형이 잡힌다 - 한 장을 크게 세우던 모자이크의 대체안이다. */
.gal-quad { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--box-gap); }
.gal-quad__item { position: relative; border-radius: var(--r-lg); overflow: hidden; }
.gal-quad__item .gal-pic { aspect-ratio: var(--ratio-photo); border-radius: 0; }
.gal-quad .gal-title { font-size: var(--fs-content-title); }
@media (max-width: 991.98px) {
  .gal-quad { grid-template-columns: minmax(0, 1fr); }
}

/* ══════════════════ D) 번호 스텝 (.gal-steps)
   4장에 순서가 있을 때(1차 → 4차 코스). 세로선에 번호를 꿴다.
   사진은 썸네일이다 - 키우면 번호선이 장식으로 밀려나고 단계가 안 읽힌다. */
.gal-steps { display: grid; row-gap: var(--sp-7); position: relative;
  --gal-dot: calc(var(--sp-6) * 1.2); }
.gal-steps::before {
  content: ""; position: absolute; top: 0; bottom: 0;
  left: calc(var(--gal-dot) / 2 - var(--hairline) / 2);
  width: var(--hairline); background: var(--gray-light); }
.gal-steps__item {
  display: grid; grid-template-columns: var(--gal-dot) minmax(0, 3fr) minmax(0, 7fr);
  gap: var(--sp-5); align-items: center; position: relative; }
.gal-steps__num {
  width: var(--gal-dot); height: var(--gal-dot); border-radius: var(--r-pill);
  display: grid; place-items: center;
  background: var(--point); color: var(--white);
  font-size: var(--fs-eyebrow); font-weight: 600; }
.gal-steps__body { display: grid; gap: var(--sp-2); }
@media (max-width: 991.98px) {
  .gal-steps::before { display: none; }
  .gal-steps__item { grid-template-columns: var(--gal-dot) minmax(0, 1fr);
    row-gap: var(--sp-4); }
  .gal-steps__item .gal-pic, .gal-steps__body { grid-column: 2; }
}

/* ══════════════════ E) 세로 4열 오버레이 (.gal-overlay)
   C 와 달리 세로로 긴 4열이다. 사진이 강할 때 카드 아래 여백을 없애 밀도를 올린다. */
/* (요청 2026-07-14) 항목이 4개 미만이어도 **카드 폭은 4열 기준 그대로 두고 가운데로 모은다.**
   grow 를 1 로 두면 3개일 때 카드가 늘어나 한 줄을 억지로 채운다 → grow 0 + justify-content: center.
   4개일 때는 basis 합이 정확히 100% 라 종전과 똑같이 꽉 찬다. */
.gal-overlay { display: flex; flex-wrap: wrap; gap: var(--box-gap); justify-content: center; }
.gal-overlay__item {
  position: relative; flex: 0 1 calc((100% - var(--box-gap) * 3) / 4);
  border-radius: var(--r-lg); overflow: hidden; }
.gal-overlay__item .gal-pic { aspect-ratio: var(--ratio-portrait); border-radius: 0; }
/* (요청 2026-07-14) 항목이 3개뿐이면 4열 기준 폭은 카드가 작고 좌우가 허전하다
   → 그 줄을 **3열 기준 폭**으로 채운다. 항목 수는 :has 로 스스로 안다(마크업에 클래스를 더하지 않는다). */
.gal-overlay:has(.gal-overlay__item:nth-child(3):last-child) .gal-overlay__item {
  flex-basis: calc((100% - var(--box-gap) * 2) / 3); }
/* (요청 2026-07-14) 2개뿐이면 더 크게 - **3열 기준 폭**까지 키운다.
   2열 기준(597)까지 벌리면 3:4 세로컷이라 높이가 800 을 넘어 한 화면을 통째로 먹는다. */
.gal-overlay:has(.gal-overlay__item:nth-child(2):last-child) .gal-overlay__item {
  flex-basis: calc((100% - var(--box-gap) * 2) / 3); }
@media (max-width: 991.98px) {
  .gal-overlay__item { flex-basis: calc((100% - var(--box-gap)) / 2); }
  /* ⚠️ 위 "2개 → 3열 기준" 규칙은 :has 라 특이도가 높아 이 미디어쿼리를 이긴다.
     그대로 두면 모바일에서도 33% 폭(99px)이 적용돼 사진이 우표만 해진다.
     → 3개짜리와 같이 **1단**으로 세운다. 2열(159px)로는 오버레이 캡션(제목 + 설명)이
       사진을 통째로 덮어 인물이 안 보인다. 사진은 세로컷(3:4) 그대로 - 인물이라 눕히지 않는다.
     (요청 2026-07-14 : 원장 사진이 너무 작다) */
  .gal-overlay:has(.gal-overlay__item:nth-child(2):last-child) .gal-overlay__item {
    flex-basis: 100%; }
  /* (요청 2026-07-14) 3개짜리는 모바일에서 **1단**이다.
     2열로 접으면 카드가 좁아 캡션(제목 + 설명)이 3:4 슬롯 높이를 넘겨 위로 삐져나가 잘린다.
     4개짜리는 캡션이 짧아 2열로도 들어가므로 종전 그대로 둔다. */
  .gal-overlay:has(.gal-overlay__item:nth-child(3):last-child) .gal-overlay__item {
    flex-basis: 100%; }
  /* 1단이 되면 세로컷(3:4)이 한 화면을 통째로 먹는다 → **가로로 눕힌다**.
     비율은 같은 오버레이 계열인 06(.ub-ov__card)의 모바일 값(--ratio-photo 4:3)에 맞춘다.
     ⚠️ 16:9 까지 낮추면 카드 높이(191)가 캡션 높이(157)와 맞먹어 사진이 거의 안 보인다. */
  .gal-overlay:has(.gal-overlay__item:nth-child(3):last-child) .gal-overlay__item .gal-pic {
    aspect-ratio: var(--ratio-photo); }
}

/* ══════════════════ F) 매거진 리스트 (.gal-list)
   가로 행을 구분선으로 끊는다. 박스에 안 들어가는 긴 설명을 그대로 싣는다. */
/* (요청 2026-07-14) 이 템플릿은 컨테이너 안쪽 좌우로 **150** 씩 들여쓴다.
   ★ 폭이 300 줄어드는데 열 비율(4:8)을 그대로 두면 사진까지 작아진다.
     → 사진 열이 **종전 크기를 유지**하도록 비율을 **4:5** 로 고친다.
       폭 1220, gap 30 → 1190 을 4:8 로 → 사진 397px   (종전)
       폭  920, gap 30 →  890 을 4:5 로 → 사진 396px   (지금)  ← 같다. 줄어든 300 은 본문이 흡수한다. */
.gal-list { display: grid; --tpl-inset: 150px; }
.gal-list__item {
  display: grid; grid-template-columns: minmax(0, 4fr) minmax(0, 5fr);
  gap: var(--sp-6); align-items: center; padding-block: var(--sp-6);
  border-top: var(--hairline) solid var(--gray-light); }
.gal-list__item:last-child { border-bottom: var(--hairline) solid var(--gray-light); }
.gal-list__body { display: grid; gap: var(--sp-3); }
.gal-list__item .gal-title { font-size: var(--fs-content-title); }
.gal-list__item .gal-desc  { line-height: var(--lh-prose); }
.gal-list__no { font-size: var(--fs-eyebrow); font-weight: 600; color: var(--point);
  letter-spacing: .08em; }
/* ⚠️ .gal-list 의 로컬 --tpl-inset(150)은 :root 의 반응형 0 보다 구체적이라 그냥 두면
   좁은 화면에서도 150 이 남는다 → 여기서 직접 푼다. */
@media (max-width: 1200px) { .gal-list { --tpl-inset: 0px; } }
@media (max-width: 991.98px) {
  .gal-list__item { grid-template-columns: minmax(0, 1fr); gap: var(--sp-4); }
}

/* ══════════════════ G) 스태거드 (.gal-stagger)
   4열인데 짝수 칸만 아래로 내려앉는다. 격자의 딱딱함을 풀되 정보 구조는 그대로다.
   내려앉는 양(--gal-drop)은 스케일에서 파생한다. */
/* (요청 2026-07-15) 사진 사이 간격 35(--box-gap) → 60. --sp-7 이 1920 에서 정확히 60 이다
   (좁아지면 37 까지 함께 줄어든다). 생짜 60px 을 박지 않는다 - 39(.bna-wipe)와 같은 처방.
   ★ 클래스 자체를 고친다 → 03 을 쓰는 모든 페이지(about · quick-ssak · quick-bbara ·
     bodylift-arm · bodylift-thigh · breast-reduction · forehead-lift · svf-lab ·
     svf-nose-contracture)가 한 번에 같은 간격이 된다. */
.gal-stagger { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--sp-7); align-items: start; --gal-drop: var(--sp-9); }
/* (2026-07-17) 행은 auto 1fr - .gal-circle 과 같은 이유(stretch 분배로 제목이 밀림) */
.gal-stagger__item { display: grid; gap: var(--box-gap-md); grid-template-rows: auto 1fr; }
.gal-stagger__item:nth-child(even) { margin-top: var(--gal-drop); }
.gal-stagger .gal-pic { aspect-ratio: var(--ratio-portrait); }
/* (요청 2026-07-15) --flat : 지그재그를 끄고 카드 윗선을 한 줄로 맞춘 뒤 가운데 세운다.
   ★ 칸 폭은 4열 격자 기준값 calc((100% - gap*3) / 4) 을 "고정폭"으로 못박는다.
     1fr 로 두면 항목이 3개일 때 칸이 넓어져 박스가 커진다 - 크기는 그대로 두라는 요청이라
     폭을 4열 기준에 묶고, 남는 자리는 justify-content:center 로 좌우에 똑같이 나눈다. */
.gal-stagger--flat {
  /* 칸 폭은 4열 기준값. gap 이 바뀌면 이 식도 함께 바뀌어야 하므로 위 gap 과 같은 변수를 쓴다 */
  grid-template-columns: repeat(auto-fit, calc((100% - var(--sp-7) * 3) / 4));
  justify-content: center;
}
.gal-stagger--flat .gal-stagger__item:nth-child(even) { margin-top: 0; }
/* (요청 2026-07-26) 제목 줄 수가 카드마다 달라(1줄 vs 2줄) 아래 본문(.gal-desc) 시작 높이가
   어긋나는 것을 막는다 - 제목에 2줄분 높이를 예약하면 1줄짜리 카드도 본문이 같은 선에서 시작한다.
   opt-in : 이 처방이 필요한 섹션 컨테이너에만 붙인다(다른 gal-stagger 는 그대로). */
.gal-stagger--titlefix .gal-title {
  min-height: calc(var(--fs-content-title) * 1.35 * 2); }
@media (max-width: 991.98px) {
  .gal-stagger { grid-template-columns: repeat(2, minmax(0, 1fr)); --gal-drop: var(--sp-6); }
  /* (요청 2026-07-17) --flat 은 모바일 1열 - 이 변형을 쓰는 곳은 전부 [사진+제목+설명] 카드라
     (about 언론 · forehead 눈썹 · quick-* · svf-*) 2열로 가르면 설명 글이 좁아 못 읽는다.
     지그재그(기본형)는 사진 위주라 종전대로 2열을 유지한다. */
  .gal-stagger--flat { grid-template-columns: minmax(0, 1fr); }
}

/* ══════════════════ G-2) 정렬 4열 격자 (.gal-grid) - 46
   03 과 같은 골격이되 짝수 칸이 내려앉지 않는다. 카드 윗선·아랫선이 한 줄로 선다.
   전후사진처럼 Before ↔ After 를 나란히 대조하는 자리에 쓴다 -
   지그재그로 어긋나면 비교선이 흐트러져 무엇과 무엇을 견주는지 읽히지 않는다. */
.gal-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--box-gap); align-items: start; }
/* (2026-07-17) 행은 auto 1fr - .gal-circle 과 같은 이유(stretch 분배로 제목이 밀림) */
.gal-grid__item { display: grid; gap: var(--box-gap-md); grid-template-rows: auto 1fr; }
.gal-grid .gal-pic { aspect-ratio: var(--ratio-portrait); }
/* 한 섹션에 격자를 두 벌 놓을 때(시점·부위별 묶음) 사이를 벌린다 (요청 2026-07-15).
   붙여 두면 카드 사이 간격(--box-gap 35)과 구별이 안 돼 8장이 한 덩어리로 읽힌다
   → 묶음 간격은 그보다 확실히 큰 --sp-8(50~80). 이 템플릿을 쓰는 전 페이지에 함께 걸린다. */
.gal-grid + .gal-grid { margin-top: var(--sp-8); }
/* 수직 리듬(요청): 사진 → 20(행간10+마진10, 인라인 토큰) → 이름 → 50 → 다음 사진 */
#withstarGrid { row-gap: 50px; }
/* (요청 2026-07-17) 접힌 갤러리(.is-collapsed) - PC 는 hidden 속성이 12개(4열×3줄)를 정하지만
   모바일은 2열이라 같은 12개가 6줄이 된다 → 5줄(10개)까지만 보인다.
   더보기(data-more)가 hidden 과 함께 이 클래스도 걷는다(templates.js). */
@media (max-width: 991.98px) {
  .gal-grid.is-collapsed > :nth-child(n+11) { display: none; }
}
@media (max-width: 991.98px) {
  .gal-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ══════════════════ H) 원형 마스크 (.gal-circle)
   사진을 동그랗게 오린다. 사진이 인물·장비 클로즈업이라 배경이 지저분할 때
   가운데만 남겨 시선을 모은다. 아이콘 격자와 같은 리듬이 된다. */
.gal-circle { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--box-gap); text-align: center; }
/* ★ (2026-07-17) 행을 암묵 auto 로 두면 칸이 같은 높이로 늘어날 때 남는 공간이
   align-content:stretch 로 두 행에 나뉜다 → 본문이 짧은 칸만 사진 행이 커지고 제목이
   아래로 밀려 제목 줄이 어긋난다(실측 11px). 사진 행은 내용 크기(auto), 남는 공간은
   글 행(1fr)이 전부 먹게 해 제목 시작점을 통일한다. (.gal-timeline·5장 포맷과 같은 처방) */
.gal-circle__item { display: grid; gap: var(--box-gap-md); justify-items: center;
  grid-template-rows: auto 1fr; }
/* (요청 2026-07-27) 제목 줄 수(1~3줄)가 카드마다 달라 그 아래 본문(.gal-desc) 시작 높이가
   어긋나던 것을 막는다 - 제목에 3줄 높이를 예약하면 짧은 제목 카드도 본문이 같은 선에서 시작한다.
   opt-in : 필요한 gal-circle 에만 붙인다(다른 사용처는 그대로). */
.gal-circle--titlefix .gal-title { min-height: calc(var(--fs-content-title) * 1.35 * 3); }
.gal-circle .gal-pic {
  aspect-ratio: var(--ratio-square); border-radius: var(--r-pill);
  width: 100%; max-width: calc(var(--sp-10) * 1.5);
  border: var(--sp-1) solid var(--point-bg); }
@media (max-width: 991.98px) {
  .gal-circle { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ══════════════════ I) 풀블리드 4분할 밴드 (.gal-band)
   화면 끝까지 사진 네 장을 붙여 띠를 만든다. 간격도 라운드도 없다.
   섹션 하나를 통째로 사진이 지배한다 - 센터 소개처럼 인상이 먼저일 때.
   ★ .container 가 아니라 .container--full 안에 넣는다. */
/* ★ 헤더와의 간격을 여기서 준다.
   헤더는 .container, 띠는 .container--full 로 부모가 갈라진다 →
   .tpl-head 의 margin-bottom 이 padding 없는 .container 밖으로 새어나가(collapse)
   띠를 밀어내지 못한다. 다른 안들은 헤더와 콘텐츠가 같은 .container 안이라 이 문제가 없다. */
.gal-band { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0;
  margin-top: var(--head-gap-body); }
.gal-band__item { position: relative; }
.gal-band__item .gal-pic { aspect-ratio: var(--ratio-portrait); border-radius: 0; }
/* 사진끼리 맞닿는 경계를 흰 선으로 가른다(간격 대신) */
.gal-band__item + .gal-band__item { border-left: var(--hairline) solid var(--white); }
@media (max-width: 991.98px) {
  .gal-band { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .gal-band__item:nth-child(odd) { border-left: 0; }
  .gal-band__item:nth-child(n+3) { border-top: var(--hairline) solid var(--white); }
}

/* ══════════════════ J) 오버랩 카드 (.gal-overlap)
   글 카드가 사진 아래끝을 물고 올라온다. 사진과 글이 한 덩어리로 읽힌다.
   물리는 양(--gal-bite)만큼 카드가 위로 당겨진다. */
.gal-overlap { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--box-gap); --gal-bite: var(--sp-7); }
.gal-overlap__item { display: grid; }
.gal-overlap__item .gal-pic { aspect-ratio: var(--ratio-photo); }
.gal-overlap__body {
  margin: calc(var(--gal-bite) * -1) var(--sp-5) 0;   /* 위로 물어 올린다 */
  position: relative; z-index: 1;
  padding: var(--sp-5); display: grid; gap: var(--sp-2);
  background: var(--white); border-radius: var(--r-lg);
  border: var(--hairline) solid var(--gray-light); }
@media (max-width: 991.98px) {
  .gal-overlap { grid-template-columns: minmax(0, 1fr); }
}

/* ══════════════════ K) 매스너리 2열 (.gal-masonry)
   두 열의 사진 높이를 서로 다르게 준다. 4장의 성격이 제각각일 때(장비·인물·개념도)
   같은 틀에 우겨넣지 않고 사진 원래의 결을 살린다. */
.gal-masonry { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--box-gap); }
.gal-masonry__item { display: grid; gap: var(--box-gap-md); align-content: start; }
/* 1·4 는 세로로 길게, 2·3 은 납작하게 - 열마다 아래끝이 어긋나며 리듬이 생긴다 */
.gal-masonry__item:nth-child(1) .gal-pic,
.gal-masonry__item:nth-child(4) .gal-pic { aspect-ratio: var(--ratio-portrait); }
.gal-masonry__item:nth-child(2) .gal-pic,
.gal-masonry__item:nth-child(3) .gal-pic { aspect-ratio: var(--ratio-photo-m); }
@media (max-width: 991.98px) {
  .gal-masonry { grid-template-columns: minmax(0, 1fr); }
  .gal-masonry .gal-pic { aspect-ratio: var(--ratio-photo) !important; }
}

/* ══════════════════ L) 아코디언 (.gal-acc)
   제목만 쌓아두고 편 것만 사진을 연다. 세로를 가장 아끼면서도 JS 가 필요 없다.
   ★ <details> 라 JS 를 꺼도 열린다(SSR). 첫 항목은 open 으로 둔다. */
.gal-acc { display: grid; }
.gal-acc__item { border-top: var(--hairline) solid var(--gray-light); }
.gal-acc__item:last-child { border-bottom: var(--hairline) solid var(--gray-light); }
.gal-acc__sum {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-4);
  padding-block: var(--sp-5); cursor: pointer; list-style: none;
  font-size: var(--fs-content-title); font-weight: 600; color: var(--ink); }
.gal-acc__sum::-webkit-details-marker { display: none; }
.gal-acc__sum i { color: var(--point); transition: transform .25s; }
.gal-acc__item[open] .gal-acc__sum i { transform: rotate(45deg); }   /* + → × */
.gal-acc__body {
  display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  gap: var(--sp-6); align-items: center; padding-bottom: var(--sp-6); }
.gal-acc__body .gal-desc { line-height: var(--lh-prose); }
@media (max-width: 991.98px) {
  .gal-acc__body { grid-template-columns: minmax(0, 1fr); gap: var(--sp-4); }
}

/* ══════════════════ M) 가로 타임라인 (.gal-timeline)
   순서를 가로로 눕힌다(D 스텝의 가로판). 4단계가 한눈에 들어오고 세로를 아낀다.
   점과 점을 잇는 선이 "이어진 코스"임을 말한다. */
.gal-timeline { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--box-gap); position: relative; --gal-dot: var(--sp-4); }
/* ★ justify-items:center 를 쓰지 않는다 - 자식이 내용 크기로 줄어들어 사진 폭이
   열마다 달라지고 아래끝이 어긋난다. 늘리기는 그대로 두고 글만 가운데로 모은다. */
/* 행을 [점 / 사진 / 글] 로 못박는다. 점 행을 auto 로 두면 칸마다 높이가 달라져
   (점 뒤 공백이 행 높이를 밀어올린다) 사진 윗선이 어긋난다. */
/* ★ (2026-07-17) 행을 [점] auto auto 로 두면 칸이 같은 높이로 늘어날 때 남는 공간이
   align-content:stretch 로 두 auto 행에 나뉜다 → 본문이 짧은 칸만 사진 행이 커지고
   제목이 아래로 밀려 제목 줄이 어긋난다(실측 12px).
   → 사진 행은 내용 크기(auto), 남는 공간은 글 행(1fr)이 전부 먹게 해 제목 시작점을 통일한다. */
.gal-timeline__item { display: grid; gap: var(--box-gap-md);
  grid-template-rows: var(--gal-dot) auto 1fr;
  text-align: center; position: relative; }
/* (요청 2026-07-27) 제목 줄 수(1~2줄)가 스텝마다 달라 그 아래 본문(.gal-desc) 시작 높이가
   어긋나던 것을 막는다 - 제목에 2줄 높이를 예약해 모든 스텝의 본문이 같은 선에서 시작한다.
   opt-in : 필요한 gal-timeline 에만 붙인다(다른 사용처는 그대로). */
.gal-timeline--titlefix .gal-title { min-height: calc(var(--fs-content-title) * 1.35 * 2); }
.gal-timeline .gal-pic { aspect-ratio: var(--ratio-square); }
.gal-timeline__dot {
  width: var(--gal-dot); height: var(--gal-dot); border-radius: var(--r-pill);
  background: var(--point); margin-inline: auto; }
/* 점과 점을 잇는 선. 선의 주인은 점이 아니라 칸이다 - 점(20px)을 기준으로 100% 를 재면
   선이 20px 밖에 안 나가 다음 점에 닿지 못한다. 칸을 기준으로 재야 옆 칸까지 건너간다.
   마지막 칸은 잇지 않는다(끝이니까). */
.gal-timeline__item:not(:last-child)::after {
  content: ""; position: absolute; z-index: -1;
  top: calc(var(--gal-dot) / 2 - var(--hairline) / 2);
  left: 50%; width: calc(100% + var(--box-gap));
  height: var(--hairline); background: var(--gray-light); }
/* (요청 2026-07-15) --center : 항목이 4개보다 적을 때. 칸 폭은 4열 기준값에 못박고
   남는 자리를 좌우로 똑같이 나눈다 → 박스가 커지지 않고 가운데 선다 (.gal-stagger--flat 과 같은 처방). */
.gal-timeline--center {
  grid-template-columns: repeat(auto-fit, calc((100% - var(--box-gap) * 3) / 4));
  justify-content: center;
}
/* --fit : 단면 도해처럼 잘리면 정보가 사라지는 그림. 1:1 슬롯에 cover 하면 가장자리가 깎인다
   → 통째로 넣고(contain) 남는 자리는 흰 면으로 채운다 (.tpl-boxes--fit 과 같은 취지). */
.gal-timeline--fit .gal-pic { object-fit: contain; background: var(--white); }
/* (요청 2026-07-15) --5 : 단계가 5개인 코스(하수 5단계 등). 4열이면 5번째가 줄을 넘어가
   "이어진 코스"가 끊긴다 → 한 줄에 5칸. 칸이 좁아지는 만큼 사진도 함께 작아진다. */
.gal-timeline--5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
/* --portrait : 원본이 세로컷(3:4)인 그림. 1:1 슬롯에 cover 하면 위아래가 잘린다
   → 슬롯을 원본 비율로 맞춘다. 잘림도 없고 여백도 남지 않는다. */
.gal-timeline--portrait .gal-pic { aspect-ratio: var(--ratio-portrait); }
@media (max-width: 991.98px) {
  .gal-timeline { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .gal-timeline--center { grid-template-columns: repeat(auto-fit, calc((100% - var(--box-gap)) / 2)); }
  .gal-timeline--5 { grid-template-columns: repeat(2, minmax(0, 1fr)); }   /* 모바일은 2열 기준으로 되돌린다 */
  .gal-timeline__item::after { display: none; }
  /* (요청 2026-07-31) 점을 잇는 선(::after)이 모바일에선 이미 숨겨져, 순서용 점만 사진 위에
     외롭게 남는다 → 점도 숨기고 점이 차지하던 행도 접어 사진이 위로 붙게 한다. */
  .gal-timeline__dot { display: none; }
  .gal-timeline__item { grid-template-rows: auto 1fr; }
}

/* ══════════════════ N) 스티키 사이드 (.gal-sticky)
   왼쪽 글이 멈춰 선 채로 오른쪽 사진 넷이 흘러간다.
   센터 전체를 한 문장으로 소개하면서 시술을 차례로 보여줄 때. */
.gal-sticky { display: grid; grid-template-columns: minmax(0, 4fr) minmax(0, 7fr);
  gap: var(--sp-8); align-items: start; }
.gal-sticky__aside { position: sticky; top: var(--sp-9); display: grid; gap: var(--sp-4); }
.gal-sticky__aside .gal-title { font-size: var(--fs-content-title); }
.gal-sticky__aside .gal-desc  { line-height: var(--lh-prose); }
.gal-sticky__flow { display: grid; gap: var(--sp-7); }
.gal-sticky__item { display: grid; gap: var(--box-gap-md); }
@media (max-width: 991.98px) {
  .gal-sticky { grid-template-columns: minmax(0, 1fr); gap: var(--sp-6); }
  .gal-sticky__aside { position: static; }
}

/* ══════════════════ O) 넘버 워터마크 (.gal-water)
   큰 번호가 사진 뒤에 옅게 깔린다. 4개를 "01~04 라인업"으로 묶어 보이게 한다. */
.gal-water { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--sp-8); }
/* 위 여백은 번호(--fs-display 80)보다 살짝 작게 준다 → 번호의 아래끝만 사진에 물린다.
   여백이 번호보다 작으면(예: 40) 숫자가 반으로 잘려 읽히지 않는다. */
.gal-water__item { position: relative; display: grid; gap: var(--box-gap-md);
  padding-top: var(--sp-7); padding-left: var(--sp-6); }
/* 사진 왼쪽 위로 번호가 삐져나온다 - 사진에 가려지지 않게 z-index 0 */
.gal-water__num {
  position: absolute; top: 0; left: 0; z-index: 0;
  font-size: var(--fs-h2title); font-weight: 600; line-height: 1;
  color: var(--point-bg); }
.gal-water__item .gal-pic { position: relative; z-index: 1; }
@media (max-width: 991.98px) {
  .gal-water { grid-template-columns: minmax(0, 1fr); gap: var(--sp-7); }
}

/* ══════════════════ P) 인라인 썸네일 문단 (.gal-inline)
   글이 주인공이고 사진은 곁들임이다. 한 문단 옆에 작은 사진이 붙는다.
   설명이 길고 사진이 보조 자료일 때(연구·논문 성격의 센터). */
.gal-inline { display: grid; gap: var(--sp-6); }
.gal-inline__item {
  display: grid; grid-template-columns: var(--sp-10) minmax(0, 1fr);
  gap: var(--sp-5); align-items: start; }
.gal-inline .gal-pic { aspect-ratio: var(--ratio-square); }
.gal-inline__body { display: grid; gap: var(--sp-2); }
.gal-inline__body .gal-desc { line-height: var(--lh-prose); }
@media (max-width: 991.98px) {
  .gal-inline__item { grid-template-columns: minmax(0, 1fr); }
}

/* ── 42) About 인트로 (.tpl-about--intro) — phpnew2 sec-7 이관 ───────────
   히어로 배너 바로 다음, 섹션 헤드 없이 단독으로 서는 "이 페이지가 무엇인가" 블록.
   구 사이트 58개 페이지가 전부 갖고 있던 필수 요소다(사용자 지시 2026-07-14).

   ★ 새 컴포넌트가 아니다. 15번 좌우 2단(.tpl-about)을 그대로 쓴다 - 이미 영상(iframe)과
     사진을 같은 박스(--about-ratio 16:9)에 담고 데코 테두리까지 갖고 있다.
     여기서 더하는 것은 두 가지뿐이다: ① 좌측 정렬 라벨 ② 해시태그 한 줄.
   ★ 제목은 h3(22) 가 아니라 h2(42) 다. 히어로 다음의 첫 제목이라 페이지의 h2 위계에 선다.  */
/* 좌측 정렬 - 섹션 헤드가 아니라 2단의 오른쪽 열이다. base 의 h2 는 가운데 정렬이라 되돌린다
   (heading 은 태그 셀렉터 하나만 쓴다는 규칙을 지키려면 여기서 정렬만 뒤집는 수밖에 없다) */
.tpl-about--intro .tpl-eyebrow,
.tpl-about--intro .tpl-about__body > h2 { text-align: left; }
/* 컨테이너 안에서 좌우 50 씩 들여쓴다 (사용자 지시 2026-07-14. 100 → 50 으로 반감).
   ★ --about-gutter(60) 를 덮어쓰지 않는다 - 그 토큰은 미디어↔텍스트 간격(--about-gap)을 파생시키므로
     건드리면 가운데 간격까지 함께 벌어진다. 바깥 여백만 따로 준다.
   ★ 인셋을 줄인 만큼(100) 미디어에 준다 → 영상이 커져도 글줄이 좁아지지 않는다. */
/* 미디어를 키운다 (사용자 지시 2026-07-14). 488 → 560.
   ★ :root 의 --about-media 를 고치지 않는다 - 15번(gal-zigzag)을 쓰는 페이지까지 함께 커진다.
     인트로는 페이지의 얼굴이라 영상이 커야 하고, 15번은 4개가 반복되는 목록이라 지금 크기가 맞다.
   텍스트 열은 1fr 이라 남는 폭을 가져간다 → 미디어를 키운 만큼 글줄이 좁아진다.
   ★ 488 → 660 (사용자 지시 2026-07-14). 두 가지가 함께 가능하게 했다:
     ① 제목을 2줄·25자로 조였다(원문 그대로였다면 이 폭에서 제목이 3줄로 뭉갠다)
     ② 좌우 인셋을 100 → 50 으로 반감해 폭 100 을 벌었다 → 그만큼 미디어에 줬다
   ⚠️ 660 이 상한이다. 더 키우면 글줄이 400 아래로 떨어져 **제목이 3줄로 깨진다**(실측 확인).
     영상을 더 키우려면 제목을 더 줄이거나 인셋을 더 좁혀야 한다 - 셋은 폭 하나를 나눠 쓴다. */
.tpl-about--intro { padding-inline: 50px; --about-media: 660px;
  /* ⚠️ --about-media 만 덮어써서는 안 바뀐다. :root 의 --about-cols 안에 있는 var(--about-media) 는
     "선언된 요소(:root)" 에서 이미 488 로 치환돼 굳는다(커스텀 속성의 치환 시점 규칙).
     → 격자를 여기서 다시 세워 이 요소의 --about-media 로 치환되게 한다. */
  grid-template-columns: var(--about-media) minmax(0, 1fr); }
@media (max-width: 1200px) {
  /* 좁은 화면은 이미 폭이 없다 → 푼다 (--tpl-inset · --band-inset 과 같은 기준).
     ⚠️ .tpl-about 의 모바일 규칙(padding-inline: 0)보다 이쪽 특이도가 높다 → 여기서 직접 푼다 */
  .tpl-about--intro { padding-inline: 0; }
}
/* ★ 본문은 [eyebrow → H2 → 리드] 딱 셋이다 (사용자 지시 2026-07-14).
   해시태그·강조 문단을 덧붙이지 않는다 - 섹션 헤드와 같은 3줄 골격으로 통일한다.
   간격도 헤드 토큰을 그대로 쓴다 → 페이지 어디서나 [라벨 → 제목 → 리드] 리듬이 같다. */
.tpl-about--intro .tpl-about__body > h2     { margin-top: var(--head-gap-title); }  /* 10 */
.tpl-about--intro .tpl-about__body > h2 + p { margin-top: var(--head-gap-sub); }    /* 20 */

/* 모바일 - 위아래 2단으로 세우고 [글 → 영상] 순으로 뒤집는다 (사용자 지시 2026-07-14).
   ★ DOM 은 [미디어 → 글] 이라 그대로 접으면 영상이 화면을 먼저 채우고, 이 페이지가 무엇인지
     말하는 eyebrow·제목이 스크롤 아래로 밀린다 → order 로 글을 위로 올린다.
   ⚠️ .tpl-about 의 모바일 1열 규칙(grid-template-columns: minmax(0,1fr))은 여기까지 오지 못한다 -
     위에서 .tpl-about--intro 가 격자를 다시 세워 특이도로 이기기 때문이다(텍스트 열이 0px 로 뭉갠다).
     → 1열도 여기서 직접 되돌린다. */
@media (max-width: 991.98px) {
  .tpl-about--intro { grid-template-columns: minmax(0, 1fr); row-gap: var(--sp-6); }
  .tpl-about--intro .tpl-about__body  { order: 1; }
  .tpl-about--intro .tpl-about__media { order: 2; }
  /* 가운데 정렬 (사용자 지시). 1열이 되면 글이 왼쪽으로만 쏠려 영상과 축이 어긋난다 -
     섹션 헤드가 모바일에서 가운데 서는 것과 같은 이유다.
     ⚠️ 리드(p)는 .tpl-about__body p 의 text-align: left 를 다시 이겨야 한다 → 셋을 함께 적는다 */
  .tpl-about--intro .tpl-about__body,
  .tpl-about--intro .tpl-about__body > .tpl-eyebrow,
  .tpl-about--intro .tpl-about__body > h2,
  .tpl-about--intro .tpl-about__body > p { text-align: center; }
}

/* ══════════════════════════════════════ 이벤트·가격 3종 (.ev-*) — phpnew2 이관
   구 사이트가 모든 시술 페이지에서 쓰던 "가격을 알리는 블록" 세 개다.
     43 .ev-cost : 시술 비용 배너      (히어로 → About 다음, 본문 앞)
     44 .ev-pick : 함께 하면 좋은 수술 (본문 끝)
     45 .ev-band : HOT EVENT 띠        (페이지 최하단, 풀블리드)

   ★ 색은 팔레트 7색만 쓴다. 구 사이트의 베이지(#A7968C)·오렌지(#FF7C32)를 들여오지 않는다
     (사용자 확인 2026-07-14). 대신 면의 밝기로 셋을 구분한다:
       .ev-cost 연한 면(--point-bg)  → 정보를 읽는 배너
       .ev-pick 사진 위 어두운 스크림 → 고르는 배너
       .ev-band 검정 면(--ink)        → 누르는 띠
     셋 다 어두우면 페이지 하단이 검정 덩어리가 된다.
   ★ 가격 숫자는 --fs-event-only 를 쓴다. 이 토큰이 존재하는 이유가 바로 이 자리다.  */

/* ── 43) EVENT 비용 배너 (쿠폰형) ────────────────────────────────────────
   [가격] │ [체크리스트] 2단을 가운데 절취선으로 가르고, 좌우에 노치를 판 티켓.
   "이벤트가" 라는 성격을 형태로 말한다 - 시안 5개 중 채택안 (사용자 선택 2026-07-14).

   ★ 컨테이너를 다 쓰지 않는다. 쿠폰은 "뜯어 가는 것"이라 화면을 가로지르면 쿠폰이 아니라 띠가 된다
     → 폭 700(--coupon-w)으로 묶고 가운데 세운다.
   ★ 가격은 h2title(42)이다. --fs-event-only(60)를 쓰면 좁은 폭에서 체크리스트와 좌우로 못 선다.
   ★ 이미지를 넣지 않는다. 구 사이트 14개 페이지 전수 확인 결과 이미지가 붙는 변형이 없다 -
     가격이 주인공이다.                                                                    */
.ev-cost { position: relative;
  display: grid; grid-template-columns: auto minmax(0, 1fr);
  align-items: center; column-gap: 0;
  max-width: var(--coupon-w, 700px); margin-inline: auto;
  padding: var(--sp-6) var(--sp-7);
  border-radius: var(--r-lg); background: var(--point-bg); }
.ev-cost__label { font-size: var(--fs-content-title); font-weight: 600; color: var(--ink); }
/* 가격 - 이 쿠폰의 주인공. 숫자만 크게 서고 단위·물결표는 같은 줄에 붙는다 */
.ev-cost__price { margin-top: var(--sp-3);
  font-size: var(--fs-h2title); font-weight: 600; line-height: 1;
  letter-spacing: -.03em; color: var(--point); white-space: nowrap; }
/* "상태에 따라 견적 가능" 처럼 숫자가 아닌 페이지가 있다(fat-graft-balance · lipo-revision).
   큰 글씨로 세우면 쿠폰을 넘긴다 → 문장형은 본문 크기로 내린다. 마크업에 --quote 만 붙인다. */
.ev-cost__price--quote { font-size: var(--fs-content-body); font-weight: 400;
  line-height: var(--lh-body); color: var(--ink); white-space: normal; }
/* 절취선 - 두 덩어리를 가르는 세로 점선 */
.ev-cost__list { display: grid; row-gap: var(--sp-3);
  padding-left: var(--sp-5); margin-left: var(--sp-5);
  border-left: var(--hairline) dashed var(--point-soft); }
.ev-cost__list li { display: grid; grid-template-columns: auto minmax(0, 1fr);
  align-items: center; column-gap: var(--sp-4);
  font-size: var(--fs-content-subtext); color: var(--ink); }
.ev-cost__list i { font-size: var(--ico-lg); color: var(--point); line-height: 1; }
/* 노치 - 티켓을 뜯어낸 자리. 배경(흰 면)과 같은 색이라 쿠폰이 파먹힌 것처럼 보인다 */
.ev-cost::before, .ev-cost::after {
  content: ''; position: absolute; top: 50%; width: var(--sp-6); aspect-ratio: 1;
  border-radius: 50%; background: var(--white); transform: translateY(-50%); }
.ev-cost::before { left: calc(var(--sp-6) / -2); }
.ev-cost::after  { right: calc(var(--sp-6) / -2); }

@media (max-width: 991.98px) {
  /* 1열로 접고, 세로 절취선을 가로 절취선으로 눕힌다.
     ★ 좌우 여백은 [기본 여백 + 노치 반지름] 이다 (사용자 지시 2026-07-14).
       노치는 중심이 카드 경계에 있으므로 반지름만큼 카드 안쪽을 파먹는다 → 그만큼 글을 안으로 들인다.
       여백과 노치 위치가 같은 값(--notch-pad)에서 나오므로 둘이 어긋날 수 없다. */
  .ev-cost { --notch-r: calc(var(--sp-6) / 2);
    --notch-pad: calc(var(--sp-5) + var(--notch-r));
    grid-template-columns: minmax(0, 1fr); row-gap: var(--sp-5);
    padding: var(--sp-6) var(--notch-pad); }
  .ev-cost__list { position: relative;
    padding: var(--sp-5) 0 0; margin-left: 0;
    border-left: 0; border-top: var(--hairline) dashed var(--point-soft); }
  /* 노치는 모바일에서도 남긴다 (사용자 지시 2026-07-14).
     ★ 다만 자리가 다르다. PC 의 노치는 "카드 세로 중앙"(.ev-cost::before/after)에 있지만,
       모바일은 절취선이 가로로 누웠으므로 노치도 그 선의 양 끝에 있어야 티켓으로 읽힌다.
       → 노치를 절취선의 주인(.ev-cost__list)에게 맡긴다. top:0 이 곧 그 선이다.
     좌우로는 쿠폰 바깥까지 밀어야 파먹은 것처럼 보인다 → 여백 + 노치 반지름만큼 뺀다. */
  .ev-cost::before, .ev-cost::after { display: none; }
  .ev-cost__list::before, .ev-cost__list::after {
    content: ''; position: absolute; top: 0; width: var(--sp-6); aspect-ratio: 1;
    border-radius: 50%; background: var(--white); transform: translateY(-50%); }
  .ev-cost__list::before { left:  calc((var(--notch-pad) + var(--notch-r)) * -1); }
  .ev-cost__list::after  { right: calc((var(--notch-pad) + var(--notch-r)) * -1); }
}

/* ── 44) 함께 하면 좋은 수술 ─────────────────────────────────────────────
   ★ index 의 PROMOTION 카드(.promo__card)를 그대로 쓴다 (사용자 지시 2026-07-14).
     사진 위에 글을 얹지 않는다 - [1:1 사진] 아래에 [시술명 + 가격] 이 선다.
     구 사이트 promotion 썸네일에는 가격·문구가 이미 박혀 있어, 사진 위에 얹으면 겹쳐 읽힌다.
   ★ 여기서 새로 정하는 것은 "폭" 하나뿐이다. 홈은 마퀴라 카드가 고정폭으로 흐르지만,
     하위 페이지는 흐르지 않는 3열 격자다 → 카드의 고정폭·좌우 padding 만 풀어 준다.
     사진 비율 · hover 확대 · 캡션 baseline · 숫자 크기는 전부 .promo__* 가 이미 갖고 있다.
   ★ 카드 수는 3개 고정이다(구 사이트 22개 페이지 전수 3개).  */
/* ★ 카드는 컨테이너를 꽉 채우지 않는다 (사용자 지시 2026-07-14).
     1fr 3칸이면 카드가 컨테이너 폭에 끌려 376 까지 커진다 → 폭을 340 으로 묶고 가운데 모은다.
     간격은 60 고정(--pick-gap). --sp-7 은 화면에 따라 37~60 으로 움직여 1600 에서 50 이 된다 -
     여기는 "60" 이 지시값이라 고정한다(--band-inset 50 · intro 인셋 100 과 같은 성격).
     남는 폭은 좌우 여백이 된다.
     minmax(0, ...) 라서 화면이 좁아지면 카드가 알아서 줄어든다(넘치지 않는다). */
.ev-pick { --pick-w: 340px; --pick-gap: 60px;
  display: grid; grid-template-columns: repeat(3, minmax(0, var(--pick-w)));
  column-gap: var(--pick-gap); justify-content: center; }
.ev-pick .promo__card { width: auto; padding: 0; }
/* promotion 페이지(요청 2026-07-18) - 이미지 아래 글자 블럭을 위로 붙이고(메타 여백 20→10),
   카드(글자)와 아래 이미지 사이는 50px. 프로모션 격자에만 적용(ev-pick--promo). */
.ev-pick--promo .promo__meta { margin-top: var(--sp-2); }
.ev-pick.ev-pick--promo { row-gap: 50px; }
/* ★ 숫자 옆에 단위("만~")를 붙이지 않는다 (사용자 지시 2026-07-14) - 홈과 똑같이 숫자만 세운다.
   단위·VAT 는 격자 아래 캡션 한 줄이 대신 말한다. */
@media (max-width: 991.98px) {
  /* 3열을 유지하면 카드가 100px 대로 쪼그라들어 사진도 가격도 안 보인다 → 1열.
     1열이면 1:1 사진이 한 화면을 통째로 먹는다 → 가로(16:9)로 눕힌다 */
  .ev-pick { grid-template-columns: minmax(0, 1fr); row-gap: var(--sp-6); }
  .ev-pick .promo__card img { aspect-ratio: 16 / 9; }
}

/* ── 45) TheLINE HOT EVENT 띠 ────────────────────────────────────────────
   페이지 최하단 풀블리드 띠. 구 사이트는 [검정 77% | 오렌지 23%] 사선이었다
   → 오렌지 자리를 --point 로 바꿔 팔레트 안에 넣는다.
   ★ 사선 분기점(88%)은 컨테이너(1280) 오른쪽 끝보다 바깥이어야 한다. 안쪽으로 당기면
     CTA 버튼이 --point 면 위에 올라타 테두리가 사라진다.  */
/* ★ 색이 갈리는 사선의 "끝 꼭짓점"(위쪽) 이 컨테이너(1280) 오른쪽 경계선에 닿는다
     (사용자 지시 2026-07-14).
     그라디언트의 % 로는 못 맞춘다 - % 는 화면 폭에 비례해 움직이므로 화면이 커지면 경계선에서 벗어난다.
     → 색 면을 따로 세우고 좌표를 컨테이너에서 직접 파생시킨다.

     기울기(--band-slant)를 px 로 고정하고, 면을 경계선보다 그만큼 왼쪽에서 시작시킨다.
     그러면 사선은 [아래 꼭짓점 = 경계선 - slant] 에서 시작해 [위 꼭짓점 = 경계선] 에서 끝난다
     → 사선 전체가 컨테이너 경계선 안쪽에 머물고, 끝점만 경계선에 정확히 닿는다.
     화면이 컨테이너보다 좁아지면 폭이 0 이하가 되어 면이 저절로 사라진다. */
.ev-band { --band-slant: var(--sp-7);            /* 60 : 사선이 좌우로 벌어지는 폭 */
  --band-inset: 50px;                            /* 50 : 제목·버튼을 컨테이너 안쪽으로 들여쓴다 */
  position: relative; overflow: hidden;
  padding-block: var(--sp-5); background: var(--ink); }
.ev-band::after { content: ''; position: absolute; z-index: 0; inset-block: 0;
  inset-inline: calc(50% + var(--container) / 2 - var(--band-slant)) 0;
  background: var(--point);
  clip-path: polygon(var(--band-slant) 0, 100% 0, 100% 100%, 0 100%); }
/* 제목·버튼은 컨테이너 안에서 좌우 50 씩 더 들여쓴다 (사용자 지시 2026-07-14).
   ★ 들여쓰는 것은 "글과 버튼"이지 색 면이 아니다 - 사선은 그대로 컨테이너 경계선에 닿는다.
     그래서 padding 을 .ev-band(면) 가 아니라 .ev-band__in(내용) 이 갖는다. */
.ev-band__in { position: relative; z-index: 1;
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-6); padding-inline: var(--band-inset); }
.ev-band__txt strong { display: block; font-size: var(--fs-h2title); font-weight: 700;
  line-height: var(--lh-title); letter-spacing: -.03em; color: var(--white); }
.ev-band__txt strong em { font-style: normal; color: var(--point); }
/* 부제("최대 40% 할인") - 흰 30%(--veil-line) 로는 검정 면에서 읽히지 않는다. 선 색과 글자 색은 다르다 */
.ev-band__txt span { display: block; margin-top: var(--sp-1);
  font-size: var(--fs-h2lead); font-weight: 400;
  color: color-mix(in srgb, var(--white) 75%, transparent); }
/* 어두운 면 위 CTA - .cta 가 크기·굵기·라운드를 정하고 여기서 색만 뒤집는다
   (.shortcut__cap .cta--onphoto 와 같은 벌. 마크업은 .cta 그대로 둔다) */
.ev-band .cta { color: var(--white); box-shadow: inset 0 0 0 var(--hairline) var(--white); }
.ev-band .cta:hover { background: var(--white); color: var(--ink); }
/* 띠는 위·아래 여백이 같아야 한다 (사용자 지시 2026-07-14).
   위쪽 180 은 .tpl-sec 가 주므로 아래쪽만 같은 값으로 맞춘다.
   ⚠️ 띠 뒤에는 항상 오시는 길(.locate)이 오는데, 그쪽이 제 마진(110)을 갖고 있다 →
     그대로 두면 아래가 110 이 되어 위와 어긋난다. 인접 형제에서 그 마진을 지운다. */
.ev-band-sec { margin-bottom: var(--sec-gap); }
.ev-band-sec + .locate { margin-top: 0; }

@media (max-width: 1200px) {
  /* 좁은 화면은 이미 폭이 없다 → 들여쓰기를 푼다 (--tpl-inset 과 같은 기준) */
  .ev-band { --band-inset: 0px; }
}
@media (max-width: 991.98px) {
  /* 좁은 화면엔 컨테이너 바깥 여백이 없다 → 색 면도 없다(::after 폭이 0). 검정 면 하나로 선다 */
  .ev-band { padding-block: var(--sp-6); }
  .ev-band__in { flex-direction: column; text-align: center; gap: var(--sp-5); }
}

}

/* ============================================================================
   TEMPLATES-TYPE - 콘텐츠 컴포넌트의 글자 규격 (구 all_template.css 의 .at-body 스코프)

   통합 전에는 `.at-body ...` 로 쓰여, 스코프뿐 아니라 특이도 +1 을 얻어
   컴포넌트 룰(.gal-cap 등)을 이기고 있었다. 스코프를 풀면 그 우위가 사라지므로,
   특이도 대신 레이어 순서로 우위를 되돌린다 - templates 보다 뒤에 선다.
   ============================================================================ */
@layer templates-type {

/* ============================================================================
   폰트 5스케일 적용 레이어 (2026-07-14 전면 재작성)
   main.css 가 정한 5개 토큰만 쓴다. 여기서 새 크기를 만들지 않는다.

     --fs-h2title        42 -> 26 / 700 / 1.3  / -.03em   대제목 · "1994" 같은 대형 숫자
     --fs-h2lead         18 -> 16 / 400 / 1.6  / -.01em   토글 · 패널 kicker
     --fs-content-title  22 -> 18 / 600 / 1.35 / -.01em   제목 (제목+서브텍스트 묶음의 제목)
     --fs-content-subtext 16 -> 14 / 400 / 1.6 / 0        위 제목에 딸린 서브텍스트
     --fs-content-body   20 -> 15 / 400 / 1.6  / -.01em   제목 없이 본문만 · 표 내용
     --fs-eyebrow        14      / 600                    라벨 · STEP · 경고문 · 주의문구

   판별 규칙(사용자 검수 2026-07-14):
     · 제목이 있으면    → 제목 content-title + 딸린 글 content-subtext
     · 제목이 없으면    → 본문 content-body  (박스 안이어도 제목이 없으면 body)
     · 라벨/STEP/경고문 → eyebrow
     · 토글/kicker      → h2lead
   ============================================================================ */

/* ── 기본값 : 제목 · 서브텍스트 ─────────────────────────────────────────── */
:where(h3, h4, .gal-title, .ub-hero__cap h3, .ub-exp__cap h3, .ub-row__item h3,
                .ub-rail__card h3, .ub-time__body h3, .tpl-about__body h3, .ua-time__txt h3,
                .tpl-intro__item h3, .gal-acc__sum, .gal-sticky__aside .gal-title) {
  font-size: var(--fs-content-title); font-weight: 600;
  line-height: 1.35; letter-spacing: -.01em; }

/* 예외 : 긴 본문을 끊는 소제목 - [문단 다음에 오는 h3] 만 해당한다(.tpl-about__body p + h3).
   블록 맨 앞의 h3 는 여전히 카드 제목이므로 건드리지 않는다(svf-liposuction·svf-scar 가 그 형태다).
   글 안의 소제목이라 크기는 본문과 같게 두고 색(--point)으로만 위계를 준다. 굵기 600 은 기본값 그대로.
   ★ (요청) 위·아래를 각각 절반으로 줄였다 - 위 --sp-5(30) > 아래 --sp-3(15).
     비율(2:1)은 그대로 두고 절대값만 반으로 내린다. 아래쪽은 공통 룰
     [h3 + p = --box-gap-md 30] 를 덮어야 하므로 여기서 함께 지정한다. */
.tpl-about__body p + h3 {
  font-size: var(--fs-content-subtext); color: var(--point);
  margin-top: var(--sp-5); }
.tpl-about__body p + h3 + p { margin-top: var(--sp-3); }

/* 제목에 딸린 서브텍스트 - 제목(h3)이 있는 묶음 안의 글 */
:where(.gal-cap, .gal-list__body, .gal-steps__body, .gal-stagger__item, .gal-grid__item,
                .gal-circle__item, .gal-timeline__item, .gal-quad,
                .ub-hero__cap, .ub-hero__item, .ub-row__item, .ub-time__body,
                .ub-rail__body, .ub-ov__veil, .ub-ov__more, .ub-exp__cap, .ub-exp__more,
                .tpl-about__body, .tpl-intro__item, .ua-time__txt,
                .tpl-check__list li)
  :where(p, .ub-txt, .gal-desc, .ub-tag) {
  font-size: var(--fs-content-subtext); font-weight: 400;
  line-height: var(--lh-body); letter-spacing: normal; }

/* 03 · 04 · 46 : 제목 + 서브텍스트 중앙 정렬 */
:where(.gal-stagger__item, .gal-circle__item, .gal-grid__item) { text-align: center; }
:where(.gal-stagger__item, .gal-circle__item, .gal-grid__item) :where(h3, .gal-title, p, .gal-desc) {
  text-align: center; }

/* 05 : 세로 4열 캡션 오버레이 - 제목 위치를 고정한다.
   서브텍스트를 2줄 높이로 잡아 두어, 1줄짜리 카드도 제목이 같은 선에 선다. */
.gal-cap { display: grid; align-content: end; }
.gal-cap .gal-desc {
  min-height: calc(var(--fs-content-subtext) * var(--lh-body) * 2); }

/* 06 : 호버 확장 사진 카드 - 아이콘(이모지) 제거. eyebrow → title → subtext 로 세운다.
   여백이 아예 없어 글이 서로 붙어 있었다 → 라벨 5 · 제목 30 간격을 준다. */
.ub-ov__veil { display: grid; align-content: end; row-gap: 0;
  padding: var(--sp-6); }
/* 06 예외 : 5장짜리 - 33(Surgery Steps)과 같은 골격이라 캡션이 사진 **아래**에 온다.
   (구조·색은 templates 레이어 쪽 참조. 여기서 덮지 않으면 align-content: end 가 이겨 글이 아래로 쏠린다) */
.ub-ov:not(.ub-ov--circle):has(.ub-ov__card:nth-child(5):last-child) .ub-ov__veil {
  align-content: start; padding: var(--sp-5); }
/* (요청 2026-08-01) 태그·제목 윗줄을 카드마다 맞춘다 - 태그는 한 줄 고정("Stage 5, extended"가
   줄바꿈돼 제목이 한 줄 내려가던 것 방지), 제목은 2줄 높이를 예약해 본문 시작선도 맞춘다. */
.ub-ov:not(.ub-ov--circle):has(.ub-ov__card:nth-child(5):last-child) .ub-ov__veil .ub-tag {
  white-space: nowrap; }
.ub-ov:not(.ub-ov--circle):has(.ub-ov__card:nth-child(5):last-child) .ub-ov__veil h3 {
  margin-top: var(--box-gap-sm); min-height: calc(var(--fs-content-title) * 1.35 * 2); }
.ub-ov:not(.ub-ov--circle):has(.ub-ov__card:nth-child(5):last-child) .ub-ov__more {
  margin-top: var(--box-gap-md); }

/* 06 예외 : 원형 이미지 카드(.ub-ov--circle) - 캡션은 원 **아래 가운데**다.
   (구조·색은 templates 레이어 쪽 참조) */
.ub-ov--circle .ub-ov__veil {
  align-content: start; justify-items: center; text-align: center;
  padding: var(--sp-4) 0 0; }
/* 모바일은 캡션이 **원 안 정중앙**으로 들어간다(요청).
   ⚠️ 여기서 덮지 않으면 위 규칙(align-content: start · 좌우 padding 0)이 레이어 우선순위로 이겨
     글자가 위로 붙고 원 밖으로 삐져나간다.
   좌우 padding 은 **15%** - 정사각 안에 내접한 원의 여백이라 글이 원 밖으로 나가지 않는다. */
@media (max-width: 991.98px) {
  .ub-ov--circle .ub-ov__veil {
    align-content: center; padding: 15%; }
}
.ub-ov__veil .ub-tag {
  font-size: var(--fs-eyebrow); font-weight: 600; letter-spacing: .08em;
  text-transform: uppercase; line-height: 1.5; }
.ub-ov__veil h3 { margin-top: var(--box-gap-sm); }
.ub-ov__more { margin-top: var(--box-gap-md); }
.ub-ov__more > p,
.ub-exp__more > p {
  font-size: var(--fs-content-subtext); font-weight: 400;
  line-height: var(--lh-body); letter-spacing: normal; }
/* (2026-07-16) 가로 확장 패널 본문만 한 단계 작게(subtext 16 → eyebrow 14) */
.ub-exp__more > p { font-size: var(--fs-eyebrow); }

/* 10 : 매거진 리스트 - eyebrow(SVF CARE 01) → title → subtext */
.gal-list__no {
  font-size: var(--fs-eyebrow); font-weight: 600; letter-spacing: .08em;
  text-transform: uppercase; line-height: 1.5; }
.gal-list__body .gal-title { margin-top: var(--box-gap-sm); }
.gal-list__body .gal-desc { margin-top: var(--box-gap-md); }

/* 08 : 비교표 - 좌측 비교 항목은 title, 각 칸의 값은 subtext.
   (요청 2026-07-14) 표 안의 값이 규격 없이 body(20) 로 서 있었다 → 제목이 있는 묶음의 본문이므로 subtext.
   머리행(옵션명)은 라벨이라 eyebrow 그대로다. */
.ub-tbl tbody th[scope="row"] .ub-tbl__key {
  font-size: var(--fs-content-title); font-weight: 600; line-height: 1.35; letter-spacing: -.01em; }
.ub-tbl tbody td {
  font-size: var(--fs-content-subtext); font-weight: 400;
  line-height: var(--lh-body); letter-spacing: normal; }

/* 11 : 구분선 아이콘 행 - 왼쪽부터 title → subtext → subtext.
   ub-tag 도 라벨이 아니라 서브텍스트다(위 기본 규칙에서 이미 subtext). */
.ub-row__item .ub-tag { text-transform: none; letter-spacing: normal;
  font-weight: 400; }
/* PC(>1200) 는 [아이콘|제목|빨강|검정] 4열이라 세로 마진이 필요 없다.
   ≤1200 에서 [아이콘|제목] 아래로 빨강 → 검정이 쌓일 때만 리듬을 준다.
   (요청 2026-07-14) 빨강↔검정은 한 덩어리로 읽혀야 한다 → 제목과의 간격(10)보다 바짝(5) 붙인다. */
.ub-row__item h3 + .ub-tag,
.ub-row__item .ub-tag + .ub-txt { margin-top: 0; }
@media (max-width: 1200px) {
  .ub-row__item h3 + .ub-tag { margin-top: var(--sp-2); }
  .ub-row__item .ub-tag + .ub-txt { margin-top: var(--sp-1); }
}

/* 13 · 22 : 제목 없이 본문만 있는 안 → content-body. 표 내용도 같다.
   (12 체크리스트는 제목(h3)이 생겨 위의 title + subtext 규칙으로 넘어갔다) */
:where(.ti-spec__k, .ti-spec__v,
                .ua-sticky__txt p) {
  font-size: var(--fs-content-body); font-weight: 400;
  line-height: var(--lh-body); letter-spacing: -.01em; }

/* 29 : 중앙 축 타임라인 - cue(연구의 시작)가 제목을 맡는다.
   cue 는 h3 가 아니라 p 라서 위의 서브텍스트 규격에 함께 걸린다.
   그 규격이 소스 순서상 뒤에 서므로, 특이도를 세워 제목 규격을 되찾는다. */
.ua-time__txt .ua-time__cue {
  font-size: var(--fs-content-title); font-weight: 600;
  line-height: 1.35; letter-spacing: -.01em; }

/* 15 : 좌우 2단 - title → subtext */
.tpl-about__body h3 { color: var(--point); }
.tpl-about__body h3 + p { margin-top: var(--box-gap-md); }
/* 42 About 인트로의 세 번째 줄은 "리드"다 - h2 아래 리드는 어디서나 --fs-h2lead(18).
   .tpl-about__body 의 기본 서브텍스트(16)를 이기려면 templates-type 안에 있어야 한다
   (templates 레이어에 적으면 위 :where(.tpl-about__body) p 규칙에 진다) */
.tpl-about--intro .tpl-about__body > h2 + p {
  font-size: var(--fs-h2lead); font-weight: 400;
  line-height: var(--lh-body); letter-spacing: -.01em; }
/* ⚠️ eyebrow 는 <p> 라서 위 .tpl-about__body p 규칙들에 걸려 뭉개진다
   (실측: --point 빨강·600·자간 .08em 이어야 하는데 ink 검정·400·자간 normal 로 나왔다).
   .tpl-eyebrow 는 components 레이어라 templates/templates-type 을 이기지 못한다
   → 공식 eyebrow 값을 여기서 그대로 되돌린다. 새 값을 만들지 않는다 - 섹션 헤드의 라벨과 똑같다. */
.tpl-about--intro .tpl-about__body > .tpl-eyebrow {
  font-size: var(--fs-eyebrow); font-weight: 600; letter-spacing: .08em;
  text-transform: uppercase; color: var(--point); line-height: 1.5; }

/* 17 · 20 : 토글/kicker 는 h2lead · 본문은 content-body (제목이 없다) */
.ua-offset__tag,
.ua-bleed__kicker {
  font-size: var(--fs-h2lead); font-weight: 400;
  line-height: var(--lh-body); letter-spacing: -.01em;
  text-transform: none; }
/* 본문 - 토글(tag/kicker)은 같은 <p> 라서 반드시 빼 준다(안 그러면 본문 규칙이 이긴다) */
.ua-offset__text > p:not(.ua-offset__tag),
.ua-bleed__inner > p:not(.ua-bleed__kicker) {
  font-size: var(--fs-content-body); font-weight: 400;
  line-height: var(--lh-body); letter-spacing: -.01em; }

/* 19 : 사진 밑 캡션 카드 - 하단 추가문(ua-cap__foot)은 경고/보충 성격 → eyebrow */
.ua-cap__foot {
  font-size: var(--fs-eyebrow); font-weight: 400;
  line-height: var(--lh-tight); letter-spacing: normal; color: var(--gray-dark); }
.ua-cap__title {
  font-size: var(--fs-content-title); font-weight: 600;
  line-height: 1.35; letter-spacing: -.01em; }
.ua-cap__card > p:not(.ua-cap__title) {
  font-size: var(--fs-content-subtext); font-weight: 400; line-height: var(--lh-body); }
.ua-cap__title + p { margin-top: var(--box-gap-md); }

/* 21 : sticky 사진 + 번호 카드 - title → subtext. CTA 는 main.css 규격 그대로. */
.tpl-intro__item h3 + p { margin-top: var(--box-gap-md); }

/* 26 : 사진 위 숫자 타일 - "1994" 같은 큰 숫자는 h2title */
.ua-stat__n {
  font-size: var(--fs-h2title); font-weight: 700;
  line-height: 1.3; letter-spacing: -.03em; }
.ua-stat__n span { font-size: var(--fs-content-title); font-weight: 600; }
.ua-stat__k {
  font-size: var(--fs-content-subtext); font-weight: 400;
  line-height: var(--lh-body); letter-spacing: normal; }
.ua-stat__body { padding-inline: var(--sp-8); column-gap: 0; }
.ua-stat__body > p { padding-inline: var(--sp-5);
  font-size: var(--fs-content-body); line-height: var(--lh-body); }

/* 28 : 세로 타임라인 - STEP 은 eyebrow → title → subtext */
.ub-time__step {
  font-size: var(--fs-eyebrow); font-weight: 600; letter-spacing: .08em;
  text-transform: uppercase; line-height: 1.5; }
.ub-time__body h3 { margin-top: var(--box-gap-sm); }
.ub-time__body .ub-txt { margin-top: var(--box-gap-md); }

/* 33 : 가로 스냅 레일 - 라벨(ub-tag) 은 eyebrow → title → subtext */
.ub-rail__body .ub-tag {
  font-size: var(--fs-eyebrow); font-weight: 600; letter-spacing: .08em;
  text-transform: uppercase; line-height: 1.5; }
.ub-rail__body h3 { margin-top: var(--box-gap-sm); }
.ub-rail__body .ub-txt { margin-top: var(--box-gap-md); }

/* 34 : 가로 확장 패널 · title → subtext
   (2026-07-16) 패딩 - 상 sp-5 · 우 sp-4 · 하 sp-3 · 좌 sp-3.
   좌측 여백은 한 단계 줄이고, 하단 여백도 줄여 이모지·제목 블록을 아래로 내린다. */
.ub-exp__cap { display: grid; align-content: end; row-gap: 0;
  padding: var(--sp-5) var(--sp-4) var(--sp-3) var(--sp-3); }
.ub-exp__more { margin-top: var(--box-gap-md); }

/* 35 : 마퀴 흐름 - 하단 주의 문구는 eyebrow */
:where(.bna-note, .bna-cap, .bna-fade__hint, .bna-grid__meta,
                .bna-film__cap, .bna-lb__cap) {
  font-size: var(--fs-eyebrow); font-weight: 400;
  line-height: var(--lh-tight); letter-spacing: normal; }

/* ── 공통 여백 : 제목 ↔ 서브텍스트 · 사진 ↔ 제목 ───────────────────────── */
:where(h3, h4, .gal-title) + :where(p, .ub-txt, .gal-desc) {
  margin-top: var(--box-gap-md); }
:where(img, figure, picture, .gal-pic, .ub-rail__ph, .tpl-box__photo)
  + :where(h3, h4, .gal-title) { margin-top: var(--box-gap-photo); }

/* 세로 배치 카드의 내부 간격 주인을 margin 하나로 몰아준다(grid gap 과 이중으로 더해지지 않게) */
:where(.gal-cap, .gal-list__body, .gal-steps__body, .ub-hero__cap, .ub-hero__item,
                .ub-time__body, .ub-rail__body, .ub-ov__veil, .ub-exp__cap) { row-gap: 0; }

/* 10 : 히어로 위성 항목 - 모바일에선 [아이콘 + 제목] 한 줄, 그 아래 내용이다(§ 반응형).
   제목↔내용 간격은 11(.ub-row__item)과 같은 리듬(10)으로 맞춘다.
   ※ 위 `h3 + p` 공통 규칙(--box-gap-md, 19)이 레이어 우선순위로 이기므로 반드시 여기서 덮는다. */
@media (max-width: 991.98px) {
  .ub-hero__item h3 + .ub-tag { margin-top: var(--sp-2); }
}

/* 가로형 사진 안(10 매거진 리스트)은 사진칸을 16:9 로 눕힌다 */
.gal-list__item .gal-pic { aspect-ratio: var(--ratio-photo-m); }

/* 13 정의형 2열 표 - 사진과 표가 붙어 있었다 */
.ti-spec { column-gap: var(--sp-8); }
}

/* ═══════════════════════════════════════════════════════════════════════════
   연구소 사진 그리드 (.lab-grid) — svf-hair "Cell Matrix Lab"
   (요청 2026-07-14) 예전엔 사진 4장이 가로로 붙은 **합성 이미지 한 장**(1280×424)이었다.
   단일 <img> 라 모바일에서 통째로 줄어들어 각 사진이 알아볼 수 없이 작아졌다.
   → 원본을 4장으로 쪼개고 그리드로 세운다. PC 는 가로 4열(원본과 같은 줄), 모바일은 2×2.
   ═══════════════════════════════════════════════════════════════════════════ */
.lab-grid { display: grid; grid-template-columns: repeat(4, 1fr);
  align-items: center; gap: var(--sp-6);
  margin: 0; padding: 0; list-style: none; }
.lab-grid li { display: grid; place-items: center; }
.lab-grid img { width: 100%; height: auto; object-fit: contain; }
/* 모바일 - 2×2. 4장이 두 줄로 접히면서 각 사진이 화면의 절반 폭을 쓴다 */
@media (max-width: 767.98px) {
  .lab-grid { grid-template-columns: repeat(2, 1fr); gap: var(--sp-5); }
}

/* Root Cause Solution 도식 (.root-fig) — svf-hair
   (요청 2026-07-14) 1170 → 880 → 720 으로 줄이고 가운데 세운다. 원·아치 몇 개뿐인 단순
   도식이라 크게 키울 이유가 없다.
   ★ 이미지 자체의 위쪽 여백(54px)도 잘라냈다(1001×540 → 1001×486) - 도식 위가 비어
     제목과의 간격이 실제보다 멀어 보였다. HTML width/height 도 새 비율로 갱신했다. */
.root-fig { display: block; width: 100%; max-width: 720px; height: auto;
  margin-inline: auto; }
@media (max-width: 767.98px) { .root-fig { max-width: 100%; } }

/* ═══════════════════════════════════════════════════════════════════════════
   드래그 와이프 - 사진 원본 비율 변형 (.bna-wipe--photo)
   (요청 2026-07-14 · signature-heogolseung 리얼 셀피)
   기본 .bna-wipe 는 3열 · 정사각(490/492)에 "1250px 원본을 크롭해 반쪽만 보여주는" 좌표계를
   갖고 있다(.bna-shot--b/--a img 의 width/left calc). 셀피는 전·후가 각각 독립된 사진이라
   크롭이 필요 없다 → 좌표계를 풀고 사진을 그대로 채운다.
     · 4열  : before+after 4세트가 한 줄에 선다
     · 세로 : 원본 비율(303:383)을 그대로 살려 인물이 잘리지 않는다
   ═══════════════════════════════════════════════════════════════════════════ */
.bna-wipe--photo { grid-template-columns: repeat(4, 1fr); }
.bna-wipe--photo .bna-wipe__box { aspect-ratio: 303 / 383; }
/* 크롭 좌표계 해제 - 사진이 박스를 그대로 채운다 */
.bna-wipe--photo .bna-shot { aspect-ratio: auto; }
.bna-wipe--photo .bna-shot img { position: absolute; inset: 0;
  width: 100%; height: 100%; left: 0; object-fit: cover; }
/* 모바일 1단 - 4열을 유지하면 사진이 80px 로 쪼그라들어 전후 비교가 불가능하다 */
@media (max-width: 991.98px) {
  .bna-wipe--photo { grid-template-columns: 1fr; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   좋은 라인 조건 그래프 (.cond-chart) — svf-liposuction "Body Line Conditions"
   (요청 2026-07-14 · 재작업) 검정 막대와 헤더 띠를 걷어냈다. 카드 안에 또 제목을 얹으면
   섹션 H2 와 제목이 두 번 나온다 → 그래프만 은은하게 둔다.
   색: 트랙 --bg-soft(연회색) · 채움 --point-soft(흐린 포인트) · SVF 만 --point(진한 포인트)
   막대 길이(--w)는 각 조건이 "얼마나 갖춰져야 하는가". SVF 만 100% - 앞의 네 조건이
   부족해도 SVF 가 전 구간을 보완한다는 뜻이다.
   ═══════════════════════════════════════════════════════════════════════════ */
.cond-chart { margin: 0; }
.cond-chart__list { display: grid; gap: var(--sp-6);
  margin: 0; padding: 0; list-style: none; }
/* 한 행 = [라벨 ─ 값] 한 줄, 그 아래 막대 */
.cond-bar { display: grid; grid-template-columns: 1fr auto; align-items: baseline;
  column-gap: var(--sp-4); row-gap: var(--sp-2); }
.cond-bar__label { font-size: var(--fs-content-subtext); font-weight: 600;
  letter-spacing: -.01em; color: var(--ink); }
.cond-bar__value { font-size: var(--fs-eyebrow); font-weight: 400; color: var(--gray-dark); }
.cond-bar__track { grid-column: 1 / -1; display: block; height: 8px;
  border-radius: var(--r-pill); background: var(--bg-soft); overflow: hidden; }
.cond-bar__fill { display: block; width: var(--w); height: 100%;
  border-radius: var(--r-pill); background: var(--point-soft); }
/* SVF 회복력 - 결론이라 진한 포인트로 찍는다 */
.cond-bar--svf .cond-bar__label { color: var(--point); }
.cond-bar--svf .cond-bar__value { color: var(--point); font-weight: 600; }
.cond-bar--svf .cond-bar__fill { background: var(--point); }
/* (요청 2026-07-14) 그래프도 사진처럼 sticky - 조건 카드를 읽어 내려가는 동안 왼쪽에 붙어
   따라온다. 기본 .tpl-intro__aside 규칙(sticky · top --sp-6)을 그대로 쓰므로 여기서
   position 을 덮지 않는다.
   ★ sticky 가 실제로 붙으려면 왼쪽이 오른쪽보다 "짧아야" 한다 - 그래프(555)가 조건 5개(986)
     보다 짧아 430px 의 스크롤 여지가 생긴다. */

/* ═══════════════════════════════════════════════════════════════════════════
   SVF 지방흡입 기대 변화 (.effect-row) — svf-liposuction
   (요청 2026-07-14) 팔각형 도식 이미지(42_4.webp)를 걷어내고 마크업으로 세웠다.
   원본은 텍스트가 그림에 박혀 있어 검색엔진이 못 읽고, 모바일에서 라벨이 뭉개졌다.
   8개를 한 줄로 죽 늘어놓는다. 한 칸 = [아이콘 ⏎ 이름 + 방향 화살표].
   색으로 방향을 읽힌다: 올라감 --point(포인트) · 내려감 --gray-dark(중립).
   ═══════════════════════════════════════════════════════════════════════════ */
.effect-row { display: grid; grid-template-columns: repeat(8, minmax(0, 1fr));
  gap: var(--sp-4); margin: var(--head-gap-body) 0 0; padding: 0; list-style: none; }
.effect-cell { display: grid; justify-items: center; align-content: center;
  gap: var(--sp-3);
  padding: var(--sp-5) var(--sp-3); border-radius: var(--r-lg);
  background: var(--bg-soft); text-align: center; }
.effect-cell__ico { font-size: var(--ico-xl); line-height: 1; }
.effect-cell__name { display: flex; align-items: center; justify-content: center; gap: .3em;
  font-size: var(--fs-content-subtext); font-weight: 600; letter-spacing: -.01em;
  color: var(--ink); white-space: nowrap; }
.effect-cell__arrow { font-size: var(--ico-sm); line-height: 1; }
/* 올라가는 것 - 포인트색. 배경도 아주 옅게 깔아 한 덩어리로 읽힌다 */
.effect-cell--up   { background: var(--point-bg); }
.effect-cell--up   :is(.effect-cell__ico, .effect-cell__arrow) { color: var(--point); }
/* 내려가는 것 - 중립 */
.effect-cell--down :is(.effect-cell__ico, .effect-cell__arrow) { color: var(--gray-dark); }

@media (max-width: 991.98px) { .effect-row { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (max-width: 575.98px) { .effect-row { grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--sp-3); } }

/* 시술 프로세스 sticky 이미지 - 가로형 예외 (.tpl-process__img--wide)
   (요청 2026-07-14) 기본 슬롯은 정사각(--ratio-square)이라 가로 사진을 넣으면 좌우가 18%씩
   잘린다(JCI 인증 마크의 월계관 잎이 날아갔다) → 원본 비율(700:449)을 그대로 쓴다.
   ★ 기본 .tpl-process--sticky 규칙은 건드리지 않는다 - 정사각 사진을 쓰는 다른 페이지가 있다. */
.tpl-process--sticky .tpl-process__img--wide { aspect-ratio: 700 / 449; }
/* 모바일 - 기본 규칙이 img 에 aspect-ratio: 4/5(세로) 를 강제한다. 가로 사진은 그 비율로 늘어나
   부모(700:449)를 넘쳐 아래가 잘린다(340 폭에서 img 425 vs figure 218) → 원본 비율로 되돌린다.
   figure 는 auto 로 풀어 img 높이를 그대로 따라가게 한다. (2026-07-14) */
@media (max-width: 991.98px) {
  .tpl-process__img--wide,
  .tpl-process--sticky .tpl-process__img--wide { aspect-ratio: auto; }
  .tpl-process__img--wide img,
  .tpl-process--sticky .tpl-process__img--wide img { aspect-ratio: 700 / 449; object-fit: contain; }
}

/* 시술 프로세스 sticky 이미지 - 세로형 예외 (.tpl-process__img--tall)
   주사기 세로컷(1030:1179) 등. 모바일에서 기본 규칙이 img 에 4:3(가로) 비율 + cover 를 강제해
   위아래가 잘린다(주사기 상단이 날아감) → 원본 비율로 되돌려 통째로 보이게 한다. (2026-07-26)
   ★ PC 규칙은 건드리지 않는다 - 사용자 지적은 모바일 한정. */
@media (max-width: 991.98px) {
  .tpl-process__img--tall,
  .tpl-process--sticky .tpl-process__img--tall { aspect-ratio: auto; }
  .tpl-process__img--tall img,
  .tpl-process--sticky .tpl-process__img--tall img { aspect-ratio: 1030 / 1179; object-fit: contain; }
}

/* 연속된 주석 줄(※)은 한 덩어리다 - 사이를 40 → 5 로 좁힌다. (요청 2026-07-14)
   .tpl-eyebrow 는 섹션 머리 라벨과 하단 주석을 겸하는데, 주석이 2줄 이상 연달아 오면
   각자 40px 마진을 받아 별개 문단처럼 뚝뚝 떨어졌다.
   ★ 섹션 머리 eyebrow 는 h2 앞에 하나뿐이라 이 선택자(연속)에 걸리지 않는다. */
.tpl-eyebrow + .tpl-eyebrow { margin-top: var(--sp-1); }

/* 인물 사진 - 얼굴이 위쪽에 있는 컷 (.tpl-intro--facetop)
   (요청 2026-07-14 · lipo-face-vline) 모바일 슬롯은 16:9 가로라, 세로 인물 사진(539:631)을
   중앙 크롭하면 얼굴(상단)이 잘리고 몸통·배경(하단)만 남는다.
   → ① 크롭 기준을 위로 올려 얼굴을 살리고 ② 슬롯을 4:3 으로 세워 세로를 조금 더 확보한다.
     "하단을 덜 보이게" = 위에서부터 담고 아래를 버린다. */
@media (max-width: 991.98px) {
  .tpl-intro--facetop .tpl-intro__aside img {
    aspect-ratio: 4 / 3;
    object-position: 50% 12%;
  }
}

/* ── 48) 관련 시술·비수술 + 참고 논문 ──────────────────────────────────
   정식 섹션(중앙 .section__head) 아래, 카드 두 폭에 맞춘 한 벌.
   ① 2단 카드(시술·비수술 : 종류 라벨 + 이름 + 한 줄 설명, 넘치면 …)
   ② 카드 폭과 같은 회색선 아래 "참고 논문 : 링크" 두 줄.
   새 색·크기를 만들지 않는다 - --fs-*·--gray-dark·--point·--sp·--r-lg 토큰을 쓴다. */
.rel-cite { max-width: 760px; margin-inline: auto; }
/* 이 블록만 헤드↔카드 간격을 줄인다(전역 --head-gap-body 80 은 그대로 둔다).
   특이도를 전역 규칙(0,3,0)보다 높여(0,4,0) 순서와 무관하게 이긴다. */
.tpl-sec > .container > .section__head + .rel-cite { margin-top: var(--sp-7); }
/* 카드 2단(모바일 1단). 너비는 .rel-cite 가 정한다 → 아래 회색선과 폭이 맞는다 */
.rel-links { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-4); }
.rel-card { display: grid; gap: var(--sp-1); padding: var(--sp-4) var(--sp-5);
  border: var(--hairline) solid var(--point); border-radius: var(--r-lg);
  transition: background-color .2s, box-shadow .2s; }
.rel-card:hover { background: var(--point-bg);
  box-shadow: inset 0 0 0 var(--hairline) var(--point); }
/* 제목은 본문 스케일(--fs-content-body 20)로 한 단계 내린다.
   이 카드는 "읽을거리 안내"라 본문 h3(--fs-content-title 22)과 같은 무게로 서면 과하다.
   굵기 600 은 유지해 설명(--fs-content-subtext 16)과의 위계는 그대로 둔다. */
.rel-card__name { font-size: var(--fs-content-body); font-weight: 600; color: var(--ink); }
/* 설명은 한 줄만 - 넘치면 … (2줄로 늘어지지 않게) */
.rel-card__desc { font-size: var(--fs-content-subtext); color: var(--gray-dark);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Related Treatments / Related Articles 카드(일반형만: last-diet 목록 .article-list, 상세 이전/다음
   .blog-nav 제외). 한 줄 말줄임이 긴 설명을 잘라내던 문제를 풀고, 제목을 2줄 높이로 예약해
   같은 줄의 두 카드에서 [제목→설명] 시작 높이가 (한 카드 1줄·다른 카드 2줄이어도) 맞도록 한다. */
.rel-links:not(.article-list) > .rel-card:not(.blog-nav) { align-content: start; }
.rel-links:not(.article-list) > .rel-card:not(.blog-nav) .rel-card__name {
  line-height: var(--lh-tight);
  min-height: calc(var(--fs-content-body) * var(--lh-tight) * 2);
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }
.rel-links:not(.article-list) > .rel-card:not(.blog-nav) .rel-card__desc {
  white-space: normal;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }
/* 참고 논문 : 카드 폭과 같은 회색선, "참고 논문 : 링크" 한 줄씩(각주 크기) */
.refs { margin-top: var(--sp-5); padding-top: var(--sp-4);
  border-top: var(--hairline) solid var(--gray-light); }
/* 참고 논문 한 줄(cite) : eyebrow 보다 작은 --fs-ref, 1줄 초과 금지 → 끝 … 처리 */
.refs__item { font-size: var(--fs-ref); line-height: 1.7; color: var(--gray-dark); margin: 0;
  text-align: center;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.refs__item cite { font-style: normal; }
.refs__item a { color: var(--gray-dark); text-decoration: underline; text-underline-offset: 2px; }
.refs__item a:hover { color: var(--point); }
@media (max-width: 767.98px) {
  .rel-links { grid-template-columns: minmax(0, 1fr); }
}

/* (요청 2026-07-17) 스타 방문 갤러리 - 캡션이 "직업+이름" 한 줄뿐이라 제목 급(22/600)이 과하다
   → 본문 급(subtext/400)으로 한 단계 내린다. 캡션이 문장인 다른 gal-grid 는 그대로다.
   ⚠️ 캡션 굵기·크기는 @layer templates-type 이 정한다 → 그보다 센 "레이어 밖"(여기)에 둔다.
     gal-grid 블록(templates 레이어) 옆에 두면 templates-type 에 진다. */
#withstarGrid .gal-title { font-size: var(--fs-content-subtext); font-weight: 400; }
/* ⚠️ hidden 속성만 믿으면 안 된다 (2026-07-17 버그 수정 - 사용자 로컬 재현).
   hidden 의 숨김은 브라우저 내장(UA) 스타일인데, 카드의 display:grid(작성자 규칙)가
   이를 덮는 브라우저가 있어 46장이 전부 보였다(크롬은 UA 쪽이 !important 라 우연히 살았다).
   탭 패널의 기존 처방([role="tabpanel"][hidden])과 같은 방식으로 직접 못 박는다.
   ※ 전역 [hidden] 규칙은 금지 - .mobile-menu[hidden]{display:flex} 가 의도적으로 hidden 을 덮는다. */
.gal-grid__item[hidden] { display: none !important; }
.rel-card[hidden] { display: none !important; }   /* last-diet 후기 더보기 - 같은 함정 방어 */
.selfie-card[hidden] { display: none !important; }   /* 셀카 피드 더보기 - 같은 함정 방어 */
.tpl-box[hidden] { display: none !important; }   /* 성형 이벤트 카테고리 필터 - .tpl-box{display:grid} 가 hidden 을 덮는 함정 방어 */

/* (요청 2026-07-17) 아카데미 수료 갤러리 캡션 - 제목↔설명을 좁히고(10→5)
   묶음을 카드 하단으로 내린다(하단 패딩 30→15). 이 섹션 한정 - .gal-cap 은 공용이다. */
[aria-labelledby="completionTitle"] .gal-cap { gap: var(--sp-1); padding-bottom: var(--sp-3); }
/* 제목+본문 공용 마진(30)이 gap 위에 얹힌다 → 여기선 gap(5) 하나만 남긴다 */
[aria-labelledby="completionTitle"] .gal-cap .gal-desc { margin-top: 0; }

/* (요청 2026-07-17) 라스트 다이어트 실제 후기 - PC 3열 (rel-links 기본은 2열·폭 760 제한) */
.rel-cite:has(.article-list) { max-width: none; }
/* (요청 2026-07-18) 셀카후기·전후사진 본문(사진 그리드)은 760 → 850 으로 넓힌다.
   그리드가 폭을 채우므로 사진도 함께 커진다. */
.rel-cite:has(.selfie-feed), .rel-cite:has(.bna__grid) { max-width: 850px; }
/* (요청 2026-07-18) 전후사진 리스트(articles-bna)는 모바일에서 1줄 1개 - 전후 비교가 작아지지 않게.
   index 의 전후사진 그리드(#bna-panel-*)는 그대로 두고, 리스트(#articleList)에만 건다. */
@media (max-width: 767.98px) {
  .bna__grid#articleList { grid-template-columns: minmax(0, 1fr); }
}
/* (요청 2026-07-17) 아티클 리스트 - 텍스트만 있는 카드라 3열은 어지럽다 → 2열.
   카드도 톤 다운: 빨간 외곽선 대신 사이트 표준 카드 면(--bg-soft), 포인트는 hover 에만. */
.article-list { grid-template-columns: repeat(2, minmax(0, 1fr)); max-width: 1000px; margin-inline: auto; }
.article-list .rel-card,
.blog-nav.rel-card { border-color: transparent; background: var(--bg-soft); }
.article-list .rel-card:hover,
.blog-nav.rel-card:hover { background: var(--point-bg); box-shadow: none; }
/* ★★ 아티클 카드의 제목·발췌 규칙은 여기 "한 벌"만 둔다 (2026-07-17).
   리스트(.article-list)와 아티클 하단 이전/다음(.blog-nav)은 같은 카드다 → 셀렉터에 나란히 적는다.
   따로 복붙하면 값이 갈라진다(실제로 갈라져서 되돌린 이력).
   제목: 2줄 고정(min) + 2줄 클램프(max) - 1줄짜리도 발췌가 같은 선에서 시작한다. */
.article-list .rel-card__name,
.blog-nav .rel-card__name {
  min-height: calc(var(--fs-content-body) * 1.35 * 2); line-height: 1.35;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }
/* 아티클 카드의 날짜 줄 - 발췌 아래 작게 */
.rel-card__date { font-size: var(--fs-eyebrow); color: var(--gray-dark); }
/* 발췌: 최대 2줄 - 기본 1줄 말줄임(nowrap)을 풀고 2줄에서 자른다. min-width:0 이라야 셀에 갇힌다 */
.article-list .rel-card__desc,
.blog-nav .rel-card__desc { white-space: normal; min-width: 0; max-width: 100%;
  /* ★ word-break: break-all - 전역 keep-all(단어 단위)은 줄 끝을 못 채워 2줄이 제각각 길이로
     어정쩡하게 끝난다(실측 둘째 줄 235~346 / 셀 446). 글자 단위로 끊어야 폭을 채우고 … 로 닫힌다. */
  word-break: break-all;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }
/* (요청 2026-07-17) 리스트 헤더(설명) ↔ 카테고리 토글 간격은 표준(112)의 절반.
   토글이 헤더에 딸린 필터라 붙어 읽혀야 한다. calc 라 모바일 스케일도 함께 절반이 된다.
   아티클 토글에만 - index 쇼츠/전후사진 토글(112)은 그대로다. */
.section__head + .section__toggle[aria-label="Article categories"] {
  margin-top: calc(var(--head-gap-body) / 2); }
/* 아티클 바이라인 - H2 아래 [작성자 · 날짜], 본문보다 작게.
   셀카후기는 우측 끝에 별점(.selfie-star, 리스트 카드와 동일 컴포넌트 재사용)이 붙는다 -
   flex 로 눕히면 별점이 margin-left:auto 로 오른쪽에 정렬된다. 별점 없는 글은 바이라인만 있어
   단일 아이템 flex 라 보이는 변화가 없다. */
.section__head .article-meta { font-size: var(--fs-content-subtext); color: var(--gray-dark);
  margin-top: var(--sp-3); display: flex; align-items: center; gap: var(--sp-3); }
.article-list__empty { grid-column: 1 / -1; text-align: center; color: var(--gray-dark);
  font-size: var(--fs-content-body); padding-block: var(--sp-8); }
@media (max-width: 767.98px) {
  .article-list { grid-template-columns: minmax(0, 1fr); }
  /* (요청 2026-07-17) 모바일 아티클 리스트 = PC 와 같은 연회색 카드, 단 제목만 보여준다.
     제목은 본문 급(15)/400 으로 낮춘다 - 카드가 촘촘해 제목 급(18/600)은 과하다. */
  .article-list { gap: var(--sp-3); }
  .article-list .rel-card__desc,
  .blog-nav .rel-card__desc { display: none; }
  /* (요청 2026-07-17) 모바일에선 이전/다음 카드도 리스트 행과 "완전히 같은 UI" -
     좌우 방향 화살표를 버리고 제목 1줄 + 우측 꺾쇠(>)만 남긴다(아래 ::after 규칙이 함께 건다).
     ⚠️ 감싼 span 을 block(=리스트 카드의 grid 와 같은 흐름)으로 되돌려야
        제목이 카드 폭을 다 쓰고 꺾쇠 자리(padding-right)도 지켜진다. inline 이면 둘 다 깨진다. */
  .blog-nav { display: block; text-align: left; }
  .blog-nav--next { text-align: left; }
  .blog-nav > i { display: none; }
  .blog-nav > span { display: block; }
  /* 제목은 무조건 1줄 - line-clamp(1) + max-height 이중 방어.
     -webkit-box + line-clamp 가 말줄임(…)까지 처리한다(nowrap 은 쓰지 않는다 -
     그리드 셀을 뚫고 나가는 원인이었다).
     ★ word-break: break-all - 기본 규칙은 "단어" 단위로만 끊어서, 마지막 단어가 길면
       그 앞에서 끊긴다 → 카드마다 … 위치가 제각각이 된다(실측 274 vs 245).
       글자 단위로 끊어야 폭을 끝까지 채우고 … 가 같은 자리에 선다. */
  .article-list .rel-card__name,
  .blog-nav .rel-card__name { min-height: 0;
    font-size: var(--fs-content-body); font-weight: 400;
    -webkit-line-clamp: 1; word-break: break-all;
    max-height: calc(var(--fs-content-body) * 1.35); }
  /* 우측 끝 빨간 꺾쇠(>) - 게시글(이동 가능한 행)이라는 어포던스. 마크업 없이 카드가 그린다.
     화살표(→)보다 홀쭉해 제목 공간을 덜 먹는다. */
  .article-list .rel-card,
  .blog-nav.rel-card { position: relative; padding-right: calc(var(--sp-4) + var(--ico-sm) + var(--sp-2)); }
  .article-list .rel-card::after,
  .blog-nav.rel-card::after { content: "\e13a"; font-family: "Phosphor";
    position: absolute; right: var(--sp-4); top: 50%; transform: translateY(-50%);
    color: var(--point); font-size: var(--ico-sm); }
}

/* ══════ (요청 2026-07-20) 블로그 리스트 카드 - articles-blog 전용 ══════
   빌드가 붙이는 것: 리스트에 .article-list--blog,
     이미지 있는 글 → .rel-card--thumb + <img class="rel-card__thumb">
     이미지 없는 글(공지 5건) → .rel-card--nothumb
   PC    : 1열 · 썸네일 240×135(16:9)를 오른쪽에 (다른 리스트는 2열 그대로 - 블로그만 바꾼다)
   모바일: 상단 전폭 이미지 + 하단 텍스트 로 세워 쌓는다
   ⚠️ 래퍼를 두지 않는다 - .rel-card 가 이미 grid 다. 행·열만 나눠 쓴다.
      (래퍼를 넣으면 제목 2줄 클램프·모바일 발췌 숨김 규칙의 셀렉터가 전부 어긋난다)
   ⚠️⚠️ --blog-thumb 를 :has() 안에서 정의하지 않는다. :has() 미지원 브라우저(구형 iOS Safari,
      카카오톡·네이버 인앱 웹뷰)에서 변수가 죽으면 width: var(--blog-thumb) 가 통째로 무효가 되고
      width:auto 로 떨어져 원본 이미지 폭(600~1200)이 그대로 펼쳐진다 → 가로 스크롤.
      클래스는 빌드가 붙이므로 :has() 없이 다 된다. var() 마다 폴백값도 함께 적는다. */
.article-list--blog { grid-template-columns: minmax(0, 1fr); max-width: 900px; }
.article-list--blog .rel-card--thumb,
.article-list--blog .rel-card--nothumb { --blog-thumb: 240px; }
.article-list--blog .rel-card--thumb {
  grid-template-columns: minmax(0, 1fr) var(--blog-thumb, 240px);
  /* ★ 행을 명시해야 썸네일의 grid-row:1/-1 이 제목+발췌를 덮는다.
     빼면 -1 이 암묵 행을 못 세어 썸네일이 1행에만 얹히고 카드가 그만큼 길어진다.
     ★★ 위아래 1fr 은 "남는 높이를 받아내는 빈 행"이다. 썸네일(135)이 글 두 줄(97)보다
        높은데, 빈 행이 없으면 그 차이가 제목·발췌 행에 나눠 들어가 둘 사이가 벌어진다.
        1fr 트랙이 있으면 남는 높이가 그쪽으로 먼저 가고, 덤으로 글이 세로 가운데에 선다. */
  grid-template-rows: 1fr auto auto 1fr;
  column-gap: var(--sp-5);
  max-width: 100%; overflow: hidden; }
/* min-width:0 + overflow:hidden - 사파리는 -webkit-box(줄 클램프) 요소의 최소 폭을
   "줄바꿈 안 한 전체 문장"으로 잡는 버그가 있다. 그러면 1fr 트랙이 밀려 카드가 화면을 뚫는다.
   크롬에선 보이지 않는 차이라, 값을 빼도 화면상 변화가 없다고 지우면 안 된다. */
.article-list--blog .rel-card--thumb .rel-card__name,
.article-list--blog .rel-card--thumb .rel-card__desc {
  grid-column: 1; min-width: 0; overflow: hidden; }
.article-list--blog .rel-card--thumb .rel-card__name { grid-row: 2; }
.article-list--blog .rel-card--thumb .rel-card__desc { grid-row: 3; }
.rel-card__thumb { grid-column: 2; grid-row: 1 / -1;
  width: var(--blog-thumb, 240px); max-width: 100%;  /* max-width - 변수가 죽어도 화면은 안 뚫는다 */
  height: auto; aspect-ratio: 16 / 9; object-fit: cover;
  border-radius: var(--r-lg); background: var(--bg-soft); }
/* 이미지 없는 글도 썸네일 카드와 같은 높이로 세운다 - 줄 높이가 들쭉날쭉해 보이지 않게 */
.article-list--blog .rel-card--nothumb {
  min-height: calc(var(--blog-thumb, 240px) * 9 / 16 + var(--sp-4) * 2); }
@media (max-width: 767.98px) {
  /* 세로 카드로 전환 - 이미지가 카드 상단을 가장자리까지 채우고 그 아래 제목.
     그래서 카드 패딩을 0 으로 내리고, 텍스트에만 좌우·아래 여백을 준다.
     (.rel-card 의 overflow:hidden + --r-lg 덕에 이미지 위쪽 모서리가 카드 곡률대로 잘린다) */
  .article-list--blog .rel-card--thumb {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto auto;    /* 발췌는 모바일에서 숨김 → 실제 행은 이미지 + 제목 둘 */
    row-gap: 0; padding: 0 0 var(--sp-4); align-items: start; }
  .article-list--blog .rel-card__thumb {
    grid-column: 1; grid-row: 1; width: 100%; border-radius: 0; }
  /* 행 배정(제목 2행)은 위 공통 규칙 그대로 - 여기선 여백과 줄 수만 바꾼다 */
  .article-list--blog .rel-card--thumb .rel-card__name {
    padding-inline: var(--sp-4); margin-top: var(--sp-3);
    -webkit-line-clamp: 2; max-height: calc(var(--fs-content-body) * 1.35 * 2); }
  .article-list--blog .rel-card--thumb::after { content: none; }   /* 우측 꺾쇠 - 세로 카드엔 안 맞는다 */
  .article-list--blog .rel-card--nothumb { min-height: 0; }        /* 텍스트만 있는 카드는 원래 높이로 */
}

/* (요청 2026-07-17) LAST DIET 관리 프로그램 - dr-cv 항목이 짧아 기본 폭(컨테이너 전폭)이면
   우측이 텅 빈다 → 표 전체를 좁혀 가운데 세운다. */
[aria-labelledby="programTitle"] .dr-cv { max-width: 720px; margin-inline: auto; }

/* ══════════════════════════════ 아티클 (.container--blog + .article-body) ══
   후기(diet-review-*)와 블로그 글이 공용하는 "읽는 글" 템플릿. 구성은 4부분:
     ① H2 영역   : .container--blog > .section__head (eyebrow + h2)
     ② 본문 영역 : .article-body - 좁은 글줄(780) · 본문 content-body · 전체 중앙 정렬
                   문단 <p> · 소제목 <h3> · 사진 <img> · 사진 캡션 <p class="tpl-eyebrow">
     ③ 이전/다음 : 일반 .container > .rel-links > .blog-nav 카드 (← 이전 / 다음 →)
     ④ 목록 보기 : .section__foot > .cta
   생성기는 phpall/_build/build_diet_reviews.py - 블로그 글도 같은 구조로 만들면 된다.
   ※ 소제목 색은 본문색(--ink) 그대로다. 후기의 Q 강조색 같은 변주는 페이지 스코프로 얹는다. */
.container--blog { max-width: 780px; margin-inline: auto; padding-inline: var(--sp-5); }
/* 헤드 ↔ 본문 간격 - 전역 규칙(80)은 .container 만 매칭해 여기엔 안 닿는다(실측 30).
   좁은 글줄에 112 는 과해서 60 으로 준다. */
.container--blog > .section__head + * { margin-top: var(--sp-7); }
/* 본문(좁은 글줄) ↔ 이전·다음 내비(일반 컨테이너) 사이 숨 */
.container--blog + .container { margin-top: var(--sp-8); }

.article-body { text-align: center; }
/* 본문 급 명시 - templates-type 의 서브텍스트 공용 규칙(14)이 이겨 버려 한 단계 더 작아진다 */
.article-body p { font-size: var(--fs-content-body); font-weight: 400;
  line-height: var(--lh-prose, 1.6); color: var(--ink); text-align: center; }
.article-body p + p { margin-top: var(--sp-4); }
.article-body h3 { font-size: var(--fs-content-title); font-weight: 600;
  line-height: 1.35; letter-spacing: -.01em; text-align: center; margin-top: var(--sp-6); }
.article-body h3 + p { margin-top: var(--sp-3); }
.article-body > img { display: block; margin: var(--sp-5) auto;
  max-width: min(100%, 720px); border-radius: var(--r-lg); }
/* 본문 영상 - .ratio 는 원래 tpl-about__media 스코프뿐이라 여기서 한 벌 더 정의한다.
   쇼츠(세로 영상)는 index 더라인 Shorts 카드와 같은 규격(비율 252:458 · 폭 313)이다. */
.article-body .ratio { position: relative; width: 100%; aspect-ratio: 16 / 9;
  margin: var(--sp-5) auto; border-radius: var(--r-lg); overflow: hidden; background: var(--bg-soft); }
.article-body .ratio iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.article-body .ratio--shorts { aspect-ratio: 252 / 458; max-width: 313px; }
.article-body > .tpl-eyebrow { text-align: center; margin-top: var(--sp-6); }

/* ══════ (요청 2026-07-21) 장문 아티클 읽기 레이아웃 (.article-body--long) ══════
   위의 중앙 정렬은 짧은 후기(셀카·상담·다이어트)를 위한 규격이다. 소제목을 여러 개 두는
   긴 글에서는 같은 규칙이 무너진다 - 문장이 가운데로 몰려 눈이 줄 시작점을 매번 새로 찾고,
   전역 h2(--fs-h2title 31.5px)가 그대로 걸려 제목(h1)과 크기가 같아져 계층이 사라진다.
   그래서 "소제목이 있는 글"에만 얹는 변형을 따로 둔다(빌더가 h·q 파트를 보고 클래스를 붙인다).
   ⚠️ .article-body 본체는 건드리지 않는다 - 기존 후기 800여 편의 룩이 그대로 유지돼야 한다.
   기준: georank.co.kr 리포트 레이아웃(H2 24/700 좌측 · 본문 17 좌측 · 행간 1.8). */
.article-body--long,
.article-body--long p { text-align: left; }
.article-body--long p { line-height: var(--lh-prose); }
.article-body--long p + p { margin-top: var(--sp-4); }
/* 소제목 계층: h1(31.5) > h2(≈22) > h3(18) > 본문(15).
   토큰에서 파생시켜 화면 폭에 따라 함께 움직이게 한다(고정 px 금지). */
.article-body--long > h2 {
  font-size: calc(var(--fs-content-title) * 1.25); font-weight: 700;
  line-height: 1.4; letter-spacing: -.02em; color: var(--ink); text-align: left;
  margin-top: var(--sp-7); margin-bottom: var(--sp-4); }
.article-body--long > h2:first-child { margin-top: 0; }
/* 이미지 바로 뒤 소제목은 위 여백을 줄인다 - 이미지 자체 마진과 겹쳐 과하게 벌어진다 */
.article-body--long > img + h2 { margin-top: var(--sp-6); }
.article-body--long h3 { text-align: left; }
/* 사진 앞 리드 문구(.tpl-eyebrow)도 좌측으로 - 본문이 전부 좌측인데 이것만 가운데면 혼자 튄다.
   ⚠️ .article-body > .tpl-eyebrow (0,2,0) 가 컨테이너 상속을 이기므로 같은 급으로 다시 적는다. */
.article-body--long > .tpl-eyebrow { text-align: left; }
/* 본문 이미지도 글줄 폭에 맞춘다 - 720 제한이 좁은 글줄에선 오히려 어긋나 보인다 */
.article-body--long > img { max-width: 100%; margin-block: var(--sp-6); }

/* ══════ FAQ (.faq) - 장문 아티클 하단 ══════
   기존 .gal-acc(아코디언)는 사진 갤러리용이라 얇은 구분선뿐이어서 글 하단에서 존재감이 없다.
   여기서는 카드 면(--bg-soft)을 깔아 본문과 분리하고, 열리면 포인트 테두리로 상태를 보여 준다.
   ★ <details> 라 JS 없이 동작하고, 접혀 있어도 답변이 DOM 에 있어 크롤러·AI 가 읽는다. */
.faq { display: grid; gap: var(--sp-3); margin-top: var(--sp-5); }
.faq__item { background: var(--bg-soft); border-radius: var(--r-lg);
  border: var(--hairline) solid transparent; transition: border-color .2s, background-color .2s; }
.faq__item[open] { background: var(--point-bg); border-color: var(--point); }
.faq__sum { display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-4); padding: var(--sp-4) var(--sp-5); cursor: pointer; list-style: none; }
.faq__sum::-webkit-details-marker { display: none; }
/* summary 안의 h3 - 크롤러가 질문을 문서 구조로 읽게 하되, 보이기는 한 줄로 붙인다.
   (h3 는 기본이 블록이라 그대로 두면 아이콘과 어긋난다) */
.faq__sum h3 { display: inline; margin: 0; font-size: var(--fs-content-body); font-weight: 600;
  line-height: 1.5; color: var(--ink); text-align: left; }
.faq__sum i { flex: 0 0 auto; color: var(--point); font-size: var(--ico-sm);
  transition: transform .25s; }
.faq__item[open] .faq__sum i { transform: rotate(45deg); }      /* + → × */
.faq__ans { margin: 0; padding: 0 var(--sp-5) var(--sp-4);
  font-size: var(--fs-content-body); line-height: var(--lh-prose);
  color: var(--gray-dark); text-align: left; }

/* 출처(.refs) - 컴포넌트 본래 규격(각주 급 --fs-ref · --gray-dark)으로 되돌린다.
   ⚠️ .article-body p (0,1,1) 가 .refs__item (0,1,0) 을 이겨서 본문과 똑같은 15px·먹색이 됐었다.
      셀렉터를 한 단계 올려 되찾는다 - 다른 페이지의 참고논문과 같은 크기로 보여야 한다.
   정렬만 본문을 따라 좌측으로 둔다(장문 레이아웃은 전부 좌측이라 가운데 정렬이 혼자 튄다). */
.article-body .refs__item { font-size: var(--fs-ref); color: var(--gray-dark); line-height: 1.6; }
.article-body--long .refs__item { text-align: left; }
.article-body .refs__item a { font-size: inherit; }
/* 출처끼리는 붙여 둔다 - .article-body p + p 의 문단 간격(15)이 각주 목록엔 과하다 */
.article-body .refs__item + .refs__item { margin-top: 2px; }

/* 본문 내부 링크 - 밑줄 없이 색만으로 구분한다(요청 2026-07-21).
   글줄이 촘촘한 본문에서 밑줄은 아래 줄과 붙어 읽기를 방해한다.
   ★ 색만 쓰므로 굵기를 한 단계 올려(500) 색약 사용자도 구분할 수 있게 한다.
   ※ 출처(.refs__item)는 각주라 기존 밑줄 스타일 그대로 둔다 - 아래 셀렉터가 p 직속만 잡는다. */
.article-body--long > p a { color: var(--point); font-weight: 500;
  text-decoration: none; transition: opacity .2s; }
.article-body--long > p a:hover { opacity: .65; }

/* 이전/다음 내비 - 카드(제목+발췌)에 방향 화살표를 붙인 변형.
   왼쪽 카드는 왼쪽에 ←(이전 글), 오른쪽 카드는 오른쪽에 →(다음 글).
   (요청 2026-07-17) 룩(면·제목·발췌)은 .article-list 와 "같은 규칙"을 공유한다 - 위 블록의
   셀렉터에 .blog-nav 가 함께 적혀 있다. 여기엔 내비만의 델타(폭·화살표 배치)만 둔다.
   폭도 리스트 격자와 같은 1000. */
.container--blog + .container .rel-cite { max-width: 1000px; }
/* PC 한정 - 좌우 방향 화살표 배치. 모바일은 이 배치를 쓰지 않는다(리스트 행과 같은 UI).
   ★ min-width 로 가둔다 - 모바일 규칙이 위(앞)에 있어 순서로는 못 이긴다. */
@media (min-width: 768px) {
  .blog-nav { display: flex; align-items: center; gap: var(--sp-4); text-align: left; }
  .blog-nav > i { flex: 0 0 auto; color: var(--point); font-size: var(--ico-md, 24px); }
  /* ⚠️ 텍스트 열은 minmax(0,1fr) - auto 로 두면 발췌가 콘텐츠 폭만큼 부풀어
     카드 밖(옆 카드 위)까지 삐져나간다. 0 으로 눌러야 클램프(…)가 작동한다. */
  .blog-nav > span { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--sp-1); min-width: 0; flex: 1 1 0; }
  /* 다음 글 카드 = 화살표만 오른쪽으로 보낸다. 글은 두 카드 모두 좌측 정렬(요청 2026-07-17) -
     제목·발췌의 시작선이 좌우 카드에서 같은 자리에 서야 나란히 읽힌다.
     ⚠️ text-align:right / justify-items:end 를 쓰지 않는다 - 후자는 항목이 max-content 로 줄어
        셀을 넘어 삐져나가고, 전자는 말줄임(…) 위치가 카드마다 어긋난다. */
  .blog-nav--next { flex-direction: row-reverse; }
}


/* (요청 2026-07-17) 라스트 다이어트 REAL 데이터 - 카드가 확대(hover)되어도 그래프 전체가
   보여야 한다. 기본 cover 는 수치 라벨을 잘라 먹는다 → contain + 배경으로 여백을 채운다. */
[aria-labelledby="dataTitle"] .ub-exp__item { background: var(--bg-soft); }
[aria-labelledby="dataTitle"] .ub-exp__item img { object-fit: contain; }

/* ══════════════════════════════ 셀카 후기 (.selfie-*) - articles-selfie / selfie-review-* ══
   앱 피드(바비톡) 느낌 - 사진 2장이 먼저, 그 아래 [시술 태그 · 아이디 | 별점] 한 줄, 후기 3줄.
   (요청 2026-07-17) PC 도 한 줄에 카드 1개 - 대신 폭을 넓혀 사진을 크게 본다.
   색·간격·R 은 전부 사이트 토큰을 쓴다. */
.selfie-feed { display: grid; grid-template-columns: minmax(0, 1fr);
  gap: var(--box-gap); max-width: 1200px; margin-inline: auto; }
.selfie-card { display: block; border-radius: var(--r-lg); overflow: hidden;
  background: var(--bg-soft); transition: background .2s; }
.selfie-card:hover { background: var(--point-bg); }
/* 사진 [전 | 후] 나란히 - 정사각. object-fit 이 원본 비율과 무관하게 칸을 채운다.
   한쪽만 있는 글은 1장이 칸을 다 쓴다(auto-fit). */
.selfie-card__pics { display: grid; grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
  gap: var(--hairline); }
.selfie-shot { position: relative; margin: 0; }
.selfie-shot img { width: 100%; aspect-ratio: var(--ratio-square); object-fit: cover; display: block; }
/* 좌상단 전/후 배지 - 마크업 없이 data-ba 를 읽어 그린다 */
.selfie-shot::before { content: attr(data-ba); position: absolute; top: var(--sp-2); left: var(--sp-2);
  z-index: 1; display: grid; place-items: center; width: 1.9em; height: 1.9em; border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--ink) 72%, transparent); color: var(--white);
  font-size: var(--fs-eyebrow); font-weight: 600; line-height: 1.2; }
.selfie-card__body { padding: var(--sp-4) var(--sp-5) var(--sp-5); }
/* 메타 줄 - 좌: 시술 태그 + 아이디 · 날짜 / 우 끝: 별점(있을 때만) */
.selfie-card__meta { display: flex; align-items: center; gap: var(--sp-3);
  margin-bottom: var(--sp-3); }
.selfie-tag { flex: 0 0 auto; padding: var(--sp-1) var(--sp-3); border-radius: var(--r-pill);
  background: var(--point-bg); color: var(--point);
  font-size: var(--fs-eyebrow); font-weight: 600; white-space: nowrap; }
/* 아이디와 날짜는 같은 글씨(크기·색)로 한 덩어리처럼 읽힌다. 자리가 모자라면 아이디만
   말줄임으로 줄고 날짜는 끝까지 온전히 남는다. */
.selfie-id, .selfie-date { color: var(--gray-dark); font-size: var(--fs-eyebrow);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.selfie-id { min-width: 0; }
/* 메타 줄 gap(sp-3)은 태그와 떼어놓는 간격이라, 아이디 옆에 붙을 날짜만 sp-1 로 당긴다. */
.selfie-date { flex: 0 0 auto; margin-left: calc(var(--sp-1) - var(--sp-3)); }
.selfie-date::before { content: "·"; margin-right: var(--sp-1); }
/* 별점 - 데이터(rating)가 있는 글에만 마크업이 생긴다. 없으면 이 자리는 비어 있다.
   PC 는 별 5칸을 깔고 점수만큼 채운 별(--point), 나머지는 빈 별(--gray-light) / 모바일은 폭이
   좁아 별 1개 + 숫자로 줄인다.
   ※ 번들된 Phosphor 는 regular(빈 별) 웨이트뿐이라, 채운 별은 공식 Phosphor-Fill 에서 별
     글리프(U+E46A) 하나만 서브셋해 따로 싣는다(488B). 두 웨이트가 코드포인트를 공유하므로
     글리프 지정은 `.ph.ph-star` 에 맡기고 여기서는 font-family 만 갈아끼운다.
     라이브러리 전체를 싣지 않았으니 `ph-fill` 류 클래스는 쓰지 말 것 - 별 외에는 글리프가 없다. */
@font-face {
  font-family: "Phosphor-Fill-Star";
  src:
    url("../fonts/phosphor/Phosphor-Fill-star.woff2") format("woff2"),
    url("../fonts/phosphor/Phosphor-Fill-star.woff") format("woff");
  font-weight: normal; font-style: normal; font-display: block;
}
.selfie-star { margin-left: auto; flex: 0 0 auto; display: inline-flex; align-items: center;
  gap: 2px; color: var(--point); font-size: var(--fs-eyebrow); font-weight: 600; }
/* 서브셋을 못 받으면 "Phosphor" 로 흘러 빈 별이 된다 - 색은 남으니 점수는 계속 읽힌다.
   ※ 선택자를 `.selfie-star i` 로 좁혀 둔다. phosphor.css 의 `.ph { font-family:"Phosphor" !important }`
     와 특정도가 같으면(둘 다 클래스 1개 + !important) 나중에 실린 쪽이 이긴다. 지금은 main.css 가
     뒤에 실려 우연히 이기고 있을 뿐이라, 로드 순서가 바뀌면 그대로 빈 별이 된다. */
.selfie-star i.selfie-star__on { font-family: "Phosphor-Fill-Star", "Phosphor" !important; }
.selfie-star__off { color: var(--gray-light); }
.selfie-star__num { display: none; }
.selfie-card__text { color: var(--ink); font-size: var(--fs-content-subtext);
  line-height: var(--lh-body); word-break: break-all;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden; }
@media (max-width: 767.98px) {
  .selfie-feed { grid-template-columns: minmax(0, 1fr); gap: var(--sp-6); }
  .selfie-star { gap: var(--sp-1); }
  .selfie-star i + i { display: none; }
  .selfie-star__num { display: inline; }
}

/* ── 상세 : 원본 비율 그대로 보이는 2열 그리드 (클릭 → 원본 라이트박스)
   (요청 2026-07-17) 정사각 crop 을 쓰지 않는다 - 가로 사진은 가로가, 세로 사진은 세로가 다 보여야 한다.
   2열 기준으로 각 사진은 컨테이너 폭의 50%를 넘지 않는다(자르지 않고 원본 비율). */
.selfie-shots { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--sp-3); align-items: start;
  max-width: 780px; margin: 0 auto var(--sp-7); }
.selfie-shots button { padding: 0; border: 0; background: none; cursor: zoom-in;
  border-radius: var(--r-lg); overflow: hidden; position: relative; display: block; }
/* 사진은 원본 비율 그대로 - 칸 폭에 맞춰 높이가 알아서 정해진다(자르지 않는다) */
.selfie-shots img { width: 100%; height: auto; display: block; transition: transform .4s; }
.selfie-shots button:hover img { transform: scale(var(--card-zoom, 1.05)); }
/* masonry (요청 2026-07-18) - 왼쪽 칸이 길고 오른쪽 칸이 짧으면 다음 사진이 짧은 칸 아래로 붙어
   빈틈이 안 생긴다. templates.js 가 사진 높이를 재어 grid-row-end(span) 를 넣고 is-masonry 를 켠다.
   row-gap 은 0 으로 두고(1px auto-row 라 span 계산이 깔끔해진다) 세로 간격은 JS 가 span 에 얹는다.
   ※ JS 가 없거나 못 켜면 이 규칙이 적용되지 않아 위의 기본 2열 그리드(row 정렬)로 그대로 보인다. */
.selfie-shots.is-masonry { grid-auto-rows: 1px; row-gap: 0; grid-auto-flow: row dense; }
/* 모든 사진은 2열 기준 - 어떤 사진도 폭이 컨테이너의 50%를 넘지 않는다(요청 2026-07-18).
   3장이면 마지막 1장은 왼쪽 칸(50%)에만 놓이고 오른쪽 칸은 비운다(전폭으로 늘리지 않는다).
   1장뿐이어도 50% 폭으로 가운데 세운다. */
.selfie-shots[data-shots="1"] { grid-template-columns: minmax(0, calc(50% - var(--sp-3) / 2));
  justify-content: center; }
/* 모바일에서도 2열 유지(요청 2026-07-17) - 전/후를 나란히 두고 비율대로 보이게. gap 만 좁힌다.
   단, 사진이 1장뿐이면 위의 data-shots="1" 규칙대로 가운데 한 칸으로 세운다. */
@media (max-width: 575.98px) {
  .selfie-shots { gap: var(--sp-2); }
}
/* 상세 사진에도 좌상단 전/후 배지 */
.selfie-shots button::before { content: attr(data-ba); position: absolute; top: var(--sp-3); left: var(--sp-3);
  z-index: 1; display: grid; place-items: center; width: 1.9em; height: 1.9em; border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--ink) 72%, transparent); color: var(--white);
  font-size: var(--fs-eyebrow); font-weight: 600; line-height: 1.2; }
/* 시술 연관 페이지 박스 링크 */
.selfie-link { display: flex; align-items: center; gap: var(--sp-4);
  max-width: 660px; margin: var(--sp-7) auto 0; padding: var(--sp-5);
  border-radius: var(--r-lg); background: var(--bg-soft); text-align: left;
  transition: background .2s; }
.selfie-link:hover { background: var(--point-bg); }
.selfie-link > i { flex: 0 0 auto; color: var(--point); font-size: var(--ico-xl); }
.selfie-link__t { display: grid; gap: var(--sp-1); min-width: 0; }
.selfie-link__t strong { font-size: var(--fs-content-title); font-weight: 600; color: var(--ink); }
.selfie-link__t span { font-size: var(--fs-eyebrow); color: var(--gray-dark); }
.selfie-link > .ph-caret-right { margin-left: auto; font-size: var(--ico-sm); }

/* ── 라이트박스 (원본 보기) - 사이트에 없던 것이라 여기서 정의한다 ── */
.lightbox { position: fixed; inset: 0; z-index: 9100; display: grid; place-items: center;
  padding: var(--sp-6); background: color-mix(in srgb, var(--ink) 88%, transparent); }
.lightbox[hidden] { display: none !important; }
.lightbox img { max-width: min(100%, 1100px); max-height: 88vh; width: auto; height: auto;
  border-radius: var(--r-sm); }
.lightbox__close { position: absolute; top: var(--sp-5); right: var(--sp-5);
  color: var(--white); font-size: var(--ico-xl); background: none; border: 0; cursor: pointer; }
.lightbox__nav { position: absolute; top: 50%; transform: translateY(-50%);
  color: var(--white); font-size: var(--ico-xl); background: none; border: 0; cursor: pointer;
  padding: var(--sp-4); }
.lightbox__nav--prev { left: var(--sp-3); }
.lightbox__nav--next { right: var(--sp-3); }
.lightbox__count { position: absolute; bottom: var(--sp-5); left: 50%; transform: translateX(-50%);
  color: var(--white); font-size: var(--fs-eyebrow); }

/* ══════════════════════════════ 이벤트 상세 팝업 (.promo-modal) ══════════════════════════════
   프로모션 카드 클릭 -> 상세페이지 긴 이미지(webp, 분할 스택)를 팝업으로. op-modal 룩(veil·흰 박스·닫기) 재사용.
   요청: 세로 높이에 맞추지 말고 "가로폭을 충분히 확보"(min 880) + 세로 스크롤. PC·모바일 공용, X 닫기. */
.promo-modal { position: fixed; inset: 0; z-index: 2000; background: var(--veil-modal);
  display: flex; align-items: flex-start; justify-content: center; padding: var(--sp-5); }
.promo-modal[hidden] { display: none; }
.promo-modal__box { position: relative; background: var(--white); border-radius: var(--r-lg);
  width: min(880px, 100%); max-height: 92vh; overflow: hidden; display: flex; flex-direction: column; }
.promo-modal__close { position: absolute; top: var(--sp-3); right: var(--sp-3); z-index: 2;
  width: 42px; height: 42px; display: inline-flex; align-items: center; justify-content: center;
  border: 0; border-radius: 999px; background: var(--white); color: var(--ink); cursor: pointer;
  font-size: var(--ico-md); box-shadow: 0 2px 10px rgba(0, 0, 0, .18); }
.promo-modal__close:hover { background: var(--point); color: var(--white); }
.promo-modal__scroll { overflow-y: auto; -webkit-overflow-scrolling: touch; }
.promo-modal__scroll img { display: block; width: 100%; height: auto; }
@media (max-width: 575.98px) {
  .promo-modal { padding: var(--sp-2); }
  .promo-modal__box { max-height: 94vh; }
}

/* QR 시트(.promo-modal--qr) - WhatsApp · LINE 알약을 PC 에서 눌렀을 때.
   이벤트 상세는 "긴 이미지를 훑는" 팝업이라 넓지만(880), QR 은 한 장짜리 그림이다
   → 박스 폭만 좁히고 화면 중앙에 세운다. 나머지(면 · 닫기 · 여백)는 .promo-modal 그대로 쓴다. */
.promo-modal--qr { align-items: center; }
.promo-modal--qr .promo-modal__box { width: min(420px, 100%); }
/* QR 아래 아이디(data-qr-id) - 스캔이 안 될 때 직접 검색·추가할 수 있게 병기한다. */
.promo-modal__qrid { margin-top: var(--sp-3); text-align: center;
  font-size: var(--fs-content-title); font-weight: 600; letter-spacing: -.02em; color: var(--ink); }

/* ══════════════════════════════ 의료진 약력 (.dr-cv) - doctors 전용 ══
   (요청 2026-07-17) 기존 약력(tpl-intro 문답·tpl-process 스텝)은 카드가 가벼워 보인다는 지적.
   → 카드·아이콘 없이 [분류 라벨 | 항목 리스트] 2열의 연감(annual report) 조판으로 만든다.
     격은 색이 아니라 "선"이 만든다 - 분류가 바뀔 때 먹색 선, 항목 사이 헤어라인.
   새 값을 만들지 않는다 - 열 비율은 소개 슬림형과 같은 32:86, 나머지는 전부 토큰. */
.dr-cv { display: grid; }
.dr-cv__block { display: grid; grid-template-columns: minmax(0, 32fr) minmax(0, 86fr);
  column-gap: var(--tpl-col-gap); align-items: start;
  padding-block: var(--sp-6);
  border-top: var(--hairline) solid var(--ink); }
/* 분류 라벨 = [영문 eyebrow 위 + 국문 제목 아래]. 긴 리스트를 따라 내려오게 sticky */
.dr-cv__cat { position: sticky; top: var(--sp-6);
  display: grid; gap: var(--sp-2);
  font-size: var(--fs-content-title); font-weight: 600; color: var(--ink);
  line-height: var(--lh-title); }
.dr-cv__cat span { color: var(--point); font-size: var(--fs-eyebrow); font-weight: 600;
  letter-spacing: .14em; text-transform: uppercase; }
.dr-cv__list { display: grid; }
.dr-cv__list li { padding-block: var(--sp-3);
  font-size: var(--fs-content-body); line-height: var(--lh-body); color: var(--ink); }
.dr-cv__list li + li { border-top: var(--hairline) solid var(--gray-light); }
/* 연도·직함 태그 - 이탤릭이 아니라 포인트색 라벨. 본문과 한 줄에 붙는다 */
.dr-cv__list em { font-style: normal; font-weight: 600; color: var(--point);
  font-size: var(--fs-eyebrow); margin-right: var(--sp-3); letter-spacing: .04em; }
@media (max-width: 991.98px) {
  .dr-cv__block { grid-template-columns: minmax(0, 1fr); row-gap: var(--sp-4); }
  .dr-cv__cat { position: static; }
}

/* ════════════════════════════════════════════════ 로그인 - 소셜 버튼 ══ */
.social-login { max-width: 460px; margin-inline: auto; display: flex; flex-direction: column; gap: var(--sp-4); }
/* 제목 ↔ 버튼 사이 여백 충분히 (컨테이너 직속 자식 margin:0 규칙을 특이도로 덮는다) */
.tpl-sec .container > .social-login { margin-top: var(--sp-8); }
.social-btn { display: flex; align-items: center; justify-content: center; gap: var(--sp-3);
  height: clamp(52px, 6vw, 60px); border-radius: 12px; border: 1px solid transparent;
  font-size: var(--fs-content-body); font-weight: 600; letter-spacing: -.01em;
  text-decoration: none; transition: filter .15s, background .15s; }
.social-btn__ico { display: grid; place-items: center; width: 22px; height: 22px; flex: 0 0 auto; }
.social-btn__ico svg { width: 100%; height: 100%; display: block; }
.social-btn--naver  { background: #03C75A; color: #fff; }
.social-btn--kakao  { background: #FEE500; color: #191919; }
.social-btn--google { background: #fff; color: #3c4043; border-color: #dadce0; }
.social-btn--naver:hover,
.social-btn--kakao:hover { filter: brightness(.96); }
.social-btn--google:hover { background: #f8f9fa; }
.social-login__status { text-align: center; color: var(--gray-dark); font-size: var(--fs-content-body); }
/* 로그인 상태(내 계정) 카드 - 소셜 로그인과 같은 폭·토큰을 쓴다. */
.account-card { max-width: 460px; margin-inline: auto; margin-top: var(--sp-8);
  display: grid; justify-items: center; gap: var(--sp-3);
  padding: var(--sp-7) var(--sp-6); border: var(--hairline) solid var(--gray-light);
  border-radius: var(--r-lg); background: var(--bg-soft); }
.account-card__avatar { width: 72px; height: 72px; border-radius: 50%;
  display: grid; place-items: center; background: var(--point); color: var(--white);
  font-size: var(--fs-content-title); font-weight: 600; }
.account-card__name { font-size: var(--fs-content-title); font-weight: 600; color: var(--ink); }
.account-card__email { font-size: var(--fs-content-subtext); color: var(--gray-dark); }
.account-card .cta { margin-top: var(--sp-3); }

/* ══════════════════════════════════════ 진료 일정 달력 (.cal) ══
   (요청 2026-07-21) 진료시간 안내의 4개 박스를 걷어 내고 그 자리에 달력을 넣는다.
   데이터는 구글 캘린더(thelineps103@gmail.com)에서 온다 - assets/js/templates.js 의 clinicCalendar().
   ⚠️ 새 색·새 폰트를 만들지 않는다. 아래 값은 전부 기존 토큰에서 가져온다
      (--point / --point-bg / --gray-light / --bg-soft / --sp-* / --fs-*).
   레이어 밖에 두는 이유 : 소셜 버튼과 같은 벌로, 페이지 하나가 쓰는 늦은 추가분이다. */
.cal { margin-top: var(--sp-7); max-width: 820px; margin-inline: auto; }

/* 머리 : ‹ 2026년 7월 › */
.cal__head { display: flex; align-items: center; justify-content: center;
  gap: var(--sp-5); margin-bottom: var(--sp-5); }
.cal__title { font-size: var(--fs-content-title); font-weight: 600; color: var(--ink);
  min-width: 8em; text-align: center; }
.cal__nav { display: grid; place-items: center; width: 42px; height: 42px;
  border-radius: var(--r-pill); border: var(--hairline) solid var(--gray-light);
  background: var(--white); color: var(--gray-dark); cursor: pointer;
  transition: color .15s, border-color .15s; }
.cal__nav:hover { color: var(--point); border-color: var(--point); }
.cal__nav i { font-size: 18px; }

/* 격자 : 요일 7칸 + 날짜 6줄. 테두리는 셀이 위·왼쪽만 그려 겹선을 피한다 */
.cal__grid { display: grid;
  /* 일요일 열만 따로 잡아 둔다 - 좁은 화면에서 이 값만 줄여 평일 폭을 벌어 준다 */
  grid-template-columns: var(--cal-sun, 1fr) repeat(6, minmax(0, 1fr));
  border-top: var(--hairline) solid var(--gray-light);
  border-left: var(--hairline) solid var(--gray-light); }
.cal__dow, .cal__cell {
  border-right: var(--hairline) solid var(--gray-light);
  border-bottom: var(--hairline) solid var(--gray-light); }
.cal__dow { padding: var(--sp-3) 0; text-align: center; background: var(--bg-soft);
  font-size: var(--fs-eyebrow); font-weight: 600; color: var(--ink); }
.cal__dow--sun { color: var(--point); }

.cal__cell { min-height: 74px; padding: var(--sp-3) var(--sp-2); text-align: left; }
.cal__cell--out { background: var(--bg-soft); }          /* 앞·뒷달 날짜 */
.cal__num { font-size: var(--fs-content-subtext); font-weight: 600; color: var(--ink); }
.cal__cell--out .cal__num { color: var(--gray-light); font-weight: 400; }
.cal__cell--sun .cal__num { color: var(--point); }
/* 오늘 - 포인트색 원 */
.cal__cell--today .cal__num { display: inline-grid; place-items: center;
  width: 2em; height: 2em; margin: -.25em 0 -.25em -.4em;
  border-radius: var(--r-pill); background: var(--point); color: var(--white); }

/* 지난 날 - 이미 지나간 날은 눌러 둔다. opacity 로 통째 흐리게 하면 테두리까지 옅어져
   격자가 끊겨 보이므로, 안쪽 요소의 색만 바꾼다. 일요일 규칙보다 뒤에 두어 이기게 한다. */
.cal__cell--past .cal__num,
.cal__cell--past.cal__cell--sun .cal__num { color: var(--gray-light); font-weight: 400; }
.cal__cell--past .cal__tag { background: var(--bg-soft); color: var(--gray-dark);
  font-weight: 400; }

/* 일정 알약 - 휴진 표시
   (요청) 한 줄을 넘는 일정도 잘리면 안 된다 → 말줄임 대신 여러 줄로 접는다.
   칸(.cal__cell)의 min-height 는 최소값이라 줄이 늘면 칸이 따라 늘어난다. */
.cal__tag { display: block; margin-top: var(--sp-2); padding: .35em .7em;
  border-radius: var(--r-sm); background: var(--point-bg); color: var(--point);
  font-size: var(--fs-eyebrow); font-weight: 600; line-height: 1.4;
  white-space: normal; overflow-wrap: anywhere; }
.cal__tag + .cal__tag { margin-top: var(--sp-1); }

/* 아래 한 줄 안내 - 진료시간 요약 */
.cal__foot { margin-top: var(--sp-5); text-align: center;
  font-size: calc(var(--fs-content-subtext) * 1.2); color: var(--gray-dark); }
/* (요청 2026-07-27) 영업시간을 [요일 | 시간] 2열로 정렬한다(한국어판 느낌).
   블록을 가운데 세우고, 요일·시간은 각 열에서 왼쪽 정렬해 시간 시작점이 줄마다 맞는다. */
.cal__hours { width: fit-content; margin: 0 auto; display: grid;
  grid-template-columns: auto auto; column-gap: var(--sp-8); row-gap: var(--sp-2);
  text-align: left; }
.cal__hours dt { font-weight: 600; color: var(--ink); }
.cal__hours dd { margin: 0; }
.cal__foot-note { margin-top: var(--sp-3); }
.cal[data-state="loading"] .cal__grid { opacity: .45; }

@media (max-width: 991.98px) {
  /* 좁은 화면 : 칸을 낮추고 글자를 줄인다. 7칸 격자는 유지한다(달력은 요일 정렬이 생명이다) */
  .cal__cell { min-height: 60px; padding: var(--sp-2) var(--sp-2); text-align: center; }
  .cal__tag { padding: .3em .4em; letter-spacing: -.04em; }
  .cal__head { gap: var(--sp-4); margin-bottom: var(--sp-4); }
  .cal__nav { width: 36px; height: 36px; }
}
@media (max-width: 575.98px) {
  /* 폰 : 한 달이 한눈에 들어와야 한다 → 요일·숫자를 더 줄이고 칸 높이를 낮춘다.
     한 칸이 45px 남짓이라 "전체휴진" 은 한 줄에 안 들어간다 → 말줄임 대신 두 줄로 접는다.
     숫자는 모두 가운데 정렬(달력은 세로줄이 맞아야 읽힌다). */
  /* (요청) 일요일은 늘 휴진이라 칸을 절반 이하로 줄이고, 남는 폭을 월~토에 넘긴다.
     그만큼 평일 칸이 넓어지므로 요일·날짜 글자를 키울 수 있다. */
  .cal__grid { --cal-sun: .52fr; }
  .cal__dow { padding: var(--sp-2) 0; font-size: var(--fs-eyebrow); }
  .cal__dow--sun { font-size: calc(var(--fs-eyebrow) * .86); letter-spacing: -.06em; }
  .cal__cell { min-height: 52px; padding: 4px 2px; text-align: center; }
  .cal__num { font-size: calc(var(--fs-content-subtext) * .92); }
  .cal__cell--sun .cal__num { font-size: calc(var(--fs-eyebrow) * .9); }
  /* 오늘 원 - 가운데 정렬이므로 왼쪽으로 당기던 보정을 없앤다 */
  .cal__cell--today .cal__num { width: 1.9em; height: 1.9em; margin: -.2em 0; }
  .cal__tag { white-space: normal; overflow: visible; text-overflow: clip;
    margin-top: 3px; padding: .2em .15em; text-align: center; letter-spacing: -.06em;
    font-size: calc(var(--fs-eyebrow) * .88); line-height: 1.2; }
  .cal__foot { font-size: calc(var(--fs-content-subtext) * 1.1); }
}

/* ══════════════════════════════════════════════ 사이트 팝업 (.pop) ══
   (요청 2026-07-22) 이미지 + [다시 보지 않기 / 닫기] 한 줄.
   PC 는 화면 왼쪽에 떠 있고, 모바일은 가로를 꽉 채운다.
   ⚠️ 새 색·새 폰트를 만들지 않는다 - 전부 기존 토큰(--ink / --gray-* / --sp-* / --fs-*)이다.
   레이어 밖에 두는 이유 : 소셜 버튼·달력과 같은 벌로, 늦게 붙은 독립 컴포넌트다. */
/* 자리 : PC 는 GNB(스티키 헤더, 65px) 바로 아래 왼쪽. 모바일은 화면 맨 위(0)부터.
   --pop-top 한 값만 바꾸면 두 경우가 다 따라온다. */
.pop { position: fixed; z-index: 9100;
  --pop-top: 65px;
  top: calc(var(--pop-top) + var(--sp-3));
  left: clamp(20px, 3.125vw, 60px);
  width: clamp(300px, 26vw, 400px);
  /* 세로가 화면을 넘지 않게 폭 자체에 상한을 건다.
     이미지 비율이 600:760 이므로 "쓸 수 있는 높이 × 600/760" 이 곧 폭의 한계다.
     120px 은 하단 버튼 줄과 위아래 여백 몫이다. */
  max-width: calc((100vh - var(--pop-top) - 120px) * 600 / 760);
  background: var(--white); border-radius: var(--r-lg); overflow: hidden;
  box-shadow: 0 10px 40px rgba(0, 0, 0, .16); }
.pop[hidden] { display: none; }
.pop__body { display: block; }
.pop__body img { width: 100%; height: auto; display: block; }

/* 하단 줄 - 왼쪽 "다시 보지 않기", 오른쪽 "닫기" */
.pop__foot { display: flex; align-items: stretch;
  border-top: var(--hairline) solid var(--gray-light); }
.pop__btn { flex: 1 1 auto; padding: var(--sp-4) var(--sp-3);
  background: var(--white); border: 0; cursor: pointer;
  font-size: var(--fs-content-subtext); color: var(--gray-dark);
  letter-spacing: -.01em; transition: background .15s, color .15s; }
.pop__btn:hover { background: var(--bg-soft); color: var(--ink); }
/* 닫기는 "끝내는 동작"이라 조금 더 또렷하게. 폭은 글자만큼만 차지한다 */
.pop__btn--close { flex: 0 0 auto; min-width: 96px; color: var(--ink); font-weight: 600;
  border-left: var(--hairline) solid var(--gray-light); }

@media (max-width: 991.98px) {
  /* 모바일 : 화면 맨 위에서 시작하고 가로는 꽉 채운다(요청 2026-07-22).
     폭을 다 쓰면 세로가 화면을 넘길 수 있으므로 폭 상한 대신 **이미지 높이**를 자른다
     - 가로 풀사이즈라는 조건을 지키면서 한 화면에 들어오게 하는 유일한 방법이다. */
  .pop { --pop-top: 0px;
    top: 0; left: 0; right: 0; width: auto; max-width: none;
    border-radius: 0 0 var(--r-lg) var(--r-lg); }
  .pop__body img { max-height: calc(100vh - 120px); object-fit: cover; object-position: top; }
  .pop__btn { padding: var(--sp-4) var(--sp-2); }
}

/* ══════════════════════════════════════ 페이지 전환 (View Transitions) ══
   (요청 2026-07-22) 메뉴를 누를 때마다 화면 전체가 사라졌다 다시 그려져 "꿀렁" 인다.
   문서를 통째로 새로 그리는 건 그대로 두되, 브라우저가 앞뒤 화면을 스냅샷으로 이어 붙여
   **GNB 는 제자리에 남고 본문만 바뀌는** 것처럼 보이게 한다.

   · HTML·JS 를 하나도 안 고친다. 링크는 여전히 진짜 이동이라 크롤러가 보는 것도 그대로다.
   · 미지원 브라우저(구형 사파리 등)는 이 블록을 통째로 무시한다 → 지금과 똑같이 동작한다.
   · 전환은 220ms 로 짧게 잡는다. 길면 다음 화면을 기다리는 느낌이 든다. */
@view-transition { navigation: auto; }

/* 헤더에 이름을 주면 앞·뒤 화면의 같은 이름끼리 하나로 이어져 "안 움직이는 것"이 된다.
   ★ 이름은 한 문서에 하나만 존재해야 한다 - .site-header 는 페이지당 1개라 안전하다. */
.site-header { view-transition-name: gnb; }
/* 하단 고정 상담바·우측 퀵바·좌하단 배지도 페이지가 바뀌어도 그대로 있는 것들이라 같이 묶는다 */
.consult-bar { view-transition-name: consultbar; }
.quick-side  { view-transition-name: quickside; }

/* 본문은 살짝 밀면서 크로스페이드 - 방향이 있으면 "넘어갔다"는 느낌이 생긴다 */
::view-transition-old(root) { animation: vt-out 220ms cubic-bezier(.4, 0, .2, 1) both; }
::view-transition-new(root) { animation: vt-in  220ms cubic-bezier(.4, 0, .2, 1) both; }
@keyframes vt-out { to   { opacity: 0; transform: translateY(-8px); } }
@keyframes vt-in  { from { opacity: 0; transform: translateY(8px); } }

/* 움직임을 줄이도록 설정한 사용자에겐 이동 없이 페이드만 준다 */
@media (prefers-reduced-motion: reduce) {
  ::view-transition-old(root),
  ::view-transition-new(root) { animation-duration: 120ms; }
  @keyframes vt-out { to   { opacity: 0; } }
  @keyframes vt-in  { from { opacity: 0; } }
}

/* 관련 시술 → 관련 아티클 : 마지막 두 섹션은 한 덩어리로 읽혀야 한다.
   (요청 2026-07-22) 둘 사이만 섹션 기본 간격(--sec-gap 150)에서 --sp-8(80) 로 좁힌다.
   앞뒤 다른 섹션의 리듬은 건드리지 않는다. */
section[aria-labelledby="relArtTitle"] { margin-top: var(--sp-8); }

/* ── 아티클 본문 표 (.ub-tbl--plain) ───────────────────────────────
   (요청 2026-07-22) 시술 페이지의 비교표(.ub-tbl)는 포인트색 머리띠 + 회색 면이라
   글 안에 놓으면 무겁다. 아티클 본문에는 **외곽선만 회색인 담백한 표**를 쓴다.
     · 배경·라운드 없음. 선은 --gray-light 하나만.
     · 셀 글자 크기를 전부 같게 둔다(머리행도 같은 크기, 굵기로만 구분).
     · 본문 문단과 붙지 않도록 위쪽 여백을 준다.
   모바일에서도 표 모양을 유지한다 - 세로 카드로 풀면 "표"라는 형식이 사라진다.
   대신 .ub-tbl 의 overflow-x 를 그대로 살려 좁은 화면에서는 옆으로 밀어 본다. */
.ub-tbl--plain { background: none; border-radius: 0;
  margin-top: var(--sp-6); margin-bottom: var(--sp-5); }
.ub-tbl--plain table { min-width: 0; border: var(--hairline) solid var(--gray-light); }
/* 셀 여백은 촘촘하게 - 표가 문단 사이에서 덩어리로 튀지 않게 한다 */
.ub-tbl--plain :is(th, td) {
  padding: var(--sp-2) var(--sp-3);
  border: var(--hairline) solid var(--gray-light);
  font-size: var(--fs-content-subtext); line-height: var(--lh-body);
  letter-spacing: normal; color: var(--ink); vertical-align: top;
  text-align: left; font-weight: 400; }
/* 머리행만 아주 옅은 회색 면 + 가운데 정렬 + 굵게. 색은 --bg-soft(≈#F8F8F8) 를 쓴다 */
.ub-tbl--plain thead th { background: var(--bg-soft); color: var(--ink);
  font-weight: 600; text-align: center; }
/* 첫 열도 본문과 같은 굵기로 둔다 - 격자 안에서 위계를 만들지 않는다 */
.ub-tbl--plain tbody th[scope="row"] { font-weight: 400; }
.ub-tbl--plain tbody tr:hover :is(th, td) { background: none; }
/* 표 안에서는 강조 색을 쓰지 않는다 - 글자 크기·색을 셀 전체와 같게 맞춘다 */
.ub-tbl--plain :is(.ub-tbl__key, .ub-tbl__val) {
  display: inline; font-size: inherit; font-weight: inherit; color: inherit;
  white-space: normal; }

@media (max-width: 991.98px) {
  /* .ub-tbl 의 모바일 카드 변환을 되돌린다(표 형식 유지). 셀 여백만 줄인다. */
  .ub-tbl--plain { overflow-x: auto; }
  .ub-tbl--plain table { display: table; min-width: 520px; }
  .ub-tbl--plain thead { display: table-header-group; }
  .ub-tbl--plain tbody { display: table-row-group; gap: 0; }
  .ub-tbl--plain tbody tr { display: table-row; background: none;
    border: 0; border-radius: 0; padding: 0; }
  .ub-tbl--plain tbody :is(th, td) { display: table-cell;
    padding: var(--sp-2) var(--sp-3); border: var(--hairline) solid var(--gray-light); }
  .ub-tbl--plain tbody td::before { content: none; }
}
