/* 앱 셸 — 상단바 + 좌측 사이드바 + 본문 (D-115 · 그룹 사이드바 개편 v2.0 §1).
   색·타이포는 기존 토스톤 토큰(tokens.css) 그대로. 치수만 시안 v2.0으로 맞췄다:
     사이드바 확장 248 / 접힘 68 · 탑바 62(일터) · 행 40/radius 10 · 아이콘 18/stroke 1.7 ·
     라벨 14/600 · 그룹 캡션 11/600 +0.04em

   ⚠ 40여 개 템플릿이 layout.html 하나를 공유한다. 여기 클래스명을 바꾸면 전 페이지가 영향받는다. */

/* ── 일터 셸의 상단바 높이 (v2.0 §1 ⑥) ────────────────────────────
   🔴 **body에 건다.** 예전에 `.shell-client .topbar { --topbar-h: 48px }`처럼 상단바에만 걸었다가
      사이드바 top·스크림 inset·본문 padding-top이 그 값을 못 봐서 셋이 어긋난 적이 있다.
      body에 걸면 .topbar·.sidebar·.shell·.main이 **모두 같은 조상**에서 상속받는다.
   ⚠ 의뢰인(마케팅) 지면은 68px 그대로다 — home.css의 배너 여백이 "68 + 24 + 60 = 152"로
     맞춰져 있어(그 파일 주석) 여기서 낮추면 홈 위쪽 리듬이 통째로 어긋난다. */
body.shell-pro { --topbar-h: 62px; }

/* ── 상단바 ─────────────────────────────────────────── */
/* 좌 / 가운데(브랜드) / 우 3구역. 브랜드를 정확히 가운데 세우려면 좌우가 같은 폭을
   차지해야 한다 — flex + margin:auto로 맞추면 좌우 내용 폭 차이만큼 어긋난다.
   grid 1fr auto 1fr이면 내용과 무관하게 늘 중앙이다.
   🔴 가운데 칸(.top-c)은 **비어도 남긴다**(관리자 셸에는 심볼이 없고, /login도 칼럼 락업이 로고라
      비어 있다 — 로그인 A안 `hideTopBrand`). 없애면 우측 구역이
      2번 칸으로 올라와 오른쪽 정렬이 통째로 무너진다. */
.topbar {
  position: fixed; inset: 0 0 auto 0; height: var(--topbar-h); z-index: 30;
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center;
  gap: var(--s-lg); padding: 0 var(--s-xl);
  background: var(--bg, var(--background)); border-bottom: 1px solid var(--divider);
}
.top-l { display: flex; align-items: center; justify-content: flex-start; gap: 10px; min-width: 0; }
.top-c { display: flex; align-items: center; justify-content: center; min-width: 0; }
.top-r { display: flex; align-items: center; justify-content: flex-end; gap: 8px; }

/* 브랜드 — **심볼만** 가운데 (D-138b → D-167에서 워드마크 제거).
   ⚠ 심볼 자체가 '로세' 두 글자라, 글자 수가 줄어든 만큼 **크기를 키워야** 획이 읽힌다.
     더 줄이면 '로세'의 계단 획이 뭉쳐서 무슨 글자인지 안 보인다. */
.topbar .brand {
  display: inline-flex; align-items: center;
  white-space: nowrap; color: var(--text-primary);
}
/* ── 락업 렌더 — **캔버스가 아니라 잉크를 기준으로 재운다** (D-259) ──────────────
   🔴 예전엔 `.brand-mark { height: 26px }`였다. 그런데 락업 PNG는 **여백이 절반**이다:
      `logo-kr-light@4x.png`는 580×256 캔버스인데 잉크는 **425×129**(세로의 50.4%)뿐이고,
      여백도 비대칭이다(좌 100 · 우 55 · 상 51 · 하 76 — 직접 재서 확인).
      그래서 26px을 주면 **화면에 보이는 로고는 13.1px**이 됐다 — 브랜드 가이드가 요구하는
      **최소 24px의 55%**다. 「로고 영역이 안 보인다」는 지적의 진짜 원인이 이것이었다.

   그래서 창(.brand)에 잉크만 보이게 잘라 넣는다. 계산 근거(잉크 높이 H 기준):
     · 이미지 높이 = H ÷ (127/256)          = H × 2.0157
     · 이미지 너비 = 이미지높이 × (580/256)   = H × 4.5669
     · 창 너비    = 이미지너비 × (432.5/580) = H × 3.4055
     · 왼쪽 밀기  = 이미지너비 × (99.5/580)  = H × 0.7835
     · 위로 밀기  = 이미지높이 × (51/256)    = H × 0.4016
   🔴 D-890(타이포그래피 C1, 2026-10-02) 워드마크 교체 뒤의 숫자다 — logo-kr.png는 이제 SemTalk Sans Round
      SemiBold «셈톡»(자간 +0.12em, 사용자 선택) 1160×512(2배, 캔버스 비율 580×256 그대로)이고 잉크는 1배 기준
      점 왼쪽 99.5 · 글자 오른쪽 548 · 글자 윗선 51 · 아랫선 178(잉크 448.5×127, 여백 좌 99.5 · 우 32 · 상 51 · 하 78).
      예전 Pretendard 로고(잉크 425×129)의 숫자 1.9845 · 3.2946 · 0.7752 · 0.3953은 LoginBrandRenderTest와 함께 바꿨다.
   🔴 2026-10-06 «셈»–«톡» 자간 +0.12em → **0em**(사용자 지시, 워드마크만 — 본문 --ls-* 무관). 같은 스크립트
      (docs/requests/2026-10-02-typography/scripts/wordmark.py --tracking 0, 같은 600 글리프)로 다시 그렸고 캔버스·점·«셈»·
      글자 높이·세로 위치·색은 그대로, «톡»만 왼쪽으로 16.25(1배). 글자 오른쪽 548 → **532**(잉크 432.5×127, 여백 우 48)라
      창 너비만 3.5315 → 3.4055, 나머지 세 숫자는 그대로. 옛 +0.12em PNG = tool/brand/legacy/logo-kr.d890-tracking012.png.
   ⚠ **자산이 바뀌면 이 다섯 숫자를 다시 재라.** 파일이 바뀌었는지는
     `python3 -c "from PIL import Image; im=Image.open('...').convert('RGBA'); print(im.size, im.split()[3].getbbox())"`
     로 확인한다. 숫자만 고치면 나머지는 따라온다.
   ⚠ 비대칭 여백을 창으로 잘라 내므로 **광학 중심이 저절로 맞는다** — 예전엔 로고가
     칩 안에서 왼쪽·위로 치우쳐 보였다. */
.brand-mark {
  --brand-ink: 24px;                       /* 가이드 최소치. 더 줄이지 마라. */
  display: block; flex: 0 0 auto; position: relative; overflow: hidden;
  height: var(--brand-ink);
  width: calc(var(--brand-ink) * 3.4055);
}
.brand-mark img {
  position: absolute; display: block; max-width: none;
  height: calc(var(--brand-ink) * 2.0157); width: auto;
  left: calc(var(--brand-ink) * -0.7835);
  top: calc(var(--brand-ink) * -0.4016);
}
/* 62px 일터 바에서도 잉크는 24px 그대로다 — 최소치라 줄일 여지가 없다. 대신 칩 여백을 조인다. */
.shell-pro .topbar .brand { padding: 6px 16px; }

/* 관리자 표식 (v2.0 §1 ⑥) — 워드마크 #191F28 + ADMIN 배지.
   ⚠ 색은 tokens.css의 --text-primary(#191F28) 그대로다. 새 색을 만들지 마라. */
.brand-admin { display: inline-flex; align-items: center; gap: 8px; white-space: nowrap; }
/* 관리자 락업도 타입 스케일 규칙대로다(사용자 결정 2026-10-03 — 로고 자리라 먼저 물었다):
   워드마크 = heading 16/24/600(옛 16/700 — 렌더 동일, 둘 다 SemiBold 파일).
   자간만 0 = var(--ls-36)(옛 --ls-14 +0.02em): 로고 글자라 자간 곡선 예외 — 사용자 결정 2026-10-07 L2.
   가로 로고 PNG(logo-kr.png, 2026-10-06 «셈»–«톡» 0em)와 같은 자간이다. 본문 --ls-* 정의는 그대로. */
.brand-admin-word {
  font-size: var(--fs-heading); line-height: var(--lh-heading); font-weight: var(--fw-semibold); letter-spacing: var(--ls-36);
  color: var(--text-primary);
}
/* ADMIN 배지 = caption2 12/18/600(최소 크기 — 옛 10px/700/.06em/줄 1). 높이는 그대로 18px: 옛 글자 10 + 위아래 4 → 줄 18 + 위아래 0.
   ⚠ 마이 «관리자» 배지(.badge.badge-admin, mypage.html)도 이 규칙을 받는다 — 옛 10px이 .badge 12px을 덮던 것이 같이 풀린다. */
.badge-admin {
  font-size: var(--fs-caption2); line-height: var(--lh-caption2); font-weight: var(--fw-semibold); letter-spacing: var(--ls-12);
  padding: 0 6px; border-radius: 6px;
  background: var(--text-primary); color: #fff;
}

/* 상단바 검색 320px (v2.0 §1 ⑥) — 전역 입력 칸(app.css .input)과 같은 **흰 칸**이다(3차 정리 X1 · design.md §4 «검색 칸도
   같은 흰 칸» · P-076 3-(가)). 옛 회색 알약(#F2F4F6)은 걷었다 — 채워진 회색은 어디서나 «잠김» 신호다(app.css .input 주석).
   관리자 상단바는 흰 바탕(--background)이라 흰 칸은 1px #D1D6DB 테두리로 선다. 높이만 상단바 결(36px)로 둔다.
   ⚠ 칸 안 input은 outline을 끄고, 포커스는 칸(:focus-within)이 전역 입력 칸과 **같은 값**(2px 파랑 + 3px 링)으로 그린다 —
     app.css `.input:focus` 값을 바꾸면 여기도 함께 바꿔라.
   ⚠ 갈 곳이 있는 셸에만 그린다(layout.html 주석) — 여기 스타일이 있다고 아무 데나 붙이지 마라. */
.top-search {
  display: flex; align-items: center; gap: 8px;
  width: 320px; max-width: 38vw; height: 36px; padding: 0 12px;
  border-radius: 10px; background: var(--surface); border: 1px solid var(--grey300);
}
.top-search:focus-within {
  border-color: var(--primary);
  box-shadow: inset 0 0 0 1px var(--primary), 0 0 0 3px rgba(49, 130, 246, .2);
}
.top-search .ts-ic {
  width: 16px; height: 16px; flex: 0 0 16px;
  stroke: var(--text-tertiary); fill: none; stroke-width: 1.8; stroke-linecap: round;
}
.top-search input {
  flex: 1; min-width: 0; height: 100%;
  border: 0; background: transparent; outline: none;
  font-family: inherit; font-size: 14px; color: var(--text-primary);
}
.top-search input::placeholder { color: var(--text-disabled); }

/* 상단바 버튼은 검색칸과 같은 결로 맞춘다 — 기본 .btn(48px)은 너무 크다. */
.topbar .btn { height: 36px; padding: 0 16px; font-size: 14px; }
.icon-btn {
  width: 38px; height: 38px; border-radius: var(--r-md);
  display: inline-flex; align-items: center; justify-content: center; color: var(--text-secondary);
}
.icon-btn:hover { background: var(--surface-alt); }

/* 안읽음 점 — **서버가 알려줄 때만** 그려진다(layout.html 주석의 판단).
   테두리를 상단바 배경색으로 둘러 종 획 위에 얹혀도 점으로 읽히게 한다. */
.top-bell { position: relative; }
.top-dot {
  position: absolute; top: 7px; right: 8px;
  width: 7px; height: 7px; border-radius: var(--r-full);
  background: var(--error); box-shadow: 0 0 0 2px var(--bg, var(--background));
}

/* ── 브랜드 락업 자리 (D-262, 사용자 지시로 테두리 제거) ──────────────────────
   D-258에서 «눌러지는 자리»가 안 보인다는 지적이 있었다. 회색 면 알약(D-259 이전) → 선만(D-259)
   → **아무 장식도 없음**(지금)으로 왔다.

   🔴 되짚어 둘 것: 그때 지적의 **진짜 원인은 대비가 아니라 크기**였다. 락업 PNG의 잉크가
      캔버스의 50.4%뿐이라 `height:26px`이 실제로는 13.1px로 그려지고 있었다(가이드 최소치
      24px의 55%). 그걸 잡은 것은 아래 `--brand-ink` 창(crop-window)이지 면도 선도 아니다.
      그래서 선을 걷어도 그 결함은 돌아오지 않는다 — **--brand-ink를 24px 밑으로 내리면
      돌아온다.** 로고가 다시 안 보인다는 말이 나오면 테두리가 아니라 그 값을 먼저 재라.

   ⚠ 로고 자체는 손대지 않는다(브랜드 가이드: 색 변형·회전·그림자 금지). 바뀌는 것은
     그 뒤에 깔리는 **우리 UI**뿐이다.
   ⚠ padding은 남긴다. hover 면과 focus 링이 락업에 달라붙지 않게 하는 자리다.
     테두리를 지웠다고 padding까지 지우면 키보드 링이 글자를 물고 그려진다. */
.topbar .brand {
  padding: 8px 18px; border-radius: var(--r-full);
  background: transparent;                 /* 상단바 흰색이 그대로 비친다 */
  transition: background .15s ease;
}
.topbar .brand:hover { background: var(--grey50); }
.topbar .brand:active { background: var(--surface-alt); }
.topbar .brand:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }

/* 아바타 — 사진이 있으면 사진, 없으면 이름 첫 글자(layout.html 주석 참고). */
.top-avatar {
  width: 34px; height: 34px; flex: 0 0 34px; border-radius: var(--r-full);
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--primary-light); color: var(--primary-pressed);
  font-size: var(--fs-label2); font-weight: var(--fw-semibold);   /* 머리글자(34px 원): label2 크기 14(옛 14/700) */
  overflow: hidden; cursor: pointer; list-style: none;
}
.top-avatar::-webkit-details-marker { display: none; }  /* summary 기본 삼각형 */
.top-avatar:hover { background: #DCEBFF; }
.top-avatar-img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* ── 계정 메뉴 (D-258) ────────────────────────────────────────────
   🔴 <details>로 짓는다 — JS 없이도 여닫힌다. shell.js는 «바깥 클릭·Esc로 닫기»만 얹는다. */
.acct { position: relative; }
.acct-menu {
  position: absolute; right: 0; top: calc(100% + 8px); z-index: 40;
  min-width: 208px; padding: 6px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-md); box-shadow: var(--shadow-float);
}
.acct-head {
  display: flex; flex-direction: column; gap: 2px;
  padding: 8px 10px 10px; margin-bottom: 4px; border-bottom: 1px solid var(--divider);
}
/* 이름 = heading 16/24/600(«사람 이름», 옛 14/700) — 아래 메뉴 줄(14/600)보다 한 단 위. */
.acct-name {
  font-size: var(--fs-heading); line-height: var(--lh-heading); font-weight: var(--fw-semibold); letter-spacing: var(--ls-14);
  color: var(--text-primary);
}
/* 이메일은 길다 — 메뉴 폭을 늘리지 말고 줄인다. 글자 = caption2 크기·행간 12/18(옛 12px · 줄은 body 상속 22/24) · 굵기 400 그대로
   (주소는 배지가 아니라 메타라 caption2의 500을 쓰지 않는다) · --text-tertiary 흰 메뉴 4.62:1. */
.acct-mail {
  font-size: var(--fs-caption2); line-height: var(--lh-caption2); font-weight: var(--fw-regular); letter-spacing: var(--ls-12);
  color: var(--text-tertiary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 196px;
}
/* 메뉴 줄 = label2 14/20 · 굵기 600 그대로(옛 14/600 · 줄은 body 상속 22/24). 줄 높이가 2~4px 줄어든 만큼 위아래 여백 9 → 10px —
   줄 높이 40px(옛 폰 40 · 데스크톱 42). 세무사 명함 메뉴(app.css .taxm)도 같은 클래스다. */
.acct-item {
  display: block; width: 100%; text-align: left;
  padding: 10px; border: 0; border-radius: var(--r-sm);
  background: transparent; color: var(--text-secondary);
  font-family: inherit;
  font-size: var(--fs-label2); line-height: var(--lh-label2); font-weight: var(--fw-semibold); letter-spacing: var(--ls-14);
  cursor: pointer;
}
.acct-item:hover { background: var(--surface-alt); color: var(--text-primary); }
.acct-item:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }
/* 로그아웃은 되돌릴 수 없는 조작이라 한 칸 띄우고 톤을 낮춘다(빨강까지는 가지 않는다 —
   위험한 삭제가 아니라 «나가기»다). */
.acct-out { margin-top: 4px; border-top: 1px solid var(--divider); border-radius: 0 0 var(--r-sm) var(--r-sm); }

/* 사이드바 프로필 사진 — 상단바와 같은 값을 그린다. */
.sp-av { overflow: hidden; }
.sp-av-img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* ── 사이드바 모드 전환 (D-138c) ─────────────────────────────
   상단바에서 내려온 세그먼트 컨트롤. 메뉴 머리에 있어야 "이걸 누르면 아래 목록이 바뀐다"가
   위치로 읽힌다. 사이드바 폭을 꽉 채워 두 칸으로 나눈다. */
.side-mode {
  display: grid; grid-template-columns: 1fr 1fr; gap: 2px;
  padding: 3px; margin-bottom: 8px;
  background: var(--surface-alt); border: 1px solid var(--border);
  border-radius: var(--r-full);
}
.side-mode-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  height: 34px; border: 0; border-radius: var(--r-full);
  /* 글자 = label2 14/20(34px 버튼 ≤40, 옛 14.5px) · 굵기 600 그대로. 색 grey700 — 옛 --text-tertiary는 회색 트랙(#F2F4F6) 위 4.19:1로
     14px 이하 AA(4.5:1) 미달이었다 → #4E5968 6.45:1(흰 레일 칸 7.11:1). hover(--text-secondary)는 그보다 한 단 진하다. */
  background: transparent; color: var(--grey700);
  font-size: var(--fs-label2); line-height: var(--lh-label2); font-weight: var(--fw-semibold); letter-spacing: var(--ls-14);
  white-space: nowrap; cursor: pointer;
}
.side-mode-btn svg {
  width: 16px; height: 16px; flex: 0 0 16px;
  stroke: currentColor; fill: none; stroke-width: 1.8;
  stroke-linecap: round; stroke-linejoin: round;
}
.side-mode-btn:hover { color: var(--text-secondary); }
/* 선택된 쪽은 메인 컬러 알약 — 흰 알약은 회색 트랙 위에서 대비가 약해
   "지금 어느 모드인지"가 한눈에 안 읽혔다(D-123 당시 사용자 피드백). */
.side-mode-btn.on { background: var(--primary); color: #fff; }
.side-mode-btn.on:hover { color: #fff; }

/* 접힌 레일(68px)에는 두 칸이 안 들어간다. **지금이 아닌 쪽**만 아이콘으로 남겨
   누르면 바로 그 모드로 넘어가게 한다 — 접어 둔 사람도 모드를 바꿀 수 있어야 한다. */
html.rail .side-mode {
  grid-template-columns: 1fr; background: none; border: 0; padding: 0; margin-bottom: 10px;
}
html.rail .side-mode-btn.on { display: none; }
html.rail .side-mode-btn {
  width: 40px; height: 40px; margin: 0 auto;
  border: 1px solid var(--border); background: var(--surface);
}
html.rail .side-mode-btn svg { width: 18px; height: 18px; flex: 0 0 18px; }

/* ── 셸 ─────────────────────────────────────────────── */
.shell { display: flex; padding-top: var(--topbar-h); min-height: 100vh; }

/* 🔴 사이드바는 **세 층**이다: 스크롤 되는 메뉴(.side-scroll) + 바닥에 고정된 프로필 카드
      (.side-profile). 그래서 스크롤을 사이드바가 아니라 안쪽 칸이 가진다 — 예전처럼
      .sidebar에 overflow-y를 두면 메뉴가 길 때 프로필 카드가 같이 밀려 올라가 바닥에서 사라진다. */
.sidebar {
  position: fixed; top: var(--topbar-h); bottom: 0; left: 0; z-index: 20;
  width: var(--sidebar-w); overflow: hidden;
  display: flex; flex-direction: column;
  background: var(--bg, var(--background)); border-right: 1px solid var(--divider);
  transition: width .18s ease;
}
.side-scroll {
  flex: 1 1 auto; min-height: 0;
  overflow-y: auto; overscroll-behavior: contain;
  display: flex; flex-direction: column; padding: 8px 10px;
}

/* ── 그룹 (v2.0 §1 ①) ────────────────────────────────
   평평한 목록을 이름 붙은 묶음으로. 캡션은 caption2 12/18 · 600 · --ls-12 — 읽으라고 두는 글자가 아니라
   **어디쯤인지 알려주는 표식**이라 본문(메뉴 16px · --text-secondary)보다 확실히 작고 흐리다.
   (타이포 3단계 묶음 ①) 옛 12.5px(소수점)/줄 1/+.04em · 색 --text-disabled #9AA3AE는 흰 사이드바에서 2.55:1로 AA 미달이었다 →
   --text-tertiary #6B7684 4.62:1. 줄이 12.5 → 18px로 늘어난 만큼 아래 여백 4px를 걷어 묶음 높이는 +1.5px만 는다. */
.nav-group { display: flex; flex-direction: column; }
.nav-group + .nav-group { margin-top: 8px; }
/* 캡션 13px(caption1 — 13px 이상 규칙, D-936). 옛 caption2 12/18. */
.nav-cap {
  margin: 0; padding: 0 12px;
  font-size: var(--fs-caption1); line-height: var(--lh-caption1); font-weight: var(--fw-semibold); letter-spacing: var(--ls-13);
  color: var(--text-tertiary);
}

/* 높이 44 = T2 타입 스케일(메뉴 16px). 원안 40. T3(46/17)는 과해서 T2로 내림.
   ≤768 드로어에서는 44(design.md §4 모바일 히트 타깃) — 아래 미디어 블록. */
/* 글자 = heading 16/24/600(audit §3 «내비 16/600 → heading», 옛 16/600 · 줄은 body 상속). 줄 높이는 44px 상자가 정해 행간이 바뀌어도 그대로다. */
.nav-item {
  display: flex; align-items: center; gap: 10px;
  height: 44px; padding: 0 12px; border-radius: 10px;
  font-size: var(--fs-heading); line-height: var(--lh-heading); font-weight: var(--fw-semibold); letter-spacing: var(--ls-14);
  color: var(--text-secondary); white-space: nowrap;
}
.nav-item:hover { background: var(--surface-alt); }
.nav-item.active { background: var(--primary-light); color: var(--primary); }
.nav-item svg {
  flex: 0 0 18px; width: 18px; height: 18px;
  stroke: currentColor; fill: none; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round;
}
.nav-sep { height: 1px; background: var(--divider); margin: 6px 8px; }

/* ── 활주 하이라이트 — B안 «파랑 기미»(D-778, Q-343 사용자 확정 · 참고: x.com/theshanelevine) ──
   줄마다 배경이 켜지는 대신 **알약 한 장**(.nav-glide)이 커서를 따라 줄 사이를 미끄러진다. 알약은 스크롤 칸
   (.side-scroll) 안에 절대 배치돼 스크롤과 함께 움직이고, shell.js mountGlide가 붙여 준다.
   · JS 없이도 성립(design.md): 위 `.nav-item:hover`는 그대로 살고, 알약이 붙은 칸(.has-glide)에서만 hover 배경을
     투명으로 바꿔 알약이 대신한다. 글자·아이콘은 잉크(--text-primary)로 한 단 진해진다.
   · 움직이는 속성은 transform·opacity뿐(§7). 감속 모션이면 자리만 옮긴다.
   · 알약 색 #F0F6FF = --surface-tint(#F8FBFF)와 --primary-light(#E8F3FF) 사이 — 선택 줄(--primary-light + --primary)
     보다 한 단 옅어 «지금 여기»와 «고른 곳»이 갈린다. 토큰이 아닌 값은 이 한 곳뿐이다.
   🔴 `:not(.active)` — `.has-glide .nav-item:hover`(0,3,0)가 `.nav-item.active`(0,2,0)를 이겨 선택 줄이 hover에서
      알약 색으로 바뀐다(정지 비교 시트에서 잡았다). 선택 줄은 z-index 1의 불투명 배경이라 알약을 자연히 덮는다.
   🔴 캡션·구분선도 z-index 1 — 알약이 묶음을 건너갈 때 「커뮤니티」 같은 캡션이 가려지지 않는다. */
.side-scroll { position: relative; }
.nav-item, .nav-cap, .nav-sep { position: relative; z-index: 1; }
.nav-glide {
  position: absolute; top: 0; left: 0; z-index: 0; width: 0; height: 36px; border-radius: 10px; pointer-events: none;
  background: #F0F6FF; opacity: 0; transform: translate3d(0, 0, 0);
  transition: transform 160ms cubic-bezier(.2, .7, .2, 1), opacity 120ms ease;
}
.nav-glide.on { opacity: 1; }
.has-glide .nav-item:hover:not(.active) { background: transparent; color: var(--text-primary); }
@media (prefers-reduced-motion: reduce) { .nav-glide { transition: none; } }
.nav-foot { margin-top: auto; }
.nav-logout { width: 100%; text-align: left; }

/* ── 하단 고정 프로필 카드 (v2.0 §1 ⑤) ────────────────
   스크롤 밖이라 어느 화면에서도 같은 자리에 있다 — 구독 상태를 "찾아서" 보는 게 아니라
   "지나가다" 보게 하려는 자리다. */
.side-profile {
  position: relative; flex: 0 0 auto; margin-top: auto;   /* 🔴 어떤 셸 변형에서도 사이드바 **맨 밑**(D-777 보강) — 위 .side-scroll이 다 못 채워도 바닥으로 */
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px; border-top: 1px solid var(--divider);
  background: var(--bg, var(--background));
}
/* 메뉴가 넘칠 때 마지막 줄이 **반쯤 잘린 채** 멈추면 고장으로 읽힌다. 스크롤 칸 바닥에
   배경색으로 사라지는 20px 그라데이션을 덮어 "아래 더 있다"로 읽히게 한다.
   내용이 짧아 넘치지 않으면 배경 위에 배경이라 눈에 띄지 않는다 — 알아서 숨는다. */
.side-profile::before {
  content: ''; position: absolute; left: 0; right: 0; bottom: 100%; height: 20px;
  pointer-events: none;
  background: linear-gradient(to top, var(--bg, var(--background)), transparent);
}
.side-profile:hover { background: var(--surface-alt); }
/* 마이페이지 계열(/mypage·계정·매출·알림·공지·고객센터 등)에서는 카드가 켜진다 — 메뉴 개편에서 [마이페이지] 줄을 걷어 카드가 그 자리다. 색은 .nav-item.active와 같다. */
.side-profile.active { background: var(--primary-light); }
.side-profile.active .sp-name { color: var(--primary); }
.sp-av {
  width: 34px; height: 34px; flex: 0 0 34px; border-radius: var(--r-full);
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--primary-light); color: var(--primary-pressed);
  font-size: var(--fs-label2); font-weight: var(--fw-semibold);   /* 머리글자(34px 원): 상단바 .top-avatar와 같은 값(옛 14/700) */
}
.sp-txt { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.sp-name {   /* heading 16/24/600(«사람 이름», 옛 15/700) — 계정 메뉴 .acct-name과 같은 값 */
  font-size: var(--fs-heading); line-height: var(--lh-heading); font-weight: var(--fw-semibold); letter-spacing: var(--ls-14);
  color: var(--text-primary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sp-sub {   /* caption1 13/20/400(옛 13px · 줄은 body 상속 22/24) — 이름(.sp-name heading) 아래 메타 한 줄 */
  font-size: var(--fs-caption1); line-height: var(--lh-caption1); font-weight: var(--fw-regular); letter-spacing: var(--ls-13);
  color: var(--text-tertiary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ── 접힘(레일 68px) — 라벨만 감추고 아이콘은 남긴다 ────────────
   아이콘 상자 40px + 좌우 14px = 68px. 라벨은 shell.js가 title(툴팁)로 옮겨 준다
   (사이드바가 overflow:hidden이라 CSS 말풍선은 잘린다 — 그래서 네이티브 툴팁을 쓴다). */
html.rail .sidebar { width: var(--rail-w); }
html.rail .side-scroll { padding: 8px 14px; }
html.rail .nav-item { width: 40px; padding: 0; gap: 0; justify-content: center; }
html.rail .nlabel { display: none; }
html.rail .nav-cap { display: none; }
/* 캡션이 사라져도 묶음은 남아야 한다 — 이름표 대신 선으로 가른다. */
html.rail .nav-group + .nav-group {
  margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--divider);
}
html.rail .nav-sep { margin: 10px 4px; }
html.rail .side-profile { justify-content: center; padding: 10px 0; }
html.rail .sp-txt { display: none; }
html.rail .main { margin-left: var(--rail-w); }

/* ── 레일 엿보기(peek, D-779 — 사용자 지시 「아이콘만 남은 사이드바에 마우스를 올리면 메뉴 이름이 보이게」) ──
   접힌 레일 위에 커서가 머물면(shell.js, 140ms 뒤) <html class="rail peek">가 되고 사이드바가 **본문을 밀지 않고
   덮으며** 펼침 폭으로 넓어진다 — 이름·캡션·프로필 글자가 돌아온다. 커서가 나가면(180ms 뒤) 다시 레일.
   본문(.main)의 왼쪽 여백은 레일 그대로다(위 `html.rail .main`) — 밀면 화면이 들썩인다.
   아래 규칙은 «접힌 레일이 감춘 것»을 되돌리는 짝이다(좁은 화면 블록의 되돌림과 같은 목록) — 레일 규칙을 고치면
   여기도 같이 고쳐라. 메뉴 이름 말풍선(.rail-tip)은 엿보기가 되는 환경(마우스)에서는 뜨지 않는다(shell.js). */
html.rail.peek .sidebar { width: var(--sidebar-w); box-shadow: 0 8px 40px rgba(17, 31, 40, .14); }
html.rail.peek .side-scroll { padding: 8px 10px; }
html.rail.peek .nav-item { width: auto; padding: 0 12px; gap: 10px; justify-content: flex-start; }
html.rail.peek .nlabel { display: inline; }
html.rail.peek .nav-cap { display: block; }
html.rail.peek .nav-group + .nav-group { margin-top: 8px; padding-top: 0; border-top: 0; }
html.rail.peek .nav-sep { margin: 6px 8px; }
html.rail.peek .side-profile { justify-content: flex-start; padding: 10px 12px; }
html.rail.peek .sp-txt { display: flex; }
html.rail.peek .side-mode {
  grid-template-columns: 1fr 1fr; padding: 3px; margin-bottom: 8px;
  background: var(--surface-alt); border: 1px solid var(--border);
}
html.rail.peek .side-mode-btn { width: auto; height: 32px; margin: 0; border: 0; background: transparent; }
html.rail.peek .side-mode-btn.on { display: inline-flex; background: var(--primary); }
html.rail.peek .side-mode-btn svg { width: 16px; height: 16px; flex: 0 0 16px; }
/* 폭 전이(.sidebar transition: width .18s)는 D-115부터 있던 것 — 감속 모션이면 끈다(§7). */
@media (prefers-reduced-motion: reduce) { .sidebar { transition: none; } }

/* 접힌 레일의 메뉴 이름 말풍선 (D-281).
   🔴 **body에 붙는다.** 사이드바 안에 두면 `.sidebar { overflow:hidden }`이 오른쪽으로 나가는
      말풍선을 잘라 버린다 — 예전에 네이티브 `title`을 쓸 수밖에 없었던 이유가 그것이다.
      `position: fixed` + JS가 계산한 좌표라 클리핑을 통째로 벗어난다.
   ⚠ `pointer-events: none` — 말풍선이 커서를 가로채면 그 위에서 mouseleave가 나 깜빡인다.
   ⚠ z-index는 사이드바(20)보다 위여야 한다. 아래면 사이드바 뒤로 숨는다.
   ⚠ 위치는 JS가 아이콘 **세로 가운데**를 주므로 여기서 translateY(-50%)로 맞춘다. */
.rail-tip {
  position: fixed; z-index: 60; pointer-events: none;
  transform: translateY(-50%);
  padding: 6px 10px; border-radius: var(--r-sm, 6px);
  background: var(--text-primary); color: #fff;
  font-size: 12px; font-weight: 600; line-height: 1.3; white-space: nowrap;
  box-shadow: 0 4px 14px rgba(17, 31, 40, .18);
  opacity: 0; visibility: hidden;
  transition: opacity .12s ease;
}
.rail-tip.on { opacity: 1; visibility: visible; }
/* 화살표 — 어느 아이콘을 가리키는지 분명히 한다. */
.rail-tip::before {
  content: ''; position: absolute; right: 100%; top: 50%;
  transform: translateY(-50%);
  border: 5px solid transparent; border-right-color: var(--text-primary);
}
@media (prefers-reduced-motion: reduce) { .rail-tip { transition: none; } }

/* 본문은 남은 자리를 **전부** 쓴다(D-154). 예전엔 `max-width: 사이드바 + 1240`으로 묶어
   넓은 화면에서 오른쪽이 통째로 비었다. 좌우 여백만 화면 폭에 따라 준다. */
.main {
  flex: 1; margin-left: var(--sidebar-w); min-width: 0;
  /* 🔴 본문 패딩은 **변수로** 둔다(D-736). 아래 `--main-fill`과 app.css의 로그인 지면이 같은
        값을 봐야 «한 화면»의 셈이 맞는다 — 예전에는 88px·64px이 세 파일에 손으로 적혀 있었다. */
  --main-pad-t: 24px;
  --main-pad-b: 64px;
  /* «한 화면» = 뷰포트에서 상단바와 본문 위 패딩을 뺀 높이. 본문 칸이 최소한 이만큼 차지하면
     푸터는 언제나 첫 화면 **아래**로 밀린다(D-736, 사용자 지시). 아래 패딩은 빼지 않는다 —
     그 여백은 푸터 **뒤**에 붙지 본문과 푸터 사이에 있지 않다(실측으로 8px 어긋났던 자리다). */
  --main-fill: calc(100vh - var(--topbar-h) - var(--main-pad-t));
  padding: var(--main-pad-t) var(--shell-pad) var(--main-pad-b); transition: margin-left .18s ease;
  /* 🔴 **푸터를 아래에 붙이기 위한 세로 격자**(D-241). `.shell`이 이미 `min-height:100vh`라
        `.main`은 화면 끝까지 늘어나 있었는데, 그 안의 푸터는 일반 흐름 블록이라 **본문 바로 뒤**에
        섰다. 그래서 내용이 짧으면 푸터가 화면 한가운데 뜨고 그 아래가 죽은 여백이 됐다.
     ⚠ 푸터에 `margin-top:auto`를 주지 않는다. 그러면 내용이 길 때 auto가 0으로 줄어 본문과
       구분선이 붙는다. 대신 **본문 칸을 늘려**(아래 `> :first-child`) 밀어내고, 푸터의
       56px 간격은 내용 길이와 무관하게 그대로 남긴다. */
  display: flex; flex-direction: column;
}
/* 일터 지면의 회색 판(v2.0 §1 ⑦)은 D-420에서 은퇴 — 전 메뉴가 캘린더(D-416)처럼
   흰 바탕이다. 카드 경계는 카드 자신의 테두리·그림자가 만든다. */

/* 본문 조각(`layout:fragment="content"`의 div)이 남는 세로를 가져간다.
   ⚠ `flex: 1 0 auto` — 세 번째 값이 `auto`여야 내용이 화면보다 길 때 줄어들지 않는다.
   🔴 **`:first-child`로 잡으면 안 된다**(D-525, 실측 사고). 플래시(page-flash)가 뜨면 그것이
      첫 자식이 되어 **늘어나는 것이 본문이 아니라 플래시**가 된다 — 결제 직후 화면에서
      한 줄짜리 안내가 **660px 빈 회색 상자**로 떴다. 플래시가 있는 **모든 지면**이 같았다.
   🔴 푸터는 언제나 마지막이므로 «푸터 **바로 앞**»을 잡는다 — 플래시가 있든 없든 본문이 걸린다.
   🔴 **`min-height: var(--main-fill)`**(D-736, 사용자 지시) — 내용이 짧아도 본문 칸이 한 화면을
      채우고, 남는 자리는 그냥 아래 여백이 된다. 그래서 푸터는 **스크롤해야** 나온다.
      예전에는 `flex:1 0 auto`가 «푸터를 뺀 나머지»만 채워서, 내용이 짧으면 푸터가 화면 안에
      통째로 들어와 앉았다(실측 900px 화면에서 푸터 top y=558 — 본문 아래 342px이 푸터였다).
      ⚠ `flex-shrink`는 0이라 이 min-height가 늘 이긴다. 플래시가 뜨면 그 높이만큼 본문이
        아래로 내려가고 푸터도 함께 내려간다 — 첫 화면에 푸터가 없다는 약속은 그대로다. */
.main > :nth-last-child(2) { flex: 1 0 auto; min-width: 0; min-height: var(--main-fill); }
/* ⚠ 플래시는 제 높이만 쓴다 — 위 규칙이 어떤 이유로 플래시를 잡아도 늘어나지 않게 못 박는다. */
.main > .page-flash { flex: 0 0 auto; }

/* ── 셸 안의 푸터 «말»(D-710, 시안 B 확정) — 본문 흐름 끝에 붙는다(위 격자가 늘 화면 아래로 민다).
   브랜드 블록 = 락업(잉크 32px · 위 .brand-mark 창 패턴 재사용) + 태그라인 + 질문 한 줄
   (낱말 단위로 어긋나게 떠오름 → 3초 머묾 → 조용히 사라짐 · 4문장 순환 16s) + 고정 답줄.
   락업·심볼은 움직이지 않는다(브랜드 README). 움직이는 속성은 transform·opacity뿐(design.md §7).
   배경은 흰색이다 — 13px 회색 글자(--text-tertiary)가 --grey50 위에서는 4.42:1로 하한(4.5)에
   못 미친다(실측). 반응형은 @container(푸터 폭 기준) — 960px 위에서 «브랜드 | 링크» 두 단.
   🔴 푸터 자신이 컨테이너(테두리·위 여백)이고 안쪽 .sf-in이 격자다 — 컨테이너 쿼리는 컨테이너
      자신에게는 적용되지 않으므로 격자 규칙은 안쪽 상자에 둔다(푸터에 두면 두 단이 «암묵 열»로
      생겨 열 간격·행 정의가 사라진다 — 시안 단계에서 실제로 그렇게 깨졌다).
   바닥 줄은 subgrid로 같은 두 열을 이어받아 약관 링크가 링크 열의 왼쪽 끝선에 선다(미지원
   브라우저에서는 「셈톡」 아래 약관이 쌓일 뿐 내용·접근성은 그대로). */
.shell-footer {
  --sf-gap: 64px;              /* 두 단 사이 */
  container-type: inline-size;
  margin-top: 56px; padding-top: 32px;
  border-top: 1px solid var(--border);
  /* 글자 기본 = caption1 크기 13px(옛 리터럴 13px과 같은 값 — 타이포 점검 F9 검증 지적). 자식(.sf-cap·.sf-legal a 등)이 제 크기를 따로 적는다. */
  color: var(--text-tertiary); font-size: var(--fs-caption1);
  flex: 0 0 auto;
}
.shell-footer .sf-in { display: grid; grid-template-columns: minmax(0, 1fr); align-items: start; }

/* ── 브랜드 블록: 락업 → 태그라인 → 질문 글줄 → 답줄 ───────────────────────────────── */
.shell-footer .sf-brand { min-width: 0; }
.shell-footer .brand-mark { --brand-ink: 32px; }
/* 태그라인 16/24/500(타이포 점검 F9 — 옛 16/1.4 = 22.4px · 넓은 푸터 17px을 한 벌로). 크기·행간은 16/24 짝(heading)을,
   굵기는 500을 쓴다(질문 글줄과 같은 무게 — 락업 아래 한 줄이 제목처럼 무거워지지 않게). */
.shell-footer .sf-tag {
  margin: 14px 0 0; font-size: var(--fs-heading); font-weight: var(--fw-medium); line-height: var(--lh-heading);
  letter-spacing: var(--ls-14); color: var(--text-primary); text-wrap: balance;
}

/* 질문 글줄 — 네 문장은 절대배치로 같은 자리에 겹치고 가장 긴 문장(프리랜서…)을 visibility:hidden
   으로 한 벌 더(.sf-ghost) 흐름에 두어 높이를 잡는다 → 문장이 바뀌어도 레이아웃 점프 0.
   낱말은 inline-block이라 낱말 안에서 줄이 갈리지 않는다. 유령도 같은 낱말 구조·keep-all이라
   접히는 자리가 실제 문장과 같다.
   글자 = title2 크기·행간(모바일 20/28 · 폭 ≥768 22/30) · 500 — 타이포 점검 F9(옛 20/1.4 · 넓은 푸터 24/1.35). 두 단(≥960)에서만
   title1(28/38)로 키운다(아래 @container (min-width: 960px)). text-wrap: pretty — 360 폭에서 두 줄로 접힐 때 «하죠?» 한 낱말만 끝줄에 남지 않게 한다
   (실측: 기본 «…종합소득세는 어떻게 / 하죠?» → pretty «…종합소득세는 / 어떻게 하죠?». balance는 낱말 span 단위라
   «프리랜서인데 / 종합소득세는 어떻게 하죠?»로 첫 줄이 짧아져 고르지 않았다). 유령도 같은 규칙이라 높이·접히는 자리가 그대로 맞는다. */
.shell-footer .sf-talk { position: relative; margin-top: 24px; }
.shell-footer .sf-q {
  margin: 0; min-width: 0; word-break: keep-all; overflow-wrap: normal;
  font-size: var(--fs-title2); font-weight: var(--fw-medium); line-height: var(--lh-title2);
  letter-spacing: var(--ls-18); color: var(--text-primary); text-wrap: pretty;
}
.shell-footer .sf-q:not(.sf-ghost) { position: absolute; inset: 0; }
.shell-footer .sf-ghost { visibility: hidden; }

/* 낱말 모션 — 기본 상태는 «아직 안 나온 낱말»(투명·8px 아래).
   지연 = 문장 위상(--t: 0/4/8/12s) + 낱말 차례(--w: 0~4) × 60ms. 유령의 낱말은 움직이지 않는다. */
.shell-footer .sf-q span {
  display: inline-block; opacity: 0; transform: translateY(8px);
  animation: sf-word 16s ease-out infinite;
  animation-delay: calc(var(--t, 0s) + var(--w, 0) * 60ms);
}
.shell-footer .sf-ghost span { animation: none; }
.shell-footer .sf-q2 { --t: 4s; }
.shell-footer .sf-q3 { --t: 8s; }
.shell-footer .sf-q4 { --t: 12s; }
.shell-footer .sf-q span:nth-child(2) { --w: 1; }
.shell-footer .sf-q span:nth-child(3) { --w: 2; }
.shell-footer .sf-q span:nth-child(4) { --w: 3; }
.shell-footer .sf-q span:nth-child(5) { --w: 4; }
/* 16s = 100% (1% = 0.16s). 0~0.55s 떠오름(ease-out) · 3.5s까지 머묾(첫 낱말 기준 2.95s) ·
   3.5~3.76s 사라짐(opacity만 · ease-in-out) · 나머지는 투명 대기. 다섯째 낱말(+0.24s)도 4.0s에
   다 사라져 다음 문장(4.0s)과 겹치지 않는다. 마지막 키프레임 = 첫 키프레임 → 루프 이음새 없음. */
@keyframes sf-word {
  0%      { opacity: 0; transform: translateY(8px); animation-timing-function: ease-out; }
  3.4375% { opacity: 1; transform: translateY(0);   animation-timing-function: linear; }
  21.875% { opacity: 1; transform: translateY(0);   animation-timing-function: ease-in-out; }
  23.5%   { opacity: 0; transform: translateY(0); }
  23.6%   { opacity: 0; transform: translateY(8px); }
  100%    { opacity: 0; transform: translateY(8px); }
}
/* 답줄 = body2(14/22 · 폭 ≥768 15/24) — 옛 15/1.4. 흰 바탕 위 --text-tertiary #6B7684 = 4.62:1(14px도 AA 4.5 이상). */
.shell-footer .sf-ans { margin: 8px 0 0; font-size: var(--fs-body2); line-height: var(--lh-body2); color: var(--text-tertiary); }

/* ── 링크 3열 — 열 머리 13px/500 · 링크 14px/400. 모바일 히트 44px(11+22+11) ──────────── */
.shell-footer .sf-nav { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); column-gap: 16px; margin-top: 32px; }
.shell-footer .sf-cap { margin: 0 0 4px; font-size: 13px; font-weight: 500; line-height: 20px; color: var(--text-tertiary); }
.shell-footer .sf-col ul { list-style: none; margin: 0; padding: 0; }
.shell-footer .sf-col a {
  display: inline-block; padding: 11px 0; font-size: 14px; font-weight: 400; line-height: 22px;
  color: var(--text-secondary); text-decoration: none;
}
/* 세무사 한 줄 — 마지막 링크의 아래 패딩(11)과 합쳐 글자 사이 37px */
.shell-footer .sf-pro { margin: 26px 0 0; font-size: 14px; line-height: 22px; color: var(--text-tertiary); }
.shell-footer .sf-pro a {
  display: inline-block; padding: 11px 0; margin: -11px 0; color: var(--text-secondary);
  text-decoration: underline; text-underline-offset: 3px; text-decoration-color: var(--grey300);
}

/* ── 바닥 줄 — 「셈톡」 글자 + 약관 3링크(필수). 위 칸과는 더 옅은 --divider 헤어라인 ──────── */
.shell-footer .sf-bottom {
  display: flex; align-items: center; justify-content: space-between; gap: 0 16px; flex-wrap: wrap;
  margin-top: 24px; padding-top: 6px; border-top: 1px solid var(--divider);
}
.shell-footer .sf-name { font-size: 13px; font-weight: 500; line-height: 20px; color: var(--text-tertiary); }
.shell-footer .sf-legal { display: flex; flex-wrap: wrap; column-gap: 20px; list-style: none; margin: 0; padding: 0; }
.shell-footer .sf-legal a { display: inline-block; padding: 12px 0; font-size: 13px; line-height: 20px; color: var(--text-secondary); text-decoration: none; }

/* ── 링크 상태 — hover는 잉크 진해짐 + 밑줄 · 키보드 포커스는 브랜드 파랑 링 ─────────────── */
.shell-footer a { transition: color .15s ease; }
.shell-footer a:hover { color: var(--text-primary); text-decoration: underline; text-underline-offset: 3px; }
.shell-footer a:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; border-radius: 4px; }

/* ── 넓은 푸터(컨테이너 ≥ 600) — 링크 열 고정 폭 · 데스크톱 히트(32px) ──────────
   글자는 따로 키우지 않는다(타이포 점검 F9): 태그라인 16/24 한 벌, 질문 글줄은 title2(폭 ≥768이면 22/30 — 옛 24px에 가장 가까운 토큰). */
@container (min-width: 600px) {
  .shell-footer .sf-in { padding-top: 8px; }   /* 푸터 32 + 8 = 테두리 아래 40px */
  .shell-footer .sf-talk { margin-top: 28px; }
  /* 열 피치 152(112 + 40) 둘 · 셋째 열은 제 폭 — 두 단일 때 오른쪽 끝선이 본문 끝선과 맞는다 */
  .shell-footer .sf-nav { grid-template-columns: 112px 112px auto; column-gap: 40px; margin-top: 36px; }
  .shell-footer .sf-col a { padding: 5px 0; }
  .shell-footer .sf-legal a { padding: 6px 0; }
  .shell-footer .sf-pro a { padding: 5px 0; margin: -5px 0; }
  .shell-footer .sf-pro { margin-top: 23px; }   /* 링크 패딩 5 + 23 = 글자 사이 28px */
  .shell-footer .sf-bottom { margin-top: 32px; }
}

/* ── 두 단(컨테이너 ≥ 960 · 데스크톱 셸 1161) — 브랜드 | 링크 3열 + 세무사 한 줄.
   바닥 줄은 subgrid로 같은 두 열(같은 열 사이 간격)을 이어받는다 → 약관 링크 = 링크 열 왼쪽 끝선. */
@container (min-width: 960px) {
  .shell-footer .sf-in {
    grid-template-columns: minmax(0, 1fr) auto; grid-template-rows: auto 1fr auto;
    column-gap: var(--sf-gap);
  }
  .shell-footer .sf-brand { grid-column: 1; grid-row: 1 / span 2; }
  .shell-footer .sf-nav { grid-column: 2; grid-row: 1; margin-top: 0; }
  .shell-footer .sf-pro { grid-column: 2; grid-row: 2; align-self: end; margin-top: 20px; }
  /* 질문 글줄 = title1(28/38 — 컨테이너 ≥960이면 화면도 ≥768이라 늘 데스크톱 값). 옛 사다리(24/26/28)의 26px은 토큰에 없어 가장 가까운
     28/38로(타이포 점검 2026-10-03 F9 «데스크톱 28/38») — 가장 긴 문장 폭 490px(28px 실측) < 브랜드 열이 가장 좁은 컨테이너 960의 열 ≈ 537px → 늘 한 줄.
     토큰을 직접 적는다(옛 --sf-q-size/--sf-q-lh 간접 변수는 린트 T1이 토큰 이름을 못 봐 위반으로 셌다 — F9 검증 지적). */
  .shell-footer .sf-q { font-size: var(--fs-title1); line-height: var(--lh-title1); letter-spacing: var(--ls-22); }
  .shell-footer .sf-bottom {
    grid-column: 1 / 3; grid-row: 3;
    display: grid; grid-template-columns: subgrid; column-gap: var(--sf-gap); align-items: center;
    margin-top: 36px;
  }
  .shell-footer .sf-name { grid-column: 1; }
  .shell-footer .sf-legal { grid-column: 2; justify-self: start; }
}

/* ── 앱 임베드 — 셸이 접혀 좌우 패딩이 0이다. 큰 글줄·락업은 접고 링크 열과 바닥 줄만 남긴다. */
.app-embed .shell-footer { margin-inline: 0; padding-inline: 16px; }
.app-embed .shell-footer .sf-in { grid-template-columns: minmax(0, 1fr); column-gap: 0; }
.app-embed .shell-footer .sf-brand { display: none; }
.app-embed .shell-footer .sf-nav,
.app-embed .shell-footer .sf-pro { grid-column: 1; grid-row: auto; }
.app-embed .shell-footer .sf-nav { margin-top: 0; }
.app-embed .shell-footer .sf-bottom { grid-column: 1; grid-row: auto; display: flex; }

/* ── 모션 줄임 — 첫 문장만 정지 표시 · 나머지는 숨김(유령이 높이를 지킨다) ───────────────── */
@media (prefers-reduced-motion: reduce) {
  .shell-footer .sf-q span { animation: none; }
  .shell-footer .sf-q1 span { opacity: 1; transform: none; }
  .shell-footer .sf-q2, .shell-footer .sf-q3, .shell-footer .sf-q4 { visibility: hidden; }
  .shell-footer a { transition: none; }
}

/* ── 드로어 모드 ────────────────────────────────────────────────
   사이드바를 화면 밖에 두고 햄버거로 밀어 넣는다. 이제 **좁은 화면(≤768px)에서만** 켜진다.

   🔴 **의뢰인모드도 데스크톱에서는 상시 노출이다**(D-281, 사용자 지시). 예전에는
      「의뢰인모드 — 폭과 무관하게 항상 드로어」였다. 그래서 같은 서비스인데 세무사는 메뉴가
      늘 보이고 의뢰인은 매번 햄버거를 눌러야 했다 — **모드가 다르다고 조작법까지 달라졌다.**
   ⇒ 골격은 하나다. 데스크톱이면 상시 노출 + 레일 접기, 좁으면 드로어. 모드는 관여하지 않는다.
   ⚠ 아래 규칙을 다시 `.shell-client`로 좁히지 마라 — 좁히는 순간 의뢰인만 레일을 잃고,
     그러면 hover 툴팁(shell.js)도 함께 죽는다(툴팁은 «라벨이 실제로 숨겨졌을 때»만 붙는다).
   ⚠ 좁은 화면용 드로어 규칙은 아래 `@media (max-width: 768px)` 블록에 **일반형으로 이미 있다**.
     여기서 의뢰인 전용 사본을 지운 것이지 드로어를 없앤 게 아니다. */
.hamburger { display: inline-flex; }
.drawer-scrim { display: none; }

/* ── 모바일(≤768px): 모드와 무관하게 드로어 ───────────── */
@media (max-width: 768px) {
  /* 드로어 줄은 손가락 크기(D-777) — 데스크톱 40, 폰 44. 모드 토글 버튼도 같은 높이를 따른다. */
  .nav-item { height: 44px; }

  /* 좁은 화면 상단바 — 참고 지면(nol.yanolja.com)도 모바일에서는 윗줄이 56px다.
     ⚠ :root와 body 양쪽에 적는다 — 위에서 body.shell-pro에 62px를 걸었으므로 :root만
       고치면 일터 셸이 그 62px를 계속 본다(가까운 조상이 이긴다). */
  :root { --topbar-h: 56px; }
  body.shell-pro { --topbar-h: 56px; }
  /* 🔴 여기서 `.brand-mark { height }`를 덮지 마라 — 그 값은 **창 높이 = 로고 잉크 높이**다
     (shell.css 위쪽 --brand-ink 주석). 심볼만 쓰던 시절의 `height: 34px`가 여기 남아 있어서
     좁은 화면에서만 잉크가 24 → 34px로 커져 있었다(실측으로 발견). 잉크는 어느 폭에서도
     가이드 최소 24px 그대로 두고, 좁은 화면에서 조일 것은 **칩 여백**뿐이다(위 .topbar .brand). */
  /* 좁은 화면에는 검색칸이 들어갈 자리가 없다 — 브랜드·햄버거가 먼저다. */
  .top-search { display: none; }
  .sidebar {
    width: var(--sidebar-w) !important;
    transform: translateX(-100%); transition: transform .2s ease;
  }
  html.drawer-open .sidebar { transform: none; box-shadow: 0 8px 40px rgba(17, 31, 40, .18); }
  html.drawer-open .drawer-scrim {
    display: block; position: fixed; inset: var(--topbar-h) 0 0 0; z-index: 15;
    background: rgba(0, 0, 0, .35);
  }
  /* 모바일에선 접기 개념이 없다 — 라벨·캡션을 항상 보이게 되돌린다. */
  html.rail .nlabel { display: inline; }
  html.rail .nav-cap { display: block; }
  html.rail .nav-item { width: auto; padding: 0 12px; gap: 10px; justify-content: flex-start; }
  html.rail .side-scroll { padding: 8px 10px; }
  /* 56px 바 — 잉크 24px + 위아래 여백 4px = 32px. 링(offset 2 + 굵기 2)까지 들어간다.
     ⚠ 잉크를 24px 밑으로 내리지 마라(가이드 최소치). 줄일 것은 칩 여백뿐이다. */
  .topbar .brand { padding: 4px 14px; }
  html.rail .nav-group + .nav-group { margin-top: 14px; padding-top: 0; border-top: 0; }
  html.rail .side-profile { justify-content: flex-start; padding: 10px 12px; }
  html.rail .sp-txt { display: flex; }
  html.rail .side-mode { grid-template-columns: 1fr 1fr; }
  html.rail .side-mode-btn { width: auto; height: 32px; margin: 0; border: 0; background: transparent; }
  html.rail .side-mode-btn.on { display: inline-flex; background: var(--primary); }
  .main {
    margin-left: 0 !important;
    --main-pad-t: 16px; --main-pad-b: 48px;
    padding: var(--main-pad-t) 16px var(--main-pad-b);
    /* 노치·둥근 모서리 기기의 가로(safe-area-inset-left/right)를 존중한다(design.md §6, D-761). 세로 방향
       폰에서는 0이라 16px 그대로다. ⚠ 밴드의 `margin-inline:-16px` 블리드는 16px을 전제하므로 안전 영역이
       있을 때만 그만큼 안쪽에서 멈춘다 — 잘리는 것보다 낫다. */
    padding-inline: max(16px, env(safe-area-inset-left, 0px)) max(16px, env(safe-area-inset-right, 0px));
  }
  /* 좁은 화면에서는 브랜드가 가운데, 햄버거가 왼쪽 — 좌측 구역은 폭만 잡는다. */
  .topbar { padding: 0 var(--s-md); gap: var(--s-sm); }
}

/* 로그인 유도 — 메뉴 안에서 다른 항목과 구분되어야 눈에 걸린다(구분은 파랑 글자가 한다).
   굵기 600(타이포 점검 2026-10-03 F12 — 옛 700은 라운드에서 어차피 SemiBold로 그려졌고, 대체 구간에서만 Pretendard Bold를 더 받았다). */
.nav-cta { color: var(--primary); font-weight: var(--fw-semibold); }
.nav-cta:hover { background: var(--primary-light); }

/* ── 의뢰인 상단바 (D-138a → 높이는 D-166에서 되돌림) ────────────────────
   ⚠ 예전엔 `.shell-client { --topbar-h: 48px }`로 **의뢰인 바만 얇게** 했다. "글자 하나와
     버튼 하나뿐이라 같은 높이면 흰 띠만 두껍게 남는다"가 이유였는데, 사용자 지시로
     **68px**(참고 지면 nol.yanolja.com 윗줄 실측)로 되돌렸다.
   ⚠ 높이를 다시 덮지 마라. --topbar-h는 사이드바 top·스크림 inset·본문 padding-top이
     모두 따라오는 값이라, 상단바에만 걸면 그 셋이 어긋난다(위 body.shell-pro 주석 참조).
   아래 항목들(패딩·아이콘)은 의뢰인 바를 **가볍게** 유지하려는 것이라 남긴다. */
.shell-client .topbar { padding: 0 var(--s-lg); }
.shell-client .icon-btn { width: 34px; height: 34px; }
.shell-client .icon-btn svg { width: 20px; height: 20px; }
/* ⚠ 의뢰인 바에서 심볼을 줄이지 않는다(D-167) — 워드마크가 없어 심볼이 유일한 표식이라
   작게 만들면 브랜드가 안 읽힌다. */

/* ══ 앱 인앱 웹뷰 임베드 (D-692) ═══════════════════════════════════════════════
   앱은 화면이 없는 기능을 웹뷰로 연다(D-252 ②, 지금 14곳). 그때 웹이 자기 상단바를 들고
   들어와 **앱 앱바 아래에 상단바가 두 겹**이 됐다 — 「맞춤 세무사」에서 사용자가 봤다.

   🔴 내비게이션은 **앱이 갖는다**(앱바·서랍·하단 탭). 그러니 여기서는 셸을 접고 본문만 준다.
   ⚠ `display:none`으로 접는다 — 폭만 0으로 만들면 상단바 높이(--topbar-h)만큼 빈 띠가 남는다.
   ⚠ 판정은 서버 한 곳(GlobalModelAdvice.appEmbed)이고 여기서는 **그리기만** 한다.
      질의문자열을 CSS가 다시 읽지 마라. */
.app-embed .topbar,
.app-embed .sidebar { display: none; }
.app-embed .shell { padding-top: 0; }
.app-embed .main {
  padding-left: 0; padding-right: 0;
  /* 상단바가 접혀 있으므로(위 `display:none` + `.shell`의 padding-top 0) «한 화면»에서
     --topbar-h를 빼면 안 된다 — 빼면 본문이 그만큼 짧아져 푸터가 다시 첫 화면에 걸린다. */
  --main-fill: calc(100vh - var(--main-pad-t));
}
/* 본문 자체의 좌우 여백은 지면들이 각자 갖고 있다 — 여기서 --shell-pad를 0으로 만들면
   글이 화면 가장자리에 붙는다. 셸이 주던 여백만 걷는다. */

/* 🔴 웹뷰(?app=1) 769px 이상 — 홈 밖 지면(/qna·/fit·/support·공지 등)의 왼쪽 빈 띠(사용자 결정 2026-10-09 11차 V3 ⓐ «작은 다듬기» ⑦).
   셸은 웹뷰에서 사이드바를 접지만(위 display: none) 본문 왼쪽 여백(.main margin-left = --sidebar-w 216 · 레일이면 html.rail .main 68)이
   ≥769에서 그대로 남아 화면 왼쪽이 빈 띠였고, 그 지면들은 제 좌우 여백이 없어 글이 띠 바로 옆(x 216)과 화면 오른쪽 끝에 붙었다.
   홈(7차 P11 — home.css .app-embed .main:has(> .home-page))과 같은 결과로 고친다: 왼쪽 여백 0 + 일반 웹 본문 여백(--shell-pad)을 본문이 든다.
   푸터는 본문과 같은 끝선(패딩 0 — 웹뷰 푸터 16은 셸 여백이 0일 때의 값이다).
   빼는 지면 — 제 웹뷰 여백·제 규칙을 드는 곳은 그대로다: 홈(.home-page — 본문 상자가 여백을 듦) · 지도(.map-layout — 화면 끝까지, content.css가 따로 걷음) ·
   받은 요청(.pr-page — 웹뷰 16, 여기서는 왼쪽 여백만 0) · 로그인(.page-login — login-stage.css).
   ≤768은 셸 폰 규칙(margin-left 0 !important)이라 이 규칙과 무관하다(웹뷰 본문 좌우 0 그대로).
   구체성 (0,4,0)이 .app-embed .main(0,2,0)·html.rail .main(0,2,1)을 이긴다(!important 없음). :has를 모르는 옛 웹뷰는 규칙 전체가 빠져 빈 띠가 남을 뿐이다(라이브와 같음 —
   여백 0과 패딩을 한 규칙에 묶은 이유: 패딩 없이 여백만 걷히면 글이 x 0에 붙는다, 7차 검토 UX-R-01). */
@media (min-width: 769px) {
  .app-embed:not(.page-login) .main:not(:has(> .home-page, .map-layout, .pr-page)) { margin-left: 0; padding-inline: var(--shell-pad); }
  .app-embed:not(.page-login) .main:not(:has(> .home-page, .map-layout, .pr-page)) > .shell-footer { padding-inline: 0; }
  .app-embed .main:has(.pr-page) { margin-left: 0; }
}

/* 검수 보기 띠(D-842) — 검수자가 픽스처 계정의 눈으로 보고 있을 때만 layout.html이 그린다.
   잉크 바탕 흰 글자로 «운영 화면이 아니라 검수 중»이 한눈에 갈리게. 상단바 위에 흐름대로 선다(고정 아님). */
.rv-strip { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 12px; padding: 8px var(--shell-pad);
  background: var(--text-primary); color: #fff; font-size: 14px; }
.rv-strip-tag { font-weight: 500; }
.rv-strip-who { flex: 1; min-width: 0; }
.rv-strip form { margin: 0; }
.rv-strip-exit { font: inherit; font-size: 14px; font-weight: 600; color: var(--text-primary); background: #fff;
  border: 0; border-radius: var(--r-sm); padding: 0 14px; min-height: 44px; cursor: pointer; }
