/* 홈 (D-115) — 대형 히어로 배너 → 분야 칩 → 광고 세무사 → 인기 세무사 → 바로가기.
   앱 홈(D-110)과 같은 우선순위이고, 구조 수치는 opensea.io 라이트 실측을 따른다.
   색·타이포는 tokens.css(토스톤) 그대로 — 여기서 새 색을 만들지 않는다. */

/* ── 홈 세로 리듬 (D-262) ────────────────────────────────────────────────────
   🔴 **홈의 위아래 간격은 이 두 값이 전부 정한다. 블록마다 따로 적지 마라.**

   왜 변수로 묶었나 — 예전엔 블록마다 `margin-top: 40px`을 손으로 적었다. 상자끼리는
   전부 40으로 맞아 있었는데 **눈에 보이는 틈은 84·40·40·61·61·229·268·40**이었다(1440px 실측).
   밴드(전폭 색면)가 자기 안쪽 패딩을 따로 갖고 있어서, 같은 margin 40이 밴드 앞에서는
   40+패딩으로 벌어졌기 때문이다. 「상자 기준으로 맞췄다」가 「보기에 맞다」를 보장하지 않는다.
   ⇒ 지금은 **두 단**뿐이다: 보통 블록 사이 --home-gap, 밴드 경계 --home-gap + --band-pad.

   ⚠ 새 블록을 홈에 추가하면 margin-top에 반드시 var(--home-gap)을 쓸 것. 숫자를 적는 순간
     그 블록만 리듬에서 빠지고, 그 사실은 아무도 모르는 채로 남는다(위 실측이 그렇게 생겼다).
   ⚠ 밴드를 새로 만들면 padding 위아래도 var(--band-pad)다. 밴드마다 다른 값을 주면
     「밴드는 넓게」가 아니라 「밴드마다 제각각」이 된다(review 80/120 vs situ 20/20이 그랬다).
   ⚠ 좁은 화면 값은 **파일 맨 끝** @media에서 이 :root를 다시 정의한다(아래 D-166 주석 참고). */
:root {
  --home-gap: 56px;
  --band-pad: 40px;
}

/* ── 히어로 배너: 한 번에 한 장 (D-161) ─────────────────────────────
   예전엔 좌우 패딩으로 이웃 카드를 살짝 노출하는 peek 캐러셀이었다(D-128) —
   "옆에 더 있다"를 보여 주려는 장치였다. 지금은 우하단 카운터(n/N)와 좌우 화살표가
   그 역할을 하므로 **이웃을 걷어내고 그 폭을 본 배너에 돌려준다**(사용자 지시).
   ⚠ 카드 폭을 **퍼센트로 두 번 쓰지 않는다**(D-153에서 실측으로 잡은 결함).
   예전엔 `--hero-w: min(920px, 84%)`를 트랙 padding과 카드 flex-basis 양쪽에 썼는데,
   **같은 84%가 서로 다른 기준으로 풀린다**: padding은 wrap 폭(1024)의 84%=860,
   flex-basis는 **트랙의 안쪽 폭**(1024−패딩 164=860)의 84%=723. 카드가 padding이 가정한
   자리보다 137px 좁아져, 그 계산을 믿고 세운 화살표·카운터가 옆 카드 위에 얹혔다.
   지금은 **옆 여백(--hero-side) 하나만** 정하고 카드는 남은 자리를 그대로 채운다
   (flex-basis:100% = 트랙 안쪽 폭). 이러면 카드 폭과 여백이 정의상 어긋날 수 없다. */
/* 배너 위아래 여백 (D-166 → D-262에서 축소, 사용자 지시 "메인배너 상하여백을 살짝 줄이고")
   예전엔 60/84였다. 화면 맨 위에서 배너까지 152px — 참고 지면이 카테고리 줄에 쓰던 64px을
   우리는 그 줄을 두지 않으니 여백으로 돌린 값이었다. 그 줄이 없는 지면에서는 그냥 빈 자리로 읽힌다.

   지금은 **두 가지를 동시에 만족시키는 하나의 수**를 쓴다:
     ⓐ 위아래 대칭 (D-167, 사용자 지시) — 상단바 아래 끝을 기준으로 잰다.
        위 = .main 위 패딩 24 + margin-top 32 = **56**, 아래 = margin-bottom 56. 같다.
     ⓑ 아래쪽이 **섹션 리듬과 같은 값**(--home-gap) — 배너가 리듬 위에 올라선다.
        예전 84는 어느 섹션 간격과도 안 맞아 배너만 혼자 떠 보였다.
   ⇒ 화면 맨 위에서 배너까지 68(상단바) + 56 = **124px**.

   ⚠ margin-top만 리듬에서 벗어난 숫자(32)다. 위는 **고정 크롬(상단바) 바로 아래**라
     블록과 블록 사이와는 성격이 다르다 — 대칭을 맞추는 쪽이 우선이다.
     `.main`의 위 패딩(24px, shell.css)이 바뀌면 이 32도 같이 고쳐야 대칭이 유지된다.
   ⚠ 아래는 다음 형제의 margin-top과 **상쇄되어 큰 쪽만 남는다.** 둘 다 --home-gap이라
     지금은 정확히 --home-gap이다. 한쪽만 키우면 그쪽이 이겨 대칭이 깨진다. */
.hero-wrap {
  position: relative;
  /* 0 = 이웃이 안 보인다. 카드 왼쪽 끝이 본문 칼럼(=섹션 제목)과 정확히 맞아떨어진다.
     ⚠ 이 값을 되살리면 그만큼 이웃 카드가 다시 걸쳐 보인다(노출 폭 = side − peek).
        화살표·카운터 위치도 이 변수로 계산하므로 여기만 바꾸면 같이 따라간다. */
  --hero-side: 0px;
  /* 카드 사이 간격. 두 장을 놓으면 **늘 보이는 사이 간격**이 된다(예전엔 넘어가는 도중에만 보였다). */
  --hero-peek: 16px;
  /* 한 화면에 놓을 배너 장수 (D-190). 폭 계산·좁은 화면 폴백이 전부 이 값 하나를 본다. */
  --hero-per: 2;
}
/* 🔴 **여백은 `.hero-wrap` 본체에 주면 안 된다.** 밴드 안 로테이션 레일도 `.hero-wrap`이다
   (`<div class="hero-wrap situ-rail">` — 위 변수들을 물려받으려고 같은 클래스를 쓴다).
   그래서 여백만 `:not(.situ-rail)`로 떼어 둔다. 레일 여백은 `.situ-rail`이 따로 정한다.

   ⚠ 예전엔 `.hero-wrap`에 그냥 margin을 적고, 뒤에 오는 `.situ-rail { margin: 14px 0 0 }`이
     **순서로** 그걸 덮는 구조였다. 데스크톱은 우연히 맞았지만 좁은 화면 규칙은 파일 맨 끝이라
     레일보다 뒤 → 밴드 안 레일이 아래 48px을 물어 밴드 아래 틈만 37 → **85**로 벌어졌다(375px 실측).
     `:not()`으로 바꾼 지금은 **어느 쪽이 앞에 오든** 레일이 페이지 배너 여백을 물지 않는다. */
.hero-wrap:not(.situ-rail) {
  margin-top: 32px;
  margin-bottom: var(--home-gap);
}
/* 좁아지면 한 장으로 접는다(사용자 지시 "좌우 공간이 줄어들면 1개씩 보여져도 괜찮아").
   반 폭 카드가 3.08:1이라 폭이 줄면 높이가 같이 줄어드는데, 태블릿 폭에서 이미 카피가
   읽히지 않을 만큼 작아진다 — 광고 지면이 안 읽히면 지면이 아니다. 그래서 한 장으로 돌린다. */
@media (max-width: 900px) {
  .hero-wrap { --hero-per: 1; }
}
/* 배너가 한 장뿐이면 두 칸으로 쪼개지 않는다 — 복제본이 옆에 서서 **같은 그림이 두 번**
   보인다(무한 순환용 클론이라 지울 수도 없다). 장수는 서버가 안다(index.html). */
.hero-wrap.hero-one { --hero-per: 1; }
.hero-track {
  display: flex; gap: var(--hero-peek); overflow-x: auto; scroll-snap-type: x mandatory;
  scrollbar-width: none; -ms-overflow-style: none;
  padding-inline: var(--hero-side);
  /* ⚠ `padding-block: 10px`을 되살리지 마라(D-167). 카드 그림자에 자리를 주려던 것인데,
     그림자를 걷어낸 지금은 배너 위아래에 **10px짜리 빈 띠**만 남는다 —
     그 띠 때문에 배너가 계산한 자리(152px)보다 아래에서 시작해 보였다. */
}
.hero-track::-webkit-scrollbar { display: none; }

/* ── 로테이션 배너를 가로 트랙으로 (D-258) ─────────────────────────────────────
   '이제 혼자 고민하지 않아도 돼요'가 이 레일을 쓴다. 밴드 안이라 위 여백을 다시 벌지 않는다
   (`.situ-band`가 이미 padding을 갖고 있다). */
.situ-rail { margin-top: 14px; margin-bottom: 0; }
/* 🔴 반 폭 카드에 글자를 **그대로** 얹으면 넘친다. 페이드 배너 시절 헤드라인은 33px/44였는데,
      2장 배치에서 카드 폭이 절반(≈680px)이 되고 글자 자리는 그 46%(≈310px)뿐이라
      네 줄이 되어 2줄 클램프에 잘렸다. 그래서 이 맥락에서만 한 단계씩 줄인다.
   ⚠ 서브(.bnr-sub)는 아예 싣지 않는다 — 줄여도 읽히지 않는 크기가 되고, 헤드라인만으로
     «어디로 가는 길인지»는 이미 말한다. */
.hero-card.hero-situ {
  aspect-ratio: 1400 / 420; min-height: 0;
  text-decoration: none; color: inherit; background: var(--grey100);
}
.hero-situ .hero-img {
  position: absolute; inset: 0; z-index: 0;
  width: 100%; height: 100%; object-fit: cover; object-position: right center;
}
/* 🔴 왼쪽 여백 68px은 **화살표를 비켜 가려고** 준 값이다(.hero-arrow 46px + 숨 쉴 틈).
      이미지 전용 배너 시절엔 화살표가 그림을 조금 가려도 됐지만, 여기는 글자가 깔린다 —
      32px으로 두었더니 헤드라인 첫 두 글자가 화살표 밑으로 들어갔다(실측).
   ⚠ `.hero-arrow`의 크기를 바꾸면 이 값도 같이 봐야 한다. */
.hero-situ-copy {
  position: relative; z-index: 2;
  /* ⚠ 왼쪽 68px은 **화살표 자리**다(.hero-arrow-prev가 세로 중앙에 선다) — 줄이지 마라.
     ⚠ 칩이 빠지면서 줄이 둘(제목·CTA)로 줄었다. gap을 8→10px로 벌려 두 줄이 붙어
       보이지 않게 하고, 제목이 카드 가운데에 앉도록 위아래 여백을 균등하게 둔다(D-297). */
  padding: 0 14px 0 68px; max-width: 56%;
  display: flex; flex-direction: column; align-items: flex-start; gap: 10px;
}
.hero-situ-head {
  font-size: 21px; line-height: 29px; font-weight: 700; letter-spacing: -0.02em; color: #111827;
  word-break: keep-all;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.hero-situ-cta {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 8px 14px; border-radius: 999px;
  background: var(--primary); color: #fff; font-size: 13px; font-weight: 700;
}
.hero-situ:hover .hero-situ-cta { background: #2570E0; }
/* 한 장만 보이는 폭에서는 카드가 넓어지므로 글자를 원래 크기 가까이 되돌린다. */
@media (max-width: 900px) {
  /* 한 장만 보이는 폭에서도 화살표는 그대로 왼쪽 끝에 있다 — 여백을 줄이지 않는다. */
  .hero-situ-copy { max-width: 60%; }
  .hero-situ-head { font-size: 19px; line-height: 26px; }
}

/* ⚠ **그림자를 넣지 마라**(D-167). 예전 `0 10px 28px rgba(0,0,0,.16)`은 흰 배경 위에
   배너를 둘러싼 **회색 번짐**으로 보였다 — 사용자가 "여백에 회색이 보인다"고 지적한 것이
   이 그림자다. 참고 지면(nol.yanolja.com)도 배너에 그림자가 없다(실측 `shadow: none`).
   카드 배경 --grey100은 그림자가 아니라 **이미지를 못 받았을 때의 바닥색**이라 남긴다. */
/* 한 화면에 **두 장**을 놓는다(D-190, 사용자 지시 · 참고 지면 NOL). 한 장짜리 전면 배너는
   3.08:1 원고를 본문 폭 전체로 늘려서 세로를 크게 먹었는데, 반 폭으로 두 장을 놓으면
   **같은 비율로 높이가 절반**이 된다 — 사용자가 예상한 "총 높이가 줄어들 것 같다"가 이것이다.

   ⚠ 폭 계산은 `--hero-per`(한 화면에 놓을 장수) 하나로 몬다. gap이 (장수−1)개 들어가므로
     `(100% − gap×(n−1)) / n`이다. 좁은 화면에서 n을 1로 바꾸면 식이 100%로 접혀
     예전 동작으로 정확히 되돌아간다 — 분기를 두 벌 쓰지 않는 이유다.
   ⚠ **snap을 center → start로 바꿨다.** 두 장이 보이는데 center로 맞추면 가운데 한 장만
     정렬되고 좌우로 반쪽씩 걸쳐 보인다. start면 왼쪽 카드가 본문 칼럼에 딱 맞는다
     (한 장일 때는 start·center가 같은 자리라 폴백도 그대로다). */
.hero-card {
  position: relative; scroll-snap-align: start;
  flex: 0 0 calc((100% - var(--hero-peek) * (var(--hero-per) - 1)) / var(--hero-per));
  min-height: 320px; border-radius: var(--r-xl); overflow: hidden;
  display: flex; align-items: center;
}
/* 이미지 전용 배너 (D-142 · 비율 D-153) — 카드 비율을 **권장 원고 비율(3.08:1 · 2480×806)** 로
   고정한다. min-height를 그대로 두면 넓은 화면에서 카드가 원고보다 세로로 길어져 위아래가 잘린다.
   앱 캐러셀도 같은 비율을 쓴다 — 원고 한 장이 두 화면에서 **똑같이** 잘려야
   운영자가 결과를 예측할 수 있다(앱 promo_banner_carousel.dart의 _bannerAspect).
   ⚠ 이 숫자를 바꾸면 **앱도 같이** 바꿔야 한다. 2.5:1이던 것을 참고 사이트(NOL)와 같은
   가로로 긴 지면에 맞춰 넓혔다 — 좁은 비율에 넓은 원고를 넣으면 위아래가 잘려 카피가 날아간다.
   규격을 지킨 원고면 cover가 잘라내는 부분이 없다. 어긋난 원고는 가운데를 남기고 자른다 —
   레터박스(빈 띠)보다 광고 지면답게 보인다. */
.hero-img-only { min-height: 0; aspect-ratio: 2480 / 806; background: var(--grey100); }
/* ⚠ `.is-active`(JS가 가운데 카드에 붙인다)로 **축소·반투명 처리를 하지 않는다**(D-161).
   그건 이웃이 보이던 시절에 깊이를 주려던 장치였다. 한 장만 보이는 지금은 넘어가는
   도중에 나가는 카드가 쪼그라드는 것만 보여서 오히려 어색하다.
   JS는 계속 이 클래스를 붙이지만(카운터 계산과 무관하게 무해하다) CSS는 쓰지 않는다. */
/* 이미지가 없거나 로드에 실패해도 이 그라디언트가 남아 레이아웃이 깨지지 않는다. */
.hero-g0 { background: linear-gradient(120deg, #5A97F8, #2F6BF0 55%, #1544A8); }
.hero-g1 { background: linear-gradient(120deg, #15C47E, #059862 55%, #04664A); }
.hero-g2 { background: linear-gradient(120deg, #7C6BF6, #5A45E0 55%, #3A2AA8); }
.hero-g3 { background: linear-gradient(120deg, #FF9F45, #FF6B00 55%, #C24E00); }

.hero-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* .hero-photo(인물 컷아웃)·.hero-scrim(글자용 어둠막)은 삭제했다(D-142) — 배너가 이미지
   전용이 되면서 얹을 글자가 없어졌고, 가릴 이유가 없는 이미지를 가리고 있었다.
   아래 .hero-body 계열은 **배너가 없을 때의 폴백 카드**가 아직 쓰므로 남긴다. */

.hero-body {
  position: relative; display: flex; flex-direction: column; gap: 10px;
  padding: 0 48px; max-width: 620px; color: #fff;
}
.hero-label {
  align-self: flex-start; padding: 4px 10px; border-radius: var(--r-full);
  background: rgba(255,255,255,.22); font-size: 12px; font-weight: 700;
}
.hero-title { font-size: 32px; font-weight: 700; line-height: 1.25; letter-spacing: var(--ls-2xl); }
.hero-sub { font-size: 15px; color: rgba(255,255,255,.88); }
.hero-cta {
  align-self: flex-start; margin-top: 6px;
  display: inline-flex; align-items: center; gap: 3px;
  height: 44px; padding: 0 20px; border-radius: var(--r-full);
  background: #fff; color: var(--text-primary); font-weight: 700; font-size: 14px;
}
.hero-cta::after { content: '›'; font-size: 16px; line-height: 1; }
/* 카드 전체를 덮는 클릭 영역 — 링크 없는 배너는 이 요소만 빠진다. */
.hero-tap { position: absolute; inset: 0; }

/* ── 화살표 · 카운터 (D-153, 참고 지면 NOL) ─────────────────────────
   점(dot) 대신 **화살표 + 우하단 카운터**를 쓴다. 배너가 10장이면 점 열 개는 하나하나가
   너무 작아 못 누르고, "몇 번째/몇 장"이라는 정보도 안 준다.
   ⚠ 셋 다 **JS가 만든다** — 눌러도 아무 일 없는 장식만 남는 상태를 만들지 않기 위해서다.
      스크립트가 죽으면 배너는 가로 스크롤로 그대로 넘길 수 있다. */

/* 좌우 화살표 — 가운데 카드의 양 끝에 걸친다. 옆 여백(--hero-side)에서 위치를 계산하므로
   화면 폭이 바뀌어도 항상 카드 모서리에 붙어 있다. */
.hero-arrow {
  position: absolute; top: 50%; transform: translateY(-50%); z-index: 2;
  width: 46px; height: 46px; border-radius: var(--r-full);
  border: 0; padding: 0; cursor: pointer;
  background: #fff; color: var(--text-primary);
  box-shadow: 0 2px 10px rgba(0, 0, 0, .18);
  display: flex; align-items: center; justify-content: center;
  transition: background .15s ease, box-shadow .15s ease, transform .15s ease;
}
.hero-arrow:hover { box-shadow: 0 4px 14px rgba(0, 0, 0, .24); }
.hero-arrow:active { transform: translateY(-50%) scale(.94); }
.hero-arrow svg { width: 20px; height: 20px; display: block; }
/* 카드 안쪽으로 22px 물려 세운다(참고 지면과 같은 자리). */
.hero-arrow-prev { left: calc(var(--hero-side) + 22px); }
.hero-arrow-next { right: calc(var(--hero-side) + 22px); }

/* ⚠ **카운터(⏸ n/N ⊞)와 펼치기 패널의 CSS는 걷었다**(D-299, 사용자 지시 —
   「좌우 화살표만으로 충분」). 마크업을 만들던 banner.js 쪽도 함께 지웠으므로 여기 규칙만
   남으면 «무엇을 그리는지 알 수 없는 규칙»이 된다.
   ⚠ D-297에서 넣었던 `.situ-rail .hero-counter`(화살표와 안 겹치게 가로로 비키기)도 함께
     사라진다 — 비킬 대상이 없어졌기 때문이다. 카운터를 되살린다면 그 규칙도 같이 되살려라.
   🔴 자동 넘김을 **멈출 수단**은 화살표가 받는다(banner.js stopAuto) — WCAG 2.2.2. */

/* 좁은 화면 — 카드가 화면을 거의 채우므로 화살표를 접고(스와이프가 자연스럽다)
   카운터만 남긴다. 46px 버튼 두 개가 배너 위를 덮으면 원고가 안 보인다.
   ⚠ 카운터도 함께 줄인다. 카드 높이가 폭÷3.08이라 375px 화면에서는 **110px 남짓**인데,
      데스크톱과 같은 34px 알약을 얹으면 카드의 3분의 1을 덮어 원고 카피를 가린다(실측). */
@media (max-width: 768px) {
  /* ⚠ 좁은 화면 `.hero-wrap` 여백은 **파일 맨 끝** 리듬 블록에 있다(D-262). 여기 다시 적으면
     둘 중 뒤에 오는 쪽이 조용히 이겨서, 고친 값이 안 먹는 것처럼 보인다. */
  .hero-arrow { display: none; }
}

/* ── '이런 고민이라면' 밴드 (D-155) ─────────────────────────────────
   광고 목록과 그 아래를 나누며 시선을 환기시키는 전폭 띠.
   참고 지면(koreanair.com "여행의 완성을 위한 경험")에서 성질 둘을 가져왔다:
     ① 배경을 한 단 낮춰 페이지를 물리적으로 끊는다
     ② **볼드를 한 글자도 쓰지 않는다** — 바로 위가 광고 구간이라 목소리를 낮춰야 한다

   🔴 참고 지면의 나머지 둘(**파랑 틴트** · **테두리 없는 반투명 카드**)은 2026-08-09에
      걷어냈다. 사용자 지적은 "하늘색 배경 + 검은 글씨가 이질감"이었고, 실측해 보니
      **대비 문제가 아니었다** — 라벨은 최악 지점에서도 11.7:1로 넉넉했다(4.5:1 기준).
      진짜 원인은 둘이다:
        ⓐ **홈에서 채도 있는 색면이 이 밴드 하나뿐**이었다. 위(프리미엄 세무사)도
           아래(지금 상담 가능)도 순백 지면 + 흰 카드인데 여기만 #DCEBFC 판이었다.
        ⓑ **카드에 테두리가 없어** 틴트 위에서 카드 경계가 녹아, 줄 전체가 '카드 넉 장'이
           아니라 '검은 글씨가 얹힌 파란 판 하나'로 읽혔다.
      그래서 홈의 기존 두 부품으로 **수렴**시켰다 —
        · 밴드 = `.review-band`와 같은 처리(--grey50 + 위아래 1px --border)
        · 카드 = `.pf-card`와 같은 처리(--surface + 1px --border + --r-md)
      안 다섯을 실제로 렌더해 비교한 결과다(A 현행 #DCEBFC / B --grey50+헤어라인 /
      C 흰 배경+헤어라인 / D --surface-alt / E --primary-light). C는 밴드가 사라져
      '구간을 끊는다'는 임무가 없어졌고, D는 회색이 무거워 흰 이웃과 부딪혔고,
      E는 옅어졌을 뿐 같은 문제가 남았다. */

/* 전폭 처리 — ⚠ `width: 100vw`를 쓰면 안 된다. `.main`이 세무사모드에서
   `margin-left: var(--sidebar-w)`라 100vw는 사이드바 폭만큼 오른쪽으로 넘친다.
   본문 좌우 패딩만 되돌리면 의뢰인모드는 화면 끝까지, 세무사모드는 본문 칼럼 끝까지 정확히 찬다. */
/* ⚠ **얇게 유지한다.** 이 구간의 임무는 위아래를 나누는 것이지 자기 존재를 주장하는 게 아니다.
   글자를 걷어내고(부제·분야줄·고지문 삭제) 여백을 줄여 200px 안쪽으로 낮췄다. */
/* ⚠ 배경·테두리는 `.review-band`(이 파일 아래쪽, 홈의 다른 전폭 밴드)와 **한 벌**이다.
   --grey50은 흰 배경 대비 1.03:1이라 **혼자서는 구간을 못 끊는다** — 위아래 헤어라인이
   실제로 끊는 일을 한다. 둘 중 하나만 남기면 밴드가 사라지거나(배경만) 뜬금없는
   구분선 두 줄만 남는다(테두리만). 한쪽을 고치면 `.review-band`도 같이 고칠 것. */
.situ-band {
  margin-inline: calc(var(--shell-pad) * -1);
  margin-top: var(--home-gap);            /* 다른 섹션과 같은 리듬 */
  padding: var(--band-pad) var(--shell-pad);  /* 안쪽 여백은 .review-band와 같은 값(D-262) */
  background: var(--grey50);
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  overflow: hidden;   /* 레일이 밴드 밖으로 새지 않게 */
}
/* ⚠ 크기·자간은 섹션 제목(.sec-head h2)과 **똑같이** 맞춘다(D-161) — 예전엔 21px/-.3px라
   바로 위 섹션 제목(20px/-.2px)과 미묘하게 어긋나 다른 서체처럼 보였다.
   굵기만 500으로 남긴다: 같은 크기·같은 자간에서 굵기만 다르면 '의도한 위계'로 읽히고,
   이 구간은 바로 위가 광고라 목소리를 낮춰야 한다(D-155). 700으로 올리지 말 것. */
.situ-title {
  font-size: 20px; font-weight: 500; letter-spacing: var(--ls-xl); color: var(--text-primary);
}

/* ── 로테이션 배너 (D-247) — 캐러셀 ──────────────────────────────────────────
   지난 버전은 상황 카드가 왼쪽으로 흐르는 순수 CSS 마퀴였다(situ-*). 이미지가 이미
   1400×420(좌측 비움 + 우측 3D 오브제)이라, 그림을 배경으로 깔고 좌측 안전영역(46%)에
   글자를 얹는 배너로 바꿨다. 슬라이드는 겹쳐 쌓고 .is-active만 페이드로 보인다.

   🔴 JS 없이도 산다: 서버가 첫 슬라이드에 .is-active를 박아 두므로 그 한 장과 링크가 보인다.
      컨트롤(점·카운터·화살표)은 banner-carousel.js가 .is-ready를 붙이기 전엔 감춰 둔다 —
      눌러도 아무 일 없는 장식을 남기지 않는다.
   ⚠ 배경·테두리(.situ-band)는 위쪽 그대로 두고(리듬·review-band와 한 벌), 그 안에 카드를 넣는다. */
.bnr {
  /* ⚠ 폴백을 남긴다 — 변수가 없으면 `max-width`가 통째로 무효가 되어 상한이 풀린다. */
  position: relative; max-width: var(--bnr-max, 1200px); margin: 14px auto 0; height: 340px;
  border-radius: 20px; overflow: hidden; background: var(--surface);
  box-shadow: 0 12px 32px rgba(20, 36, 61, .10);
}
/* ── 이미지 전용 변형 (D-258) — 홈 최상단 광고주 배너가 이 캐러셀을 쓴다 ────────────
   🔴 **높이를 원고 비율에 고정한다.** 기본 `.bnr`의 340px은 우리 원고(1400×420)에 맞춘 값이라,
      광고주 원고(2480×806 · 3.08:1)를 그 틀에 넣으면 위아래가 잘린다 — 운영자가 결과를 예측할 수
      없게 된다(D-153). 비율을 그대로 두면 `object-fit: cover`가 아무것도 자르지 않는다.
   ⚠ 이 숫자를 바꾸면 **앱도 같이** 바꿔야 한다(promo_banner_carousel.dart의 _bannerAspect).
   ⚠ 여기에는 `.bnr-copy`가 없다(D-142) — 글자를 얹으려면 그 결정부터 뒤집어야 한다. */
.bnr.bnr-img { height: auto; aspect-ratio: 2480 / 806; }
/* 광고 원고는 가운데가 주인공이다 — 기본 `.bnr-bg`의 `object-position: right center`는
   우리 일러스트(오브제가 우측)용이라 여기서 되돌린다. */
.bnr.bnr-img .bnr-bg { object-position: center; }
.bnr-track { position: absolute; inset: 0; border-radius: inherit; }

/* ══ 양옆 빈 자리에 이전·다음 배너를 앉힌다 (D-699, 사용자 지시) ═══════════════════
   신고: 「기기 모니터 환경에 따라 메인배너 양옆이 비어보인다」.
   원인은 위 `.bnr`의 **max-width: 1200px + margin auto**다 — 넓은 모니터일수록 좌우 여백이
   그대로 빈 자리가 된다(2000px 폭이면 양쪽 400px씩). 1200px 상한 자체는 지워선 안 된다:
   높이가 원고 비율(2480×806)을 따라가므로 상한을 풀면 넓은 화면에서 배너만 650px씩 자란다.

   그래서 **본 배너는 그대로 두고, 앞뒤 장을 여백으로 내보낸다.**
   ⚠ 얼마나 보일지는 CSS가 정하지 않는다 — 남는 여백이 곧 노출 폭이고, 여백이 없으면 아무것도
     안 보인다. 「모니터 환경에 따라」라는 신고에 맞춰 **자리가 스스로 정하게** 둔 것이다.
     좁은 화면에서 따로 끌 필요가 없는 이유이기도 하다.
   ⚠ 이웃은 **주인공을 넘어서면 안 된다** — 어둡게 깔고 클릭·탭·낭독에서 뺀다
     (JS가 비활성에 aria-hidden·tabindex=-1을 이미 걸어 둔다. pointer-events로 한 겹 더 받친다).
   ⚠ 두 장뿐이면 JS가 표식을 아예 안 단다(앞뒤가 같은 장이라 반쪽이 된다) — banner-carousel.js. */
/* 이웃이 상자 **밖**으로 나가야 하므로 여기서 자르지 않는다. 대신 슬라이드가 자기를 자른다
   (둥근 모서리는 원래 `.bnr`의 overflow가 만들어 주던 것이라, 그 몫을 옮겨 준다). */
.bnr.bnr-img { overflow: visible; }
.bnr-slide { border-radius: inherit; overflow: hidden; }
/* 🔴 **자르는 경계가 곧 이웃 노출 폭이다** (D-700, 사용자 지시 「양쪽 200씩」).
   예전에는 지면 폭에서 잘랐다 — 그러면 모니터가 넓을수록 이웃이 한없이 커져서(2560에서
   양쪽 520px씩 실측) 「다음 장이 있다」는 신호가 아니라 **카드 세 장**으로 읽힌다.
   그래서 경계를 배너에서 «이웃 폭 + 간격»만큼 바깥에 세운다. 이웃 자체는 손대지 않는다 —
   원래 크기 그대로 두고 보이는 만큼만 보이게 하는 것이라, 옆에 걸친 그림의 배율이
   본 배너와 같다(폭을 200px로 줄이면 그림이 따로 축소돼 다른 카드처럼 보인다).

   ⚠ 좁은 화면에서는 이 상한이 **저절로 놀고** 지면 폭이 이긴다 — 여백이 없으면 이웃도 없다.
     따로 끄는 규칙이 필요 없는 이유다(실측: 1440에서 노출 0).
   ⚠ 배너 폭은 `--bnr-max` 하나로 여기와 `.bnr`이 함께 본다. 숫자를 두 곳에 적으면
     언젠가 갈리고, 그러면 경계가 배너와 어긋나 이웃이 짝짝이로 잘린다.

   `overflow-x: clip`인 이유는 셋을 견줘 고른 것이다:
     · `overflow: hidden`  — 위아래까지 잘라 `.bnr`의 그림자(0 12px 32px)를 먹는다.
       게다가 한 축만 hidden으로 두면 다른 축이 auto로 끌려가 **스크롤 상자**가 되어 버린다.
     · `clip-path: inset()` — 🔴 **그림만 자르고 레이아웃 넘침은 그대로 둔다.** 처음에 이걸
       썼다가 실측에서 잡혔다: 뷰포트 1920에서 `scrollWidth`가 **2884**가 되어 홈 전체가
       가로로 스크롤됐다(이웃을 끄면 1920). 눈에는 멀쩡해 보여서 더 위험한 결함이다.
     · `overflow-x: clip`   — 잘라 내면서 **넘침도 없앤다**. 그리고 `clip`은 `hidden`과 달리
       반대 축의 `visible`을 auto로 끌어내리지 않아서, 위아래 그림자가 그대로 산다.
       («clip»이라는 값이 존재하는 이유가 바로 이 경우다.) */
.hero-wrap:not(.situ-rail) {
  --bnr-max: 1200px;
  --bnr-peek: 200px;      /* 한쪽에 보일 이웃 폭 — 여기 하나만 바꾸면 양쪽이 같이 따라간다 */
  --bnr-peek-gap: 16px;   /* 본 배너와 이웃 사이 */
  max-width: calc(var(--bnr-max) + 2 * (var(--bnr-peek) + var(--bnr-peek-gap)));
  margin-inline: auto;
  overflow-x: clip;
}
/* ⚠ `:not(.is-active)`은 방어다. 표식 셋은 JS가 매번 함께 갈아 끼우므로 한 장이 «활성이자
   이웃»일 수 없다 — 다만 그 규칙이 깨지는 날 **본 배너가 화면 밖으로 밀려나** 배너가 통째로
   사라진다. 값이 싼 보험이라 걸어 둔다. */
.bnr-slide.is-prev:not(.is-active), .bnr-slide.is-next:not(.is-active) {
  opacity: 1; visibility: visible; pointer-events: none;
  filter: brightness(.78) saturate(.85);
}
.bnr-slide.is-prev:not(.is-active) { transform: translateX(calc(-100% - var(--bnr-peek-gap))); }
.bnr-slide.is-next:not(.is-active) { transform: translateX(calc(100% + var(--bnr-peek-gap))); }
/* ⚠ transform은 **전환하지 않는다**. 넘어갈 때 세 장의 표식이 한꺼번에 바뀌는데 위치까지
   애니메이션하면 이웃이 화면을 가로질러 날아간다 — 이 캐러셀은 페이드다(위 .bnr-slide). */
/* 슬라이드 전체가 링크다. 겹쳐 쌓고 활성만 페이드로 보인다.
   ⚠ 비활성은 pointer-events:none — 안 보이는 슬라이드의 CTA가 탭·클릭되면 안 된다(JS도 tabindex로 막지만
     CSS가 한 겹 더 받친다). visibility까지 꺼야 스크린리더·탭에서 완전히 빠진다. */
.bnr-slide {
  position: absolute; inset: 0; display: flex; align-items: center;
  text-decoration: none; color: inherit;
  opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity .6s ease, visibility .6s ease;
}
.bnr-slide.is-active { opacity: 1; visibility: visible; pointer-events: auto; }
.bnr-slide:focus-visible { outline: 3px solid var(--primary-pressed); outline-offset: -3px; }
/* 배경 그림 — cover · 오브제 항상 우측(§1). 첫 장만 eager+preload(서버에서 건다). */
.bnr-bg {
  position: absolute; inset: 0; z-index: 0;
  width: 100%; height: 100%; object-fit: cover; object-position: right center;
}
/* 글자 자리 — 좌측 64px · 최대 46%(오브제 안전영역) · 세로 중앙. */
.bnr-copy {
  position: relative; z-index: 2;
  padding: 0 16px 0 64px; max-width: 46%;
  display: flex; flex-direction: column; align-items: flex-start; gap: 10px;
}
/* ⚠ **`.bnr-chip`(카드 위 흰 알약)은 걷었다**(D-297). 마크업이 사라졌으므로 규칙도 지운다 —
   남겨 두면 «무엇을 그리는지 알 수 없는 규칙»이 된다. 되살릴 일이 있으면 함께 되돌릴 것. */
/* 헤드라인 — 최대 2줄. 한글은 어절에서 끊는다. */
.bnr-head {
  font-size: 33px; line-height: 44px; font-weight: 700; letter-spacing: -0.02em; color: #111827;
  word-break: keep-all;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.bnr-sub { font-size: 15.5px; line-height: 24px; color: #475569; word-break: keep-all; }
.bnr-cta {
  margin-top: 6px; display: inline-flex; align-items: center; gap: 6px;
  height: 46px; padding: 0 22px; border-radius: 999px;
  background: var(--primary); color: #fff; font-size: 15px; font-weight: 600;
  box-shadow: 0 4px 12px rgba(49, 130, 246, .28); transition: background .15s ease;
}
.bnr-slide:hover .bnr-cta { background: #2570E0; }
.bnr-cta-arw { flex: 0 0 auto; }

/* ── 컨트롤 — JS(.is-ready) 전엔 감춘다 ───────────────────────────── */
.bnr:not(.is-ready) .bnr-dots,
.bnr:not(.is-ready) .bnr-nav { display: none; }
.bnr-dots {
  position: absolute; left: 20px; bottom: 16px; z-index: 3;
  display: inline-flex; align-items: center; gap: 8px; padding: 6px 12px; border-radius: 999px;
  background: rgba(255, 255, 255, .70); -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px);
}
.bnr-dot {
  width: 8px; height: 8px; padding: 0; border: 0; border-radius: 999px; cursor: pointer;
  background: rgba(17, 24, 39, .25); transition: width .2s ease, background .2s ease;
}
.bnr-dot.is-active { width: 26px; background: var(--primary); }
.bnr-dot:focus-visible { outline: 2px solid var(--primary-pressed); outline-offset: 2px; }
.bnr-count { margin-left: 4px; font-size: 12px; color: #475569; font-variant-numeric: tabular-nums; }
.bnr-nav { position: absolute; right: 20px; bottom: 16px; z-index: 3; display: inline-flex; gap: 8px; }
.bnr-arw {
  width: 38px; height: 38px; border-radius: 999px; border: 1px solid #DBE4F0; cursor: pointer;
  background: rgba(255, 255, 255, .85); -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px);
  color: #334155; display: inline-flex; align-items: center; justify-content: center;
}
.bnr-arw:hover { background: #fff; color: #111827; }
.bnr-arw:focus-visible { outline: 2px solid var(--primary-pressed); outline-offset: 2px; }

/* ── 모바일 (≤768px, §3) — 200px · 보호 그라데이션 · 서브 생략 · 화살표 숨김 ─── */
@media (max-width: 768px) {
  .situ-band { margin-inline: -16px; padding: var(--band-pad) 16px; }
  .bnr { height: 200px; border-radius: 16px; margin-top: 12px; }
  .bnr-bg { object-position: 76% center; }
  /* 좌→우 보호 막 — 76% 크롭이라 오브제가 왼쪽으로 당겨와 글자와 겹칠 수 있다(§3). */
  .bnr-slide::before {
    content: ""; position: absolute; inset: 0; z-index: 1;
    background: linear-gradient(90deg,
        rgba(232, 240, 250, .92) 0%, rgba(232, 240, 250, .55) 46%, rgba(232, 240, 250, 0) 68%);
  }
  .bnr-copy { padding-left: 20px; max-width: 66%; gap: 6px; }
  .bnr-head { font-size: 19px; line-height: 26px; }
  .bnr-sub { display: none; }               /* §3 — 모바일은 칩+헤드라인+CTA만 */
  .bnr-cta { height: 36px; padding: 0 16px; font-size: 13px; }
  .bnr-nav { display: none; }               /* 화살표 대신 스와이프 */
  .bnr-dots { left: 16px; bottom: 12px; }
}

/* 모션을 줄이겠다고 한 사용자: 자동 전환은 JS가 끄고(§4), 페이드도 없앤다 — 넘김은 즉시. */
@media (prefers-reduced-motion: reduce) {
  .bnr-slide { transition: none; }
}

/* ── 분야 칩 ────────────────────────────────────────── */
.chips { display: flex; gap: 8px; flex-wrap: wrap; margin: 22px 0 4px; }
.chip {
  height: 34px; padding: 0 14px; border-radius: var(--r-sm);
  border: 1px solid var(--border); background: var(--surface);
  font-size: 14px; font-weight: 600; color: var(--text-secondary);
  display: inline-flex; align-items: center;
}
.chip:hover { background: var(--surface-alt); }
.chip-on { background: var(--text-primary); border-color: var(--text-primary); color: #fff; }
.chip-on:hover { background: var(--text-primary); }

/* ── 섹션 공통 ──────────────────────────────────────── */
/* 섹션 사이 간격 (D-166) — 참고 지면(nol.yanolja.com)이 모든 구간을 **40px**으로 띄운다(실측).
   예전엔 24·30·34가 뒤섞여 있어 구간 경계가 들쭉날쭉했다. */
.section { margin-top: var(--home-gap); }
.sec-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 14px; flex-wrap: wrap; }
.sec-head h2 { font-size: 20px; font-weight: 700; letter-spacing: var(--ls-xl); white-space: nowrap; }
.sec-head .sub { font-size: 13px; color: var(--text-tertiary); }
.sec-head .more { margin-left: auto; font-size: 14px; font-weight: 600; color: var(--primary); white-space: nowrap; }
/* '지금 상담 가능한 세무사' 머리줄 — 부제가 **우측 끝**에 선다(D-723, 사용자 지시). 「빠른 상담 ›」
   링크를 걷어 auto 여백을 다툴 상대가 없어졌으므로 부제가 그 자리를 이어받는다. 좁은 화면에서
   줄이 접히면(flex-wrap) 둘째 줄에서도 오른쪽에 붙는다. */
#online-now .sec-head .sub { margin-left: auto; text-align: right; }

/* ── 카드 레일 좌우 화살표 — **규칙은 css/rail.css로 옮겼다**(D-356).
   스크립트(js/paged-rail.js)와 짝인 규칙이라 스크립트와 함께 다녀야 한다. 홈이 아닌 지면
   (세무시선 목록의 인기 레일 등)이 홈 CSS를 통째로 링크하지 않고도 레일을 쓸 수 있다.
   ⚠ 이 지면(index.html)도 rail.css를 **따로 링크**한다 — 여기서 지웠다고 홈에서 안 실리면
     화살표가 카드 위에 겹친다. */

/* 아바타(광고·인기 공용) */
.avatar {
  position: relative; flex: 0 0 auto; width: 52px; height: 52px; border-radius: var(--r-md);
  background: var(--primary-light); color: var(--primary);
  display: inline-flex; align-items: center; justify-content: center;
  /* ⚠ 여기만 자간 0이다. 글자 한 자를 가운데 놓는 자리라, 자간이 붙으면 마지막 글자
     뒤에도 그만큼 공간이 생겨 글자가 왼쪽으로 밀린다. 스케일(19px→-.4px)을 쓰지 말 것. */
  font-weight: 700; font-size: 19px; letter-spacing: 0; overflow: visible;
}
.avatar img { width: 100%; height: 100%; border-radius: var(--r-md); object-fit: cover; }
/* 아바타에 붙는 접속 점. ⚠ app.css의 `.presence`는 '접속중' **텍스트 배지**라 이름이
   겹치면 디렉토리·상세·빠른상담의 상태 표시가 깨진다 — 그래서 `.av-dot`으로 분리했다. */
.avatar .av-dot {
  position: absolute; right: -3px; bottom: -3px; width: 12px; height: 12px;
  border-radius: 50%; border: 2px solid var(--surface); background: var(--presence-offline);
}
.av-dot.dot-online { background: var(--presence-online); }
.av-dot.dot-away { background: var(--presence-away); }
.av-dot.dot-busy { background: var(--presence-busy); }

/* 디렉토리 카드의 광고 라벨 줄 — 셸 개편 전 home.css에 있던 규칙을 그대로 가져온다
   (directory.html이 여전히 쓴다). */
.ad-row { margin-bottom: 4px; }

/* ── 광고 세무사 카드 ───────────────────────────────── */
.ad-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 14px; }

/* ── 광고 레일 (D-171) — 4장씩 끊어 넘어간다 ─────────────────────────────
   예전엔 D-162에서 상황 밴드와 같은 연속 마퀴였다. "홈의 모든 구간이 쉬지 않고 흘러가
   정신없다"는 사용자 지적으로, **한 화면에 --ad-per장을 고정해 두고 paged-rail.js가
   몇 초마다 한 세트씩 scrollTo로 미는** 방식으로 바꿨다. 서버는 `.ad-track`에 **진짜 카드만**
   담고(scroll-snap), 자동 넘김은 JS가 `track.clientWidth`(=카드 --ad-per장 폭)만큼 스크롤
   위치를 옮기는 것뿐이다. 2026-08-09부터 **끝에 앞쪽 카드의 복제본이 붙어 무한히 순환한다** —
   그 복제본도 JS가 만들고 걷는다(폭이 바뀌면 필요한 장수가 달라져 다시 깐다).
   ⚠ 카드 폭을 **cqw 기반 가변**으로 둔다(마퀴 시절의 고정 340px과 다르다) — 폭이
      바뀌어도 "한 화면 스크롤 = 정확히 --ad-per장"이 항상 성립해야 하기 때문이다.
      고정 폭이면 화면마다 실제로 몇 장이 보이는지 어긋나 JS의 "한 세트" 가정이 깨진다. */
.ad-rail {
  /* ⚠ 처음엔(D-171) 밴드처럼 화면 끝까지 채우는 전폭이었다. "양 끝이 꽉 차 답답하다"는
     지적(사용자 지시)으로 되돌렸다 — 이제 레일 상자 자체는 본문과 같은 --shell-pad를 그대로
     받는다(전폭이 아니다).
     🔴 그렇다고 **제목 줄과 카드 줄의 좌우 끝이 맞지는 않는다.** 예전에 여기 "정확히 맞는다"고
        적어 두었는데 거짓이다 — 카드 줄은 paged-rail.js가 씌우는 .rail-shell 안에 들어가고,
        그 셸이 화살표 자리(--ra-need)만큼 안쪽으로 파고든다. 실측(Chrome, 이 지면):
        769px → 37.09px · 1280px → 25.84px 안쪽. 완전히 일치하는 것은 --shell-pad가 커져
        셸이 되밀 여유가 생기는 아주 넓은 화면(약 2455px 이상)뿐이다.
        숫자의 출처와 그렇게 만든 이유는 이 파일 위쪽 `.rail-shell` 주석에 있다 —
        두 곳이 어긋나면 그쪽이 정본이다. */
  overflow: hidden;
  container-type: inline-size;   /* 카드 폭을 이 폭 기준(cqw)으로 잡는다 */
  --ad-gap: 14px;
  /* 한 행에 보일 장수 — 6→4(2026-08-09 카드 통일). '지금 상담 가능한' 레일(--tp-per)과
     **같은 값**을 쓴다: 두 레일의 카드가 같은 디자인이므로 폭까지 같아야 같은 카드로 읽힌다. */
  --ad-per: 4;
}
.ad-track {
  display: flex; gap: var(--ad-gap);
  overflow-x: auto; scroll-snap-type: x mandatory;
  scrollbar-width: none; -ms-overflow-style: none;
}
.ad-track::-webkit-scrollbar { display: none; }
/* 레일 안에서만 cqw로 폭을 잡는다 — 격자(.ad-grid)에서는 칸이 폭을 정한다.
   폭 계산 규칙은 .pf-card 정의부 옆(아래) `.ad-rail .pf-card`에 있다. */
/* 좁아질수록 한 행 장수를 줄인다 — ⚠ 브레이크포인트도 .tp-rail과 같은 값으로 묶는다.
   한쪽만 바꾸면 어떤 폭에서 두 레일의 카드 폭이 어긋나 통일이 깨진다. */
/* ⚠ 아래 세 줄은 **폴백**이다(D-282). 실제 장수는 paged-rail.js가 레일의 **실측 폭**에서
     정해 인라인 스타일로 덮는다 — 미디어쿼리는 «창»만 보아 사이드바가 먹은 폭을 모른다.
     JS가 안 도는 환경에서만 이 값이 쓰인다. 지우지 마라. */
@media (max-width: 1200px) { .ad-rail { --ad-per: 3; } }
@media (max-width: 900px)  { .ad-rail { --ad-per: 2; } }
@media (max-width: 600px)  { .ad-rail { --ad-per: 1; } }

/* '광고' 라벨은 표시 의무다(D-013 · 약관 제6조) — 끄는 옵션을 만들지 마라.
   2026-08-09 카드 통일: 회색 배경 필 대신 **작은 회색 텍스트**만 남긴다 — 광고임은 밝히되
   카드의 시각 위계(사진·이름 1순위)를 라벨이 이기지 않는다.
   ⚠ 홈 카드(.pf-card)는 이제 이 클래스를 쓰지 않는다 — 아래 `.ad-mark`("AD")로 갈아탔다
   (2026-08-09, 로톡 참고). 여기는 디렉토리 목록·상단 레일(.dad-card)·지도·pro-ads·
   관리자 미리보기(admin-ad-preview.js)가 계속 쓴다 — 지우면 그쪽 표시 의무가 깨진다. */
.ad-label {
  margin-left: auto; align-self: flex-start;
  font-size: 11px; font-weight: 600; color: var(--text-tertiary);
  letter-spacing: 0; white-space: nowrap;
}

/* ── 광고 마커 "AD" — 두 층위 (2026-08-09 「광고」→"AD", 로톡 참고 · D-226) ────────
   D-013 표시 의무: **마커 자체는 항상 보인다** — 호버로만 존재하면 표시가 아니다.
   설명("광고비를 낸 세무사예요.")은 보조 층위 셋으로 얹는다:
   ① CSS 호버 툴팁(아래 ::after) — transition 없이 **즉시** 뜬다,
   ② title(네이티브 툴팁 겸 ::after의 content 원본 — attr(title)이라 문구가 한 곳에만 산다),
   ③ aria-label(+role=img) — 스크린리더는 "AD" 대신 뜻을 읽는다.
   색은 --text-tertiary(#6B7684) — 흰 카드 위 대비 4.62:1로 4.5:1을 넘는다(WCAG AA).

   🔴 **두 층위를 헷갈리지 마라**(D-226):
     · `.ad-mark`     = **카드별** 마커. 광고와 일반이 섞인 **혼합 지면**('지금 상담 가능한'
                        레일) 전용 — 어느 카드가 광고인지는 카드에만 적을 수 있다.
     · `.sec-ad-mark` = **섹션** 마커. 카드가 전부 광고인 지면('프리미엄 세무사' 섹션 제목 옆,
                        광고 신청 미리보기 머리줄) 전용 — 카드마다 반복해도 정보가 안 는다.
   어느 지면이든 둘 중 하나는 반드시 그려진다. 한쪽을 지우면 라벨 없는 광고가 된다.
   문구·색·툴팁은 여기 한 규칙으로 묶어 둔다 — 두 벌로 두면 한쪽만 고치게 된다. */
.ad-mark, .sec-ad-mark {
  position: relative;
  font-size: 11px; font-weight: 700; color: var(--text-tertiary);
  letter-spacing: .5px; white-space: nowrap;
}
/* 카드 마커만 우상단으로 민다. ⚠ `.sec-ad-mark`에는 이 auto를 주지 마라 — 섹션 제목 줄
   (.sec-head)에는 '전체 보기'(.more)가 이미 margin-left:auto라, 둘이 남는 폭을 나눠 가지며
   제목과 마커 사이가 화면 폭만큼 벌어진다(마커가 제목 "옆"이 아니게 된다). */
.ad-mark { margin-left: auto; align-self: flex-start; }
/* ⚠ `.sec-ad-mark`에는 align-self를 주지 않는다 — 부모 줄의 정렬을 그대로 따라야 한다.
   섹션 제목 줄(.sec-head)은 baseline, 광고 신청 미리보기 머리줄(.adm-preview-head)은
   center다. 여기서 하나로 못박으면 둘 중 한쪽에서 마커만 위아래로 어긋난다. */
.ad-mark::after, .sec-ad-mark::after {
  content: attr(title);
  position: absolute; top: calc(100% + 6px); z-index: 2;
  padding: 6px 10px; border-radius: var(--r-sm);
  background: var(--grey800); color: #fff;
  font-size: 12px; font-weight: 500; letter-spacing: var(--ls-sm); white-space: nowrap;
  opacity: 0; visibility: hidden;
  /* 툴팁이 떠 있어도 카드 링크 클릭을 가로채지 않는다. */
  pointer-events: none;
}
/* 카드 마커는 오른쪽 끝에 있어 오른쪽 정렬, 섹션 마커는 왼쪽에 있어 왼쪽 정렬 —
   반대로 두면 툴팁이 화면 밖으로 나가 잘린다. */
.ad-mark::after { right: 0; }
.sec-ad-mark::after { left: 0; }
/* 위가 아니라 **아래**로 편다 — 마커가 카드 최상단이라 위로 펴면 레일(.ad-track 등)의
   overflow에 잘린다. 키보드 사용자에게는 카드 포커스만으로 보여 준다(마커는 포커스 불가). */
.ad-mark:hover::after,
.pf-card:focus-visible .ad-mark::after,
.sec-ad-mark:hover::after { opacity: 1; visibility: visible; }

/* ── '지금 상담 가능한 세무사' 레일 (D-169 세로→가로, 넘김 방식은 D-171) ──────────
   카드 자체는 아래 .pf-card(2026-08-09 카드 통일 — 프리미엄 레일과 같은 카드)를 쓰고,
   여기는 **레일 배치**(2행 grid·열 폭·자동 넘김)만 정한다.
   ⚠ 그림자를 넣지 마라 — 홈의 다른 카드와 같은 규칙이다(D-167·D-168). hover는 테두리 색으로만.
   ⚠ D-171: 연속으로 흐르던 마퀴를 걷어냈다 — "홈의 모든 구간이 쉬지 않고 흘러가 정신없다"는
     지적으로, **3초마다 한 세트씩** paged-rail.js가 scrollTo로 미는 방식으로 바꿨다.
     서버는 진짜 카드만 그린다 — 순환용 복제본은 그 스크립트가 클라이언트에서 만든다.
   🔴 아래 `.tp-track`은 **2행 격자**다. 카드 수가 홀수면 마지막 열 아랫칸이 비는데, 거기에
     복제본이 끼면 순환 이음매가 반 칸 어긋난다 — paged-rail.js가 첫 복제본에 `grid-row-start:1`을
     걸어 새 열에서 시작시킨다. --tp-rows를 바꾸면 그 처리도 함께 봐야 한다. */
.tp-rail {
  /* ⚠ 처음엔(D-171) 밴드처럼 화면 끝까지 채우는 전폭이었다. "양 끝이 꽉 차 답답하다"는
     지적(사용자 지시)으로 광고 레일과 함께 되돌렸다 — 레일 상자는 본문과 같은 --shell-pad를
     그대로 받는다. ⚠ 다만 **카드 줄은 제목 줄보다 안쪽에 선다** — .rail-shell이 화살표 자리를
     비우기 때문이다(광고 레일과 같은 값·같은 이유, 실측은 .ad-rail·.rail-shell 주석 참고). */
  overflow: hidden;
  container-type: inline-size;   /* 카드 폭을 이 폭 기준(cqw)으로 잡는다 */
  --tp-gap: 14px;
  --tp-per: 4;                   /* 한 행에 보일 장수 — 6→4(2026-08-02 사용자 지시) */
  --tp-rows: 2;                  /* 행 수 — 1→2. 한 번에 --tp-per × --tp-rows = 8장 */
}
/* ⚠ **2행 레일**(2026-08-02 사용자 지시) — flex 한 줄에서 grid 2행으로 바꿨다.
   `grid-auto-flow: column` + `grid-template-rows: repeat(2, ...)`이면 카드가 **세로로 먼저**
   채워진 뒤 오른쪽으로 넘어간다: 1·2가 첫 열에 위아래로 서고, 3·4가 둘째 열에 선다.
   ⚠ 그래서 **읽는 순서가 행 단위가 아니라 열 단위**다 — 윗줄만 훑으면 1,3,5,7이 보인다.
     정렬은 여전히 의미가 있다(광고 우선노출이 앞) — 1·2가 나란히 첫 열(가장 눈에 띄는 자리)에
     오므로 우선순위 자체는 지켜진다. 굳이 "윗줄 1234 / 아랫줄 5678"로 만들려면 서버에서
     8장씩 페이지로 잘라 넘겨야 하는데, 그러면 페이지 크기가 8로 **고정**돼 좁은 화면에서
     열 수를 줄일 수 없다(아래 미디어쿼리가 통째로 무력화된다). 반응형을 지키는 쪽을 택했다.
   ⚠ 카드 폭은 flex-basis가 아니라 `grid-auto-columns`가 정한다 — `.ad-rail .pf-card`의
     flex 선언은 grid 컨테이너 안에서 무시된다.
   paged-rail.js는 그대로 둔다 — `scrollBy(clientWidth)`가 곧 '한 화면(=--tp-per열)'이라,
   행이 2줄이 돼도 한 번에 8장씩 넘어간다. */
.tp-track {
  display: grid;
  grid-auto-flow: column;
  grid-template-rows: repeat(var(--tp-rows), auto);
  grid-auto-columns: calc((100cqw - (var(--tp-per) - 1) * var(--tp-gap)) / var(--tp-per));
  gap: var(--tp-gap);
  overflow-x: auto; scroll-snap-type: x mandatory;
  scrollbar-width: none; -ms-overflow-style: none;
}
.tp-track::-webkit-scrollbar { display: none; }

/* ── 홈 프로필 카드 (.pf-card, 2026-08-09 카드 통일) ─────────────────────
   '프리미엄 세무사'(광고 레일·격자·신청 폼 미리보기)와 '지금 상담 가능한 세무사' 레일이
   **전부 이 카드 하나**다(fragments/ad-card.html). 광고 카드에만 있던 차별 요소
   (다크 밴드 #1B2437·4:5 대형 사진·.ad-hl-* 강조·반투명 라벨)는 홈에서 걷어냈다 —
   광고 카드와 일반 카드의 차이는 우상단 「광고」 회색 텍스트뿐이다(D-013).
   ⚠ **그림자를 넣지 마라**(D-167·D-168) — 흰 배경 위에서 카드 둘레가 회색으로 번진다.
     2026-08-09 실제 렌더 비교에서도 보더리스+그림자보다 1px 옅은 테두리(--border, grey200)가
     경계가 정갈해 이쪽으로 확정했다. 누를 수 있다는 신호는 hover 테두리 색으로만 준다. */
.pf-card {
  display: flex; flex-direction: column; gap: 10px;
  border: 1px solid var(--border); border-radius: var(--r-md); padding: 16px;
  background: var(--surface); transition: border-color .15s ease;
}
.pf-card:hover { border-color: var(--grey300); }
.pf-card:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }

/* 레일 폭 — 광고 레일(flex)은 이 규칙이, '지금 상담 가능' 레일(grid)은
   `.tp-track { grid-auto-columns }`가 폭을 정한다(플렉스 선언은 grid 안에서 조용히 무시된다).
   격자(.ad-grid)·신청 폼 미리보기에서는 부모가 폭을 정하므로 별도 분기가 필요 없다. */
.ad-rail .pf-card {
  flex: 0 0 calc((100cqw - (var(--ad-per) - 1) * var(--ad-gap)) / var(--ad-per));
  scroll-snap-align: start;
}
.tp-rail .pf-card { scroll-snap-align: start; }

.pf-top { display: flex; align-items: center; gap: 12px; }
/* 프로필 사진은 **크게** 본다(D-162, 사용자 지시) — 52px에서는 얼굴이 식별되지 않아
   "누구에게 상담받는지"가 안 보였다. 사진·이름이 카드에서 가장 먼저 읽혀야 한다.
   ⚠ 접속 점(.av-dot)도 같이 키운다. 88px 사진에 12px 점을 그대로 두면 먼지처럼 보인다. */
.pf-card .avatar { width: 88px; height: 88px; font-size: 32px; border-radius: var(--r-lg); }
.pf-card .avatar img { border-radius: var(--r-lg); }
.pf-card .avatar .av-dot { width: 16px; height: 16px; right: -2px; bottom: -2px; border-width: 3px; }

/* min-width:0이 없으면 flex item이 줄어들지 않아 이름·상호 말줄임(ellipsis)이 아예 안 걸린다. */
.pf-id { min-width: 0; }
/* 이름 16→18px(2026-08-09 사용자 지시 — "이름 더 크게"). --ls-lg가 16~18px 구간이라
   자간 토큰은 그대로다. 앱 미러도 같은 한 단계(label1 16→title2 18, home_screen.dart). */
/* ⚠ 이름 18→20px(D-638, 사용자 지시: 「폰트가 작아서 가독성이 떨어진다」). 40대 이상 가독성이
   이번 상향의 배경이다 — /fit에서 같은 이유로 한 벌을 올렸다(D-636·D-637). */
.pf-name {
  font-size: 20px; font-weight: 700; line-height: 1.25; letter-spacing: var(--ls-lg);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.pf-office {
  margin-top: 3px; font-size: 15px; color: var(--text-tertiary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* ── 행 정렬(2026-08-09 사용자 지시) — 멘트(.ad-tagline) 유무로 아래 줄이 출렁이지 않게.
   카드가 flex column이고 레일(flex)·격자(grid)의 기본 stretch로 **한 행의 카드 높이는
   이미 같다** — 여기에 평점 줄에 margin-top:auto를 주면 평점·칩 블록이 카드 바닥에
   정렬돼, 멘트 없는 카드도 같은 높이에 두 줄이 선다. 남는 공간은 멘트 자리가 삼킨다.
   멘트 슬롯 고정 높이(다른 후보안)보다 나은 점: 멘트 자체가 없는 지면('지금 상담 가능'
   레일, withTagline=false)에 유령 여백이 안 생긴다. 멘트가 길어도 .ad-tagline이
   -webkit-line-clamp:1로 한 줄 말줄임이라 카드 높이를 두 줄로 키우지 못한다. */
.pf-meta { display: flex; align-items: center; gap: 6px; font-size: 15px; color: var(--text-tertiary); }
.pf-card .pf-meta { margin-top: auto; }
.pf-meta .star { color: var(--warning); font-weight: 700; }
/* 분야 칩 — app.css 기본(.spec-row margin-top:8px)은 카드 gap과 겹쳐 간격이 두 배가 된다.
   min-height 21px = 칩 한 줄(line-height 17 + 세로 패딩 2×2) — 분야 없는 카드도 빈 줄이
   같은 높이를 차지해 평점 줄이 내려앉지 않는다(조각이 빈 .spec-row를 항상 그린다).
   ⚠ line-height를 지우면 상속값(호스트 폰트에 따라 유동)으로 min-height와 어긋난다. */
/* 🔴 이 셋은 한 몸이다 — 칩 글자 13.5 + line-height 20 + 세로 패딩 2×2 = 24px이 곧
      .spec-row의 min-height다. 하나만 고치면 분야 없는 카드에서 평점 줄이 내려앉는다
      (위 주석이 경고한 그대로). D-638에서 11.5→13.5로 올리며 21→24로 함께 옮겼다. */
.pf-card .spec-row { margin-top: 0; min-height: 24px; }
.pf-card .spec { font-size: 13.5px; line-height: 20px; padding: 2px 8px; }

/* 좁아질수록 한 행 장수를 줄인다(행 수 --tp-rows는 2로 고정).
   ⚠ D-171에서 **정수로 바꿨다**(예전엔 4.4·3.2·1.8 — 계속 흐르는 마퀴 시절, 끝 장이
     반쯤 걸쳐야 "더 있다"가 읽혔다). 지금은 몇 초에 한 번 딱딱 끊어 넘어가는 방식이라
     페이지마다 카드가 반쯤 잘려 있으면 오히려 어수선하다 — 매 세트가 정수 장으로 딱 채워진다.
   ⚠ **미디어쿼리**를 쓴다. `container-type`이 .tp-rail 자신에 걸려 있어 `@container`로
      자기 자신을 다시 꾸밀 수 없다(후손에만 적용된다 — D-159에서 겪었다). */
/* ⚠ 아래 세 줄은 **폴백**이다(D-282). 실제 장수는 paged-rail.js가 레일의 **실측 폭**에서
     정해 인라인 스타일로 덮는다 — 미디어쿼리는 «창»만 보아 사이드바가 먹은 폭을 모른다.
     JS가 안 도는 환경에서만 이 값이 쓰인다. 지우지 마라. */
@media (max-width: 1200px) { .tp-rail { --tp-per: 3; } }
@media (max-width: 900px)  { .tp-rail { --tp-per: 2; } }
@media (max-width: 600px)  { .tp-rail { --tp-per: 1; } }

/* ── 세무 Q&A (D-173) — '이런 것도 있어요' 타일 자리를 대신한다. 카드 3장, 채택된 답변만.
   (2026-08-09 사용자 지시: 4장→3장. 카드가 넓어진 만큼 제목·프로필사진·이름을 키운다 —
   본문 미리보기는 3줄 clamp·14px **그대로**다.)
   레이아웃: 제목 → 답변 미리보기(3줄로 자른다) → 작성자 줄(사진·이름 + **분야 라벨 우측 끝**).
   ⚠ 분야 라벨 자리는 두 번 옮겼다: 제목 **위** 배지 → 제목 줄 우측 끝 → (2026-08-09 사용자
      지시) **작성자 줄 우측 끝**. 되돌리지 마라 — 제목 줄에 있으면 긴 제목이 라벨과 폭을
      다퉈 제목이 늘 2줄로 잘렸다. QnaHomeRenderTest가 마크업 순서를 고정한다.
   ⚠ 그림자를 넣지 않는다 — 홈의 다른 카드(광고·세무사 레일)와 같은 규칙(D-167·D-168), hover는
      테두리 색으로만 신호를 준다.
   🔴 한 화면 장수(--qna-per: 3)와 HomeController.QNA_HOME_LIMIT(6)는 한 몸이다 —
      **상한이 한 화면 장수의 배수이면서 그보다 커야** 화살표로 넘길 다음 장이 생긴다.
      둘이 같았을 때(3/3) 트랙 폭이 정확히 한 화면이라 데스크톱에서 화살표가 영구 비활성이었다
      (실측 1280px: scrollWidth == clientWidth). QnaHomeRenderTest가 이 관계를 못박는다.
      ⚠ 상한은 천장일 뿐이라 실제 채택 답변이 3건 이하면 여전히 화살표가 사라진다 —
        눌러도 안 움직이는 버튼을 남기지 않는 쪽이 의도된 동작이다.

   ── 좌우 화살표 레일 (2026-08-09 사용자 지시) ────────────────────────────────
   격자였던 것을 **한 화면 --qna-per장짜리 가로 레일**로 바꿨다. 한 화면에 보이는 장수는
   그대로(3) — 보이는 그림은 같고, 넘길 수 있게만 됐다. 폭 계산은 광고 레일(.ad-rail)과
   같은 관용구(container-type + cqw)를 쓴다 — 두 레일이 다른 방식으로 폭을 잡으면 한쪽만
   어긋난다.
   ⚠ `.qna-home-grid`라는 이름은 그대로 둔다(격자가 아니게 됐어도) — 렌더 시험대와
     QnaHomeRenderTest가 이 클래스로 지면을 집는다. */
.qna-rail {
  /* ⚠ 화살표(.rail-arrow)의 기준은 여기가 아니라 paged-rail.js가 만드는 `.rail-shell`이다
     (버튼은 레일의 형제로 셸에 붙는다). 여기 position은 레일 안쪽 절대 위치 요소용으로만 남긴다. */
  position: relative;
  container-type: inline-size;
  --qna-gap: 16px;
  --qna-per: 3;
}
.qna-home-grid {
  display: grid; grid-auto-flow: column;
  grid-auto-columns: calc((100cqw - (var(--qna-per) - 1) * var(--qna-gap)) / var(--qna-per));
  gap: var(--qna-gap);
  overflow-x: auto; scroll-snap-type: x mandatory;
  scrollbar-width: none; -ms-overflow-style: none;
}
.qna-home-grid::-webkit-scrollbar { display: none; }
.qna-home-card { scroll-snap-align: start; }
.qna-home-card {
  display: flex; flex-direction: column; gap: 10px; padding: 20px;
  border: 1px solid var(--border); border-radius: var(--r-md); background: var(--surface);
  color: inherit; transition: border-color .15s ease, background .15s ease;
  /* 격자 칸의 기본 min-width는 auto — 안 끊기는 긴 낱말이 칸을 밀면 페이지가 가로로
     스크롤된다(세무시선 카드 .sisun-card2와 같은 이유). 제목은 질문자가 쓰는 자유 입력이다. */
  min-width: 0;
}
.qna-home-card:hover { border-color: var(--grey300); background: var(--grey50); }
/* ── 카드 안 — 시안 A «대표 질문 카드» (D-720, 사용자 확정 2026-09-09) ───────────────
   보내 준 휴대폰 화면의 문제는 «카드 가운데가 휑함»이었다. 카드·레일 문법은 그대로 두고 안을
   넷으로 채운다: 분야 칩·질문자 → 제목 → 질문 본문 2줄 → 답한 세무사 얼굴+N → 채택 한 마디 판 →
   세무사 행. 층마다 «항상 있는 값»이라 카드끼리 밀도가 같다(한 마디만 조건부 — 폴백 판이 선다).
   🔴 프로필은 여전히 카드 바닥에 선다(D-704) — 이제 그 몫을 `.qna-home-author{margin-top:auto}`가
      진다. 예전엔 제목의 margin-bottom:auto였는데, 층이 넷이 되면서 «남는 세로»는 한 마디 판과
      세무사 행 사이가 맞다(제목 바로 아래가 벌어지면 본문이 제목에서 떨어져 보인다).
   ⚠ 유채색은 새로 없다. 한 마디 판은 --surface-tint(#F8FBFF)인데 카드 hover 배경 --grey50(#F9FAFB)과
     거의 같아 hover에서 면이 사라진다 — 그래서 판에 1px #DDEBFF 테두리를 함께 둔다. */
/* 분야 칩 — 세무사 행 **우측 끝**(D-720 3판, 사용자 지시: 「채택된 답변」 자리에). 2판에서 제목 위로
   올렸다가 돌아왔다. margin-left:auto가 민다. ⚠ flex:none — 이름·상호가 길어도 칩이 먼저 찌그러지지
   않는다(줄어들 몫은 .qna-home-id가 진다). */
.qna-home-cat {
  flex: none; margin-left: auto; align-self: center; white-space: nowrap; font-size: 12.5px; font-weight: 700;
  color: var(--primary-pressed); background: var(--primary-light); border-radius: 6px; padding: 3px 8px;
}
.qna-home-title {
  min-width: 0; margin: 0;
  font-size: 20px; font-weight: 700; line-height: 1.35; letter-spacing: var(--ls-xl);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  word-break: keep-all;
}
/* 답한 세무사 얼굴 + N — 사진은 **최초 답변자** 한 장(D-720 2판) + «+N» 칩(가짜 얼굴을 그리지
   않는다). 얼굴 30px은 아래 프로필(채택 세무사) 40px보다 작아 «같은 사진 두 번»으로 안 읽힌다. */
/* 얼굴+N과 「세무사 N명이 답했어요」가 **한 덩어리로 오른쪽 끝**에 선다(D-720 5판, 사용자 지시
   「프로필사진+N 이미지도 우측 정렬」). 4판의 space-between(얼굴 왼쪽·글 오른쪽)에서 바꿨다.
   아래 세무사 행의 우측 끝 분야 칩과 오른쪽 선이 맞는다. */
.qna-home-faces { display: flex; align-items: center; justify-content: flex-end; gap: 10px; min-width: 0; }
.qna-home-stack { display: flex; flex: none; }
.qna-home-face { width: 30px; height: 30px; border-radius: 50%; object-fit: cover; border: 2px solid var(--surface); }
.qna-home-face-empty {
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--surface-alt); color: var(--text-secondary); font-size: 12px; font-weight: 700;
}
.qna-home-plus {
  display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 30px;
  border-radius: 50%; margin-left: -9px; border: 2px solid var(--surface);
  background: var(--primary-light); color: var(--primary-pressed); font-size: 11.5px; font-weight: 700;
}
/* 「세무사 N명이 답했어요」 한 줄. («상담 희망 N명»은 D-720 2판에서 걷었다.) */
.qna-home-n { min-width: 0; font-size: 14px; font-weight: 700; color: var(--text-primary); text-align: right; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 채택 한 마디 판 — 라벨 「홍** 님의 채택 한 마디」(사용자 지정 문구).
   🔴 본문에 min-height 44px(22px × 2줄)을 둔다 — 한 마디가 1줄이든 2줄이든 판 높이가 같아야
      카드끼리 세무사 행 위치가 안 흔들린다. 따옴표 글리프는 넣지 않는다(2줄 클램프가 닫는
      따옴표를 잘라 긴 한 마디에서만 짝이 안 맞는다). */
.qna-home-say { min-width: 0; padding: 12px 14px; border-radius: var(--r-md); background: var(--surface-tint); border: 1px solid #DDEBFF; }
.qna-home-say-l { display: block; font-size: 12px; font-weight: 700; color: var(--primary-pressed); margin-bottom: 4px; }
.qna-home-say-t {
  margin: 0; font-size: 14.5px; line-height: 22px; color: var(--text-primary); min-height: 44px;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
/* 한 마디가 없는 카드 — 같은 자리·같은 높이의 회색 판. 색만이 아니라 글자(「아직 채택 전이에요」)가 다르다. */
.qna-home-say-none { background: var(--surface-alt); border-color: var(--border); }
.qna-home-say-none .qna-home-say-l { color: var(--text-secondary); }
.qna-home-say-none .qna-home-say-t { color: var(--text-tertiary); }
/* 세무사 행 — 이름 + 상호명만(사용자 지시: 지역 제외). 바닥에 붙는다(margin-top:auto, D-704). */
.qna-home-author { display: flex; align-items: center; gap: 10px; margin-top: auto; padding-top: 12px; border-top: 1px solid var(--divider); }
.qna-home-avatar { width: 40px; height: 40px; border-radius: 50%; object-fit: cover; flex: none; }
.qna-home-avatar-empty {
  display: flex; align-items: center; justify-content: center;
  background: var(--primary-light); color: var(--primary); font-size: 15px; font-weight: 700;
}
.qna-home-id { min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.qna-home-name { min-width: 0; font-size: 15px; font-weight: 700; color: var(--text-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.qna-home-office { min-width: 0; font-size: 12.5px; color: var(--text-tertiary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 「채택된 답변」 상태 줄은 3판에서 걷었다 — 채택 여부는 한 마디 판이 말한다(있음 / 「아직 채택 전이에요」). */

@media (max-width: 900px) { .qna-rail { --qna-per: 2; } }

/* ── 세무시선 홈 섹션 (D-221) — 카드는 여기 없다.
   2026-08 카드 개편(이미지 상단 카드형): 홈·목록이 **같은 조각**(fragments/sisun-card.html)과
   **같은 CSS**(sisun-card.css — index.html이 home.css와 나란히 링크)를 쓴다. 카드·플레이스홀더는
   전부 그 파일에 있다 — 여기에 .sisun-card2 스타일을 다시 만들지 마라(두 벌이 되면 한쪽만 고친다).

   여기 있는 것은 **홈에서만 다른 것** 하나뿐이다: 좌우 화살표 레일(2026-08-09 사용자 지시).
   목록(/sisun)은 그대로 격자여야 하므로 `.sisun-rail` 아래로만 스코프한다 — sisun-card.css의
   `.sisun-grid2{ display:grid; grid-template-columns: repeat(2,1fr) }`를 홈에서만 덮어쓴다
   (선택자 특정도 0,2,0 > 0,1,0이라 파일 링크 순서와 무관하게 이긴다).
   ⚠ **한 화면 2장**(사용자 지시) — 격자였을 때의 한 행 장수와 같다. 늘리지 마라. */
.sisun-rail {
  position: relative;
  container-type: inline-size;
  --sisun-gap: 16px;
  --sisun-per: 2;
}
.sisun-rail .sisun-grid2 {
  display: grid; grid-auto-flow: column;
  /* 🔴 `grid-template-columns`를 **반드시 지운다**. sisun-card.css의 `repeat(2, 1fr)`이 그대로
     남아 있으면 앞 두 장만 그 1fr 칸에 들어가고 나머지가 grid-auto-columns로 흘러, 트랙 폭이
     한 화면보다 조금만 넓어진다 — 화살표를 눌러도 36px밖에 안 움직인다(실측으로 잡았다). */
  grid-template-columns: none;
  grid-auto-columns: calc((100cqw - (var(--sisun-per) - 1) * var(--sisun-gap)) / var(--sisun-per));
  gap: var(--sisun-gap);
  overflow-x: auto; scroll-snap-type: x mandatory;
  scrollbar-width: none; -ms-overflow-style: none;
}
.sisun-rail .sisun-grid2::-webkit-scrollbar { display: none; }
.sisun-rail .sisun-card2 { scroll-snap-align: start; }
/* 좁은 화면은 한 장씩 — 목록 격자의 768px 분기와 같은 값으로 묶는다. */
@media (max-width: 768px) { .sisun-rail { --sisun-per: 1; } }

/* ── 모바일 ─────────────────────────────────────────── */
@media (max-width: 768px) {
  /* ⚠ 이미지 전용 배너는 제외한다(:not). 이 min-height는 **글자가 들어가는 폴백 카드**를 위한
     값인데, 셀렉터 특이도가 같고 파일에서 뒤에 있어 `.hero-img-only { min-height: 0 }`을
     이겨 버렸다 — 좁은 화면에서 배너 카드가 240px로 늘어나 원고가 위아래로 잘렸다
     ("NOLDAY"가 "OLDA"로 잘리는 걸 실측으로 봤다). 비율은 원고가 정한다. */
  .hero-card:not(.hero-img-only) { min-height: 240px; }
  .hero-body { padding: 0 22px; }
  .hero-title { font-size: 23px; letter-spacing: var(--ls-xl); }
  .hero-photo { width: 52%; }
  .ad-grid { grid-template-columns: 1fr; }
  /* ⚠ `.qna-home-grid`는 여기서 빠졌다 — 2026-08-09에 레일이 되면서 `grid-auto-flow: column`이
     됐고, 그 위에 `grid-template-columns: 1fr`을 얹으면 **첫 카드만** 1fr 칸에 들어가고
     나머지는 grid-auto-columns로 흘러 한 화면 장수가 어긋난다. 장수는 --qna-per로만 정한다. */
  .qna-rail { --qna-per: 1; }
}

/* ── 광고 상품 표현 (D-124) ─────────────────────────────────────
   광고주가 산 '한 줄 멘트'와 '강조'. 강조를 늘리면 여기와 관리자 select,
   admin-ad-preview.js 를 함께 늘려야 한다.
   ⚠ 2026-08-09 카드 통일: **홈 카드(.pf-card)는 .ad-hl-*를 더 이상 붙이지 않는다** —
     홈의 광고 카드는 일반 카드와 완전히 같아야 하고, 차이는 「광고」 라벨뿐이다.
     .ad-hl-*를 아직 그리는 지면: 디렉토리 목록 카드(directory.html)·디렉토리 상단 레일
     (fragments/directory-ad-rail.html)·pro-ads.html·관리자 미리보기(admin-ad-preview.js).
     여기 규칙을 지우면 그쪽이 깨진다.
   ⚠ 어떤 강조를 써도 '광고' 라벨은 그대로 붙는다(D-013) — 강조로 라벨을 가리지 말 것.
   한 줄 멘트(.ad-tagline)는 홈 통일 카드에서도 유지하되 **일반 본문 톤**으로만 그린다. */
.ad-tagline {
  margin-top: 4px; font-size: 15px; line-height: 1.45; color: var(--text-secondary);
  display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical; overflow: hidden;
}
/* 카드 gap이 이미 간격을 준다 — 통일 카드에서는 위 margin이 겹쳐 두 배가 된다. */
.pf-card .ad-tagline { margin-top: 0; }

.ad-hl-outline { border-color: var(--primary); box-shadow: 0 0 0 1px var(--primary) inset; }
/* tint는 배경 대부분이 사진에 가려지는 카드(디렉토리 레일)에서는 테두리도 함께 준다 —
   그렇지 않으면 본문 여백에만 옅게 비쳐 강조가 잘 안 보인다. */
.ad-hl-tint { background: var(--primary-light); border-color: var(--primary); }
/* 리본 — 카드 우상단 모서리에 얇게. 카드가 overflow:hidden 이 아니어도 삐져나오지 않게 안쪽에 둔다. */
.ad-hl-ribbon { position: relative; overflow: hidden; }
.ad-hl-ribbon::after {
  content: 'AD'; position: absolute; top: 10px; right: -26px;
  transform: rotate(45deg); width: 96px; padding: 3px 0;
  background: var(--primary); color: #fff;
  /* ⚠ 스케일의 예외. 대문자 'AD' 두 글자라 오히려 벌려야 읽힌다(음수 자간은 붙어 보인다). */
  font-size: 11px; font-weight: 700; letter-spacing: .5px; text-align: center;
}
.ad-hl-none { /* 기본 카드 그대로 */ }

/* ── 이용 후기 (D-128) ─────────────────────────────────────────── */
/* ── 후기 밴드 (D-163) — 한 화면을 통째로 쓰는 구간 ─────────────────────────
   참고 지면 kmong.com '고객 만족도' 구간 실측(1280×720):
     섹션 790px(뷰포트의 110%) · 배경 #FAFAFC · 위아래 테두리 1px · 패딩 80/120
     제목 36px/700/44 가운데 · 별 줄 min-h 101px(위 여백 40) · 레일 위 여백 80
     카드 390×279(1.40:1) · 흰 배경 · 패딩 32 · 테두리 1px #F2F3F7 · 그림자 없음
     프로필 50×50 원형 · 이름 20/700/30 · 본문 16/400/24
     마퀴 gap 24 · translate(0)→(-50%) · 150s → 8682px/150s = **58px/s**

   ⚠ 참고 지면의 이동 거리 `-50%`는 **gap 보정이 없다** — 매 바퀴 gap의 절반(12px)씩
      어긋난다. 그대로 베끼지 않고 우리가 쓰는 정확한 식을 쓴다(D-159·D-162).
   ⚠ 배경 #FAFAFC는 새로 만들지 않고 기존 --grey50(#F9FAFB)을 쓴다. 차이는 눈에 안 보이고,
      색을 하나 더 늘리면 그때부터 어느 회색이 맞는지 아무도 모른다.
   ⚠ 이 배경+헤어라인 조합은 위쪽 `.situ-band`와 **한 벌**이다(2026-08-09) — 홈의 전폭 밴드는
      둘뿐이고 둘이 같은 얼굴이어야 한다. 한쪽만 바꾸지 말 것. */
.review-band {
  /* 전폭 — 본문 좌우 패딩을 되돌린다. 밴드가 화면을 가로질러야 '구간이 바뀌었다'가 읽힌다. */
  margin-inline: calc(var(--shell-pad) * -1);
  margin-top: var(--home-gap);
  /* 사용자 지시: **한 페이지 높이를 완전히** 쓴다. 내용이 더 길면 알아서 늘어난다. */
  min-height: 100vh;
  display: flex; flex-direction: column; justify-content: center;
  /* 🔴 위아래가 **같은 값**이어야 한다(D-262). 예전엔 80/120이었는데, `justify-content:center`가
     **패딩을 뺀 안쪽 상자**의 가운데에 내용을 놓기 때문에 그 40px 차이가 내용을 통째로
     20px 위로 밀었다 — 밴드 위 틈 229 vs 아래 틈 268로 벌어져 있었다(1440×1000 실측).
     한 페이지를 쓰는 구간이라 남는 자리가 크고, 그래서 **작은 비대칭도 크게 보인다.**
     ⚠ 여기에 위아래 다른 값을 다시 넣지 마라. 넓게 보이고 싶으면 --band-pad를 올릴 것
       (그러면 .situ-band도 같이 따라와 두 밴드가 계속 한 벌로 남는다). */
  padding: var(--band-pad) 0;
  background: var(--grey50);
  border-top: 1px solid var(--border); border-bottom: 1px solid var(--border);
  overflow: hidden;   /* 레일이 밴드 밖으로 새지 않게 */
}
.review-title {
  /* 참고 지면 36px. 좁은 화면에서 두 줄 제목이 화면을 잡아먹지 않게 clamp로 줄인다. */
  font-size: clamp(25px, 3.2vw, 36px); font-weight: 700; line-height: 1.24;
  letter-spacing: var(--ls-2xl); text-align: center; color: var(--text-primary);
  padding-inline: var(--shell-pad);
}

.review-score {
  margin-top: 40px; display: flex; flex-direction: column; align-items: center; gap: 14px;
  padding-inline: var(--shell-pad);
}
/* 별 — 회색 5개를 깔고 그 위에 파란 5개를 평점 비율만큼만 잘라 덮는다.
   ⚠ 개수를 반올림해 그리면 4.9와 5.0이 같은 그림이 되어 옆의 숫자와 어긋난다.
   ⚠ 색은 참고 지면의 초록이 아니라 **메인 파랑**이다(사용자 지시). */
.review-stars-gfx { position: relative; display: inline-block; --rs-size: clamp(38px, 5.4vw, 84px); }
.rs-row { display: flex; gap: clamp(5px, .7vw, 11px); }
.rs-row svg { width: var(--rs-size); height: var(--rs-size); display: block; flex: none; }
.rs-empty svg { fill: var(--grey200); }
.rs-fill {
  position: absolute; top: 0; left: 0; overflow: hidden;   /* width는 서버가 넣는다 */
}
.rs-fill svg { fill: var(--primary); }
.review-avg {
  display: flex; align-items: center; gap: 8px; margin: 0;
  font-size: 18px; font-weight: 600; letter-spacing: var(--ls-lg); color: var(--text-secondary);
}

/* ── 후기 격자 (R3) — 마퀴를 세운 자리 ─────────────────────────────────────
   🔴 예전에는 마퀴였다(D-162). 흘리려면 같은 카드를 `reviewSets`벌 복제해야 하는데,
      후기가 3~4장뿐이라 **같은 문장이 화면에 나란히 두 번** 보였다. 신뢰를 만드는 자리에서
      복제가 보이면 오히려 「지어낸 것」으로 읽힌다. 마퀴·복제·@keyframes를 함께 걷었다.
   ⚠ 되살리지 마라 — 후기 수가 늘어도 «흐르는 글»은 읽으려면 쫓아가야 한다(WCAG 2.2.2).
     많아지면 격자를 늘리거나 [더 보기]를 두는 쪽이 맞다.
   ⚠ `auto-fit`이 아니라 **`auto-fill`**이다: 후기가 한 장일 때 카드 하나가 밴드 폭을 다 먹지
     않게 한다(D-241에서 같은 실수를 배너 격자에서 겪었다). */
/* 카드 레일 — 광고 레일과 같은 마퀴(D-162 · D-279에서 복원). 인덱스는 두지 않는다.
   🔴 **한 번 격자로 바꿨다가 되돌렸다.** 요구서 R3은 「복제 세트를 돌리지 않는다」며 격자를
      지시했고 그대로 했는데(D-263), 실제 화면에서는 후기 3장이 한 줄에 놓이고 밴드가
      한 페이지(100vh)라 **가운데 282px만 차 있고 위아래가 199px씩 빈** 모양이 됐다(실측).
      사용자 판단으로 레일을 되살린다(D-279).
   ⚠ **복제가 다시 생긴다.** 흐르게 하려면 같은 카드를 `reviewSets`벌 이어 붙여야 한다 —
      후기가 적으면 같은 글이 화면에 두 번 이상 보인다. 그게 R3이 격자로 바꾼 이유였고,
      되돌린 지금은 **아는 채로 감수하는 것**이다. 후기가 늘면 자연히 옅어진다.
   ⚠ 복제본은 템플릿에서 `aria-hidden`으로 가린다 — 스크린리더가 같은 글을 여러 번 읽지 않게. */
.review-rail {
  margin-top: 56px; overflow: hidden;
  --rv-w: min(390px, 86vw);
  --rv-gap: 24px;
}
/* ⚠ 트랙에 padding을 주지 마라 — `translateX(-100%)`의 100%가 패딩을 포함해 이음매가 벌어진다
   (D-162에서 실측으로 잡았다). 여백은 바깥 `.review-rail`에 줄 것. */
.review-marquee {
  display: flex; gap: var(--rv-gap); width: max-content;
  animation: rv-roll var(--rv-dur, 29s) linear infinite;
}
.review-set { display: flex; gap: var(--rv-gap); }
@keyframes rv-roll {
  from { transform: translateX(0); }
  to   { transform: translateX(calc((-100% - var(--rv-gap)) / var(--rv-sets))); }
}
/* 후기는 **읽는** 내용이다 — 흘러가는 글을 쫓아 읽게 두면 안 된다(WCAG 2.2.2).
   ⚠ 이 두 줄을 지우지 마라. 마퀴를 되살린 이상 «멈출 방법»이 반드시 함께 있어야 한다. */
.review-rail:hover .review-marquee,
.review-rail:focus-within .review-marquee { animation-play-state: paused; }
@media (prefers-reduced-motion: reduce) {
  .review-marquee { animation: none; }
  .review-rail { overflow-x: auto; }
}
@media (max-width: 768px) { .review-rail { margin-top: 36px; --rv-gap: 12px; } }

.review-card {
  flex: 0 0 var(--rv-w);
  /* 비율을 실측값 그대로 지킨다(사용자 지시) — 좁은 화면에서도 같은 모양으로 줄어든다. */
  aspect-ratio: 390 / 279;
  display: flex; flex-direction: column; gap: 18px;
  padding: clamp(20px, 2.2vw, 32px);
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-md);
  overflow: hidden;
}
/* 카드 상단 = **후기를 받은 세무사**(사용자 지시). 예전엔 여기가 의뢰인이었다. */
.rv-top { display: flex; align-items: center; gap: 14px; }
.rv-avatar {
  flex: none; width: 50px; height: 50px; border-radius: var(--r-full);
  background: var(--primary-light); color: var(--primary);
  display: inline-flex; align-items: center; justify-content: center;
  /* ⚠ 한 글자를 가운데 놓는 자리라 자간 0이다(아바타와 같은 이유, D-161). */
  font-size: 20px; font-weight: 700; letter-spacing: 0;
  /* 사진이 들어오면 원형 밖으로 새지 않게 자른다(이니셜일 때는 아무 영향 없다). */
  overflow: hidden;
}
.rv-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.rv-id { min-width: 0; }
/* ⚠ 한 줄로 고정한다. 이름이 길어 두 줄이 되면 카드 비율(390:279)이 그대로라
   맨 아래 의뢰인 줄이 밀려 잘린다. */
.rv-who {
  font-size: 20px; font-weight: 700; line-height: 1.5; letter-spacing: var(--ls-xl);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* 이름 옆 직함 — 이름보다 약하게. 이게 있어야 위(세무사)와 아래(의뢰인) 이름이
   같은 사람으로 읽히지 않는다. */
.rv-role { font-size: 13px; font-weight: 600; color: var(--text-tertiary); letter-spacing: var(--ls-md); }
.rv-rating { display: flex; align-items: center; gap: 4px; font-size: 14px; font-weight: 600; color: var(--text-tertiary); }
.rv-rating svg { width: 15px; height: 15px; fill: var(--primary); display: block; }
.rv-body {
  margin: 0; font-size: 16px; line-height: 1.5; color: var(--text-secondary);
  /* 🔴 **부호 / 본문 / 부호** 세 칸짜리 세로 배치다(D-301). 클램프는 .rv-text가 가진다 —
     여기 두면 부호 줄까지 세어 본문이 그만큼 더 잘린다.
     ⚠ overflow를 hidden으로 두지 마라. 부호 글리프는 조인 줄 높이보다 커서 살짝 넘치는데,
       여기서 자르면 위아래가 뭉텅 잘린다. 카드(.review-card)가 이미 overflow:hidden이라
       카드 밖으로 새지 않는다. */
  display: flex; flex-direction: column;
  flex: 1 1 auto; min-height: 0;
}

/* 본문 — **잘리는 것은 여기뿐**이다.
   🔴 `flex: 0 0 auto`가 이 배치의 안전장치다. 처음에 `1 1 auto`로 두었더니, 카드 높이가
      고정(390:279)이라 남는 자리가 모자란 순간 **본문이 높이 0으로 사라졌다**(실측 —
      후기 글자가 통째로 없어졌다). 줄어들지 못하게 하면 최악의 경우 닫는 부호가 조금
      잘릴 뿐 글은 남는다. **옳은 실패 쪽으로 기울인다.**
   ⚠ 줄 수 4 → 3. 부호가 각각 자기 줄을 가져간 만큼 본문이 한 줄을 내줬다 — 그게 이
     배치의 값이다. 4로 되돌리면 아래 「…님이 남긴 후기」가 카드 밖으로 밀려 사라진다. */
.rv-text {
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
  flex: 0 0 auto;
}

/* 따옴표 줄 — 장식이라 **글자 한 줄만큼 자리를 먹지 않게** 줄 높이를 조인다.
   ⚠ `line-height: 0`을 쓰지 마라. 인라인 시절의 값인데, 블록이 된 지금은 0이면 글자가
     자기 상자 밖으로 나가 **보이지 않는다**(여는 부호가 통째로 사라졌다 — 직접 겪었다).
   ⚠ 글꼴은 세리프다(D-299). 본문 글꼴의 인용부호는 가는 사선이라 눈금(〃)처럼 읽힌다. */
.rv-quote {
  flex: none; display: block;
  font-family: Georgia, "Times New Roman", "Nanum Myeongjo", serif;
  color: var(--primary); opacity: 0.38; font-weight: 700;
  font-size: 1.9em; line-height: 0.62;
}
/* 여는 부호는 왼쪽 위, 닫는 부호는 **오른쪽 아래** — 그래야 «감쌌다»는 모양이 완성된다. */
.rv-quote-close { text-align: right; }
/* 카드 하단 = **후기를 쓴 의뢰인 닉네임**(사용자 지시). 보조 위계라 작고 흐리게,
   그리고 절대 잘리지 않게 flex:none으로 바닥에 고정한다. */
.rv-client {
  flex: none; margin: 0; font-size: 13px; line-height: 1.4;
  color: var(--text-tertiary); letter-spacing: var(--ls-md);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* ⚠ `.review-note`(하단 예시 고지)는 사용자 지시로 제거했다(D-164). 되살릴 일이 생기면
   마크업과 함께 이 자리에 다시 넣을 것 — 레일 아래 가운데 정렬 13px 회색 한 줄이었다. */

@media (max-width: 768px) {
  .review-band { margin-inline: -16px; padding: var(--band-pad) 0; }
  .review-score { margin-top: 28px; gap: 10px; }
  .review-avg { font-size: 15px; }
  /* 하단 의뢰인 줄이 한 칸을 더 먹는다 — 카드 비율(390:279)은 그대로라 좁은 화면에서는
     줄 간격을 좁혀 그 자리를 만든다. 18로 되돌리면 본문 마지막 줄이 글자 중간에서 잘린다. */
  .review-card { gap: 12px; }
  .rv-avatar { width: 42px; height: 42px; font-size: 17px; }
  .rv-who { font-size: 17px; letter-spacing: var(--ls-lg); }
  .rv-role { font-size: 12px; }
  /* 카드가 작아지면 본문 줄 수도 줄여야 비율 안에 들어간다.
     🔴 **클램프는 이제 .rv-text에 건다**(D-301). `.rv-body`는 부호/본문/부호를 담는
        세로 flex라 `-webkit-box`가 아니고, 거기 클램프를 걸면 **아무 일도 일어나지 않는다** —
        모바일에서 본문이 안 잘려 카드를 뚫는다. 글자 크기는 그대로 .rv-body가 정한다. */
  .rv-body { font-size: 14px; }
  .rv-text { -webkit-line-clamp: 3; }
  .rv-client { font-size: 12px; }
}

/* 가장 좁은 화면(320px대) — 카드 높이가 197px까지 줄어 본문 네 줄이 들어가지 않는다.
   ⚠ 이 구간을 지우면 마지막 줄이 **글자 중간에서 가로로 잘린** 채 보인다(실측으로 잡았다).
     후기 레일 묶음 수 계산(HomeController.REVIEW_CARD_MIN)도 이 폭을 기준으로 잡혀 있다. */
@media (max-width: 359px) {
  .rv-text { -webkit-line-clamp: 2; }   /* ⚠ .rv-body가 아니다 — 위 주석(D-301) */
}

/* ⚠ 예전에 여기 `@media (max-width: 768px) { .hero-wrap { --hero-side: 28px } }`가 있었다.
   좁은 화면에서 옆 카드를 걸쳐 보이게 하려던 것인데, 이제는 어느 폭에서도 한 장만
   보여야 하므로 지웠다(D-161). 되살리면 모바일에서만 이웃이 다시 나타난다. */

/* ── 지금 상담 가능 (D-129) ─────────────────────────────────── */
/* ⚠ `.live-dot`('상담 가능' 초록 배지)은 지웠다(D-169) — 세로 목록의 오른쪽 칸에만 쓰던
   것이고, 카드 레일에는 그 칸이 없다. 접속 상태는 카드 본문의 점(.tp-region .av-dot)이 말한다. */
.online-empty { margin-top: 12px; text-align: center; padding: 28px 20px; }

/* ══ 메인 기능 카드 3장 (D-137) ═══════════════════════════════════
   지역 격자 + 분야 카테고리 격자가 있던 자리. 이 셋이 서비스의 전부라, 홈에서
   가장 큰 덩어리를 차지한다.

   그림은 전부 인라인 SVG다 — 벡터라 레티나·4K에서도 그대로 선명하고, 카드마다
   래스터 이미지를 얹는 것보다 가볍다(이미지 요청 0건).

   3D는 `perspective`를 **부모**(.mainc-grid)에 두고 자식 카드를 회전시킨다. 카드마다
   perspective를 주면 각 카드가 자기 중심으로만 소실점을 잡아 나란히 놓았을 때 어긋나 보인다. */
/* 배너 바로 아래 블록 — 사용자가 콕 집은 자리다. 24px이라 배너에 붙어 있었다.
   ⚠ `--s-2xl`(24px)로 되돌리지 마라. 다른 섹션과 같은 40px이어야 리듬이 맞는다. */
.mainc-sec { margin-top: var(--home-gap); }
.mainc-grid {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px;
  perspective: 1400px;
}

.mainc {
  --rx: 0deg; --ry: 0deg;          /* JS가 포인터 위치로 채운다 */
  --px: 0px;  --py: 0px;           /* 그림 시차(parallax) */
  --mx: 50%;  --my: 40%;           /* 광택 위치 */
  --lift: 0px;
  position: relative; display: flex; flex-direction: column; justify-content: space-between;
  aspect-ratio: 5 / 7; padding: 26px 24px;
  border-radius: var(--r-xl); color: #fff; isolation: isolate;
  transform-style: preserve-3d;
  transform: translateY(var(--lift)) rotateX(var(--rx)) rotateY(var(--ry));
  transition: transform .5s cubic-bezier(.22,.61,.36,1), box-shadow .5s cubic-bezier(.22,.61,.36,1);
  box-shadow: 0 2px 6px rgba(11, 27, 61, .10), 0 12px 28px rgba(11, 27, 61, .12);
}
/* 넓은 화면에서는 **비율 대신 높이를 고정**한다(D-154).
   본문이 전폭이 되면서 1920 화면에서 한 장이 590×826까지 부풀어 첫 화면을 통째로 먹었다(실측).
   ⚠ `max-height`로 누르면 안 된다 — aspect-ratio가 살아 있으면 높이 상한에 맞춰 **폭까지
      328px로 같이 줄어** 카드 사이가 휑하게 벌어진다(실측). 비율을 꺼야 트랙을 채운 채 눕는다.
   ⚠ 이 블록은 반드시 `.mainc`**뒤에** 둔다 — 미디어쿼리는 특정도를 올려 주지 않아서,
      앞에 두면 뒤따르는 `aspect-ratio: 5/7`이 이겨 아무 일도 일어나지 않는다(실측으로 겪었다).
   좁은 화면(1080 미만)은 기존 5:7 그대로다 — 그 폭에서는 비율이 이미 460px 근처를 준다. */
@media (min-width: 1080px) {
  .mainc { aspect-ratio: auto; height: 460px; }
}

/* 포인터를 올리면 살짝 떠오르고, 놓는 동안은 JS가 기울기를 실시간으로 준다.
   전환 시간을 짧게 바꿔 손을 따라오는 느낌을 만든다(놓으면 다시 길어져 부드럽게 복귀). */
.mainc:hover, .mainc:focus-visible {
  --lift: -10px;
  transition: transform .12s ease-out, box-shadow .3s ease;
  box-shadow: 0 6px 14px rgba(11, 27, 61, .14), 0 26px 56px rgba(11, 27, 61, .22);
}
.mainc:focus-visible { outline: 3px solid #fff; outline-offset: 3px; }
.mainc:active { --lift: -4px; }

/* 배경면 — 그라디언트·그림·광택이 여기 갇힌다. 라운드 클리핑은 이 층에서만 하고
   부모(.mainc)에는 overflow를 걸지 않는다: overflow:hidden은 preserve-3d를 무력화해
   자식의 translateZ가 통째로 죽는다. */
.mainc-face {
  position: absolute; inset: 0; z-index: -1;
  border-radius: inherit; overflow: hidden;
  transform: translateZ(0);
}
.mainc-1 .mainc-face { background: linear-gradient(150deg, #2F80FF 0%, #1B64DA 52%, #1348AE 100%); }
.mainc-2 .mainc-face { background: linear-gradient(150deg, #2B3EC7 0%, #1E2A96 50%, #131C6B 100%); }
.mainc-3 .mainc-face { background: linear-gradient(150deg, #12B39A 0%, #0A8C7E 52%, #06655E 100%); }

/* 그림 — 카드 아래쪽 절반을 채우고, 포인터를 따라 아주 조금 어긋난다(시차). */
.mainc-art {
  position: absolute; left: 50%; top: 52%;
  width: 78%; height: auto; pointer-events: none;
  transform: translate(-50%, -46%) translate(var(--px), var(--py));
  transition: transform .5s cubic-bezier(.22,.61,.36,1);
}
.mainc:hover .mainc-art { transition: transform .12s ease-out; }
/* ①은 심볼(프로필 카드 한 장)이 ③ 핀보다 화폭을 덜 채워 한 치수 키운다(D-608 보정). */
.mainc-1 .mainc-art { width: 88%; }

/* 광택 — 포인터 자리에 빛이 고인다. 3D 기울기만으로는 평면이 도는 것에 그치고,
   빛이 함께 움직여야 표면이 있다고 읽힌다. */
.mainc-glare {
  position: absolute; inset: 0; pointer-events: none; opacity: 0;
  background: radial-gradient(420px circle at var(--mx) var(--my),
              rgba(255,255,255,.30), rgba(255,255,255,.06) 45%, transparent 70%);
  transition: opacity .35s ease;
}
.mainc:hover .mainc-glare, .mainc:focus-visible .mainc-glare { opacity: 1; }

/* 글자층 — 배경보다 앞으로 끌어내야 기울일 때 깊이가 보인다. */
.mainc-top, .mainc-bottom { position: relative; display: flex; flex-direction: column; }
.mainc-top { gap: 10px; transform: translateZ(48px); }
.mainc-bottom { gap: 14px; transform: translateZ(28px); }

.mainc-live {
  align-self: flex-start; display: inline-flex; align-items: center; gap: 6px;
  font-size: 12px; font-weight: 700; letter-spacing: var(--ls-sm);
  background: rgba(255, 255, 255, .18); border: 1px solid rgba(255, 255, 255, .28);
  border-radius: var(--r-full); padding: 5px 11px 5px 9px;
  backdrop-filter: blur(6px);
}
.mainc-live::before {
  content: ''; width: 7px; height: 7px; border-radius: 50%; background: #4AE3A6;
  box-shadow: 0 0 0 3px rgba(74, 227, 166, .28);
  animation: mainc-pulse 2s ease-in-out infinite;
}
@keyframes mainc-pulse {
  0%, 100% { box-shadow: 0 0 0 3px rgba(74, 227, 166, .28); }
  50%      { box-shadow: 0 0 0 6px rgba(74, 227, 166, .10); }
}

.mainc-title {
  /* 자간은 스케일에서 고른다(D-161) — 예전 -.7px는 같은 화면의 다른 제목(-.2·-.3)과 어긋나
     혼자 다른 서체처럼 보였다. */
  font-size: 26px; font-weight: 700; line-height: 1.28; letter-spacing: var(--ls-2xl);
  text-shadow: 0 1px 12px rgba(6, 20, 48, .28);
}
.mainc-desc {
  font-size: 15px; line-height: 1.55; color: rgba(255, 255, 255, .88);
  text-shadow: 0 1px 10px rgba(6, 20, 48, .3);
}
/* 화살표는 hover 때만 밀려 나간다 — '누를 수 있다'를 말로 하지 않고 움직임으로 말한다.
   ⚠ 예전에 의사요소 두 개(가로선 + 회전한 세로선)로 그렸다가 회전 기준점이 어긋나
      찌그러진 갈고리가 나왔다. 선을 손으로 맞추지 말고 path 하나로 그린다. */
.mainc-go {
  display: inline-flex; align-items: center; gap: 8px; align-self: flex-start;
  font-size: 15px; font-weight: 700;
}
.mainc-go svg {
  width: 26px; height: 26px; flex: 0 0 26px; padding: 5px; border-radius: 50%;
  background: rgba(255, 255, 255, .2); border: 1px solid rgba(255, 255, 255, .3);
  fill: none; stroke: #fff; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round;
  transition: transform .3s cubic-bezier(.22,.61,.36,1), background .3s ease;
}
.mainc:hover .mainc-go svg { transform: translateX(5px); background: rgba(255, 255, 255, .34); }

@media (max-width: 900px) {
  /* 3장이 좁아지면 글자가 갇힌다 — 가로 스크롤로 바꾸고 카드 크기는 지킨다(홈 배너와 같은 규약). */
  .mainc-grid {
    display: flex; gap: 14px; overflow-x: auto; scroll-snap-type: x mandatory;
    scrollbar-width: none; padding-bottom: 4px; perspective: none;
  }
  .mainc-grid::-webkit-scrollbar { display: none; }
  .mainc { flex: 0 0 min(300px, 78%); scroll-snap-align: start; padding: 22px 20px; }
  .mainc-title { font-size: 23px; letter-spacing: var(--ls-xl); }
}

/* 손가락 입력·모션 최소화 환경에서는 기울이지 않는다. 기기가 흔들리는 것처럼 보일 뿐이다. */
@media (prefers-reduced-motion: reduce) {
  .mainc, .mainc-art, .mainc-go svg { transition: none; }
  .mainc { transform: none; }
  .mainc:hover { --lift: 0px; }
  .mainc-live::before { animation: none; }
}

/* ── 세무사 찾기 상단 광고 레일 (D-189 §3.2) ────────────────────────────────
   조각: templates/fragments/directory-ad-rail.html — /directory와 /directory/map이 함께 쓴다.
   ⚠ **홈 파일에 두는 이유.** 이 카드가 `.ad-label`(D-013 표시 의무)·`.ad-tagline`(D-124)·
     `.ad-hl-*`(강조)·`.sec-head`를 **그대로** 쓴다. 파일을 나누면 같은 광고 스타일이 두 벌이
     되어 라벨 하나 고칠 때 한쪽만 고치게 된다. 대신 /directory/map은 home.css를 링크해야
     한다(조각의 `assets` 참고 — /directory는 이미 링크한다).
   ⚠ 카드 언어는 홈(.tp-card·.ad-card)이 아니라 **디렉토리 목록 카드(.tax-card)** 쪽을 따른다 —
     바로 아래 붙는 것이 그 목록이라, 사진·글자·그림자가 다르면 두 덩어리가 남처럼 보인다.
     그림자를 지우지 않는 것도 같은 이유다: D-167·D-168의 "배너 옆에서 광고 카드만 떠 보인다"는
     홈의 사정이고, 여기 이웃은 그림자가 있는 `.card`(.tax-card)다. */
.dad-sec { margin-bottom: var(--s-2xl); }

/* ⚠ 바깥에 overflow:hidden을 걸어 **페이지 가로 스크롤이 절대 생기지 않게** 한다 — 넘치는
     장수는 `.dad-track` 안쪽에서만 흐른다.
   ⚠ 카드 폭은 cqw(컨테이너 폭) 기준이다. 사이드바가 접히고 펴지며 본문 폭이 바뀌어도
     "한 화면 = 정수 장"이 유지돼야 자동 넘김(paged-rail.js)의 '한 세트' 가정이 안 깨진다
     (D-171에서 소수 장수를 정수로 되돌린 것과 같은 이유). */
.dad-rail { overflow: hidden; container-type: inline-size; --dad-gap: 12px; --dad-per: 1; }
.dad-track {
  display: flex; gap: var(--dad-gap);
  overflow-x: auto; scroll-snap-type: x mandatory;
  scrollbar-width: none; -ms-overflow-style: none;
}
.dad-track::-webkit-scrollbar { display: none; }

.dad-card {
  flex: 0 0 calc((100cqw - (var(--dad-per) - 1) * var(--dad-gap)) / var(--dad-per));
  scroll-snap-align: start; min-width: 0; padding: 14px 16px;
  transition: border-color .15s ease;
}
/* 카드 안에 링크가 둘이라, hover만 두면 키보드로 왔을 때 지금 어느 카드에 있는지 알 수 없다. */
.dad-card:hover, .dad-card:focus-within { border-color: var(--grey300); }
/* `.ad-label`은 홈에서 flex 행 오른쪽 끝에 붙던 것이라 margin-left:auto를 갖는다. 여기서는
   블록 안의 인라인이라 그 값이 무해하지만, 나중에 이 줄을 flex로 바꾸는 사람이 라벨이
   오른쪽으로 튀는 이유를 못 찾게 되므로 여기서 명시적으로 되돌려 둔다. */
.dad-card .ad-row { margin-bottom: 8px; }
.dad-card .ad-label { margin-left: 0; }

.dad-body { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
/* 카드 본문 링크 — 사진+정보 한 덩어리. 카드 전체를 덮는 오버레이는 쓰지 않는다(조각 주석). */
/* ⚠ 사진은 **위로** 붙인다(align-items:center 아님). 좁은 화면에서는 정보가 다섯 줄까지
   늘어나는데, 가운데 정렬이면 사진이 아래로 내려가 이름 줄이 사진보다 위에 뜬다 —
   목록 카드(.tax-card)도 같은 이유로 flex-start다. */
.dad-main { flex: 1 1 240px; min-width: 0; display: flex; align-items: flex-start; gap: 12px; color: inherit; }
.dad-photo { width: 96px; height: 96px; font-size: 34px; border-radius: var(--r-lg); }
.dad-info { flex: 1; min-width: 0; }

.dad-head { display: flex; align-items: center; flex-wrap: wrap; gap: 4px 8px; min-width: 0; }
/* 이름이 길어도 배지·상태·평점을 밀어내지 않게 — min-width:0이 없으면 flex item이 줄어들지
   않아 말줄임(ellipsis)이 아예 걸리지 않는다(.tp-id·.ad-id와 같은 관행). */
.dad-card .tax-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dad-card .badge, .dad-presence { flex: none; }
.dad-rating {
  margin-left: auto; flex: none; display: flex; align-items: center; gap: 5px;
  font-size: 13px; color: var(--text-secondary); white-space: nowrap;
}
.dad-rating .star { color: var(--warning); font-weight: 700; }
.dad-sub { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* [상담 예약] — 본문 링크의 **형제**다(<a> 중첩 금지, 조각 주석 참고). */
.dad-cta { flex: none; margin-left: auto; }

/* **기본은 한 화면 한 장이다.** 두 장으로 나누면 정보 칸이 240px 남짓으로 눌려 이름 줄
   (이름·배지·접속상태·평점)이 두 줄로 접힌다 — 1280 실측에서 정확히 그랬다(정보 칸 237px).
   가로로 넓게 쓰는 것이 이 지면의 요지이므로, 두 장은 **정보 칸이 400px을 넘기는 폭**에서만 쓴다
   (사이드바 256 + 좌우 여백을 뺀 값 기준 — 1400에서 정보 칸 약 415px).
   ⚠ `@container`로 자기 자신을 다시 꾸밀 수 없어(container-type이 .dad-rail 자신에 걸려 있고
     컨테이너 쿼리는 후손에만 적용된다 — D-159에서 겪었다) 미디어쿼리를 쓴다. 그래서 사이드바가
     접힌(rail) 상태의 여유 폭까지는 못 본다 — 한 장으로 남을 뿐 깨지지는 않는다. */
@media (min-width: 1400px) { .dad-rail { --dad-per: 2; } }

@media (max-width: 600px) {
  .dad-sec { margin-bottom: var(--s-lg); }
  .dad-photo { width: 76px; height: 76px; font-size: 28px; }
  /* 사진+정보가 한 줄을 다 쓰고 버튼은 아래 줄 전체를 쓴다. 한 줄에 밀어 넣으면 정보 칸이
     150px 남짓으로 눌려 이름·사무소가 전부 말줄임으로 끝난다(375px 실측). */
  .dad-main { flex: 1 1 100%; }
  /* 줄바꿈된 뒤에도 margin-left:auto가 남아 있으면 값이 혼자 오른쪽에 떨어져 어느 줄에
     속한 것인지 안 읽힌다. */
  .dad-rating { margin-left: 0; }
  .dad-cta { margin-left: 0; width: 100%; }
}

/* ── «지금 상담노트» 띠 (D-670) — 배너와 메인 카드 3장 사이. 홈·빠른 상담 공통
   (fragments/brief-current.html). 세 카드가 전부 이 노트로 열리므로 카드보다 먼저 보인다.
   ⚠ 섹션 리듬은 .cur-brief-sec의 --home-gap 하나 — 숫자를 적지 마라(파일 머리 규칙). */
.cur-brief-sec { margin-top: var(--home-gap); }
.cur-brief {
  display: flex; align-items: center; gap: 14px;
  padding: 14px 18px; border: 1px solid var(--border); border-radius: var(--r-lg);
  background: var(--surface);
}
.cur-brief-ico {
  flex: 0 0 40px; width: 40px; height: 40px; display: grid; place-items: center;
  border-radius: 12px; background: var(--primary-light); color: var(--primary);
}
.cur-brief-ico svg {
  width: 22px; height: 22px; stroke: currentColor; fill: none;
  stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round;
}
.cur-brief-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.cur-brief-cap { font-size: 12px; font-weight: 600; color: var(--text-tertiary); }
.cur-brief-line { display: flex; align-items: baseline; gap: 8px; min-width: 0; }
.cur-brief-title {
  font-size: 16px; font-weight: 700; color: var(--text-primary); min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cur-brief-cat {
  flex: none; font-size: 12px; font-weight: 600; color: var(--primary);
  background: var(--primary-light); border-radius: 999px; padding: 2px 8px;
}
.cur-brief-view { flex: none; font-size: 13px; color: var(--text-tertiary); white-space: nowrap; }
.cur-brief-lead { font-size: 13px; color: var(--text-secondary); }
.cur-brief-acts { flex: none; }
.cur-brief-chg { font-size: 14px; font-weight: 700; color: var(--primary); white-space: nowrap; }
.cur-brief-chg:focus-visible, .cur-brief-view:focus-visible {
  outline: 2px solid var(--primary); outline-offset: 3px; border-radius: 6px;
}
/* 없을 때 — 캡션이 제목 자리에 선다(굵기로 가른다, 색 아님). */
.cur-brief-off .cur-brief-cap { font-size: 15px; font-weight: 700; color: var(--text-primary); }
.cur-brief-cta { flex: none; }
@media (max-width: 640px) {
  .cur-brief { flex-wrap: wrap; padding: 12px 14px; gap: 10px 12px; }
  .cur-brief-body { flex: 1 1 calc(100% - 52px); }
  .cur-brief-acts { flex-basis: 100%; text-align: right; }
  .cur-brief-cta { flex-basis: 100%; width: 100%; }
}

/* ── 좁은 화면 세로 리듬 (D-166 · D-262) ───────────────────────────────────
   참고 지면 실측(375×812): 섹션 사이 **16**. 그 값은 그대로 둔다.

   D-262에서 **선언 방식만 바꿨다.** 예전엔 여기서
     `.section, .mainc-sec, .situ-band, .review-band { margin-top: 16px }`
   처럼 대상을 하나하나 적었다. 그래서 목록에서 `.review-band`를 빠뜨렸을 때
   마지막 구간만 40px로 남아 리듬이 거기서 끊겼다(실측 16,16,16,16,40).
   지금은 **변수 두 개만 다시 정의한다** — 홈의 모든 블록이 이미 그 변수를 보고 있으므로
   «목록에서 빠뜨린다»는 실수가 구조적으로 불가능하다. 새 블록을 추가해도 자동으로 따라온다.

   ⚠ **이 블록은 파일 맨 끝에 있어야 한다.** 미디어쿼리는 특이도를 올리지 않는다 —
     위쪽 `:root`보다 앞에 두면 뒤에 오는 56px이 이겨서 좁은 화면에서도 56px이 적용된다.
     실제로 예전에 그렇게 넣었다가 잡았다. */
@media (max-width: 768px) {
  :root {
    --home-gap: 16px;
    /* 밴드 안쪽도 함께 줄인다. 예전엔 situ 20 · review 56/72로 제각각이라
       좁은 화면에서 보이는 틈이 16,16,36,36,16,72,88,16이었다. */
    --band-pad: 20px;
  }
  /* 배너만 리듬에서 벗어난다(위 .hero-wrap 주석의 ⓐ·ⓑ와 같은 이유).
     대칭: 위 = .main 위 패딩 16 + 32 = 48, 아래 = 48. 화면 맨 위에서 56 + 48 = 104px.
     ⚠ 여기서 아래를 --home-gap(16)으로 내리지 마라 — 배너는 큰 그림 한 장이라
       16px만 남기면 다음 섹션 카드가 배너에 달라붙는다.
     🔴 `:not(.situ-rail)`을 떼지 마라 — 밴드 안 레일이 이 48px을 물어 간다(위 주석 참고). */
  .hero-wrap:not(.situ-rail) { margin-top: 32px; margin-bottom: 48px; }
}

/* ══ 광고 슬라이드 (D-453) — 프리미엄(3명×3장)·지금 상담(6명×3장) 공용. ══
   🔴 JS 없이는 전 슬라이드가 세로로 쌓여 다 보인다(완전한 폴백) — .is-carousel이 붙어야
      한 장씩 보인다(ad-slides.js). 마크업 hidden 금지. */
.ad-slides { position: relative; }
.ad-slide {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px;
  margin-top: 12px;
  /* 🔴 **줄이 모자라는 장에서 카드가 세로로 늘어나던 것**(D-707, 사용자 신고 「카드가 길게
     늘어져 보인다」). 아래 D-698 수정이 모든 장을 **같은 격자 칸에 겹쳐** 두는데, 그러면
     장 하나하나가 «가장 큰 장»의 높이로 늘어난 칸을 받는다. `align-content`의 기본값
     `normal`은 격자에서 **stretch**라, 그 남는 세로를 `auto` 행들이 나눠 먹는다 —
     카드가 그만큼 키워진다.
     실측(모바일 한 열, 온라인 18명 = 8·8·2): 8장 장은 카드 212px인데 **2장 장은 884px**.
     사진칸(.on-th)이 `align-items: stretch`로 행 높이를 그대로 받아 사진이 통짜로 늘어났다.
     ⚠ 이건 «드문 경우»가 아니라 **매번**이다 — 마지막 장은 늘 나머지 인원만 담는다
       (18 % 8 = 2). 열 수가 4→2→1로 바뀌면 줄 수도 함께 바뀌어 나누어떨어지게 만들 수도 없다.
     ⇒ `start`로 못박는다: 행은 내용 높이 그대로, 남는 세로는 **아래에 남긴다**.
       겹쳐 놓은 칸의 높이(=지면 높이)는 그대로라 D-698의 «장을 갈아 끼워도 높이가 안 변한다»는
       하나도 안 깨진다. 두 수정은 서로 다른 축을 잡는다 — D-698은 «칸의 높이», 이것은 «칸 안의 배치».
     ⚠ 프리미엄 장(.ad-slide-photo, 9명 = 5+4)도 같은 병이었다. 거기는 `.fp-photo`가
       `aspect-ratio`를 들고 있어 사진이 늘지는 않았지만 카드 아래에 빈 자리가 생겼다. */
  align-content: start;
}
/* 🔴 '지금 상담 가능한 세무사'는 **4열**이다(D-682) — 2행이면 한 장에 8명.
   ⚠ HomeController.ONLINE_PER_SLIDE(8)와 **짝**이다. 한쪽만 바꾸면 마지막 줄이 빈다. */
.ad-slide.wide { grid-template-columns: repeat(4, 1fr); }
/* 🔴 **장을 갈아 끼워도 지면 높이가 변하지 않는다** (D-698, 사용자 신고).
   예전에는 `display: none ↔ grid`로 갈아 끼웠다 — 그러면 **컨테이너 높이가 «지금 켜진 장»의
   높이**가 된다. 그런데 마지막 장은 남는 인원만 담는다: 「지금 상담 가능한 세무사」는
   ONLINE_SLOTS 18을 8명씩 나눠 **8·8·2**라, 마지막 장은 늘 2명 = 한 줄이다
   (실측 334px → 170px). 3초마다 지면이 **164px 줄었다 늘고**, 그 아래 것들이 통째로 위아래로
   튀었다 — 바로 아래가 후기 밴드라 사용자에게는 「리뷰 영역이 새로고침되는」 것으로 보였다.
   ⚠ 이건 드문 경우가 아니라 **매번**이다(18 % 8 = 2). 인원 수를 고쳐 나누어떨어지게 만드는
     길도 있지만, 열 수는 화면 폭에 따라 4→2→1로 바뀌어(아래 미디어쿼리) 줄 수도 함께 바뀐다.
     그래서 «나누어떨어지게»로는 못 막는다 — 구조로 막아야 한다.

   해법: 모든 장을 **같은 격자 칸에 겹쳐** 두고 보이기만 갈아 끼운다. 높이는 언제나 가장 큰 장이다.
   ⚠ `display: none`이 아니라 `visibility: hidden`인 이유 — display:none은 자리를 만들지 않아
     겹쳐 놔도 높이에 기여하지 않는다(즉 이 수정의 전부가 무효가 된다).
     visibility:hidden은 자리를 지키면서도 **포커스·낭독 대상에서 빠진다** — 탭이 안 보이는
     카드로 새지 않는다(ad-slides.js가 거는 aria-hidden과 같은 뜻이고, 서로 방해하지 않는다).
   ⚠ 점(dots)은 **2행**에 둔다. 같은 칸에 넣으면 카드 위에 겹쳐 찍힌다.
   ⚠ JS가 죽으면 `.is-carousel`이 안 붙어 이 규칙이 통째로 꺼진다 — 전 슬라이드가 세로로
     쌓이는 폴백은 그대로다. */
.ad-slides.is-carousel { display: grid; grid-template-rows: auto auto; }
.ad-slides.is-carousel .ad-slide {
  grid-area: 1 / 1; display: grid; margin-top: 12px; visibility: hidden;
}
.ad-slides.is-carousel .ad-slide.on { visibility: visible; }
.ad-slides.is-carousel .ad-slide-dots { grid-area: 2 / 1; }
.ad-slide-dots { display: flex; justify-content: center; gap: 6px; margin-top: 12px; }
.ad-slide-dots button {
  width: 7px; height: 7px; border-radius: 50%; border: 0; padding: 0;
  background: var(--border); cursor: pointer;
}
.ad-slide-dots button[aria-current="true"] { background: var(--primary); width: 18px; border-radius: 4px; }
@media (max-width: 900px) {
  .ad-slide, .ad-slide.wide { grid-template-columns: repeat(2, 1fr); }
}
/* 🔴 560 이하는 **한 열**이다(D-638). 두 열은 카드가 173px로 줄어 이름이 「박…」이 되고
      (실측), 게다가 격자 칸이 카드의 min-content 아래로 못 내려가 **문서가 가로로 스크롤**됐다
      (문서 폭 390 → 646, 이 상향 이전부터 있던 결함이다).
   ⚠ `min-width: 0`으로 두 열을 유지하는 길도 있고 넘침은 그것으로도 잡힌다 — 다만 이름이
      두 글자로 잘려 «누구에게 상담받는지»를 못 읽는다. 이 지면의 존재 이유가 그것이라(D-162)
      폭을 주는 쪽을 골랐다. 대가는 세로다: 한 슬라이드가 카드 수만큼 길어진다. */
@media (max-width: 560px) {
  .ad-slide, .ad-slide.wide { grid-template-columns: 1fr; }
}

/* ══ '지금 상담 가능한 세무사' 카드 — 사진 블리드형 (D-682, 사용자 확정) ═══════════════
   왼쪽 9대16 사진이 카드 끝까지 차고, 오른쪽에 **이름 · 리뷰 · 지역|상호 · 분야** 네 줄.

   🔴 **사진칸 비율은 «올라오는 사진»이 정한다 — 4대5다**(D-702, 사용자 신고 「사진이 짤려서
      보기 불편하다」). 등록되는 프로필 사진은 **800×1000(4:5 = 0.800)**이다
      (`tool/register_tax_photos.js`가 그 규격으로 굽는다).
      칸을 9대16(0.563)으로 두면 `object-fit: cover`가 채우면서 **좌우 29.7%를 잘라낸다** —
      양쪽 어깨가 날아간다(실측으로 확인). 칸을 사진과 같은 비율로 두면 한 픽셀도 안 잘린다.
   ⚠ **9대16으로 되돌리지 마라.** 되돌리려면 사진부터 9대16으로 다시 만들어야 한다 —
      비율이 어긋난 채로는 «잘리거나(cover) 빈 띠가 생기거나(contain)» 둘 중 하나다.
      규격을 바꾸려거든 `register_tax_photos.js`의 800×1000과 **함께** 바꿔라.
   ⚠ 4:5가 아닌 사진 하나가 섞여 있다(김세무 1080×1080) — 그건 좌우가 조금 잘린다.
      `object-position`을 남겨 둔 이유다.

   🔴 **카드 높이는 사진이 정한다** — 높이 = 사진 폭 × 5/4다.

   🔴 **사진 폭은 카드에 비례한다**(D-701, 사용자 지시 「이미지 너비를 더 넓게」).
      예전에는 **84px 고정**이었다. 그런데 카드는 열이 넷이라 지면 폭을 따라 넓어진다 —
      사진 비중이 이렇게 무너졌다(실측):
        1440 → 카드 281 · 사진 84 = **29.9%**
        1920 → 카드 396 · 사진 84 = **21.2%**
        2560 → 카드 549 · 사진 84 = **15.3%**   ← 넓은 띠에 도장 하나 찍힌 모양
      비율이 지면마다 다르면 «같은 카드»가 아니게 된다. 그래서 폭을 비례로 준다.
   ⚠ 상한(168px)이 필요한 이유 — 사진 폭이 곧 카드 높이(×1.25)이기도 하지만, 더 큰 이유는
      **글자 칸**이다. 카드 폭에서 사진·간격·여백을 뺀 나머지가 「지역 | 상호」가 설 자리인데,
      사진을 키울수록 그 줄이 먼저 말줄임된다(예전 84px 시절의 주석이 그 싸움 기록이다).
   ⚠ 하한(112px)은 좁은 화면 몫이다. 비례만 두면 1440에서 카드가 281px이라 사진이 101px에
      머물러 「더 넓게」가 넓은 모니터에서만 일어난다.
   ⚠ 남는 세로는 `.on-body`의 `justify-content: center`가 먹는다 — 글자가 가운데 서므로
      «아래가 비는» 모양이 되지 않는다. 예전 주석이 걱정하던 것이 이 지점인데, 그때는
      정렬이 위쪽이었다.
   ⚠ **앱은 따라오지 않았다**(앱 동결, D-391). `home_screen.dart`의 `_onlineCard`는 아직
      고정 폭이다 — 앱을 다시 열 때 이 값을 같이 옮겨야 두 지면이 같은 카드로 남는다.
   🔴 **글자 칸은 166px**이다(272 − 84 − 12 − 10). 지역|상호를 16px로 올렸더니 「서울 송파구 |
      현우택스」처럼 **짧은 상호까지 잘렸다**(실측) — 그래서 15px로 두고 우측 여백을 10px로 좁혔다.
      이름만 키우고 그 아래는 폭이 허락하는 선을 지킨다.
   ⚠ 별 기호는 `::before`가 그린다 — 마크업에 「★」을 넣으면 두 번 찍힌다.
   ⚠ 별점 노랑(--warning)은 **새 색이 아니다**. `.pf-meta .star`·`.tr-rating`·`.tax-rating`이
      이미 같은 토큰을 쓴다(목록·지도·광고 카드). 여기만 다른 색을 쓰면 평점이 지면마다 갈린다. */
.on-card {
  display: flex; gap: 12px; min-width: 0; text-decoration: none;
  border: 1px solid var(--border); border-radius: var(--r-md); overflow: hidden;
  background: var(--surface); transition: border-color .15s ease;
}
.on-card:hover { border-color: var(--grey300); }
.on-card:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
.on-th {
  /* 🔴 하한 112px을 **내리지 마라**(D-702 · OnlineCardPhotoTest.floorKeepsAspectFromBreaking).
     D-704 작업 중 글자 칸을 넓히려고 92px로 내렸다가 시험이 잡았다: `.on-card`가 flex이고
     기본이 `align-items: stretch`라 **글자가 사진보다 높으면 사진칸이 늘어난다** — 늘어나는
     순간 aspect-ratio가 무효가 되고 cover가 다시 자른다. 실측 104px에서 5.2% 재절단.
     사용자가 「사진이 짤려있어서 보기 불편해」로 신고했던 바로 그 증상이다.
     글자 칸이 좁으면 **글자 쪽을 줄여라**(아래 `.on-rt`가 그렇게 했다). */
  position: relative; flex: 0 0 clamp(112px, 36%, 168px); aspect-ratio: 4 / 5;
  overflow: hidden; background: var(--grey100);
}
.on-img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  /* ⚠ 칸과 사진이 같은 4:5라 규격대로 올라온 사진은 **아무것도 잘리지 않는다**.
     object-position은 규격을 벗어난 사진(예: 1:1)을 위한 보험이다 — 그때만 위쪽을 남긴다. */
  object-fit: cover; object-position: 50% 12%;
}
.on-noimg { display: grid; place-items: center; font-size: 30px; color: var(--grey500); }
.on-body {
  min-width: 0; flex: 1 1 auto; display: flex; flex-direction: column;
  justify-content: center; gap: 4px; padding: 13px 10px 13px 0;
}
.on-nm {
  font-size: 24px; font-weight: 700; color: var(--text-primary); line-height: 1.3;
  letter-spacing: -.01em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* 리뷰 — 이름 바로 아래다(사용자 지시로 지역보다 위).
   🔴 **한 줄에서 끝난다**(D-704, 사용자 지시). 4열 슬라이드에서 글자 칸이 90px 언저리라
      「리뷰 3」의 낱말 사이가 끊겨 **「★ 4.7 / 리뷰 / 3」이 두 줄로 섰다**(실측). 이름·지역은
      이미 nowrap+말줄임인데 이 줄만 규칙 밖이었다 — 한 줄이 넘치면 자르고 「…」을 찍는다. */
.on-rt {
  /* 🔴 글자를 15.5 → 14.5px, 사이를 6 → 4px로 좁혔다(D-704). 4열 슬라이드에서 글자 칸이
     93px인데 「★ 4.7 리뷰 3」이 15.5px에서 103px을 요구해 **두 줄로 섰다**(실측).
     사진칸을 줄여 자리를 벌 수는 없다 — 위 `.on-th` 주석(D-702 재절단)이 그 길을 막는다.
     그래서 이 한 줄만 한 눈금 내린다: 이름 24px·지역 15px은 그대로다. 실측 88px로 든다.
     ⚠ 그래도 넘치면 자르고 「…」을 찍는다(아래 `.on-rvw`) — 두 줄로 새는 것보다 낫다. */
  display: flex; align-items: center; gap: 4px; font-size: 14.5px; line-height: 1.35;
  min-width: 0; white-space: nowrap; overflow: hidden;
}
.on-rvw { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.on-star { color: var(--warning); font-weight: 700; letter-spacing: -.01em; }
.on-star::before { content: "\2605"; margin-right: 3px; font-size: 1.06em; }
.on-rvw { color: var(--grey500); }
.on-rvw b { color: var(--text-primary); font-weight: 700; }   /* 후기 수를 한 번 더 짚는다 */
.on-norv { color: var(--grey500); font-size: 14.5px; }   /* 리뷰 줄과 같은 눈금(D-704) */
/* 지역 한 줄 — 상호는 없다(D-723, 사용자 지시). 예전 「지역 | 상호」의 구분선 규칙(.on-who i)은
   조각에서 <i>가 사라지며 함께 걷었다. */
.on-who {
  font-size: 15px; color: var(--grey500); line-height: 1.4;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* 분야 — 한 줄로만. 넘치는 칩은 반 칸으로 남지 않게 오른쪽을 흐리며 자른다.
   ⚠ 분야가 없어도 빈 줄을 그린다(조각이 빈 span을 낸다) — min-height가 그 자리를 지킨다. */
.on-cats {
  display: flex; gap: 4px; margin-top: 1px; min-height: 23px; overflow: hidden;
  -webkit-mask-image: linear-gradient(to right, #000 84%, transparent 100%);
          mask-image: linear-gradient(to right, #000 84%, transparent 100%);
}
.on-cat {
  flex: 0 0 auto; white-space: nowrap; font-size: 13px; font-weight: 600;
  color: var(--grey700); background: var(--grey100); border-radius: 6px;
  padding: 3px 8px; line-height: 1.3;
}
/* 좁은 화면 — 열이 1~2로 줄면 카드가 넓어진다. 사진은 그대로 두고 글자만 여유를 갖는다.
   ⚠ 카드 높이는 사진이 정하므로 여기서 높이를 건드릴 것은 없다. */
@media (max-width: 560px) {
  .on-body { padding-right: 14px; }
}

/* ══ 프리미엄 세무사 — 9대16 사진 카드, 한 장에 5명 (D-680, 사용자 지시) ══════════════
   카드는 `/fit/more`의 명부(.fp-*)를 **그대로** 쓴다(index.html이 fit.css를 함께 싣는다).
   여기서 정하는 것은 **열 수 하나뿐**이다.

   🔴 열 수를 못박는 이유: `.fp-grid-rest`는 `repeat(auto-fill, minmax(200px, 1fr))`이라 폭에 따라
      열이 3~6으로 흔들린다. 그러면 「슬라이드당 5장」이라는 **상품 규격**이 화면마다 달라진다.
   ⚠ `.ad-slides .ad-slide.ad-slide-photo`로 (0,3,0)을 쓴다 — fit.css가 home.css보다 **뒤에**
     실리므로 (0,2,0) 동점으로는 `.fp-grid.fp-grid-rest`에 진다.
   ⚠ 이 값은 HomeController.PREMIUM_PER_SLIDE(5)와 **짝**이다. 한쪽만 바꾸면 마지막 슬라이드에
     빈 칸이 생기거나 카드가 잘린다.

   ── 좁은 화면 ──────────────────────────────────────────────────────────────────
   ⚠ 여기서는 위 `.ad-slide`의 «560 이하 한 열»(D-638)을 따르지 않는다. 그 결정은 **가로형
     명함 카드**(사진 88px + 이름·별점·분야) 얘기였다 — 두 열이면 이름이 「박…」이 됐다.
     9대16 사진 카드는 D-651에서 **모바일 두 열 145px**이 실측으로 확정된 형태다(사진 145×259,
     오버레이가 55%만 덮는다). 같은 카드니 같은 답을 쓴다.
   ⚠ 한 열로 내리면 슬라이드 하나가 카드 다섯 장 높이(≈2,000px)가 되어 «슬라이드»가 아니게 된다. */
.ad-slides .ad-slide.ad-slide-photo { grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 14px; }
@media (max-width: 1100px) {
  .ad-slides .ad-slide.ad-slide-photo { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 560px) {
  .ad-slides .ad-slide.ad-slide-photo { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
}

/* 🔴 홈에서는 소개말이 **한 줄**이다 (D-704, 사용자 지시) ─────────────────────────────
   `.fp-why`는 두 가지를 그린다: 광고주가 산 한 줄 멘트(D-124)와 그 아래 「★ 4.7 · 후기 3」.
   멘트에는 줄 수 제한이 없어서 실측 2~3줄까지 늘어났고(「기장부터 절세까지, 20년 경력으로…」
   74px = 세 줄), 오버레이가 위로 자라 **같은 행의 카드마다 글자 시작 높이가 달라졌다**.
   사진 위 오버레이라 카드 높이로 흡수되지도 않는다 — 사진을 덮고 올라간다.

   ⚠ `/fit`·`/fit/more`의 같은 카드는 건드리지 않는다. 거기 `.fp-why`는 «왜 뽑혔는지»라는
     근거 문장이고 카드가 훨씬 커서 두 줄이 정상이다. 그래서 홈 슬라이드로만 좁힌다.
   ⚠ 선택자 무게를 (0,4,0)으로 둔다 — fit.css가 home.css보다 **뒤에** 실리므로
     `.fp-grid-rest .fp-why`(0,2,0)와 동점이면 진다(위 열 수 규칙과 같은 이유).
   ⚠ line-clamp가 아니라 nowrap+ellipsis다. 한 줄만 남길 때는 이쪽이 정확하다 —
     line-clamp:1은 `word-break: keep-all`과 만나면 낱말 하나가 칸보다 길 때 잘리는 자리가
     들쭉날쭉하다. 말줄임표는 `…` 한 글자로 브라우저가 찍는다(design.md §4). */
.ad-slides .ad-slide.ad-slide-photo .fp-why {
  display: block;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* 🔴 홈 프리미엄 카드 — 접속 알약(「지금 접속 중」·「프로필 보기」)은 **우상단**이다(D-723, 사용자 지시).
   fit.css `.fp-presence`는 좌상단(left:10px)이고 /fit·/fit/more는 그대로 둔다 — 홈 슬라이드로만
   좁힌다. 무게는 위 `.fp-why`와 같은 이유로 (0,4,0)이다(fit.css가 뒤에 실린다).
   ⚠ left:auto를 함께 써야 한다 — right만 더하면 left:10px과 둘 다 살아 알약이 가로로 늘어난다. */
.ad-slides .ad-slide.ad-slide-photo .fp-presence { left: auto; right: 10px; }
/* 지역 줄 — 홈에서는 상호 없이 지역 하나다(D-723, fragments/ad-card photoCard). 지역이 빈 세무사면
   빈 블록이 0px로 접혀 오버레이가 그 카드만 낮아진다 → 한 줄 높이를 예약한다(D-704 정렬 계약). */
.ad-slides .ad-slide.ad-slide-photo .fp-of { min-height: 1.45em; }
/* 🔴 소개말·별점 자리를 **항상 예약한다**(D-728, 사용자 지시). 둘 다 조건부라 오버레이가 0·1·2줄로
   갈렸고, 오버레이는 `bottom` 고정이라 줄이 적은 카드는 이름이 그만큼 아래에서 시작했다
   (실측 145px vs 121px). 빈 판(`.fp-why-hold`)이 한 줄을 대신 든다 — 글자는 한 자도 없다.
   ⚠ `em`이다: 이 홀더는 `.fp-why`라 데스크톱 17px·모바일 14.5px를 그대로 물려받고, min-height도
     그 글꼴을 따라 함께 줄어든다. px으로 박으면 두 눈금에서 반 줄씩 어긋난다.
   ⚠ `line-height`(1.45)와 짝이다 — `.fp-grid-rest .fp-why`의 값을 바꾸면 여기도 같이 바꿔라.
   ⚠ /fit·/fit/more에는 이 홀더가 아예 안 나간다(마크업이 홈 전용 photoCard 조각에만 있다). */
.ad-slides .ad-slide.ad-slide-photo .fp-why-hold { min-height: 1.45em; }

/* 🔴 자리를 예약했으면 **그라디언트도 따라 올라가야 한다**(D-728). 예약 전에는 글자가 0·1·2줄로
   갈렸고 fit.css의 값(`.92` 118px · 램프 끝 165px)은 «짧은 카드» 기준이었다 — 이제 모든 카드가
   가장 긴 판이라 이름 꼭대기가 **135px**(실측, 560px 초과 전 구간에서 같다. 열 폭이 231→304px로
   변해도 글꼴이 안 바뀌어 글자 덩어리 키는 그대로다)까지 올라온다. 옛 램프 끝(165px)과 겹쳐
   이름의 윗변이 알파 .59 구간에 앉았다 — 흰 사진 위 계산 대비 **3.9:1**로 design.md 본문 하한(4.5:1) 아래다.
   새 값은 이 저장소가 D-640·D-641·D-642에서 쓴 것과 **같은 산술**이다:
     글자 꼭대기 135 + 여유 6 = `.92` **141px**, 램프 폭은 명부와 같은 47px → 끝 **188px**.
   그 자리에서 이름 윗변은 알파 .92를 딛는다 → 흰 사진 위 계산 대비 **약 14:1**.
   덮는 몫: 1280에서 188/410 = 45.9%, 1000에서 188/541 = 34.8%(fit.css 명부의 45%와 같은 자리).
   ⚠ /fit·/fit/more는 그대로다 — 거기 오버레이에는 이 예약이 없어 여전히 짧다. 무게 (0,3,0)으로
     fit.css의 `.fp-grid-rest .fp-photo::after`(0,2,0)를 이긴다(그 파일이 뒤에 실려도 특정도가 이긴다).
   ⚠ 글자 크기나 예약 줄 수를 바꾸거든 **이름 꼭대기를 먼저 다시 재라** — 이 두 수는 실측에서 나온다. */
.ad-slides .ad-slide.ad-slide-photo .fp-photo::after {
  background: linear-gradient(to top, var(--grey900) 0,
              rgba(25, 31, 40, .92) 141px, rgba(25, 31, 40, 0) 188px);
}
@media (max-width: 560px) {
  /* 모바일은 글꼴이 한 단 작아 이름 꼭대기가 **113px**이다(실측, 390px 폭). 같은 산술:
     113 + 6 = `.92` 119px, 램프 47 → 166px. 덮는 몫 166/309 = 53.7% — fit.css가 모바일 명부에서
     이미 받아들인 54.9%와 같은 자리다. */
  .ad-slides .ad-slide.ad-slide-photo .fp-photo::after {
    background: linear-gradient(to top, var(--grey900) 0,
                rgba(25, 31, 40, .92) 119px, rgba(25, 31, 40, 0) 166px);
  }
}

