/* 디자인 언어: 1안 「원장(元帳) The Ledger」 (design-review-r1.md §3, binding).
   공공 기록물의 물성(잉크·종이·날짜열·일련 기입)을 헤비 웨이트 한글 타이포와
   모노 숫자로 재해석. 순백 페이지 캔버스, 저알파 헤어라인, 단일 바이올렛 CTA,
   숫자 tabular-nums. 시그니처: 시간순 근거 카드를 잇는 날짜 레일(스파인+틱).
   커밋 2 범위: 토큰·타이포·폰트 교체 (컴포넌트 재구성은 커밋 3). */

/* Pretendard Variable 셀프호스팅 (웹폰트 핫링크 없음, 라이선스 SIL OFL). */
@font-face {
  font-family: "Pretendard Variable";
  src: url("/static/fonts/PretendardVariable.woff2") format("woff2-variations");
  font-weight: 45 920;
  font-display: swap;
  font-style: normal;
}

:root {
  color-scheme: light;       /* 폼 컨트롤·스크롤바 등 UA 크롬을 라이트로 고정(원장 톤) */
  /* 표면 */
  --paper: #FFFFFF;          /* 단일 순백 페이지 캔버스. 헤더·본문·도크·푸터 전부 이 색 위에서 흐른다 */
  --paper-raised: #FFFFFF;   /* 컴포저·내부 컴포넌트 등 페이지와 극소 대비가 필요한 표면 */
  --sidebar-bg: #F7F7F8;     /* 본문보다 살짝 어두운 사이드바 전용 쿨 그레이 표면(챗지피티 관례) */
  /* 사이드바 행 상태색(무채 잉크 파생, 새 hue 아님). sidebar-bg 위에서 hover/active가
     또렷이 구분되도록 두 단계로 둔다. active는 배경 강조 위주(좌측 바 폐지, claude.ai 관례). */
  --sidebar-row-hover: rgba(22, 24, 29, 0.05);
  --sidebar-row-active: rgba(22, 24, 29, 0.10);
  --canvas: #F4F4F6;         /* 쿨 그레이 미세 채움. 유저 질의 칩·요약 카드·코드 배경 등 소품 전용(페이지 배경 아님) */
  /* 촉각 2단계: 페이지 바탕 전용 톤. --canvas(소품 채움)와는 값·용도가 다르다 - 이 토큰은
     body/랜딩 바탕에만 쓴다. 상단만 흰 광원이 깔리고(--grad-canvas) 720px 아래는 이 값 평탄. */
  --canvas-page: #F6F6F8;    /* 페이지 바탕(2단계). 흰 종이 표면(카드·컴포저·패널)이 그 위에 뜬다 */
  --grad-canvas: linear-gradient(180deg, #FFFFFF 0px, var(--canvas-page) 720px); /* 좌상단이 아니라 상단 전역 광원 - body 배경 전용 */
  --rule: rgba(22, 24, 29, 0.08); /* 저알파 헤어라인. 잉크 알파 파생이라 겹침 표면에서도 톤이 맞는다 */
  --rule-strong: #16181D;    /* 구조 룰(잔여) — 리스타일에서 대부분 --rule로 강등, 소량만 잔존 */
  /* 잉크 */
  --ink-900: #16181D;        /* 본문·제목 */
  --ink-700: #3C414D;        /* 보조 텍스트 */
  --ink-500: #656C7C;        /* 캡션·뮤트 */
  /* 색 사용 규율 (2026-09-07 개정):
     - 인터랙션 = 바이올렛(--accent) 단독. CTA·링크·포커스에만 쓴다. 데이터 의미 금지.
     - 데이터 = 정당 상징색 토큰(--party-*)과 방향쌍(--dir-warm/--dir-cool)만.
       두 계열 모두 반드시 인접 텍스트 라벨을 병기한다. 색 단독 의미 전달 금지(WCAG 1.4.1).
     - 정당색은 도트·의석·스트립 세그먼트의 채움에만 쓴다. 텍스트 색으로 쓰지 않는다
       (정당명·수치 텍스트는 잉크 토큰 유지).
     - 정당색은 등재 사실의 표시이지 평가가 아니다. 의원 사이의 비교를 표현하는 어떤
       시각화에도 쓸 수 없다.
     - 2026-09-09 좁힘: 텍스트 링크는 잉크+밑줄, accent는 filled CTA·포커스·인용 마커·
       브랜드 표기 예외·상태 배지·히어로 헤드라인 강조 구절에만. */
  --accent: #4F3DE6;         /* 잉크 바이올렛: CTA, 링크, 포커스 */
  --accent-press: #3B2DB3;
  /* 방향축 중립쌍 (칩의 방향 단어에만) */
  --dir-warm: #6E4A38;       /* 확대·강화·신설 계열 */
  --dir-cool: #2F6B63;       /* 축소·완화·폐지 계열 */
  /* 정당 상징색 (위 규율의 "데이터" 계열). 종이 톤에 맞춰 원색보다 채도를 낮춘 값이고
     --paper·--card 위에서 논텍스트 대비 3:1을 넘는다. 2026-08-27 랜딩 설계에서 확정한
     landing.css 값을 2026-09-07 설계 §2에서 그대로 승격한 것이라 랜딩 렌더는 픽셀
     무변화다. 정당명 -> 키 매핑의 SSOT는 tools.party_color_key다(서버는 색 값을 모른다). */
  --party-dp: #1A5FB4;       /* 더불어민주당 */
  --party-ppp: #D64550;      /* 국민의힘 */
  --party-rkp: #2A6FDB;      /* 조국혁신당 */
  --party-nrp: #C96A14;      /* 개혁신당 (원 주황 #E8842E는 대비 미달이라 어둡게 보정) */
  --party-jp: #C43C4E;       /* 진보당 */
  --party-etc: #8A8F98;      /* 기타·무소속 */
  /* 형태 */
  --radius-tag: 4px;         /* 색인 태그(구 칩) */
  --radius-input: 8px;
  --radius-card: 12px;
  --radius-bubble: 18px;     /* 유저 질의 칩·날짜 칩 */
  --radius-composer: 24px;   /* 하단 컴포저 입력 컨테이너 */
  --radius-pill: 9999px;     /* CTA 단독 사용 */
  --focus-ring: 0 0 0 3px rgba(79, 61, 230, 0.30);
  /* 그림자 스케일. 큰 표면(답변 시트)은 여전히 무그림자다. 오너 마감 지시(프로토타입
     느낌 제거)에 따라 상호작용 크롬(말풍선·디스클로저 행·칩·컴포저·공유 버튼)에만
     아주 옅은 단차를 준다. 원장 톤 유지를 위해 회색 번짐은 최소로 억제한다.
     - shadow-xs: 행·칩·말풍선 등 페이지 위에 살짝 뜨는 소품
     - shadow-card: 컴포저·플로팅 독·팝오버(가까운 접지 + 넓은 번짐 2겹)
     - shadow-accent: filled CTA hover 글로우 전용. --accent의 알파 파생이라
       단일 CTA 색 규율 안이다(새 브랜드색 아님). */
  --shadow-xs: 0 1px 2px rgba(22, 24, 29, 0.06);
  --shadow-card: 0 2px 4px rgba(22, 24, 29, 0.04), 0 6px 16px rgba(22, 24, 29, 0.06);
  --shadow-accent: 0 2px 12px rgba(79, 61, 230, 0.28);
  /* citation 칩 배경(인터랙션 바이올렛의 옅은 틴트). 새 브랜드색이 아니라 --accent의
     알파 파생이다(G5 단일 CTA 색 규율 유지). */
  --cite-tint: rgba(79, 61, 230, 0.09);
  --cite-tint-strong: rgba(79, 61, 230, 0.17);
  /* ───── 촉각(tactile) 표면 레이어 (2026-09-14 시안) ─────
     광원은 화면 좌상단 하나로 고정한다. 모든 표면은 위쪽이 밝고 아래쪽에 1px 엣지와
     접촉 그림자가 붙는다. 흰 종이 위에서는 흰 하이라이트가 보이지 않으므로, 종이
     표면의 하이라이트는 위가 밝은 그라디언트(--grad-paper*)가 대신하고 --surface-hi
     (흰 안쪽 선)는 채워진 액센트 표면에만 쓴다.
     강도 규율: 그림자 총량을 늘리지 않고 엣지 두께와 표면 그라디언트로 입체를 만든다.
     원장 톤(평면 종이)은 답변 시트·표·타임라인에 그대로 남는다 - 아래 값들은 버튼·
     컨트롤·패널 같은 역할 있는 표면에만 붙는다. */
  --accent-lift: #6E5CF0;    /* 액센트를 한 단 밝힌 값. 그라디언트 상단 스톱 전용 */
  --surface-hi: rgba(255, 255, 255, 0.42);   /* 채워진 표면의 상단 안쪽 하이라이트 */
  --surface-lo: rgba(22, 24, 29, 0.07);      /* 종이 표면의 하단 안쪽 엣지 */
  --edge-hi: inset 0 1px 0 var(--surface-hi);
  --edge-lo: inset 0 -1px 0 var(--surface-lo);
  --edge-lo-primary: inset 0 -1px 0 var(--accent-press);
  --grad-primary: linear-gradient(180deg, var(--accent-lift) 0%, var(--accent) 55%, var(--accent-press) 100%);
  --grad-primary-hover: linear-gradient(180deg, var(--accent) 0%, var(--accent-press) 100%);
  --grad-primary-press: linear-gradient(180deg, var(--accent-press) 0%, var(--accent) 100%);
  --grad-paper: linear-gradient(180deg, #FFFFFF 0%, #F3F3F6 100%);       /* 보조 버튼 */
  --grad-paper-soft: linear-gradient(180deg, #FFFFFF 0%, #FAFAFC 100%);  /* 카드·패널 */
  /* 들림 2겹(가까운 접촉 + 넓은 앰비언트)과 눌림 1겹. 액센트 계열 그림자는 --accent·
     --accent-press의 알파 파생이라 단일 CTA 색 규율 안이다(새 브랜드색 아님). */
  --shadow-raise: 0 1px 1px rgba(22, 24, 29, 0.05), 0 3px 8px rgba(22, 24, 29, 0.07);
  --shadow-raise-hi: 0 2px 3px rgba(22, 24, 29, 0.06), 0 8px 18px rgba(22, 24, 29, 0.10);
  --shadow-raise-primary: 0 1px 1px rgba(59, 45, 179, 0.20), 0 3px 10px rgba(79, 61, 230, 0.22);
  --shadow-raise-primary-hi: 0 2px 4px rgba(59, 45, 179, 0.22), 0 8px 20px rgba(79, 61, 230, 0.30);
  --shadow-press: inset 0 2px 4px rgba(22, 24, 29, 0.14);
  --shadow-press-soft: inset 0 1px 2px rgba(22, 24, 29, 0.10);
  --shadow-press-primary: inset 0 2px 5px rgba(59, 45, 179, 0.50);
  --shadow-panel: 0 1px 2px rgba(22, 24, 29, 0.05), 0 12px 32px rgba(22, 24, 29, 0.08);
  /* 촉각 2단계: 랜딩 데모 창틀 전용 상위 티어(패널을 더 확실한 하드웨어로 읽히게 한다). */
  --shadow-panel-hi: 0 1px 2px rgba(22, 24, 29, 0.06), 0 10px 22px rgba(22, 24, 29, 0.08), 0 28px 60px rgba(22, 24, 29, 0.10);
  /* 폰트 스택 */
  --font-sans: "Pretendard Variable", Pretendard, "Apple SD Gothic Neo",
    "Noto Sans KR", system-ui, sans-serif;
  --font-mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
}

/* ───── 시맨틱(역할) 토큰 레이어 ─────
   위 원시 토큰은 "무슨 색인가"를 말하고, 여기 역할 토큰은 "어디에 쓰는 색인가"를
   말한다(shadcn/ui 관례 차용, React 없이 CSS 변수만). 값은 전부 위 원시 토큰의
   별칭이라 계산값이 한 픽셀도 달라지지 않는다. 리디자인이 아니라 체계화다.
   매핑 근거:
   - background/foreground = --paper / --ink-900 : 페이지 캔버스와 그 위 본문 잉크.
     body가 실제로 이 짝을 쓴다.
   - card = --paper-raised : 페이지보다 한 단 뜬 표면(카드·컴포저·팝오버·토스트).
   - muted / muted-foreground = --canvas / --ink-500 : 쿨그레이 소품 채움과
     캡션·뮤트 잉크. shadcn에서 이 둘은 짝이지만 여기서는 실제 사용처가 갈린다
     (채움은 칩·hover 배경, 뮤트 잉크는 캡션). 그래서 둘 다 둔다.
   - border = --rule : 저알파 헤어라인. input = 같은 헤어라인이지만 "폼 컨트롤 테두리"
     라는 별도 역할이라 shadcn 관례대로 이름을 나눠 둔다(값은 동일).
   - primary / primary-foreground = --accent / #FFFFFF : 단일 filled CTA 색과 그
     위 글자색. #FFFFFF는 발명값이 아니라 현행 실측값이다(.query-form button·
     .blog-cta-button·.blog-page-current·.impersonation-banner이 쓰던 #fff).
   - ring = --accent : 포커스 링 색. 전역 focus-visible 아웃라인이 참조한다.
   두지 않는 것: shadcn의 secondary·destructive·popover·chart-*는 이 제품에
   대응 역할이 없다(경보색 없음, 팝오버는 card와 같은 표면). 안 쓰는 토큰은
   만들지 않는다. --ink-700(보조 텍스트)·--sidebar-*·--dir-*도 shadcn에 대응
   역할이 없어 원시 토큰 이름 그대로 계속 쓴다. */
:root {
  --background: var(--paper);
  --foreground: var(--ink-900);
  --card: var(--paper-raised);
  --muted: var(--canvas);
  --muted-foreground: var(--ink-500);
  --border: var(--rule);
  --input: var(--rule);
  --primary: var(--accent);
  --primary-foreground: #FFFFFF;
  --ring: var(--accent);

  /* ───── 스케일 토큰 ─────
     간격: 현행 CSS 실측 빈도에서 뽑은 4px 기반 스케일(tailwind/shadcn 관례로
     space-N = 4N px, 반 단계는 -0-5 접미). 값은 전부 지금 하드코딩돼 있는 값을
     그대로 옮긴 것이라 참조로 바꿔도 픽셀이 움직이지 않는다. 실측 출현 횟수
     (주석 제외): 8px 74 · 12px 55 · 16px 25 · 4px 20 · 20px 17 · 32px 15 ·
     24px 7, 반 단계 6px 33 · 10px 31 · 2px 28. 반 단계가 이렇게 많이 쓰이므로
     스케일을 8px 배수로 좁히지 않고 4px 기반 + 반 단계로 둔다.
     radius: 위 --radius-* 6종이 이미 스케일이다(용도 명명). 새로 만들지 않고,
     흩어진 하드코딩(8px·999px)만 그 토큰 참조로 되돌린다.
     그림자: xs(소품) < card(컴포저·팝오버) < lg(홈 대형 컴포저) 3단. lg는 지금
     .query-form에 인라인으로 박혀 있던 2겹 값을 이름만 붙인 것이다. */
  --space-0-5: 2px;
  --space-1: 4px;
  --space-1-5: 6px;
  --space-2: 8px;
  --space-2-5: 10px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-8: 32px;
  --shadow-lg: 0 4px 12px rgba(22, 24, 29, 0.05), 0 16px 40px rgba(22, 24, 29, 0.09);

  /* 상태 레이어 상수(shadcn 관례의 ring width/offset, disabled 불투명도).
     ring 값은 기존 전역 focus-visible 규칙의 실측값(2px/2px)을 이름만 붙인 것이다. */
  --ring-width: 2px;
  --ring-offset: 2px;
  --disabled-opacity: 0.5;
}
* { box-sizing: border-box; }
/* 모바일 더블탭 300ms 지연 제거 (web-interface-guidelines) */
a, button, input, summary { touch-action: manipulation; }
/* 탭 하이라이트 회색 사각형 제거 — 원장 톤(무채·절제). */
a, button, summary { -webkit-tap-highlight-color: transparent; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  /* 리스타일: 상단 4px 잉크 바를 걷어내 단일 근백색 위에 콘텐츠가 바로 흐르게 한다
     (claude.ai 참조 룩, 강한 상단 크롬 제거).
     촉각 2단계: 순백 단색 바탕을 걷고 옅은 쿨 그레이 바탕(--canvas-page) 위에 상단
     흰 광원(--grad-canvas)만 얹는다. 흰 종이 표면(카드·컴포저·패널)이 이 바탕 위에서
     비로소 뜬 것으로 읽힌다(1단계는 바탕이 순백이라 흰 카드가 묻혔다). 720px 아래는
     평탄한 --canvas-page 단색이라 스크롤이 길어져도 반복 그라디언트 이음선이 없다. */
  background-color: var(--canvas-page);
  background-image: var(--grad-canvas);
  background-repeat: no-repeat;
  color: var(--foreground);
  font-family: var(--font-sans);
  font-weight: 400;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  /* sticky footer: 스레드 초반처럼 본문이 짧아도 판권면이 뷰포트 하단에 붙는다
     (실측: 턴 1개 시 푸터가 화면 중간에 떠 보이는 문제) */
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}
/* width:100%는 장식이 아니라 가로 넘침 방지다. body가 sticky footer 때문에
   flex column인데 .container는 `margin: 0 auto`를 쓴다 — flexbox에서 교차축
   auto 마진은 stretch를 무효화하므로 main이 뷰포트가 아닌 max-content로 잡힌다.
   그러면 nowrap 자식이 max-content를 밀어올려 좁은 화면에서 페이지 전체가 가로로
   삐져나간다. (원 재현자였던 히어로 "내 대화" 목록은 사이드바로 이관돼 사라졌지만,
   nowrap 자식에 의한 가로 넘침 방어는 일반적으로 유효하므로 이 규칙은 유지한다.) */
main { flex: 1 0 auto; padding-bottom: 56px; width: 100%; }
/* tabular 숫자(집계·표결수). 순수 숫자열의 모노 조판은 .mono가 담당한다. */
.num { font-variant-numeric: tabular-nums; }
/* 모노 숫자(날짜 레일·타임스탬프·집계) — 커밋 3에서 컴포넌트에 적용. */
.mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; letter-spacing: 0.01em; }
.container { max-width: 760px; margin: 0 auto; padding: 0 20px; }

/* ───── 상태 레이어 공통 규율 ─────
   인터랙티브 요소는 네 상태를 모두 갖는다: hover(포인터 예고) · focus-visible
   (키보드 위치) · active(눌림 피드백) · disabled(불가). 아래 두 규칙이 focus와
   disabled의 기본값을 깔고, hover/active는 각 컴포넌트가 자기 표면에 맞게 준다.
   컴포넌트별 press 관례는 세 갈래로 통일한다(이미 있던 것을 성문화):
   - 아이콘 버튼 → transform: scale(0.94)  (.share-button·.query-form button 관례)
   - 표면 버튼·디스클로저 행 → 배경 한 단 짙게(--border 또는 각 표면의 active 톤)
   - 텍스트 링크 → color: var(--accent-press) */

/* 공통 포커스 링(접근성): 키보드 사용자에게 항상 보이는 바이올렛 링.
   값은 기존과 동일하고 색·굵기·오프셋만 역할 토큰 참조로 바꿨다. */
a:focus-visible, button:focus-visible, input:focus-visible, summary:focus-visible {
  outline: var(--ring-width) solid var(--ring);
  outline-offset: var(--ring-offset);
  border-radius: var(--radius-input);
}
/* disabled 기본값(shadcn 관례: 불투명도 강등 + 포인터 무효). 현재 템플릿·JS가
   버튼을 disabled로 렌더하는 곳은 없어 시각 회귀가 없고, 앞으로 생기는 비활성
   버튼이 각자 다른 처리를 발명하지 않게 기본선을 깐다. 컴포저 전송 버튼은 배경을
   ink-500으로 바꾸는 고유 규칙이 있어 아래에서 opacity를 1로 되돌려 제외한다. */
button:disabled {
  opacity: var(--disabled-opacity);
  cursor: default;
}

/* 스킵 링크: 포커스 시에만 보이는 표준 패턴(키보드·스크린리더 본문 바로가기). */
.skip-link {
  position: absolute; left: 8px; top: -48px; z-index: 100;
  background: var(--card); color: var(--ink-900);
  border: 1px solid var(--border); border-radius: var(--radius-input);
  padding: var(--space-2) 14px; font-size: 14px; font-weight: 500;
  text-decoration: underline; text-underline-offset: 3px;
  transition: top .15s ease;
}
.skip-link:focus { top: var(--space-2); }

/* 폴리시(claude.ai 데스크톱 참조): 상단 헤더 바 폐지. 데스크톱은 사이드바가 브랜드·계정을
   품고 콘텐츠가 페이지 최상단부터 흐른다. 모바일(≤900px)만 미니 헤더(햄버거+브랜드)를
   남긴다. 기본 숨김, 아래 max-width:900 미디어 쿼리에서 flex로 켠다. */
.mobile-header { display: none; }
/* legacy 헤더(share.html·_blog_base.html·admin.html·admin_session.html 전용): 이 4개
   공개/어드민 페이지는 이번 폴리시 스코프 밖이라 기존 .site-header 마크업을 그대로
   렌더한다. index는 헤더를 안 쓰므로(폐지) 충돌이 없다. 규칙을 지워버리면 이 페이지들의
   헤더가 sticky/blur/보더/컨테이너 레이아웃을 전부 잃어 회귀가 나므로 유지한다. */
.site-header {
  background: rgba(255, 255, 255, 0.85);
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--rule);
  position: sticky; top: 0; z-index: 10;
}
.site-header .container {
  display: flex; justify-content: space-between; align-items: center;
  padding: 12px 20px;
}
.brand-reading {
  color: var(--ink-500); font-size: 13px; letter-spacing: -0.2px;
  border-left: 1px solid var(--rule); padding-left: 9px;
  transition: color .15s ease;
}
.brand:hover .brand-reading { color: var(--ink-900); }
@media (max-width: 480px) { .brand-reading { display: none; } }
/* 브랜드: 마크(타일 9) + 워드마크 9k1 + 읽기 보조. 9k1 = 구·케이·원 → 국회의원.
   유닛 7: 브랜드는 메인('/')으로 가는 링크다. 링크 기본 밑줄·색 상속을 정리하고,
   hover는 리딩 텍스트를 ink-900으로 짙게 하는 절제된 피드백만 준다(워드마크 색 유지,
   유채색 신규 사용 없음 — 원장 톤). 로고 클릭은 세션 리셋이 아니다(리셋은 [새 대화]). */
.brand {
  display: inline-flex; align-items: center; gap: 9px;
  text-decoration: none; color: inherit; cursor: pointer;
}
.brand:focus-visible {
  outline: none; box-shadow: var(--focus-ring); border-radius: var(--radius-input);
}
.brand-mark { width: 26px; height: 26px; display: block; border-radius: 6px; }
.wordmark {
  font-weight: 800; font-size: 17px; letter-spacing: -0.2px; color: var(--ink-900);
  font-variant-numeric: lining-nums;
}
/* 워드마크 강조 글자(브랜드 웨이브 B1, 오너 결정 D5). 숫자 9·1은 800으로 기록의
   주인공을 맡고 k만 한 단 가벼운 500 + 액센트로 눌러, 기울임 없이 웨이트·색 대비
   만으로 조판한다(Pretendard는 이탤릭이 없고 합성 오블리크는 품질이 낮다).
   G5 색 규율("인터랙션은 바이올렛 단독")의 브랜드 표기 예외는 이 한 곳뿐이다:
   로고 타일이 이미 액센트 면이라 화면의 유채색 총량이 늘지 않는다. 데이터·본문
   텍스트로 확장하지 않는다. */
.wordmark-k { font-weight: 500; color: var(--accent); }
/* 사이드바 최상단 브랜드 블록: 로고(26) + 워드마크가 주인공, 부제는 그 아래 캡션.
   목록 항목과 같은 좌측 정렬 리듬(padding 8px)에 위·아래 여백으로 위계를 준다. */
.sidebar-brand { padding: 6px 8px 0; margin-bottom: 0; }
.sidebar-brand .wordmark { font-size: 18px; }
.sidebar-brand .brand-mark { width: 28px; height: 28px; }
/* 제품 부제(구 brand-reading 값 이관): 워드마크 바로 아래 작은 캡션. 아래 여백으로
   [새 대화] 버튼과 분리해 브랜드 블록을 한 덩어리로 읽히게 한다. */
.sidebar-subtitle { margin: 3px 0 16px; padding: 0 8px 0 45px; font-size: 11px;
  color: var(--ink-500); letter-spacing: -0.1px; line-height: 1.3; }

/* 계정 영역(유닛 3 이관 → 사이드바 하단 고정, claude.ai 패턴). 목록(#sidebar-list)이
   flex:1로 늘어 이 블록을 사이드바 바닥에 앉힌다. 상단 얇은 구분선 + 이메일(말줄임) +
   작은 로그아웃/로그인 링크. 유채색 신규 없음(링크는 --accent 하나, 원장 단일 CTA 규율).
   시크릿 미설정 시 서버가 이 블록을 아예 렌더하지 않는다(oauth_enabled 서버측 조건). */
.sidebar-account {
  margin-top: 8px; padding: 8px 4px 2px;
  border-top: 1px solid rgba(22, 24, 29, 0.05);   /* 존재감 낮춘 구분선(오너 지시) */
}
/* 로그인 상태: 이메일(말줄임) + 로그아웃 아이콘 버튼. 파란 하이퍼링크(--accent) 폐지.
   로그아웃은 잉크 톤 아이콘 버튼(ink-500 → hover ink-900 + 옅은 배경). */
.account-row { display: flex; align-items: center; gap: 6px; }
.account-email {
  flex: 1; min-width: 0; padding-left: 6px;
  color: var(--ink-700); font-size: 13px; letter-spacing: -0.1px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.account-logout {
  flex: none; width: 30px; height: 30px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--ink-500); border-radius: var(--radius-input);
  text-decoration: none; transition: color .15s ease, background-color .15s ease;
}
.account-logout:hover { color: var(--ink-900); background: var(--sidebar-row-hover); }
.account-logout:active { background: var(--sidebar-row-active); }
.account-logout svg { display: block; }
/* 비로그인: 정식 버튼(보더 + 흰 배경 + hover). "Google로 로그인"을 파란 링크가 아니라
   원장 톤 아웃라인 버튼으로 마감한다(오너 지시). 유채색 신규 없음. */
.account-login {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  width: 100%; min-height: 38px; padding: 0 12px;
  color: var(--ink-900); font-size: 13px; font-weight: 500; text-decoration: none;
  background: var(--card); border: 1px solid var(--border);
  border-radius: var(--radius-input);
  transition: border-color .15s ease;
}
.account-login:hover { border-color: var(--ink-500); }
.account-login:active { background: var(--muted); }
.account-login svg { display: block; flex: none; color: var(--ink-500); }
/* .auth-link: 사이드바 밖 잔존 사용처 전용(블로그 푸터 링크, 공유 UI 링크, 블로그 back).
   계정 영역은 위 .account-*가 담당하므로 여기 파란 링크색이 사이드바로 새지 않는다. */
.auth-link {
  color: var(--ink-900); font-size: 13px; font-weight: 500;
  text-decoration: underline; text-underline-offset: 3px;
}
.auth-link:hover { text-decoration-thickness: 2px; }
.auth-link:active { color: var(--ink-700); }

/* 스레드 공유 UI(유닛 U4 → 폴리시). 뷰포트 고정(position: fixed) 폐지: 스크롤할 때
   첫 말풍선과 겹쳐 보인다는 피드백을 받아 문서 흐름 안(#results 기준 absolute)으로
   내린다. 날짜 칩(.thread-date) 행과 같은 높이 라인의 우측 끝에 놓여 콘텐츠와 함께
   스크롤된다. 좌우 위치는 콘텐츠 컬럼이 결정하므로 뷰포트 폭 계산이 필요 없다.
   버튼은 스레드 뷰(완료 턴 존재)에서만 hidden이 풀린다.
   z-index 9는 스티키 모바일 헤더(10)보다 낮다: 이제 문서와 함께 스크롤되므로 헤더
   밑으로 지나가야 한다. 아래 .share-note/.share-fallback의 11은 이 요소가 만드는
   스택 컨텍스트 안쪽 값이라 서로의 순서는 그대로다(둘 다 함께 9로 내려간다). */
.share-ui {
  position: absolute; top: 18px; right: 0; z-index: 9;
  display: inline-flex; align-items: center; gap: 10px;
}
/* 공유 버튼(아이콘화): 필 대신 정사각 아이콘 버튼. 글리프는 잉크(accent 다이어트:
   filled CTA가 아닌 보조 컨트롤), hover 시 border-color 잉크. 복사 성공 시 .share-copied
   토글로 share-icon → share-check 전환 (두 SVG 겹침, 클래스만 — innerHTML 조작 없음). */
/* tactile 시안: 종이 표면이 살짝 솟은 보조 컨트롤(채워진 CTA 아님). 표면 그라디언트
   + 하단 안쪽 엣지 + 얇은 접촉 그림자. 치수·색은 그대로다. */
.share-button {
  appearance: none;
  background-color: var(--card); background-image: var(--grad-paper);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);   /* 실측 999px → 34px 원형에는 동일한 완전 원 */
  width: 34px; height: 34px; padding: 0; color: var(--ink-500);
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer; box-shadow: var(--edge-lo), var(--shadow-raise);
  transition: border-color .15s ease, background-color .15s ease, box-shadow .15s ease, transform .12s ease;
}
.share-button:hover {
  border-color: var(--ink-500);
  background-color: var(--card); background-image: var(--grad-paper);
  box-shadow: var(--edge-lo), var(--shadow-raise-hi);
}
/* 눌림: 표면을 평면으로 되돌리고 안쪽 그림자만 남긴다(솟음의 반대). */
.share-button:active {
  background-image: none; transform: scale(0.94); box-shadow: var(--shadow-press);
}
.share-button:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.share-button svg { display: block; }
.share-button .share-check { display: none; }
.share-button.share-copied .share-icon { display: none; }
.share-button.share-copied .share-check { display: block; }
.share-note {
  position: absolute; top: calc(100% + 12px); right: 0; white-space: nowrap;
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-input);
  padding: var(--space-1-5) var(--space-3); font-size: 13px; color: var(--muted-foreground);
  box-shadow: var(--shadow-card); z-index: 11;
  max-width: calc(100vw - 32px); overflow: hidden; text-overflow: ellipsis;
}
.share-note:empty { display: none; }
.share-fallback { position: absolute; top: calc(100% + 12px); right: 0; z-index: 11; }
.share-fallback input {
  width: 240px; font-size: 12px; padding: 5px var(--space-2); border: 1px solid var(--input);
  border-radius: var(--radius-input); background: var(--card); color: var(--foreground);
}

/* 히어로 — 논지 그 자체(“있는 그대로”) + 언어유희 고스트 숫자 */
/* overflow는 clip이어야 한다: hidden은 프로그램적 스크롤 컨테이너라서, 인풋 포커스
   시 브라우저가 hero.scrollLeft를 밀어 좌측이 잘리는 버그가 실측됐다(고스트 숫자가
   우측으로 삐져나가 scrollWidth > clientWidth인 상태). clip 미지원 브라우저 폴백으로
   hidden을 먼저 선언. */
/* 폴리시: 상단 헤더 바 폐지로 생긴 여백을 반영해 히어로를 수직 중앙 느낌으로 내린다
   (claude.ai 홈처럼 타이틀+컴포저가 위쪽에 붙지 않게). 좌측 정렬·고스트 숫자 유지. */
.hero { position: relative; padding: clamp(56px, 13vh, 148px) 0 28px; overflow: hidden; overflow: clip; }
.hero-body { position: relative; z-index: 1; }
/* 고스트 워터마크 "9k1" 폐지(오너 지시: 프로토타입 느낌). 요소는 DOM에 남지만 숨긴다. */
.hero-ghost { display: none; }
.hero h1 {
  font-size: 56px; font-weight: 800; letter-spacing: -0.035em; line-height: 1.14;
  margin: 0 0 10px; color: var(--ink-900); text-wrap: balance;
}
.lede {
  color: var(--ink-700); font-size: 17px; line-height: 1.55;
  max-width: 60ch; margin: 0 0 24px;
}
/* 예시 질문 알약 칩(오너 지시: 각진 보더 박스 → 라운드 필). 클릭 시 인풋 채움. */
.hero-examples { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; }
/* tactile 시안: 히어로 칩도 컴포저와 같은 화면에 사는 컨트롤이라 같은 재질을 입는다
   (한 화면 재질 통일). 강도는 보조 버튼 급이다. */
.example-q {
  font-family: inherit; font-size: 13px; color: var(--ink-700);
  background-color: var(--card); background-image: var(--grad-paper);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill); padding: 9px var(--space-4); min-height: 40px;
  box-shadow: var(--edge-lo), var(--shadow-raise);
  cursor: pointer;
  transition: border-color .15s ease, background-color .15s ease, box-shadow .15s ease;
}
.example-q:hover {
  border-color: var(--ink-500); background-color: var(--muted);
  box-shadow: var(--edge-lo), var(--shadow-raise-hi);
}
.example-q:active { background: var(--border); box-shadow: var(--shadow-press); }

/* ChatGPT 랜딩 참조: 홈(비스레드)은 헤드라인 + 큰 컴포저를 뷰포트 세로 정중앙에 두고,
   커버리지 고지는 최하단 fine print로 내린다. 모든 규칙을 #main(index 전용 id — share의
   body.share-view .coverage나 plain-body 블로그로 새지 않게)로 스코프하고, 스레드 뷰
   (body.is-thread)엔 적용하지 않아 답변 맥락의 기존 커버리지 노출은 그대로 둔다. */
body:not(.is-thread) #main { display: flex; flex-direction: column; }
body:not(.is-thread) #main .hero {
  margin-top: auto; padding: 24px 0 8px; text-align: center;
}
body:not(.is-thread) #main .hero-body { max-width: 640px; margin: 0 auto; }
body:not(.is-thread) #main .hero h1 { font-size: 44px; margin-bottom: 8px; }
body:not(.is-thread) #main .lede {
  max-width: 52ch; margin: 0 auto 22px; font-size: 15px; color: var(--ink-500);
}
body:not(.is-thread) #main .hero-examples { justify-content: center; margin-top: 16px; }
/* 히어로 세로 중앙의 아래쪽 추. 예전에는 .coverage가 margin-top:auto로 이 역할을 했는데
   오너 지시(2026-09-07)로 커버리지 고지 블록을 걷어냈다. 빈 ::after로 같은 추를 남긴다 -
   이게 없으면 .hero의 margin-top:auto만 남아 히어로가 중앙이 아니라 바닥에 붙는다. */
body:not(.is-thread) #main::after { content: ""; margin-top: auto; }
/* 홈 컴포저: 히어로의 주인공답게 크고 존재감 있게(오너 지시). 하단 도크(스레드 뷰)는
   기존 크기를 유지하도록 이 확대는 홈에만 스코프한다. */
body:not(.is-thread) #main .query-form {
  padding: var(--space-1-5) var(--space-1-5) var(--space-1-5) 22px; border-radius: 28px;
  box-shadow: var(--edge-lo), var(--shadow-lg);
}
/* 확대된 box-shadow가 컴포저 기본 :focus-within 포커스 링을 덮으므로 홈에서도 링을
   복원한다(키보드 포커스 가시성 보존). 링을 맨 앞에 두고 단차는 뒤에 남긴다. */
body:not(.is-thread) #main .query-form:focus-within {
  border-color: var(--accent);
  box-shadow: var(--focus-ring), var(--edge-lo), var(--shadow-lg);
}
body:not(.is-thread) #main .query-form input { min-height: 46px; font-size: 16px; }
/* 홈 전송은 랜딩 히어로 제출(48px)과 같은 치수로 두 표면을 일치시킨다(QA 2026-09-13). */
body:not(.is-thread) #main .query-form button[type="submit"] { width: 48px; height: 48px; }
/* 모바일: 홈 헤드라인을 축소한다. #main 스코프가 id 특이도라 아래 max-width:600
   .hero h1(32px)를 이기므로 홈에서도 같은 특이도로 32px를 명시해 준다(가로 넘침 방지). */
@media (max-width: 600px) {
  body:not(.is-thread) #main .hero h1 { font-size: 32px; }
}

/* (구 "내 대화" 서버 스레드 목록 스타일 .my-threads*는 좌측 사이드바로 이관돼 삭제됨 ,
   .sidebar* 컴포넌트가 대체한다.) */

/* 질의 폼 (리스타일): 입력창+전송을 하나의 라운드 컨테이너로 묶는다(claude/ChatGPT
   컴포저). 검은 2px 테두리 폐기 → 1px 연한 rule + 흰 배경 + 미세 그림자, radius 24px.
   입력은 컨테이너 안에서 무테두리·투명 배경으로 앉고, 전송은 우측 36px 원형 액센트. */
/* tactile 시안: 컴포저는 페이지 위에 살짝 솟은 종이 알약이다. 표면 그라디언트(위가
   밝다) + 하단 안쪽 엣지 + 접촉·앰비언트 2겹. 치수(패딩·높이)는 한 픽셀도 건드리지
   않는다 - 도크 알약 50px 계약이 이 규칙의 패딩에 걸려 있다.
   background를 색·이미지 롱핸드로 나눠 쓰는 이유: 그라디언트 토큰이 어떤 이유로든
   무효가 돼도 표면이 투명해지지 않고 기존 단색으로 내려앉는다. */
.query-form {
  display: flex; gap: var(--space-2); align-items: center;
  background-color: var(--card); background-image: var(--grad-paper-soft);
  border: 1px solid var(--input);
  border-radius: var(--radius-composer);
  /* 촉각 2단계: 채팅 컴포저는 화면에서 가장 눌러야 할 표면이라 그림자를 한 단 올린다. */
  box-shadow: var(--edge-lo), var(--shadow-raise-hi);
  padding: 5px 5px 5px 18px;
  transition: border-color .15s ease, box-shadow .15s ease;
}
/* 포커스 링은 맨 앞에 두고 들림 그림자를 뒤에 이어 둔다(링이 단차를 지우지 않게). */
.query-form:focus-within {
  border-color: var(--accent);
  box-shadow: var(--focus-ring), var(--edge-lo), var(--shadow-raise-hi);
}
.query-form input {
  flex: 1; min-width: 0; padding: var(--space-2) 0; min-height: 40px; font-size: 16px;
  border: none; background: none; color: var(--foreground);
}
.query-form input::placeholder { color: var(--muted-foreground); }
/* 포커스 링은 컨테이너 :focus-within이 담당한다 — 무테두리 입력에 중복 아웃라인이
   그려지지 않게 여기서만 억제(키보드 포커스 가시성은 컨테이너 링으로 보존). */
.query-form input:focus, .query-form input:focus-visible { outline: none; }
/* 전송 = 유일한 filled 바이올렛 CTA. 컨테이너 내부 우측의 44px 원형(밖에 떠 있는
   대형 버튼 폐기). 44px는 모바일 터치 타깃 하한이자 도크의 [새 대화] 연필(44px
   고스트)과 같은 치수다(디자인 QA 2026-09-13: 종전 36px가 홈 48px 대비 작았다).
   도크 알약 높이는 그대로 50px다(44 + 도크 패딩 3 x 2). 아이콘 stroke는
   currentColor(=버튼 색 #fff).
   셀렉터를 button[type="submit"]으로 좁힌다(2026-09-07): 스레드 모드에서 [새 대화]
   연필(type="button")이 알약 안으로 들어오므로, 태그 셀렉터 .query-form button은
   특이도(0,1,1)로 .new-thread(0,1,0)를 이겨 연필까지 filled 바이올렛으로 칠한다 -
   단일 CTA 규율(알약 안 filled는 전송 하나) 위반이다. */
.query-form button[type="submit"] {
  flex: none; align-self: center;
  width: 44px; height: 44px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  /* tactile 시안: 도톰한 플라스틱 표면. 위가 밝은 액센트 그라디언트 + 상단 1px 안쪽
     하이라이트 + 하단 눌림색 엣지 + 접촉·앰비언트 2겹. 치수 44px는 불변이다. */
  background-color: var(--primary); background-image: var(--grad-primary);
  color: var(--primary-foreground); border: none;
  border-radius: var(--radius-pill); cursor: pointer;
  box-shadow: var(--edge-hi), var(--edge-lo-primary), var(--shadow-raise-primary);
  transition: background-color .15s ease, box-shadow .15s ease, transform .12s ease;
}
.query-form button[type="submit"]:hover {
  background-color: var(--accent-press); background-image: var(--grad-primary-hover);
  box-shadow: var(--edge-hi), var(--edge-lo-primary), var(--shadow-raise-primary-hi);
}
/* 눌림: 그라디언트를 뒤집어 광원이 아래에서 오는 것처럼 보이게 하고 안쪽 그림자를
   넣는다. 축소(0.94)는 이 파일의 아이콘 버튼 press 관례 그대로다. */
.query-form button[type="submit"]:active {
  background-color: var(--accent-press); background-image: var(--grad-primary-press);
  transform: scale(0.94); box-shadow: var(--shadow-press-primary);
}
/* opacity: 1은 위 공통 button:disabled의 불투명도 강등을 이 버튼에서만 되돌린다.
   filled CTA는 배경 자체를 ink-500으로 바꾸는 고유 비활성 처리가 이미 있다. */
.query-form button[type="submit"]:disabled {
  background: var(--ink-500); cursor: default; box-shadow: none; transform: none;
  opacity: 1;
}
.query-form button[type="submit"] svg { display: block; }
.htmx-indicator { display: none; color: var(--ink-500); font-size: 14px; padding: 12px 2px; }
.htmx-request .htmx-indicator, .htmx-request.htmx-indicator { display: block; }

/* SSE 진행 단계 표시 — #results 안에서 최종 카드로 교체되기 전까지 보인다.
   .progress-phase는 서버가 보내는 단일 조각(하위호환), 실제 표시는 progress.js가
   .progress-log 패널로 누적한다. */
.progress-phase { color: var(--ink-500); font-size: 14px; padding: 12px 2px; margin: 0; }
/* 수신 로그 패널. 폴리시(톤다운): 개발자 스타일(타임스탬프 + 사각 마커) 폐지.
   .ts·.dot 노드는 남기되(JS 훅 보존) CSS로 숨기고, 은은한 단일 톤 텍스트만 남긴다.
   현재 단계는 한 단계 진한 톤 + 부드러운 호흡 애니메이션(말줄임 점은 서버 문구에 이미
   포함). reduced-motion 전역 무력화가 애니메이션을 자동으로 끈다. */
.progress-log {
  border: 1px solid var(--border); border-radius: var(--radius-card);
  background: var(--card); padding: 14px var(--space-4); margin: var(--space-4) 0;
}
.progress-line {
  font-size: 14px; color: var(--ink-500); padding: 2px 0; margin: 0; line-height: 1.6;
}
.progress-line .dot, .progress-line .ts { display: none; }   /* 사각 마커·타임스탬프 제거 */
.progress-line.is-current { color: var(--ink-700); }
.progress-line.is-current .msg { animation: phase-pulse 1.4s ease-in-out infinite; }
@keyframes phase-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.55; } }
/* 연결 상태 고지 줄(전환·끊김). 처리 과정 줄이 아니라는 걸 한 톤 옅게 구분한다. */
.progress-note { color: var(--ink-500); opacity: 0.8; font-style: italic; }

/* 완료 후 접힌 처리 과정 블록. 답변 위에 놓이고 기본은 접혀 있다. 진행 중 패널
   (.progress-log)의 스타일은 건드리지 않는다. 여기서는 타임스탬프를 보여준다:
   지나간 기록이라 진행 패널의 톤다운 규칙(.ts 숨김)이 적용될 이유가 없다. */
details.turn-process {
  border: 1px solid var(--border); border-radius: var(--radius-card);
  background: var(--card); padding: var(--space-2) 14px; margin: 0 0 var(--space-4);
  box-shadow: var(--shadow-xs);
}
details.turn-process > summary {
  cursor: pointer; font-size: 13px; color: var(--muted-foreground); padding: var(--space-1) 0;
}
details.turn-process > summary:hover { color: var(--ink-700); }
details.turn-process > summary:active { color: var(--foreground); }
.turn-process-steps { list-style: none; padding: 8px 0 4px; margin: 0; }
.turn-process-steps li {
  display: flex; gap: 10px; font-size: 13px; color: var(--ink-500);
  padding: 2px 0; line-height: 1.6;
}
.turn-process-steps li .ts { flex: none; opacity: 0.75; }

/* position: relative는 .share-ui(문서 흐름 안으로 내린 공유 UI)의 absolute 기준점이다.
   공유 페이지(share.html)의 #results에도 걸리지만 거기엔 .share-ui가 없어 무해하다. */
#results { display: block; position: relative; }

/* ---- 멀티턴 대화 스레드 (세션 스펙 6, 원장 기입 언어 계승) ----
   신규 요소는 전부 기존 잉크·룰 토큰만 쓴다(G5 유채색 없음). filled CTA는 "전송"
   하나 유지, [새 대화]는 보더·배경 없는 조용한 ghost 텍스트. */
.thread { list-style: none; margin: 0; padding: 0; }
.turn { margin: 0; }
/* 질의 채팅 버블: 유저가 보낸 메시지처럼 우측 정렬. 답변(.turn-answer)은 기존처럼
   좌측 전폭 그대로 두어 질의-답변의 대화형 시각 리듬을 만든다(첫 질의 포함 전 턴
   동일 — Kevin 피드백: "첫 메시지가 잘 눈에 안 들어와"). 채워진 바이올렛은 질의 폼
   전송 버튼과 같은 --accent 하나뿐이라 단일 CTA 색 규율(G5)을 어기지 않는다. */
/* 턴 구분(유닛 9): 1px 룰 폐기 — 턴 사이는 여백으로만 구분한다. 간격 8pt 스케일 통일:
   턴 간 여백 크게(위 32px), 턴 내 요소 간 작게(8px). */
.turn-entry {
  display: flex; flex-direction: column; align-items: flex-end; gap: 8px;
  padding: 32px 0 8px;
}
.turn:first-child .turn-entry { padding-top: 8px; }
/* 리스타일: 대형 보라 버블 → 우측 정렬 컴팩트 칩. 채도 높은 액센트 대면적을 걷고
   중립 쿨그레이 배경 + 진한 잉크 텍스트로, radius 18px, padding 10px 16px, max-width 75%. */
.turn-bubble {
  max-width: 75%; color: var(--ink-900);
  border-radius: var(--radius-bubble); padding: 10px 16px;
  /* 마감: 페이지 위 미세 단차(1px 톤 경계 + 옅은 그림자)로 말풍선이 캔버스에서 살짝
     떠 보이게 한다. 채도 높은 대면적 없이 계층감만 준다.
     촉각 2단계: 바탕이 쿨 그레이(--canvas-page)로 내려간 뒤로 이 버블은 --canvas
     소품 채움과 값이 거의 같아져 바탕에 묻힌다. 종이 솟음(흰 표면 + edge-lo + raise)으로
     바꿔 랜딩 데모 질문 버블(.landing-demo-query)과 같은 재질로 맞춘다. */
  background-color: var(--card); background-image: var(--grad-paper);
  border: 1px solid rgba(22, 24, 29, 0.04); box-shadow: var(--edge-lo), var(--shadow-raise);
}
.turn-q {
  margin: 0; font-size: 15px; font-weight: 500; color: inherit;
  letter-spacing: -0.1px; line-height: 1.5;
  white-space: pre-wrap; word-break: break-word;   /* 긴 질의 줄바꿈 */
}
/* 폴리시 원복(2026-08-25, Kevin 요청): hover/focus 시에만 노출하던 것을 상시 노출로
   되돌린다. 채팅 UI에서 메시지 시간이 항상 보여야 한다는 요구. 노드는 그대로이며
   (JS 훅·저장 포맷 불변) 시각적 숨김 규칙만 제거한다. */
.turn-ts {
  color: var(--ink-500); font-size: 12px;
}
/* 답변 완료 시각. 질의 말풍선의 ts가 버블 아래 우측이므로 답변 ts는 본문 아래 좌측에
   두어 대칭을 만든다. 톤은 .turn-ts와 동일(연한 잉크 12px). */
.answer-ts {
  display: block; margin-top: 8px;
  color: var(--ink-500); font-size: 12px;
}
/* 답변 시트 (유닛 9, 비주얼 리뷰 확정안): 어시스턴트 한 턴 = 한 장의 흰 시트.
   답변 헤더·산문·근거·고지가 전부 이 표면 안에서 산다. 원장 요소(룰·모노 숫자·날짜
   레일)는 시트 내부에 거주한다. 스코프는 클라이언트 래퍼 .turn-answer 한정 —
   홈/비스레드 렌더에는 영향이 없다. */
/* 리스타일: 답변 시트의 흰 카드+테두리 폐기 — 페이지 배경 위에 텍스트가 바로 흐른다.
   턴 사이 구분은 여백(.turn-entry 상단 패딩)이 담당한다. */
.turn-answer {
  background: none; border: none; border-radius: 0; padding: 0;
  max-width: 68ch; margin: 8px 0 0;
}
/* 빈 시트 깜빡임 방지: newTurn/resumeStream이 비운 .turn-answer가 첫 SSE 이벤트 전까지
   빈 상자로 뜨지 않게 한다(첫 진행 줄이 붙으면 :empty가 풀려 표시된다). */
.turn-answer:empty { display: none; }
.turn-answer .answer { margin-top: 0; }
/* 답변 상단 크롬 압축: 전폭 하단 rule 폐기 — 헤더 메타를 여백으로만 본문과 가른다
   (카드 배경·보더·그림자는 이미 .card에서 강등). */
.turn-answer .answer-header {
  background: none; border: none; box-shadow: none; border-radius: 0;
  padding: 0; margin: 0 0 4px;
}
/* 진행 로그도 시트 안에선 카드 인 카드가 되므로 표면을 무력화해 시트에 자연스럽게
   이어붙인다(스트리밍 중 시트 내용이 진행 로그뿐이라 이중 상자가 특히 두드러진다). */
.turn-answer .progress-log {
  border: none; background: none; box-shadow: none; padding: 0; margin: 0;
}

/* 공유 정적 뷰(share.html body.share-view) 전용 —————————————————————————
   표제는 얌전하게(18~20px), 인용 마커는 JS 없는 정적 스냅샷이라 무동작 처리한다
   (인라인 style·JS는 share CSP로 차단되므로 body 클래스 스코프로 링크된 style.css에서 처리). */
.share-title {
  font-size: 19px; font-weight: 700; letter-spacing: -0.2px; line-height: 1.35;
  color: var(--ink-900); margin: 0 0 10px;
}
body.share-view .cite { pointer-events: none; cursor: default; }

/* 세션 부기 문구 (DEGRADED_NOTE와 동일 부기 패턴): 만료 갱신·상한 강등 고지 1줄 */
.session-note {
  color: var(--ink-700); font-size: 13px; line-height: 1.5; margin: 0 0 10px;
  padding-left: 10px; border-left: 2px solid var(--rule);
}

/* 하단 고정 입력 도크(컴포저 전용, 유닛 9): 캔버스 위에 뜨는 종이 배경 + 옅은 상단
   그림자로 경계를 준다(1px 룰 대신). 판권면은 더 이상 이 안으로 들어오지 않는다 —
   스크롤 자연 끝에 인-플로우로 남는다. */
.query-dock {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 20;
  /* 리스타일: 불투명 박스·상단 그림자 폐기. 페이지색이 위로 갈수록 투명해지는
     그라디언트 페이드로 컴포저를 본문 위에 얹는다(claude/ChatGPT 방식).
     촉각 2단계: 도크는 스크롤 끝(페이지 하단)에 앉는 크롬이라 순백(--paper)이 아니라
     페이지 바탕(--canvas-page)과 이어져야 한다. 안 그러면 도크 불투명 구간이 그 위
     본문보다 밝은 흰 띠로 떠 보인다. */
  background: linear-gradient(to top, var(--canvas-page) 60%, rgba(255, 255, 255, 0));
  /* 홈 인디케이터(iOS)·제스처 바 영역만큼 하단 패딩 확보. offsetHeight가 이 값을
     포함하므로 progress.js updateDockSpacing의 body 여백 예약에 자동 반영된다. */
  /* 상단 패딩 16px -> 8px (오너 지시 2026-09-07 스크린샷: 컴포저와 그 주변이 본문에서
     떨어져 둥둥 뜬다). 페이드 그라디언트가 이미 경계를 지므로 위쪽 여백은 얇아도 된다. */
  padding: 8px 0 calc(12px + env(safe-area-inset-bottom));
}
.query-dock .container {
  display: flex; gap: 8px; align-items: center; flex-wrap: wrap;
}
/* 도크 알약은 [새 대화] 아이콘을 **안쪽 첫 자리**로 품는다(progress.js enterThreadMode).
   좌측 패딩을 우측과 같은 5px로 맞춰 44px 고스트 버튼이 알약 안쪽 가장자리에 앉게 하고,
   세로 패딩은 5px -> 3px로 줄여 알약 높이를 종전 그대로 묶는다: 알약 높이는 가장 큰
   자식이 정하는데 종전 최대는 입력(min-height 40px)이라 40 + 5 x 2 = 50px였고, 이제
   최대가 44px 버튼이라 44 + 3 x 2 = 50px다. 히어로 컴포저는 이 버튼을 품지 않아 스코프 밖. */
.query-dock .query-form { flex: 1 1 auto; min-width: 0; padding: 3px 5px; }
/* 확정 의원 컨텍스트 칩(오너 승인 2026-09-06): 컴포저 바로 위 한 줄 고정 표기.
   종이 카드 + 저알파 헤어라인 관례를 그대로 쓴다(--card/--border/--radius-input). 새 색을
   만들지 않는다. 모바일에서 입력창을 밀지 않도록 nowrap + 이름만 말줄임으로 한 줄에
   가둔다(칩 자체가 줄바꿈하면 도크가 자라 입력창이 화면 밖으로 밀린다). */
.query-dock .member-chip {
  flex: 0 1 auto; min-width: 0;
  display: inline-flex; align-items: center; gap: 6px;
  max-width: 100%; padding: 4px 10px; margin-bottom: 6px;
  background: var(--card); border: 1px solid var(--border);
  border-radius: var(--radius-input);
  font-size: 12px; line-height: 1.4; white-space: nowrap; overflow: hidden;
}
/* 빈 칩 노출 버그(오너 지시 2026-09-07 스크린샷): 위 규칙의 display: inline-flex가
   hidden 속성의 UA display: none을 이겨, 값이 없어 progress.js가 hidden으로 되돌린
   칩이 "조회 대상" 라벨만 달고 컴포저 위에 떠 있었다. hidden을 되살린다. */
.query-dock .member-chip[hidden] { display: none; }
.member-chip-label { flex: none; color: var(--ink-500); }
.member-chip-value {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; color: var(--ink-700);
}
/* [새 대화] = 조용한 ghost 아이콘 버튼(유닛 8, 유닛 2의 텍스트 버튼 대체). 입력창 좌측에
   놓여 세션을 리셋한다. 단일 CTA 규율: filled는 "전송" 하나뿐 — 이 버튼은 무보더·무배경,
   무채(currentColor) ink-500 → hover ink-900. 44px 히트박스. */
.new-thread {
  flex: none; align-self: center;
  width: 44px; height: 44px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  background: none; color: var(--muted-foreground); border: none;
  border-radius: var(--radius-input); cursor: pointer;
  transition: color .15s ease, transform .12s ease;
}
.new-thread:hover { color: var(--foreground); }
.new-thread:active { transform: scale(0.94); }
.new-thread svg { display: block; }

/* 도크 판권 줄 (오너 지시 2026-09-07): 컴포저 바로 아래 캡션 한 줄. 스레드 모드에서
   숨기는 인-플로우 판권면을 대신해 출처표시 의무(이용약관 제7조)를 진다. 도크의
   .container가 flex라 p 하나를 늘려 가운데 정렬한다(컴포저 폭과 같은 축). 도크
   그라디언트는 하단 60%가 불투명 --paper라 이 줄이 놓이는 자리에서는 페이드가 아니라
   단색 위다 - 본문 글자가 비쳐 읽기 어려워지지 않는다. */
.query-dock .dock-attribution {
  flex: 1 1 auto; min-width: 0;
  margin: 4px 0 0; text-align: center;
  color: var(--ink-500); font-size: 11px; line-height: 1.4;
}

/* 어드민 임퍼서네이션 배너: 읽기 전용 보기 중임을 상시 고지. --accent 사용은
   인터랙션 전용 규율의 예외가 아니라 "현재 모드" 상태 표시라 CTA 계열로 취급.
   데스크톱은 body padding-left(260px) 안쪽 콘텐츠 컬럼에, 모바일은 전폭에 스티키.
   z-index 30은 헤더(10)·도크(20) 위. 모바일 drawer(오버레이 40·사이드바 50)는 배너를
   덮는다(모달 우선). */
.impersonation-banner {
  position: sticky; top: 0; z-index: 30;
  display: flex; align-items: center; justify-content: center; gap: 12px;
  padding: var(--space-2) var(--space-4); background: var(--primary);
  color: var(--primary-foreground);
  font-size: 13px; letter-spacing: -0.2px;
}
.impersonation-exit-form { margin: 0; }
.impersonation-exit {
  border: 1px solid rgba(255, 255, 255, 0.6); border-radius: var(--radius-tag);
  background: transparent; color: var(--primary-foreground); font-size: 12px;
  padding: var(--space-0-5) var(--space-2-5);
  cursor: pointer;
}
.impersonation-exit:hover { background: rgba(255, 255, 255, 0.14); }
.impersonation-exit:active { background: rgba(255, 255, 255, 0.24); }
/* 임퍼서네이션 중 대상 유저 answerHTML은 sandbox iframe으로 격리 렌더(stored XSS
   방어). iframe은 자동 높이가 없어 고정 높이 + 내부 스크롤(admin.css .admin-answer-frame
   관례). */
.impersonation-answer-frame {
  width: 100%; height: 420px; border: 1px solid var(--border);
  border-radius: var(--radius-card); background: var(--card);
}

/* 스테일 탭 안내 배너(#stale-banner): 새 버전이 떴는데 자동 새로고침을 할 수 없을 때만
   노출된다(입력창에 작성 중이거나, 같은 버전으로 이미 1회 새로고침했는데도 불일치가
   남은 경우). 사이드바 레이아웃과 겹치지 않게 화면 상단 중앙에 떠 있는 조용한 칩으로
   둔다(.share-note 토스트 관례의 색·테두리·그림자를 그대로 쓴다). 클릭하면 곧바로
   새로고침하는 button이라 pointer-events는 살려 둔다(안내만 하고 방법은 안 주는 배너가
   되지 않게 - 어포던스와 키보드 접근성을 동시에 얻는다).
   z-index 35는 임퍼서네이션 배너(30) 위, 모바일 drawer 오버레이(40) 아래다 - 모달이
   열리면 이 칩이 덮이는 쪽이 맞다(위 임퍼서네이션 배너 주석의 모달 우선 규율과 동일). */
.stale-banner {
  position: fixed; top: 12px; left: 50%; transform: translateX(-50%); z-index: 35;
  max-width: calc(100vw - 32px);
  background: var(--card); border: 1px solid var(--border);
  border-radius: var(--radius-input); box-shadow: var(--shadow-card);
  padding: var(--space-1-5) 14px; font-size: 13px; color: var(--muted-foreground);
  letter-spacing: -0.2px;
  font-family: inherit; cursor: pointer;
}
.stale-banner:hover { color: var(--foreground); }
.stale-banner:active { background: var(--muted); }
.stale-banner[hidden] { display: none; }
/* 라이브 리전 래퍼: 항상 DOM에 있고 자리를 차지하지 않는다. 안내 문구는 이 안의 버튼에
   주입돼야 보조기술이 "내용 변화"로 읽는다(처음부터 렌더된 텍스트는 낭독되지 않는다). */
.stale-banner-live { position: fixed; top: 0; left: 0; z-index: 35; }

/* ---- 멀티 세션 사이드바(챗지피티식 다중 대화) ----
   뷰포트 무관 베이스 + 데스크톱 고정 레일(>900px) + 모바일 오프캔버스 drawer(≤900px).
   z-index 규율: 헤더 10, 도크 20, 오버레이 40, 사이드바 50, 모바일 drawer가 헤더·도크
   위를 덮어야 하므로 이 순서를 지킨다. 데스크톱은 body padding-left로 영역이 분리돼
   겹침이 없다. 색은 무채 기존 토큰만(유채색 신규 없음, 원장 톤). */
.sidebar {
  position: fixed; top: 0; bottom: 0; left: 0; width: 260px;
  /* 폴리시: 우측 보더를 더 옅게(--rule보다 연한 헤어라인). 내부 패딩 12px. */
  background: var(--sidebar-bg); border-right: 1px solid rgba(22, 24, 29, 0.06);
  z-index: 50; display: flex; flex-direction: column;
  padding: 12px; overflow: hidden;
}
/* [새 대화]: 확실한 버튼 질감(오너 지시). 흰 배경 + 보더 + 미세 그림자, hover 시 보더
   짙어짐. 아이콘(+)과 텍스트는 좌측 정렬. 목록 행(무배경)과 대비돼 액션임이 또렷하다. */
.sidebar-new {
  display: flex; align-items: center; gap: 8px; width: 100%;
  min-height: 38px; padding: 0 var(--space-3); font-family: inherit;
  font-size: 14px; font-weight: 500; color: var(--foreground);
  /* tactile 시안: 사이드바 회색 지면 위에서 종이 한 장이 솟은 버튼 */
  background-color: var(--card); background-image: var(--grad-paper);
  border: 1px solid var(--border);
  border-radius: var(--radius-input); cursor: pointer;
  box-shadow: var(--edge-lo), var(--shadow-raise);
  transition: border-color .15s ease, background-color .15s ease, box-shadow .15s ease;
}
.sidebar-new:hover { border-color: var(--ink-500); box-shadow: var(--edge-lo), var(--shadow-raise-hi); }
.sidebar-new:active { background: var(--muted); box-shadow: var(--shadow-press); }
.sidebar-new svg { flex: none; display: block; }
.sidebar-heading {   /* .my-threads-title 값 이식 → 폴리시: 11px, 위 여백 20px. */
  font-size: 11px; font-weight: 600; letter-spacing: .02em;
  color: var(--ink-500); margin: 20px 8px 6px;
}
/* 목록은 flex:1로 늘어 계정 영역을 사이드바 바닥에 앉힌다. 목록만 스크롤(사이드바
   overflow:hidden, 브랜드·계정은 고정, 긴 목록만 스크롤). */
.sidebar-list { list-style: none; margin: 0; padding: 0;
  flex: 1; min-height: 0; overflow-y: auto;
  display: flex; flex-direction: column; gap: 2px; }
.sidebar-item { position: relative; }
/* 폴리시: 한 줄 제목(말줄임) 중심 행, 높이 34, radius 8, hover 배경, 활성 행 옅은 강조. */
.sidebar-item-open {
  display: block; width: 100%; text-align: left; font-family: inherit;
  min-height: 34px; padding: 7px 34px 7px 10px;   /* 우측 34px = 삭제 버튼 자리 */
  font-size: 14px; color: var(--ink-700);
  background: none; border: none; border-radius: var(--radius-input); cursor: pointer;
}
.sidebar-item-open { transition: background-color .12s ease; }
.sidebar-item-open:hover { background: var(--sidebar-row-hover); }
/* 눌림 피드백: hover보다 한 단 짙은 행 톤(활성 행과 같은 값)으로, 이 컴포넌트의
   자체 상태 스케일 안에서 press를 표현한다. */
.sidebar-item-open:active { background: var(--sidebar-row-active); }
/* 활성 행: 배경 강조 + 글자 무게로 정돈(좌측 바이올렛 바 폐지: 오너 지시, claude.ai 관례).
   배경은 hover보다 한 단계 짙은 --sidebar-row-active, 텍스트는 ink-900 + weight 500. */
/* tactile 시안: 선택된 행은 표면이 살짝 파인다(눌려 있음). 배경 한 단 짙게 + 글자
   무게라는 기존 이중 인코딩은 그대로다 - 그림자만으로 상태를 전달하지 않는다. */
.sidebar-item.is-active .sidebar-item-open {
  background: var(--sidebar-row-active); color: var(--ink-900); font-weight: 500;
  box-shadow: var(--shadow-press-soft);
}
.sidebar-item-title { display: block; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; line-height: 1.4; }
.sidebar-del {
  position: absolute; right: 4px; top: 50%; transform: translateY(-50%);
  width: 28px; height: 28px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  background: none; border: none; color: var(--muted-foreground); cursor: pointer;
  border-radius: var(--radius-input); opacity: 0;   /* display:none 금지: 키보드 탭 순서 유지 */
  transition: opacity .15s ease, color .15s ease, transform .12s ease;
}
.sidebar-item:hover .sidebar-del, .sidebar-del:focus-visible { opacity: 1; }
.sidebar-del:hover { color: var(--foreground); }
.sidebar-del:active { transform: translateY(-50%) scale(0.9); }
@media (hover: none) { .sidebar-del { opacity: 1; } }   /* 터치: 상시 노출 */

/* 데스크톱: 사이드바를 고정 레일로 두고 body를 260px 밀어 콘텐츠(.container 760px 중앙
   정렬)와 겹치지 않게 한다. 도크는 fixed라 좌표를 사이드바 offset만큼 옮긴다.
   padding-left는 사이드바 마크업이 있는 페이지(index)에만 걸어야 한다 - body.has-sidebar로
   스코프한다. 사이드바가 없는 admin·blog·share는 이 여백이 남으면 콘텐츠가 우측으로
   밀리고 좌측에 빈 띠가 생기므로(오너 보고) 제외한다. 도크(.query-dock)는 index 전용
   요소라 스코프가 불필요하다. */
@media (min-width: 901px) {
  body.has-sidebar { padding-left: 260px; }
  .query-dock { left: 260px; }
  .sidebar-toggle { display: none; }
  .sidebar-overlay { display: none !important; }
}

/* 모바일: 사이드바를 화면 밖으로 밀어두고 body.sidebar-open일 때 슬라이드 인(오프캔버스
   drawer). transition은 기존 reduced-motion 전역 무력화가 자동 커버한다. */
@media (max-width: 900px) {
  /* 닫힌 drawer는 translateX로 화면 밖에 두되 visibility:hidden도 함께 걸어 탭 순서·
     스크린리더에서 빠지게 한다(화면 밖 버튼 포커스 누수 방지). visibility는 이산 전이라
     transition에 넣으면 닫힘 시 .2s 슬라이드아웃이 끝난 뒤 숨겨지고, 열림 시 즉시 보인다. */
  .sidebar { transform: translateX(-100%); visibility: hidden; transition: transform .2s ease, visibility .2s ease; }
  body.sidebar-open .sidebar { transform: none; visibility: visible; box-shadow: var(--shadow-card); }
  .sidebar-overlay {
    position: fixed; inset: 0; background: rgba(22, 24, 29, 0.4); z-index: 40;
  }
  .sidebar-toggle {   /* 헤더 안 아이콘 버튼: .new-thread 문법 계승 */
    flex: none; width: 40px; height: 40px; padding: 0;
    display: inline-flex; align-items: center; justify-content: center;
    background: none; border: none; color: var(--ink-700); cursor: pointer;
    border-radius: var(--radius-input);
    transition: color .15s ease, transform .12s ease;
  }
  /* 상태 레이어 보강: 이 버튼만 hover/active가 비어 있었다(.new-thread 문법 계승). */
  .sidebar-toggle:hover { color: var(--foreground); }
  .sidebar-toggle:active { transform: scale(0.94); }
  /* 모바일 미니 헤더: 햄버거 + 브랜드만. 페이지색 반투명 + blur + 하단 얇은 rule,
     상단 sticky. 데스크톱(위 min-width:901 없음)에서는 .mobile-header{display:none}. */
  .mobile-header {
    display: flex; align-items: center; gap: 8px; padding: 8px 16px;
    background: rgba(255, 255, 255, 0.85);
    -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
    border-bottom: 1px solid var(--rule);
    position: sticky; top: 0; z-index: 10;
  }
}

/* 스레드 모드: 히어로 숨김, 페이지 하단에 고정 도크(컴포저) 높이만큼 여백
   (고정 도크가 마지막 카드·판권면을 가리지 않게). 도크는 이제 컴포저 전용이라
   ≈ 입력 52 + 상하 패딩 24 ~76px — JS updateDockSpacing이 실측값으로 덮어쓴다. */
body.is-thread .hero { display: none; }
/* 리스타일: 스레드 모드도 단일 근백색(--paper)을 유지한다 — 베이지 캔버스를 걷어
   콘텐츠가 박스 없이 페이지 위로 바로 흐르게 한다. 하단 여백은 고정 도크용(JS가 실측
   덮어씀). 홈(비스레드)과 스레드가 이제 같은 배경색이다. */
body.is-thread { padding-bottom: 100px; }
/* 하단 밴드 제거 (오너 지시 2026-09-07 스크린샷: "하단 섹션이 왤캐 넓고"). 스레드
   모드에서 인-플로우 판권면은 숨긴다. body의 스티키 푸터(min-height:100vh + flex
   column)와 main의 flex:1 0 auto가 짧은 스레드에서 판권면을 뷰포트 바닥까지 밀어
   본문과 헤어라인 사이에 빈 밴드를 만들고 있었다. 판권 한 줄은 도크의
   .dock-attribution이 대신 진다(index.html). 히어로 상태와 공유 뷰는 그대로 둔다. */
body.is-thread .site-footer { display: none; }
/* 판권면이 사라진 자리에 main의 56px가 그대로 남으면 마지막 카드 아래가 이중 여백이
   된다. 스레드 모드에서만 걷는다 - 하단 여백은 도크 예약분(JS 실측)이 담당한다. */
body.is-thread main { padding-bottom: 0; }

/* 대화 시작 날짜 칩 (유닛 8, 메신저 관례): 첫 말풍선 위 여백 + 중앙 정렬 칩 하나.
   문구는 guards.THREAD_DATE_CHIP_FORMAT(SSOT) → progress.js가 날짜 숫자만 채운다. */
.thread-date { text-align: center; padding: 24px 0 6px; }
/* 리스타일: 테두리 있는 알약 폐기 — 12px 연한 잉크 텍스트만 중앙 배치. */
/* B2 재조판(설계 2026-09-07 §10.2): 날짜 칩도 기록물 메타 레이블 문법으로 통일한다.
   이 마크업은 progress.js가 생성하므로 .meta-label class를 붙일 수 없다(JS 무수정
   원칙). 대신 같은 값(모노 tabular·11px·자간 확장)을 이 규칙 자체에 준다.
   문구는 guards.THREAD_DATE_CHIP_FORMAT SSOT 그대로다. */
.thread-date span {
  display: inline-block; color: var(--ink-500);
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: 11px; font-weight: 500; letter-spacing: 0.05em; padding: 4px 12px;
}

/* 카드 공통 */
/* tactile 시안: 카드는 절제 구역이다. 부풀리지 않고 아주 옅은 표면 그라디언트와
   하단 안쪽 엣지만 얹어 종이 두께를 준다(그림자 총량은 기존 shadow-xs 그대로). */
.card {
  background-color: var(--card); background-image: var(--grad-paper-soft);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  box-shadow: var(--edge-lo), var(--shadow-xs);
  padding: 22px; margin: var(--space-4) 0;
}

/* 답변 헤더 — 이름 + 숫자 요약. 리스타일에서 흰 카드 상자를 걷어 페이지 위에 얹는다
   (시트 스코프의 .turn-answer .answer-header가 배경·보더를 무력화, 여기선 그림자만 폐기). */
.answer { margin-top: 8px; }
.answer-header h2 {
  margin: 0 0 10px; font-size: 28px; font-weight: 700; letter-spacing: -0.5px;
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
}
.party { color: var(--ink-700); font-size: 15px; font-weight: 400; letter-spacing: -0.2px; }
/* 숫자 요약(‘머니 셀’) — 디버그 박스 제거, 위아래 룰로 감싼 기입 라인.
   NOTE: 서버가 완성된 문자열(r.summary)만 넘겨 셀 단위 스탯 행은 불가(SKIPPED). */
/* 리스타일: 위아래 전폭 rule 폐기 — 요약 라인을 크롬 없이 여백만으로 조판한다. */
.summary {
  font-size: 16px; font-weight: 500; color: var(--ink-900); line-height: 1.7;
  letter-spacing: -0.2px; margin: 8px 0; padding: 0;
}
/* 타이포 위계: 법안 조회(bill-lookup) 응답에는 의원 h2가 없고 이 요약 줄("관련 의안 N건")이
   사실상 답변의 표제다. 그 경우에만 표제급(20px/700)으로 올려 데이터 기준일·검색 범위
   메타 라벨과 크기·무게 대비를 만든다. 의원 응답(cards)에서는 h2 아래 통계 줄이므로
   기본 스타일을 유지한다(표제 중복 방지). */
.bill-lookup .summary {
  font-size: 20px; font-weight: 700; letter-spacing: -0.3px; line-height: 1.4;
  margin: 2px 0 8px;
}
/* 카드 스코프 표기: 전수 총계 줄. 바로 아래 라벨 붙은 요약 줄(.summary)이 답변 본문
   위계를 유지하도록 메타 라벨급으로 조용히 둔다. 기존 --ink-700 토큰만 쓰고 새 색을
   만들지 않는다. */
.member-totals {
  color: var(--ink-700); font-size: 13px; line-height: 1.5; margin: 6px 0 2px;
}
.degraded {
  color: var(--ink-700); font-size: 13px; margin: 8px 0;
  padding-left: 10px; border-left: 2px solid var(--rule);
}
.scope-note { color: var(--ink-500); font-size: 13px; line-height: 1.5; margin: 3px 0; }
.scope-note.asof { margin-top: 8px; }
/* 검색 범위·주제어: 메타 라벨급 조용한 접힘(무박스 텍스트). 데이터 기준일과 같은
   층위이므로 무거운 행으로 키우지 않는다. 셰브런은 콘텐츠 디스클로저와 같은 회전
   문법으로 통일하고(architect 조언), hover 시 잉크가 짙어지는 절제된 피드백만 준다. */
.scope-details { margin: 6px 0 2px; }
.scope-details > summary {
  cursor: pointer; color: var(--ink-500); font-size: 13px; list-style: none;
  display: inline-flex; align-items: center; gap: 5px; min-height: 32px;
  width: fit-content; transition: color .15s ease;
}
.scope-details > summary:hover { color: var(--ink-700); }
.scope-details > summary:active { color: var(--foreground); }
.scope-details > summary::-webkit-details-marker { display: none; }
.scope-details > summary::before {
  content: "▸"; font-size: 9px; color: var(--ink-500);
  transition: transform .15s ease;
}
.scope-details[open] > summary::before { transform: rotate(90deg); }

/* 종합분석 산문 + citation (산문 스펙 5.2~5.3). 새 색 없음(G5): 인터랙션은
   --accent(인터랙션 전용색)에만, 표면은 기존 종이·룰 토큰만 쓴다. */
/* 유닛 9: 개별 max-width 제거 — 답변 시트(.turn-answer)가 폭을 지배한다. 산문 좌측
   flush는 시트 공통 패딩으로 자동 해소된다. */
/* 산문 블록: 아래 여백은 이어지는 디스클로저(타임라인 보기)와의 리듬을 위해 12px로
   좁힌다. 히스토리 접힘이 있으면 그것이 블록의 마지막 자식이라 이 여백이 두 디스클로저
   행 사이 간격이 된다(architect 조언: 두 행은 형제가 아니므로 래퍼 없이 간격만 통일). */
.synthesis { margin: 4px 0 12px; }
.synthesis-p {
  font-size: 16px; font-weight: 400; color: var(--ink-900);
  line-height: 1.75; letter-spacing: -0.2px; margin: 0 0 16px;
}
.synthesis-p:last-child { margin-bottom: 0; }
/* 답변 하단 유틸리티 영역(오너 승인 2026-09-06): 산문 끝 복사 버튼 한 개.
   .answer-utils가 붙으면서 마지막 문단이 더는 :last-child가 아니게 되므로, 문단 사이
   여백 규칙을 :last-of-type으로 되살려 산문 조판을 무회귀로 둔다(접힘 히스토리 안의
   문단은 여전히 위 :last-child 규칙이 잡는다 - 그쪽은 details의 자식이다). */
.synthesis > .synthesis-p:last-of-type { margin-bottom: 0; }
/* 조용한 텍스트 버튼: 단일 CTA 규율대로 무보더·무배경 뮤트 잉크다([새 대화] 전례).
   새 색을 만들지 않고 기존 잉크 토큰만 쓴다. */
.answer-utils { display: flex; gap: 8px; margin-top: 10px; }
.answer-copy {
  padding: 4px 8px; border: none; background: none; cursor: pointer;
  font-family: inherit; font-size: 12px; line-height: 1.4;
  color: var(--ink-500); border-radius: var(--radius-input);
}
.answer-copy:hover { color: var(--ink-900); background: var(--muted); }
/* 평가기준 고지: 산문 블록 바로 아래 1줄. scope-note 계열 시각 처리를 그대로 쓰고
   위 여백만 좁혀 산문에 붙인다(새 색·새 타이포 없음). */
.eval-note { margin: -4px 0 12px; }
/* 강등 고지: DEGRADED_NOTE와 동일 부기 패턴(좌측 룰 + 뮤트 캡션) */
.synthesis-note {
  color: var(--ink-500); font-size: 13px; margin: 12px 0;
  padding-left: 10px; border-left: 2px solid var(--rule);
}
/* citation 마커: 각주형 윗첨자 숫자(오너 지시 2026-09-05, 틴트 칩은 인용 밀집
   문단에서 소음이라 철거). line-height 0 + top 오프셋 조합이라 산문 줄 간격
   (1.75)을 벌리지 않는다. 색은 --accent 그대로, 새 색 없음. JS 계약(.cite·
   data-cite·cite-pop·클릭 점프) 무수정. 템플릿의 마커 텍스트도 [n]에서 n으로
   벗겼다(v3_answer·synthesis·landing_showcase 파셜). */
.cite {
  position: relative; display: inline-block; padding: 0; margin: 0 1px;
  background: none; border: none; cursor: pointer;
  font-family: var(--font-mono); font-size: 0.62em; font-weight: 600;
  color: var(--accent); line-height: 0; vertical-align: baseline; top: -0.55em;
  transition: color .12s ease;
}
/* 히트영역 확대(시각 크기 유지): 인라인 마커 주변 8px를 투명 ::after로 덮어
   탭 타깃을 넓힌다(WCAG 타깃 크기). 윗첨자로 줄어든 시각 크기를 보상한다. */
.cite::after { content: ""; position: absolute; inset: -8px; }
.cite:hover { text-decoration: underline; }
/* 팝오버: 종이 카드 + 저알파 헤어라인, 기본 숨김. hover/focus-visible 시에만 표시 */
.cite-pop {
  display: none; position: absolute; left: 0; top: 1.6em; z-index: 20;
  width: max-content; max-width: 280px; text-align: left; white-space: normal;
  background: var(--card); border: 1px solid var(--border);
  border-radius: var(--radius-tag); box-shadow: var(--shadow-card);
  padding: var(--space-2) var(--space-2-5); font-family: var(--font-sans); font-size: 13px;
  color: var(--ink-700); line-height: 1.5;
}
.cite:hover .cite-pop, .cite:focus-visible .cite-pop { display: block; }
.cite-pop-name { display: block; font-weight: 600; color: var(--ink-900); }
.cite-pop-meta { display: block; color: var(--ink-500); }
/* 모바일(호버 없음): 팝오버 상시 숨김, 탭은 스크롤 이동만(JS) */
@media (hover: none) {
  .cite:hover .cite-pop, .cite:focus-visible .cite-pop { display: none; }
}
/* ───── 답변 수준 디스클로저 행(공통 컴포넌트) ─────
   "타임라인 보기(.evidence)"와 "히스토리 자세히 보기(.synthesis-history)"는 답변 시트
   안에서 세로로 나란히 놓이는 두 콘텐츠 내비게이션 토글이다. 둘은 형제가 아니라(전자는
   section.synthesis의 형제, 후자는 그 안의 마지막 자식) 래퍼로 묶을 수 없으므로,
   동일한 시각 언어 + 통일된 간격으로 한 쌍처럼 읽히게 한다.
   마감 포인트(오너 지시): 폭 통일(전폭 행) · 종이 배경 + 옅은 단차(shadow-xs) ·
   회전 셰브런 · hover 시 테두리 스냅 대신 배경 톤 이동 · :active · 열림 상태 전환.
   무채색 유지(G5): 잉크·룰 토큰만. */
.evidence { margin: 12px 0 0; }
.evidence > summary,
.synthesis-history > summary {
  cursor: pointer; color: var(--ink-700); font-size: 14px; font-weight: 500;
  list-style: none; display: flex; align-items: center; gap: 10px;
  width: 100%; min-height: 46px; padding: 0 var(--space-4);
  background: var(--card); border: 1px solid var(--border);
  border-radius: var(--radius-card); box-shadow: var(--shadow-xs);
  transition: background-color .15s ease, border-color .15s ease, box-shadow .15s ease;
}
.evidence > summary::-webkit-details-marker,
.synthesis-history > summary::-webkit-details-marker { display: none; }
/* 커스텀 셰브런: 접힘 ▸ → 펼침 시 90도 회전. 텍스트 우측이 아니라 좌측(리딩)에 둔다. */
.evidence > summary::before,
.synthesis-history > summary::before {
  content: "▸"; font-size: 11px; color: var(--ink-500);
  transition: transform .15s ease;
}
.evidence[open] > summary::before,
.synthesis-history[open] > summary::before { transform: rotate(90deg); }
.evidence > summary:hover,
.synthesis-history > summary:hover {
  background: var(--muted); border-color: rgba(22, 24, 29, 0.14);
}
.evidence > summary:active,
.synthesis-history > summary:active { background: var(--border); }
/* 열림: 배경을 캔버스로 낮춰 "펼쳐진 헤더"임을 표시하고 내용과의 간격을 벌린다. */
.evidence[open] > summary,
.synthesis-history[open] > summary {
  margin-bottom: var(--space-2-5); background: var(--muted); box-shadow: none;
  color: var(--foreground); border-color: rgba(22, 24, 29, 0.10);
}
.evidence[open] > summary::before,
.synthesis-history[open] > summary::before { color: var(--ink-700); }

/* 카드 내 법안 요지 접힘 (유닛 9): evidence 칩 문법을 계승하되 카드 내부라 작게(칩 높이·
   글자 축소). 무채색 유지(G5). 요지는 DB 원문 인용이라 본문은 회색 톤 캡션. */
.bill-summary { margin: 8px 0 0; }
/* 컴팩트 디스클로저 변종(카드 내부): 답변 수준 행과 같은 언어를 작게 축약한다.
   전폭 아님, 종이 배경 + 1px 룰 + 회전 셰브런, hover는 배경 톤 이동. .tag-more·
   .co-proposers도 같은 규칙을 공유한다. */
.bill-summary > summary,
.co-proposers > summary {
  cursor: pointer; color: var(--ink-700); font-size: 12px; font-weight: 500;
  list-style: none; display: inline-flex; align-items: center; gap: 6px;
  min-height: 36px; padding: 0 var(--space-3); width: fit-content;
  background: var(--card); border: 1px solid var(--border);
  border-radius: var(--radius-input);
  transition: background-color .15s ease, border-color .15s ease;
}
.bill-summary > summary::-webkit-details-marker,
.co-proposers > summary::-webkit-details-marker { display: none; }
.bill-summary > summary::before,
.co-proposers > summary::before {
  content: "▸"; font-size: 9px; color: var(--ink-500);
  transition: transform .15s ease;
}
.bill-summary[open] > summary::before,
.co-proposers[open] > summary::before { transform: rotate(90deg); }
.bill-summary > summary:hover,
.co-proposers > summary:hover { background: var(--muted); border-color: rgba(22, 24, 29, 0.14); }
.bill-summary > summary:active,
.co-proposers > summary:active { background: var(--border); }
.bill-summary-body {
  margin: 8px 0 2px; max-width: 62ch;
}
.bill-summary-body p {
  margin: 0 0 6px; font-size: 13px; line-height: 1.6; color: var(--ink-700);
  letter-spacing: -0.2px;
}
.bill-summary-body p:last-child { margin-bottom: 0; }

/* 2단 접힘(2026-09-15): 600자 절단 뒤 전문을 잇는 보조 펼침. 바깥 .bill-summary의
   컴팩트 디스클로저 문법을 그대로 이어받되 새 칩 크롬은 만들지 않는다 - 텍스트 링크
   급으로 더 조용해야 "본문 1단"과 "부록 2단"의 위계가 읽힌다. */
.bill-summary-more { margin-top: 8px; }
.bill-summary-more > summary {
  cursor: pointer; font-size: 13px; color: var(--ink-700);
}

/* 법안 해설 (계획 U5, 오너 확정 D3): 해설이 있으면 카드 본문 자리에 **펼친 채로** 놓이고
   원문 요지(.bill-summary)는 그 아래 접힘으로 강등된다 — 첫 화면이 평이한 설명이어야
   원 요구("질의 결과가 너무 raw하다")를 만족한다. 접혀 있으면 목적을 달성하지 못한다.
   새 색을 만들지 않는다(G5 무채색 규율): 기존 잉크·룰 토큰만 쓰고, 좌측 굵은 룰 하나로
   "문서 안의 답변 시트"라는 기존 메타포를 카드 안에서 반복한다. */
.explainer {
  margin: 10px 0 0; padding: 12px 14px; max-width: 62ch;
  border: 1px solid var(--rule); border-left: 2px solid var(--ink-900);
  border-radius: var(--radius-input);
}
.explainer-label {
  margin: 0 0 8px; font-size: 12px; font-weight: 600; color: var(--ink-900);
  letter-spacing: -0.2px;
}
.explainer-body { margin: 0; }
.explainer-body p {
  margin: 0 0 6px; font-size: 14px; line-height: 1.65; color: var(--ink-900);
  letter-spacing: -0.2px;
}
.explainer-body p:last-child { margin-bottom: 0; }
/* effects는 발의자 귀속 인용이라 본문보다 한 단계 낮은 톤으로 둔다(층위 경계의 시각화). */
.explainer-effects-label {
  margin: 12px 0 4px; font-size: 12px; font-weight: 500; color: var(--ink-700);
  letter-spacing: -0.2px;
}
.explainer-effects p { font-size: 13px; line-height: 1.6; color: var(--ink-700); }
/* 프레임 고지: 블록의 마지막 자식이지만 감싸는 대상은 content + effects 전부다. */
.explainer-frame-note {
  margin: 12px 0 0; padding-top: 8px; border-top: 1px solid var(--rule);
  font-size: 12px; line-height: 1.5; color: var(--ink-500); letter-spacing: -0.2px;
}
.explainer-frame-mark { margin-right: 4px; }

/* 근거 카드의 인용 번호: 날짜 레일 모노 표기 */
.cite-no { color: var(--ink-500); font-size: 12px; font-family: var(--font-mono); }

/* LLM 사용량·원가 한 줄 (admin 계정에서만 렌더된다). 답변 맨 아래 소형 회색 모노
   메타 표기라 본문 흐름을 끊지 않는다. 모노 글꼴은 함께 붙는 .mono가 담당한다. */
.usage-meta { margin: 12px 0 0; font-size: 12px; color: var(--ink-500); }

/* 클릭 스크롤 하이라이트: 2px 바이올렛 아웃라인, 수 초 페이드 */
.cite-flash { animation: cite-flash 2.4s ease-out; }
@keyframes cite-flash {
  0%, 30% { box-shadow: inset 0 0 0 2px var(--accent); }
  100% { box-shadow: inset 0 0 0 2px transparent; }
}

/* 태그 색인 범례 (1회성 캡션, 스펙 3.2-10) */
.tag-legend { color: var(--ink-500); font-size: 12px; margin: 20px 0 0; letter-spacing: -0.2px; }

/* 날짜 레일(signature, 스펙 3.2-7): 좌측 날짜 컬럼 + 2px 잉크 스파인 + 사각 틱 노드.
   "시간순 기록의 기입"이라는 제품의 계약 그 자체가 첫눈에 보이는 구조가 된다. */
.timeline { list-style: none; margin: 8px 0 0; padding: 0; position: relative; }
.timeline::before {
  content: ""; position: absolute; left: 96px; top: 0; bottom: 0;
  width: 2px; background: var(--rule);   /* 리스타일: 검은 스파인 → 연한 rule로 강등 */
}
/* bill-card는 흰 카드가 아니라 레일 위의 기입 행이다(.card 상속을 무력화). */
.bill-card {
  display: grid; grid-template-columns: 96px 1fr;
  background: none; border: none; border-radius: 0; box-shadow: none;
  padding: 0; margin: 0; position: relative;
}
.bill-rail {
  display: flex; flex-direction: column; align-items: flex-end; gap: 4px;
  padding: 22px 20px 8px 0; text-align: right;
}
.date { color: var(--ink-700); font-size: 13px; letter-spacing: 0.01em; }
.kind-label {
  color: var(--ink-500); font-size: 12px; letter-spacing: 0.06em; text-transform: uppercase;
}
.bill-body {
  padding: 22px 0 24px 22px; border-bottom: 1px solid var(--rule); position: relative;
}
.timeline > .bill-card:last-child .bill-body { border-bottom: none; }
/* 사각 틱 노드: 스파인 위에 얹힌다. 데이터 공백 카드는 아웃라인 틱(경보색 없음). */
.bill-body::before {
  content: ""; position: absolute; left: 0; top: 28px; margin-left: -4px;
  width: 8px; height: 8px; background: var(--ink-900);
}
.bill-card:has(.data-gap) .bill-body::before {
  /* 이 틱은 채워진 도트가 아니라 뚫린 링이라 배경과 정확히 같은 값이어야 "빈 자리"로
     읽힌다. .bill-card는 카드가 아니라 페이지 위에 직접 얹힌 기입 행이라 순백(--paper)이
     아니라 페이지 바탕(--canvas-page)을 따라야 한다(촉각 2단계). */
  background: var(--canvas-page); box-shadow: inset 0 0 0 1px var(--ink-500);
}

.bill-name {
  font-size: 18px; font-weight: 600; margin: 0 0 8px; line-height: 1.4; letter-spacing: -0.2px;
}
.bill-name a { color: var(--ink-900); text-decoration: underline; text-underline-offset: 3px; }
.bill-name a:hover { text-decoration-thickness: 2px; }
.bill-name a:active { color: var(--ink-700); }
/* tier: 법안명 우측 사각 태그 (스펙 3.2-9). G5: 브랜드색 제거, 잉크 solid/dashed 이중 인코딩. */
.tier {
  display: inline-block; font-size: 12px; font-weight: 500; letter-spacing: -0.2px;
  padding: 1px 7px; margin-left: 8px; vertical-align: 2px;
  border: 1px solid var(--ink-900); border-radius: var(--radius-tag);
  color: var(--ink-900); background: var(--paper-raised); white-space: nowrap;
}
.tier[data-tier="관련 가능"] {
  border-style: dashed; /* 색상만이 아닌 선 스타일로도 구분(WCAG 1.4.1), 확정 아닌 폭넓은 매치임을 표현 */
}

/* 행동 표시 (스펙 3.2-8): 필 폐기, 잉크 사각 불릿 + 텍스트. 전 값 동일 처리(G5). */
.action {
  display: flex; align-items: baseline; gap: 8px;
  font-weight: 700; font-size: 15px; color: var(--ink-900);
  margin: 8px 0; padding: 0; border: none; border-radius: 0;
}
.action-bullet { color: var(--ink-900); font-size: 12px; line-height: 1; flex: none; }
.data-gap { color: var(--ink-500); font-size: 14px; margin: 8px 0; line-height: 1.5; }

/* 표결 집계 (스펙 3.2-8): 배경 박스 제거, 위아래 1px 룰, tabular 숫자. */
.vote-counts {
  color: var(--ink-700); font-size: 13px; margin: 10px 0;
  padding: 8px 0; border-top: 1px solid var(--rule); border-bottom: 1px solid var(--rule);
  letter-spacing: -0.2px;
}
.status { color: var(--ink-500); font-size: 13px; margin: 6px 0; }

/* 주제 태그 칩 — 대상·영역·방향(L2, 스펙 7). direction은 평가가 아니라 방향축이므로
   확대/축소/범주형 3계열만 구분한다 (판정어 아님, G5).
   - 확대계열/축소계열: --dir-warm/--dir-cool — 기존 의미 계열과 겹치지 않는 중립색 2종.
     명도·채도를 맞춰 두 계열이 동등한 시각 무게를 갖는다.
   - 범주형(전환/이관/명확화/절차변경): 색이 아니라 모양(radius)으로만 구분한다. */
/* 색인 태그 (스펙 3.2-10): 사각 4px, 배경 없음, 1px 룰, 12px/500. 색은 태그 전체가
   아니라 .tag-dir(방향 단어)에만 — 확대계열 웜, 축소계열 쿨, 범주형은 무채(색 없음이
   곧 "제3유형" 신호, WCAG 1.4.1: 단어 자체가 1차 구분자, 색은 보조 인코딩). */
.tag-chips { display: flex; flex-wrap: wrap; gap: 6px; margin: 8px 0; }
.tag-chip {
  display: inline-block; font-size: 12px; font-weight: 500; line-height: 1.4;
  padding: 3px 9px; border-radius: var(--radius-tag);
  border: 1px solid var(--rule); background: none; color: var(--ink-500);
}
.tag-dir[data-direction="연장"], .tag-dir[data-direction="확대"],
.tag-dir[data-direction="인상"], .tag-dir[data-direction="강화"],
.tag-dir[data-direction="신설"] { color: var(--dir-warm); font-weight: 600; }
.tag-dir[data-direction="단축"], .tag-dir[data-direction="축소"],
.tag-dir[data-direction="인하"], .tag-dir[data-direction="완화"],
.tag-dir[data-direction="폐지"] { color: var(--dir-cool); font-weight: 600; }
.tag-primary { font-size: 10px; font-weight: 700; color: var(--ink-900); margin-left: 3px; }
/* 초과 태그 접기 (+N) */
.tag-more { display: inline-block; }
.tag-more > summary {
  cursor: pointer; list-style: none; font-size: 12px; font-weight: 500;
  padding: 3px 9px; border: 1px solid var(--rule); border-radius: var(--radius-tag);
  color: var(--ink-700); min-height: 32px; display: inline-flex; align-items: center;
  background: var(--paper-raised);
  transition: background-color .15s ease, border-color .15s ease;
}
.tag-more > summary::-webkit-details-marker { display: none; }
.tag-more > summary:hover { background: var(--muted); border-color: rgba(22, 24, 29, 0.14); }
.tag-more > summary:active { background: var(--border); }
.tag-more[open] > summary { color: var(--foreground); }
.tag-more .tag-chips { margin: 8px 0 0; }
.coverage-note { color: var(--ink-500); font-size: 13px; margin: 6px 0; }

/* 서술형 배지 → 각주 스타일 (스펙 3.2-11): 칩 폐기, "※ " 접두, 카드 하단. */
.badge {
  display: block; font-size: 13px; line-height: 1.5; color: var(--ink-500);
  margin: 8px 0 0; padding: 0; background: none; border: none; border-radius: 0;
}
.badge::before { content: "※ "; }
.source { font-size: 13px; margin: 12px 0 0; padding-top: 12px; border-top: 1px solid var(--rule); }
.source a {
  color: var(--ink-900); font-weight: 500;
  text-decoration: underline; text-underline-offset: 3px;
}
.source a:hover { text-decoration-thickness: 2px; }
.source a:active { color: var(--ink-700); }

/* 고정 안내 카드 */
.notice p { margin: 0 0 8px; font-size: 15px; line-height: 1.6; color: var(--ink-900); }
.notice .scope-note { color: var(--ink-500); }

/* 동명이인 선택 — 보조(secondary) 버튼, filled 바이올렛 아님 */
.disambiguation > p { margin: 0 0 4px; font-size: 15px; color: var(--ink-900); }
.candidates { list-style: none; padding: 0; margin: 12px 0 0; display: grid; gap: 10px; }
.candidates form { margin: 0; }
.candidates button {
  width: 100%; text-align: left; padding: var(--space-3) var(--space-4); font-size: 15px; min-height: 44px;
  /* tactile 시안: 보조 버튼 재질(솟은 종이). 터치 타깃 44px 불변. */
  background-color: var(--card); background-image: var(--grad-paper);
  color: var(--foreground);
  border: 1px solid var(--border); border-radius: var(--radius-input); cursor: pointer;
  box-shadow: var(--edge-lo), var(--shadow-raise);
  transition: border-color .15s ease, box-shadow .15s ease, background-color .15s ease;
}
.candidates button:hover { border-color: var(--ink-500); box-shadow: var(--edge-lo), var(--shadow-raise-hi); }
.candidates button:active { background: var(--muted); box-shadow: var(--shadow-press); }

/* 상시 커버리지 고지 (스펙 3.2-12). 폴리시(축소): 본문급 존재감 → 작은 각주.
   좌측 보더 폐지, 옅은 그레이 13px 캡션으로 스크롤 자연 끝에 조용히 남는다.
   이 톤다운은 index에만 적용한다. 정적 공유 아카이브(share.html body.share-view)는
   스코프 밖이라 아래에서 기존(부기 블록) 스타일을 복원해 회귀를 막는다. */
.coverage {
  margin: 28px 0 8px; background: none; border: none; border-radius: 0; padding: 0;
}
.coverage p { color: var(--ink-500); font-size: 13px; line-height: 1.6; margin: 0; }
body.share-view .coverage {
  margin: 32px 0 8px; border-left: 2px solid var(--rule); padding: 4px 0 4px 10px;
}
body.share-view .coverage p { color: var(--ink-700); }

/* 푸터 → 판권면(colophon). 리스타일: 검은 2px 구조룰 → 1px 연한 rule, 배경은 페이지색. */
.site-footer { background: none; border-top: 1px solid var(--rule); margin-top: auto; }
.site-footer p { color: var(--ink-500); font-size: 13px; line-height: 1.6; margin: 6px 0; }
.site-footer .container { padding: 28px 20px; }
/* 축약 판권면 한 줄(오너 지시 2026-09-07, index·share 전용). 캡션급으로 내려 시각 존재감을
   최소화한다. 클래스로 스코프하는 이유는 .site-footer를 랜딩·블로그가 함께 쓰기 때문이다. */
.site-footer .footer-compact { font-size: 12px; color: var(--ink-500); }
/* 판권면 밴드 축소 (오너 지시 2026-09-07 스크린샷: "하단 섹션이 왤캐 넓고"). 28px 상하
   패딩이 헤어라인과 합쳐져 한 줄짜리 판권면을 밴드로 보이게 했다. 캡션급 10px로 내린다.
   헤어라인은 남긴다 - 밴드 인상은 패딩이 만들고 있었고 1px 룰은 문서 끝 표시로 유효하다.
   .site-footer가 아니라 index·share 푸터에만 붙는 이 클래스에 거는 이유는 랜딩·블로그
   판권면 픽셀 무변화가 계약이기 때문이다. 명시도는 .site-footer .container와 같으므로
   순서로 이긴다 - 이 규칙은 반드시 위 .site-footer .container 뒤에 있어야 한다. */
.site-footer-compact .container { padding: 10px 20px; }
.site-footer-compact p { margin: 0; }

@media (max-width: 600px) {
  .container { padding: 0 16px; }
  .hero { padding: 40px 0 20px; }
  .hero h1 { font-size: 32px; letter-spacing: -0.02em; }
  .hero-ghost { font-size: 160px; top: -6px; right: -6px; }
  .lede { font-size: 16px; }
  .mobile-header { padding: 8px 14px; }
  .site-header .container { padding: 12px 16px; }   /* legacy 페이지 헤더(스코프 밖) */
  /* 유닛 8: 아이콘화로 폭이 줄어 도크·히어로 모두 한 줄 유지가 자연스럽다
     ([새 대화 아이콘][입력창][전송 아이콘]). 텍스트 버튼 시절의 세로 스택·랩 규칙 제거. */
  body.is-thread { padding-bottom: 100px; }
  /* 좁은 화면에서 70%는 여백만 낭비하고 줄바꿈이 잦아진다 — 버블 최대 폭을 넓힌다. */
  .turn-bubble { max-width: 85%; }
  /* 날짜 레일: 좁은 화면에서 날짜 컬럼을 카드 상단 인라인으로 복귀 (스펙 3.2-7) */
  .timeline::before { display: none; }
  .bill-card { grid-template-columns: 1fr; }
  .bill-rail {
    flex-direction: row; align-items: baseline; gap: 8px;
    padding: 18px 0 0; text-align: left;
  }
  .bill-body { padding: 8px 0 20px; }
  .bill-body::before { display: none; }
  .timeline > .bill-card:last-child .bill-body { border-bottom: 1px solid var(--rule); }
}

/* 날짜 레일 인라인 폴백 — 시트 내부는 더 이른 폭에서(유닛 9): 96px 날짜 컬럼이 68ch
   답변 시트 안에서 빡빡하다. 컨테이너 자기 max-width(760px) 이하에서 시트 내부
   타임라인만 레일을 카드 상단 인라인으로 접는다(홈/비스레드는 위 600px 폴백 그대로).
   폭 값(760px)은 컨테이너 자기 폭 기준의 판단이다 — 리포트에 명시. */
@media (max-width: 760px) {
  .turn-answer .timeline::before { display: none; }
  .turn-answer .bill-card { grid-template-columns: 1fr; }
  .turn-answer .bill-rail {
    flex-direction: row; align-items: baseline; gap: 8px;
    padding: 18px 0 0; text-align: left;
  }
  .turn-answer .bill-body { padding: 8px 0 20px; }
  .turn-answer .bill-body::before { display: none; }
  .turn-answer .timeline > .bill-card:last-child .bill-body { border-bottom: 1px solid var(--rule); }
}

/* 사이드바 260px 오프셋 보정: 위 760px 쿼리는 "뷰포트 ≈ 콘텐츠 폭" 가정인데, 데스크톱
   사이드바가 생기면 뷰포트 901~1020px에서 콘텐츠 폭이 641~760px로 줄어도 그 쿼리가
   걸리지 않는다(뷰포트는 여전히 >760px). 같은 시트 내부 레일 접힘 규칙을 이 구간에도
   복제해 답변 카드 날짜 레일이 인라인으로 접히게 한다. */
@media (min-width: 901px) and (max-width: 1020px) {
  .turn-answer .timeline::before { display: none; }
  .turn-answer .bill-card { grid-template-columns: 1fr; }
  .turn-answer .bill-rail {
    flex-direction: row; align-items: baseline; gap: 8px;
    padding: 18px 0 0; text-align: left;
  }
  .turn-answer .bill-body { padding: 8px 0 20px; }
  .turn-answer .bill-body::before { display: none; }
  .turn-answer .timeline > .bill-card:last-child .bill-body { border-bottom: 1px solid var(--rule); }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
  /* 애니메이션이 꺼진 상태에서도 클릭 대상 근거 카드를 정적 아웃라인으로 표시한다
     (산문 스펙 5.2: reduced-motion에서 스크롤 즉시·플래시 정적 아웃라인). */
  .cite-flash { box-shadow: inset 0 0 0 2px var(--accent); }
}

/* ---- SEO 블로그 (유닛 B): 문서형 산문 레이아웃 ----
   서버렌더 검색 표면. 헤더/푸터/토큰 팔레트는 본체와 공유하고, 본문만 문서형
   좁은 단(~68ch)으로 둔다. 산문 문단은 기존 .synthesis-p 스타일을 재사용한다. */
.blog.container { padding-top: 32px; padding-bottom: 48px; }
.blog-post { max-width: 68ch; margin: 0 auto; }
.blog-index-title, .blog-post-title {
  font-size: 28px; font-weight: 800; letter-spacing: -0.5px;
  color: var(--ink-900); margin: 0 0 12px; line-height: 1.3;
}
.blog-back { margin: 0 0 16px; font-size: 14px; }
.blog-post-meta, .blog-list-meta {
  color: var(--ink-500); font-size: 13px; margin: 0 0 20px;
}
.blog-date-label { margin-right: 6px; }
/* 비주얼 업그레이드(토스피드 레퍼런스): 본문 컬럼을 넓히고(≈672px) 본문 타이포에
   섹션 호흡을 준다. 넓힘은 본문 페이지에만(.blog-post-body를 품은 article) 적용해
   목록 페이지 리듬은 건드리지 않는다. */
.blog-post:has(.blog-post-body) { max-width: 42rem; }
.blog-post-body .synthesis-p,
.blog-post-body p {
  font-size: 17px; color: var(--ink-900); line-height: 1.75;
  letter-spacing: -0.2px; margin: 0 0 1.5em;
}
/* CSS 카운터로 본문 h2 앞에 자동 번호 배지(콘텐츠 무수정). 직계 h2만 대상이라
   고지 블록(.post-notice 내부) h2는 번호가 붙지 않는다(각주 성격). */
.blog-post-body { counter-reset: post-h2; }
.blog-post-body > h2 {
  counter-increment: post-h2;
  display: flex; align-items: center; gap: 12px;
  font-size: 22px; font-weight: 700; color: var(--ink-900);
  letter-spacing: -0.3px; line-height: 1.35; margin: 3em 0 0.7em;
}
.blog-post-body > h2::before {
  content: counter(post-h2);
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; border-radius: var(--radius-input);
  /* accent 다이어트: 번호 배지는 관인이 아니라 조판 장치라 먹으로 채운다 */
  background: var(--ink-900); color: var(--primary-foreground);
  font-size: 14px; font-weight: 700; font-variant-numeric: lining-nums;
}
/* 고지 블록 내부 h2(래핑 이후)는 각주 스타일로 강등: 작은 글자·연한 색·상단 룰. */
.blog-post-body .post-notice > h2 {
  display: block; font-size: 15px; font-weight: 600; color: var(--ink-500);
  margin: 0 0 8px;
}
.blog-post-body .post-notice > h2::before { content: none; }
/* 본문 인라인 링크: 규칙 부재로 UA 기본 파랑이 새고 있었다(accent 다이어트 편입).
   .post-notice a 등 더 구체적인 기존 규칙이 그대로 이긴다. */
.blog-post-body a { color: var(--ink-900); text-decoration: underline; text-underline-offset: 3px; }
.blog-post-body a:hover { text-decoration-thickness: 2px; }
.blog-post-body a:active { color: var(--ink-700); }
.blog-post-body code {
  font-family: var(--font-mono); font-size: 0.9em;
  background: var(--canvas); border-radius: var(--radius-tag); padding: 1px 5px;
}
.blog-post-body strong { font-weight: 700; color: inherit; }

/* 세 줄 요약 카드: 도입부 뒤 연한 배경 라운드 카드. 새 색 없음(잉크·룰·캔버스 토큰만). */
.post-summary {
  background: var(--canvas); border: 1px solid var(--rule);
  border-radius: var(--radius-card); padding: 18px 20px; margin: 4px 0 2em;
}
.post-summary .post-summary-title {
  font-size: 14px; font-weight: 700; color: var(--ink-900);
  letter-spacing: -0.2px; margin: 0 0 10px;
}
.post-summary ul { margin: 0; padding-left: 1.1em; }
.post-summary li {
  font-size: 15px; color: var(--ink-700); line-height: 1.65;
  letter-spacing: -0.2px; margin: 0 0 6px;
}
.post-summary li:last-child { margin-bottom: 0; }

/* 핵심 수치 카드(데이터시트형 편): 세 줄 요약 카드의 목록 타이포를 그대로 물려받되
   배경을 빼고 좌측 규칙선으로만 구분한다. 카드 두 장이 연달아 서는 것을 피한다.
   .post-summary와 함께 쓰되 클래스 문자열이 정확히 "post-summary"가 아니어야
   발행 게이트의 세 줄 요약 구조 검사가 앞의 진짜 요약 카드를 집는다. */
.post-keyfacts {
  background: none; border: none; border-left: 3px solid var(--rule);
  border-radius: 0; padding: 2px 0 2px 18px;
}

/* 본문 텍스트 표(데이터시트형 편). 이미지·차트를 쓰지 않는 규약이라 표가 본문
   수치의 유일한 표면이고, 그대로 잘라 인용될 것을 전제로 캡션을 표 위에 둔다.
   기존 발행분에는 표가 하나도 없어 이 규칙이 닿는 편은 데이터시트형뿐이다. */
.blog-post-body table {
  width: 100%; border-collapse: collapse; margin: 0 0 2em;
  font-size: 15px; color: var(--ink-900); letter-spacing: -0.2px;
}
.blog-post-body caption {
  caption-side: top; text-align: left;
  color: var(--ink-500); font-size: 13px; line-height: 1.6; padding: 0 0 8px;
}
.blog-post-body th, .blog-post-body td {
  border-bottom: 1px solid var(--rule); padding: 8px 0; text-align: left;
  line-height: 1.5;
}
.blog-post-body thead th {
  color: var(--ink-500); font-size: 13px; font-weight: 600;
}
/* 첫 열은 항목명, 나머지 열은 수치라 우측 정렬 + 자릿수 고정폭으로 읽는다. */
.blog-post-body td + td, .blog-post-body th + th {
  text-align: right; font-variant-numeric: tabular-nums lining-nums;
  padding-left: 12px;
}
.blog-post-body tbody th { font-weight: 700; color: var(--ink-900); }

/* 고지 블록(각주): 상단 구분선 + 작은 글자·연한 색. 부기 톤을 계승한다. */
.post-notice {
  margin: 3em 0 0; padding-top: 20px; border-top: 1px solid var(--rule);
}
.post-notice p {
  font-size: 13px; color: var(--ink-500); line-height: 1.6;
  letter-spacing: -0.2px; margin: 0 0 10px;
}
.post-notice a { color: var(--ink-900); text-decoration: underline; text-underline-offset: 3px; }
.post-notice a:hover { text-decoration-thickness: 2px; }
.post-notice a:active { color: var(--ink-700); }

/* 우측 고정 목차(데스크톱 ≥1100px). 좁은 폭에선 숨김 — JS 없이도 앵커로 동작한다.
   .blog 컨테이너(760px)를 넓히지 않으려고 sticky 대신 우측 여백에 고정 배치한다.
   좌측 세로선 + 현재 섹션 악센트 하이라이트. */
.blog-toc { display: none; }

/* 좁은 폭(<1100px) 전용 접이식 목차(리뷰 2차 P2). 위 고정 목차가 숨는 구간을
   <details> 하나가 메운다 - JS 추가 없음. 1100px 이상에서는 이쪽이 숨어 둘이
   동시에 보이지 않는다. 신규 색 없이 토큰만 쓴다. */
.blog-toc-fold {
  margin: 0 0 20px; border: 1px solid var(--rule);
  border-radius: var(--radius-input); padding: 8px 12px;
}
.blog-toc-fold-summary {
  cursor: pointer; font-size: 13px; font-weight: 600;
  color: var(--ink-700); letter-spacing: -0.2px;
}
.blog-toc-fold ul { list-style: none; margin: 8px 0 0; padding: 0; }
.blog-toc-fold li { margin: 0 0 8px; }
.blog-toc-fold .blog-toc-link {
  display: block; font-size: 14px; line-height: 1.45;
  color: var(--ink-700); text-decoration: none;
}

@media (min-width: 1100px) {
  .blog-toc-fold { display: none; }
  .blog-toc {
    display: block; position: fixed; top: 132px;
    left: calc(50% + 392px); width: 152px;
    max-height: calc(100vh - 260px); overflow-y: auto;
    padding-left: 14px; border-left: 1px solid var(--rule);
  }
  .blog-toc ul { list-style: none; margin: 0; padding: 0; }
  .blog-toc li { margin: 0 0 10px; }
  .blog-toc-link {
    display: block; font-size: 13px; line-height: 1.4; color: var(--ink-500);
    text-decoration: none; letter-spacing: -0.2px; transition: color .15s ease;
  }
  .blog-toc-link:hover { color: var(--foreground); }
  .blog-toc-link:active { color: var(--ink-700); }
  .blog-toc-link.is-current { color: var(--ink-900); font-weight: 600; }
}

/* 같은 클러스터의 다른 글(본문 하단 내부링크 블록). 본문 밖 부기라 고지 블록
   (.post-notice)의 상단 구분선 + 작은 글자 톤을 그대로 계승한다. 신규 색 없음. */
.blog-related {
  max-width: 42rem; margin: 3em auto 0;
  padding-top: 20px; border-top: 1px solid var(--rule);
}
.blog-related-title {
  font-size: 14px; font-weight: 700; color: var(--ink-900);
  letter-spacing: -0.2px; margin: 0 0 12px;
}
.blog-related-list { list-style: none; margin: 0; padding: 0; }
.blog-related-item { margin: 0 0 8px; }
.blog-related-item:last-child { margin-bottom: 0; }
.blog-related-link {
  font-size: 15px; line-height: 1.6; color: var(--ink-900);
  text-decoration: underline; text-underline-offset: 3px; letter-spacing: -0.2px;
}
.blog-related-link:hover { text-decoration-thickness: 2px; }
.blog-related-link:active { color: var(--ink-700); }

/* 하단 플로팅 CTA(본문 페이지 전용): 반투명 종이 + 블러 + 카드 그림자. 사이트 팔레트. */
/* 플로팅 CTA는 fixed라 문서 끝에서 판권면 마지막 줄을 덮는다(실측 2026-09-14: 글리프
   3,445px²). spacer 88px는 main 끝만 보호하므로 본문 페이지의 판권면 하단에 바 높이만큼
   비워 둔다. 이 규칙은 위 .site-footer .container(28px 20px) 뒤에 있어 순서로 이긴다. */
.blog-post-page .site-footer .container { padding-bottom: 112px; }
.blog-cta-spacer { height: 88px; }
.blog-cta {
  position: fixed; left: 0; right: 0; bottom: calc(16px + env(safe-area-inset-bottom)); z-index: 30;
  width: min(680px, calc(100% - 32px)); margin: 0 auto;
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 14px 18px;
  background: rgba(255, 255, 255, 0.82);
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  border: 1px solid var(--rule); border-radius: var(--radius-pill);
  box-shadow: var(--shadow-card);
}
.blog-cta-text {
  margin: 0; font-size: 15px; font-weight: 500; color: var(--ink-900);
  letter-spacing: -0.2px; line-height: 1.4;
}
/* tactile 시안: 채워진 CTA 3종 공통 재질(도톰한 플라스틱). 텍스트 CTA라 눌림은
   축소가 아니라 1px 내려앉음으로 준다(원형 아이콘 버튼은 기존 축소 관례 유지). */
.blog-cta-button {
  flex: none; display: inline-flex; align-items: center; min-height: 40px;
  padding: 0 18px;
  background-color: var(--primary); background-image: var(--grad-primary);
  color: var(--primary-foreground);
  border-radius: var(--radius-pill); text-decoration: none;
  font-size: 14px; font-weight: 600; letter-spacing: -0.2px;
  box-shadow: var(--edge-hi), var(--edge-lo-primary), var(--shadow-raise-primary);
  transition: background-color .15s ease, box-shadow .15s ease, transform .12s ease;
}
.blog-cta-button:hover {
  background-color: var(--accent-press); background-image: var(--grad-primary-hover);
  transform: translateY(-1px);
  box-shadow: var(--edge-hi), var(--edge-lo-primary), var(--shadow-raise-primary-hi);
}
.blog-cta-button:active {
  background-color: var(--accent-press); background-image: var(--grad-primary-press);
  transform: translateY(1px); box-shadow: var(--shadow-press-primary);
}
/* 모바일: 플로팅 바가 본문을 덜 가리게 한 단 죈다(QA 2026-09-13: 종전 66px ->
   약 58px). 버튼 40px는 유지한다 - 바를 더 줄이면 터치 타깃이 하한 아래로 간다. */
@media (max-width: 600px) {
  .blog-cta { gap: 10px; padding: 8px 12px; bottom: calc(10px + env(safe-area-inset-bottom)); }
  .blog-cta-text { font-size: 13px; }
  .blog-cta-button { padding: 0 14px; font-size: 13px; }
}

/* 목록(blog_index): 행 → 카드형(제목·설명·날짜, hover 시 살짝 강조). 과한 장식 없음. */
.blog-list { list-style: none; padding: 0; margin: 24px 0 0; display: grid; gap: 14px; }
.blog-list-item {
  background-color: var(--card); background-image: var(--grad-paper-soft);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  /* 촉각 2단계: 랜딩 목록 카드(.landing-post)와 같은 급으로 통일. */
  box-shadow: var(--edge-hi), var(--edge-lo), var(--shadow-raise);
  transition: border-color .15s ease, box-shadow .15s ease, transform .12s ease;
}
.blog-list-item:hover {
  border-color: var(--ink-900); box-shadow: var(--edge-hi), var(--edge-lo), var(--shadow-raise-hi);
  transform: translateY(-1px);
}
.blog-list-item:active { transform: none; box-shadow: var(--shadow-press-soft); }
/* 썸네일 카드: 좌측 이미지 + 우측 본문. 기존 카드 테두리·패딩 규격을 그대로 두고
   그 안에서만 2단으로 나눈다. 좁은 화면에서는 1단으로 접어 이미지를 위에 얹는다. */
.blog-list-link {
  display: grid; grid-template-columns: 168px 1fr; gap: 18px; align-items: start;
  text-decoration: none; color: inherit; padding: 20px 22px;
}
.blog-list-thumb {
  width: 100%; height: auto; aspect-ratio: 1200 / 630;
  border: 1px solid var(--rule); border-radius: var(--radius-input);
  background: var(--paper); display: block;
  /* 주제 사진(thumbs.json)은 3:2 등 비율이 제각각이라 aspect-ratio 박스에
     그냥 넣으면 늘어난다. cover로 잘라 채운다. og.png 폴백은 이미 1200:630이라
     이 규칙이 아무 일도 하지 않는다. */
  object-fit: cover;
}
@media (max-width: 560px) {
  .blog-list-link { grid-template-columns: 1fr; gap: 14px; }
}
.blog-list-link:hover .blog-list-heading {
  color: var(--ink-900); text-decoration: underline; text-underline-offset: 3px;
  text-decoration-thickness: 2px;
}
.blog-list-link:active .blog-list-heading { color: var(--ink-700); }
.blog-list-heading { font-size: 19px; font-weight: 700; margin: 0 0 6px; color: var(--ink-900); }
.blog-list-desc { font-size: 15px; color: var(--ink-700); line-height: 1.6; margin: 0 0 8px; }
.blog-list-meta { margin: 0; }
.blog-empty { color: var(--ink-500); margin: 32px 0; }
/* 목록 하단 사진 출처 1줄(Pexels 가이드라인). 각주 성격이라 본문보다 죽인다. */
.blog-photo-credit { color: var(--ink-500); font-size: 13px; margin: 24px 0 0; }

/* 본문 히어로 사진(오너 지시 2026-09-11): 목록 카드와 같은 주제 사진을 제목 아래에
   얹는다. 비율 박스 + cover는 .blog-list-thumb과 같은 논거다. 출처 캡션은
   .blog-photo-credit과 같은 각주 톤이되 사진에 붙는 줄이라 여백만 죄인다. */
.blog-post-hero { margin: 20px 0 28px; }
.blog-post-hero-img {
  display: block; width: 100%; height: auto; aspect-ratio: 1200 / 630;
  object-fit: cover; border: 1px solid var(--rule); border-radius: var(--radius-input);
  background: var(--paper);
}
.blog-post-hero-credit { color: var(--ink-500); font-size: 12px; margin: 8px 0 0; }

/* 의원 허브(/members) 명단 표 + 이름 검색 (탈AI 유닛 4).

   허브는 위 .blog-list 카드 문법을 빌려 썼었다. 그 카드 링크(.blog-list-link)가 썸네일
   자리로 첫 열 168px를 잡아 두는데 허브에는 사진이 없어 그 폭이 통째로 빈 여백이 됐고,
   같은 크기 카드 320장이 한 줄씩 늘어섰다. 표 문법은 블로그 본문 표(.blog-post-body
   table)에서 그대로 가져온다: 열 머리는 작은 회색 글자, 행 구분은 하단 헤어라인 하나.
   .blog-post-body 스코프 안에 넣지 않는다 - 그쪽은 산문 여백 규칙을 통째로 끌고 온다.

   신규 색을 만들지 않는다. 이 블록의 유일한 유채는 정당 도트(.party-mark)이고 그건
   자료 색이라 기존 6값 SSOT를 그대로 쓴다. */
.member-search { margin: 24px 0 0; }
.member-search-input {
  width: 100%; max-width: 320px; min-height: 38px; padding: 0 12px;
  font-family: inherit; font-size: 15px;
  color: var(--foreground); background: var(--card);
  border: 1px solid var(--border); border-radius: var(--radius-input);
}
.member-search-input::placeholder { color: var(--ink-500); }
/* 열 폭을 고정한다. 자동 폭이면 두 열이 절반씩 나눠 가져 이름과 정당 사이에 눈이
   건너야 할 빈 칸이 생긴다. 이름 칸은 세 글자 이름이 들어갈 만큼만 잡고 나머지는
   정당 칸이 받는다 - 정당 도트가 320행 내내 같은 x에 선다. */
.member-roster {
  width: 100%; table-layout: fixed; border-collapse: collapse; margin: 20px 0 0;
  font-size: 15px; color: var(--ink-900); letter-spacing: -0.2px;
}
.member-roster thead th {
  color: var(--ink-500); font-size: 13px; font-weight: 600; text-align: left;
  border-bottom: 1px solid var(--rule); padding: 0 0 8px;
}
.member-roster th:first-child { width: 30%; }
.member-roster th + th, .member-roster td + td { padding-left: 16px; }
/* 이름 칸은 th(scope="row")라 굵게 나온다. 명단은 320행이 같은 층위라 기본 무게로
   되돌린다(굵기가 위계를 만들 자리가 아니다). */
.member-roster-row > * {
  border-bottom: 1px solid var(--rule); padding: 6px 0;
  text-align: left; font-weight: 400; line-height: 1.5; vertical-align: baseline;
}
/* 클라이언트 검색이 거른 행. tr의 기본 display가 [hidden]을 덮지 않도록 명시한다. */
.member-roster-row[hidden] { display: none; }
.member-roster-link { color: var(--ink-900); text-decoration: none; }
.member-roster-link:hover {
  text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 2px;
}
.member-roster-party { color: var(--ink-700); font-size: 14px; }
/* 좁은 폭에서는 이름 칸 몫을 키운다. 동명이인 행은 한자를 병기해("박지원(朴智元)")
   30% 칸에 들어가지 않는다. */
@media (max-width: 560px) {
  .member-roster { font-size: 14px; }
  .member-roster th:first-child { width: 45%; }
  .member-roster-party { font-size: 13px; }
}

/* 목록 페이지네이션(blog_index). 기존 잉크·rule·pill 토큰만 재사용, 신규 색 없음. */
.blog-pagination {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  margin: 32px 0 0; flex-wrap: wrap;
}
.blog-page-numbers { display: flex; align-items: center; gap: 6px; }
.blog-page-link, .blog-page-current {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 32px; height: 32px; padding: 0 8px;
  border-radius: var(--radius-pill); font-size: 14px; font-weight: 500;
}
.blog-page-link {
  color: var(--ink-700); text-decoration: none; border: 1px solid var(--rule);
  transition: border-color .15s ease, color .15s ease;
}
.blog-page-link:hover { border-color: var(--ink-500); color: var(--ink-900); }
.blog-page-link:active { background: var(--muted); color: var(--ink-700); }
.blog-page-current {
  color: var(--primary-foreground); background: var(--primary); border: 1px solid var(--primary);
}
.blog-page-ellipsis {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 20px; height: 32px; color: var(--ink-500);
  font-size: 14px; user-select: none;
}
/* 390px 등 좁은 화면: 여백을 줄이고 현재 ±2칸의 바깥쪽 칸을 숨겨 사실상 ±1
   윈도우로 좁힌다. 링크 자체는 DOM에 그대로 남아 크롤 가능하며(SEO 성질 보존)
   시각적으로만 감춘다. */
@media (max-width: 480px) {
  .blog-pagination { gap: 4px; }
  .blog-page-numbers { gap: 4px; }
  .blog-page-link, .blog-page-current {
    min-width: 28px; height: 28px; padding: 0 6px; font-size: 13px;
  }
  .blog-page-ellipsis { min-width: 14px; height: 28px; }
  .blog-page-mid { display: none; }
}

/* 법안 카드 (bill_lookup, 설계 3.2/3.5). 기존 .card·.timeline·.tier·.badge 재사용,
   신규는 발의자 축 최소 클래스만. */
/* 대수 배지: 두 카드 레일 공용(.bill-lookup 스코프 해제 — 보안 리뷰 MEDIUM-2).
   bill_lookup은 상시 표기(다대수 상시 혼합), trackrecord 타임라인은 대수가 섞인
   응답에서만 표기한다(cards.apply_era_badges). 다대수를 연 뒤로는 후자에도 실제로
   배지가 실리므로 스타일이 bill-lookup 안에만 있으면 17대/22대 카드가 시각적으로
   구분되지 않는다(데이터 정직성). 유채색 신규 사용 없음 — 기존 룰·잉크 토큰만. */
.era-badge {
  display: inline-block; font-size: 12px; font-weight: 500; letter-spacing: -0.2px;
  padding: 1px 6px; margin-top: 4px;
  border: 1px solid var(--rule); border-radius: var(--radius-tag);
  color: var(--ink-700); background: var(--paper-raised); white-space: nowrap;
}
.proposer-list { margin: 8px 0; }
.proposer-text { font-size: 14px; color: var(--ink-900); margin: 6px 0; }
.rep-proposers { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 6px 0; }
.proposer-role { font-size: 13px; color: var(--ink-500); }
.proposer-form { display: inline; margin: 0; }
/* 발의자 버튼: 탭 타깃 확대 — min-height 36px + 상하 패딩 확대(WCAG 타깃 크기). */
.proposer-form button {
  display: inline-flex; align-items: center; min-height: 36px;
  font-size: 13px; padding: 6px 12px; cursor: pointer;
  border: 1px solid var(--ink-900); border-radius: var(--radius-tag);
  color: var(--ink-900); background: var(--paper-raised);
}
/* 위 기본 블록은 원문 그대로 고정돼 있다(test_qplan_render가 바이트로 핀). 상태
   레이어는 별도 규칙으로만 얹는다. 기본 블록을 건드리면 채팅 발의자 알약이 함께
   무너진다는 그 테스트의 취지를 그대로 지킨다. */
.proposer-form button:hover { border-color: var(--ink-500); }
.proposer-form button:active { background: var(--muted); }
.co-proposers { margin: 6px 0; }
.co-proposers .co-list { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 6px; }
.proposer-unknown { font-size: 13px; color: var(--ink-500); }
.proposer-partial-note { font-size: 13px; color: var(--ink-500); margin: 6px 0; line-height: 1.5; }

/* 질의 계획 대수 목록 (설계 2026-08-28 query-plan §9.2). 원장 톤 목록이다: 왼쪽에
   이름·정당, 오른쪽에 수량, 행 사이 헤어라인 하나. 위 .proposer-form 규칙(법안 카드의
   테두리 알약)은 한 글자도 바뀌지 않는다 - qplan 목록 안에서만 .qplan-row 스코프로
   텍스트 링크형으로 덮어쓴다. 셀렉터 특정도가 (0,2,1)이라 위 기본 규칙보다 강하다.
   신규 색은 없다(기존 잉크·룰·accent 토큰만). */
.qplan-section .qplan-header { margin: 0; }
.qplan-section .qplan-method { margin: 6px 0 0; font-size: 14px; color: var(--ink-700); }
/* 분석 문장: 방법론 줄과 같은 계열의 보조 텍스트다(수치 표가 주인공). */
.qplan-section .qplan-analysis { margin: 6px 0 0; font-size: 14px; color: var(--ink-700); }
.qplan-rows { list-style: none; margin: 12px 0 0; padding: 0; }
.qplan-row {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 12px; padding: 10px 0;
}
/* 인접 형제에만 선을 그어 목록 위아래로 선이 새지 않게 한다. */
.qplan-row + .qplan-row { border-top: 1px solid var(--rule); }
.qplan-row .party { font-size: 14px; color: var(--ink-900); }
.qplan-row .num {
  font-family: var(--font-mono); font-size: 14px; color: var(--ink-700);
  white-space: nowrap; text-align: right;
}
/* 폼은 행의 왼쪽 칸을 통째로 차지한다(버튼 타깃을 이름 글자폭이 아니라 칸 전체로). */
.qplan-row .proposer-form { display: block; flex: 1 1 auto; min-width: 0; margin: 0; }
.qplan-row .proposer-form button {
  display: block; width: 100%; text-align: left;
  min-height: 0; padding: 0; margin: 0;
  background: none; border: none; border-radius: 0;
  font: inherit; font-size: 14px; color: var(--ink-900); cursor: pointer;
}
.qplan-row .proposer-form button:hover {
  color: var(--ink-900); text-decoration: underline; text-underline-offset: 3px;
  text-decoration-thickness: 2px;
}
/* 텍스트 링크형 press 관례(배경이 없으므로 눌림은 색으로만 표현). 위 알약 규칙의
   :active 배경도 여기서 함께 무력화한다. 이 행은 알약이 아니라 링크다. */
.qplan-row .proposer-form button:active {
  color: var(--ink-700); background: none; text-decoration: underline;
  text-underline-offset: 3px;
}
.qplan-row .proposer-unknown { flex: 1 1 auto; min-width: 0; font-size: 14px; }
/* 전체 합계는 행 목록이 아니라 값 한 줄이다: 모노 수치만 크게 둔다. 크기는 UI 캠페인
   V2에서 아래 수치 블록과 같은 스케일로 올렸다(설계 2026-09-07 §3.3): 같은 성격의 총계
   수치가 표면마다 다른 크기로 뜨지 않게 한다. 마크업은 그대로다. */
.qplan-scalar {
  margin: 12px 0 0; font-family: var(--font-mono);
  font-size: clamp(36px, 7vw, 52px); font-weight: 700;
  line-height: 1.05; letter-spacing: -0.5px; color: var(--ink-900);
}
.qplan-total {
  margin: 10px 0 0; padding-top: 10px; border-top: 1px solid var(--rule);
  font-family: var(--font-mono); font-size: 14px; color: var(--ink-700);
}

/* 답변 구조 개편(2026-08-19): 산문 히스토리 접힘. 답변 수준 디스클로저 공통 컴포넌트
   (.evidence와 공유, 위 "답변 수준 디스클로저 행" 블록 참조)를 그대로 계승한다.
   요약 행 스타일은 그 공유 규칙이 담당하고, 여기서는 여백만 둔다. 무채색(G5). */
.synthesis-history { margin: 16px 0 0; }

/* ---- 데이터 시각 요소 (UI 캠페인 V2, 설계 2026-09-07 §3) --------------------------
   색 사용 규율의 정본은 :root 머리 주석이다. 아래 도트는 정당 상징색을 채움에만 쓰고
   텍스트 색으로는 쓰지 않는다. 도트는 aria-hidden 장식이고 사실은 언제나 옆에 붙는
   정당명 텍스트가 전달한다(색 단독 의미 전달 금지, WCAG 1.4.1).

   내부 링: --canvas 같은 어두운 소품 표면 위에서 기타 색이 논텍스트 3:1 아래로
   떨어진다. 그래서 표면과 무관하게 1px 안쪽 링을 준다. 아웃라인 도트 기법 자체는
   위 빈 틱 노드 규칙의 전례이고 링 값은 다르다. 이 캠페인이 신설한 컴포넌트 한정이며
   기존 랜딩 의석·범례 도트에는 얹지 않는다(랜딩 픽셀 무변화 유지). */
.party-mark {
  display: inline-block; flex: none; width: 10px; height: 10px;
  border-radius: 50%; vertical-align: middle;
  background: var(--party-dot, var(--party-etc));
  box-shadow: inset 0 0 0 1px rgba(22, 24, 29, 0.08);
}
.party-mark[data-party="dp"] { --party-dot: var(--party-dp); }
.party-mark[data-party="ppp"] { --party-dot: var(--party-ppp); }
.party-mark[data-party="rkp"] { --party-dot: var(--party-rkp); }
.party-mark[data-party="nrp"] { --party-dot: var(--party-nrp); }
.party-mark[data-party="jp"] { --party-dot: var(--party-jp); }
.party-mark[data-party="etc"] { --party-dot: var(--party-etc); }
/* 도트와 자기 정당명을 한 덩어리로 묶는다. 덩어리 사이의 구분자 ", "는 바깥에 남아
   기존 표시 텍스트가 그대로 읽힌다. */
.party-name { display: inline-flex; align-items: center; gap: 6px; }

/* 총계 수치 블록. 수치 조판(모노 + tabular-nums)은 함께 붙는 .mono가 담당하고 여기서는
   크기·굵기만 준다. 캡션은 서버가 넘긴 guards 문구다. */
.stat-hero { display: flex; flex-wrap: wrap; gap: 24px; margin: 10px 0 0; }
.stat-hero-item { display: flex; flex-direction: column; gap: 2px; }
.stat-hero-value {
  font-size: clamp(36px, 7vw, 52px); font-weight: 700; line-height: 1.05;
  letter-spacing: -0.03em; color: var(--ink-900);
}
.stat-hero-label { font-size: 13px; color: var(--muted-foreground); }

/* v3 표면 헤더. 산문이 주인공인 표면이라 이름 크기를 답변 카드 h2(28px)보다 한 단
   낮춘다. 스코프를 .answer-v3로 좁혀 카드 표면 헤더는 건드리지 않는다. */
.answer-v3 .v3-member-header { margin: 0 0 12px; }
.answer-v3 .v3-member-header h2 {
  margin: 0; font-size: 21px; font-weight: 700; letter-spacing: -0.3px;
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
}
.answer-v3 .v3-member-header .stat-hero { margin-top: 8px; }

/* 본회의 표결 집계 스트립 (UI 캠페인 V3, 설계 2026-09-07 §3.2 (a)). 재적 길이 트랙 위에
   찬성·반대·기권 세 세그먼트가 얹힌다. 잔여 구간은 트랙 색 그대로 남고 이름도 색도
   받지 않는다. 스트립은 aria-hidden 장식이고 수치는 바로 아래 .vote-counts 줄이
   전달한다(색 단독 의미 전달 금지, WCAG 1.4.1).

   방향쌍(--dir-warm/--dir-cool)을 같은 카드 안의 .tag-dir 방향 단어와 공유한다. 알고
   한 선택이다: 두 곳 모두 색이 단독 채널이 아니고(항상 단어·수치가 옆에 붙는다) 형태가
   서로 다르다(스트립 세그먼트와 텍스트 단어).

   모서리는 clip-path로 깎는다. viewBox가 가로로 늘어나는 스트립이라 rect의 rx를 쓰면
   반지름도 함께 늘어나고, border-radius는 svg 내용을 자르지 않는다. clip-path를 모르는
   환경은 각진 모서리로 그대로 뜬다.

   1px 안쪽 링(설계 §2, 신설 컴포넌트 공통 시인성 규칙)은 세그먼트마다가 아니라 스트립
   테두리에 한 번만 준다: 맞붙은 세그먼트에 각각 두르면 경계마다 이음선이 생긴다. 링 값은
   .party-mark와 같고, 늘어나는 viewBox 밖의 CSS 아웃라인이라 굵기가 균일하다.

   찬성·반대의 색 배정은 아래 두 줄이 전부다. 뒤집으려면 이 블록의 두 값만 맞바꾼다. */
.vote-strip {
  --vs-yes: var(--dir-warm);
  --vs-no: var(--dir-cool);
  display: block; width: 100%; height: 8px; margin: 10px 0 0;
  clip-path: inset(0 round 2px);
  outline: 1px solid rgba(22, 24, 29, 0.08); outline-offset: -1px;
}
.vs-track { fill: var(--canvas); }
.vs-yes { fill: var(--vs-yes); }
.vs-no { fill: var(--vs-no); }
.vs-abstain { fill: var(--ink-500); }

/* 의원 개인 표결 분포 (UI 캠페인 V5, 설계 2026-09-07 §3.2 (b)). 네 값 폐쇄 어휘를
   그린다. 위 집계 스트립과 클래스를 갈라 둔 이유는 어휘가 다르기 때문이다: 저쪽은
   재적 트랙 위의 찬반기 셋이고 이쪽은 합이 곧 총계인 넷이다. 두 그림이 규칙을 나눠
   쓰면 한쪽을 고칠 때 다른 쪽이 조용히 따라 움직인다.

   찬성·반대의 방향쌍은 집계 스트립과 같은 배정이다(같은 사실의 같은 색). 기권은 무채
   잉크, 불참은 채움 없는 아웃라인이고, 정당색은 여기 들어오지 않는다: 표결은 정당의
   사실이 아니라 이 의원 한 사람의 사실이다.

   그림은 aria-hidden 장식이고 수치는 바로 아래 텍스트 목록이 0까지 전달한다. 모션은
   두지 않는다(허용 목록 두 항목은 채팅 신규 턴 스코프 전용이다).

   바: 세로로는 늘어나지 않는 8px 줄이라 링을 CSS 아웃라인으로 한 번만 두른다(맞붙은
   세그먼트마다 두르면 경계에 이음선이 생긴다). 불참 세그먼트의 진한 링만 늘림을 타지
   않는 stroke로 안에 들어간다.

   그리드: 한 표가 한 도트라 지름 6px에 간격 8px 격자다. svg가 px 폭을 들고 있어 좁은
   화면에서만 비례로 줄고 넓은 화면에서 도트가 커지지 않는다. 공통 시인성 링(설계 §2)은
   도트마다 필요하고, 불참 도트의 진한 링이 그 공통 규칙에 지지 않게 같은 스코프로 다시
   쓴다. */
.vote-dist {
  display: block; width: 100%; height: 8px; margin: 0 0 10px;
  clip-path: inset(0 round 2px);
  outline: 1px solid rgba(22, 24, 29, 0.08); outline-offset: -1px;
}
.vote-dist-grid { display: block; max-width: 100%; height: auto; margin: 0 0 12px; }
.vd-yes { fill: var(--dir-warm); }
.vd-no { fill: var(--dir-cool); }
.vd-abstain { fill: var(--ink-500); }
/* 불참 도트는 뚫린 링이다. 촉각 2단계에서 바탕이 --canvas-page로 내려갔지만 8px
   도트의 순백/그레이 차는 시각적으로 무의미하고 test_data_vivid_ui가 이 선언을
   바이트로 고정하므로 --paper를 유지한다(위 .bill-body 데이터 공백 틱과 달리). */
.vd-absent { fill: var(--paper); stroke: var(--ink-500); stroke-width: 1; }
.vote-dist-grid circle { stroke: rgba(22, 24, 29, 0.08); stroke-width: 1; }
.vote-dist-grid .vd-absent { stroke: var(--ink-500); }

/* 인앱 미니 의석 배치도 (UI 캠페인 V4, 설계 2026-09-07 §3.4). 랜딩 시그니처와 같은
   좌표계를 받아 폭만 줄인다. viewBox가 같으니 SVG가 비율로 스케일되고, 좁은 화면에서는
   가용 폭까지 더 줄어든다.

   랜딩 도트 규칙과 셀렉터를 갈라 둔다: 저쪽은 .landing- 프리픽스 파일에 있고 채팅이
   그 파일을 읽지 않는다. 신설 컴포넌트라 공통 시인성 링(설계 §2)을 도트마다 두른다 -
   기존 랜딩 배치도는 링 없는 현행 그대로다.

   그림은 aria-hidden 장식이고 정당명·인원은 바로 아래 행 목록이 텍스트로 전달한다.
   모션은 두지 않는다: 신규 턴 페이드가 답변 블록 단위로 이미 한 번 재생한다. */
.hemi-mini {
  display: block; width: 100%; max-width: 320px; height: auto; margin: 12px 0 0;
}
.hemi-mini circle { stroke: rgba(22, 24, 29, 0.08); stroke-width: 1; }
.hemi-mini g { fill: var(--party-etc); }
.hemi-mini [data-party="dp"] { fill: var(--party-dp); }
.hemi-mini [data-party="ppp"] { fill: var(--party-ppp); }
.hemi-mini [data-party="rkp"] { fill: var(--party-rkp); }
.hemi-mini [data-party="nrp"] { fill: var(--party-nrp); }
.hemi-mini [data-party="jp"] { fill: var(--party-jp); }
.hemi-mini [data-party="etc"] { fill: var(--party-etc); }

/* 의원 표면의 수치 블록 여백. 총계 문장 바로 아래에 붙고 다음 섹션 카드와 사이를
   벌린다. 크기·조판은 위 .stat-hero 공통 규칙 그대로다(표면마다 다른 수치 크기를
   만들지 않는다). */
.blog-post > .stat-hero { margin: 14px 0 28px; }

/* 신규 턴 등장 페이드 (설계 2026-09-07 §6 허용 목록 1, 탈AI 유닛 1에서 축약).
   transform/opacity만 쓰고 200ms를 넘지 않는다. .turn-fresh는 progress.js의 done
   경로만 부여한다: 복원 경로도 같은 innerHTML 주입이라 클래스 게이트가 없으면
   새로고침마다 스레드 전체가 다시 재생된다. from 블록만 두어 애니메이션이 꺼진
   환경에서 요소의 자연 상태가 그대로 최종 상태가 되게 한다(reduced-motion 전역
   무력화 블록과 정합).

   축약 근거(탈AI 유닛 1): 원안은 자식 요소 1~5에 40/80/120/160ms 지연을 걸어
   문단이 순차로 흘러 들어오게 했다. 이 계단식 지연은 답변 내용과 무관한 순서를
   덧씌우고(문단 2가 문단 3보다 먼저 도착할 이유가 없다) 기계 저작 표면의 최빈
   시그니처로 읽힌다. 지연을 걷어내고 답변 블록 한 덩어리에 1회 페이드만 남긴다.
   성문 규율(§6: transform/opacity, 150~300ms, 1회성)은 그대로 지킨다. 키프레임과
   재생 길이는 무변경이고 셀렉터가 자식(> *)에서 답변 컨테이너로 한 칸 올라간다:
   자식마다 같은 애니메이션을 N개 돌리는 대신 한 개만 돈다. */
@keyframes turn-fresh-in { from { opacity: 0; transform: translateY(4px); } }
.turn-answer.turn-fresh .answer {
  animation: turn-fresh-in 200ms ease-out backwards;
}

/* 표결 스트립 채움 (설계 2026-09-07 §6 허용 목록 2). transform만 쓰고 신규 턴 스코프
   안에서만 재생한다. 공유 정적 뷰에는 .turn-fresh가 없어 채워진 상태로 바로 뜬다.
   from 블록만 두어 애니메이션이 꺼진 환경에서 채워진 상태가 그대로 최종 상태가 된다.
   transform-box를 모르는 환경은 채움이 즉시 표시된다(점진 향상). */
@keyframes vote-strip-fill { from { transform: scaleX(0); } }
.turn-answer.turn-fresh .vote-strip .vs-fill {
  animation: vote-strip-fill 300ms ease-out backwards;
  transform-box: fill-box; transform-origin: left;
}

/* ---- 기록물 메타 레이블 (브랜드 웨이브 B2, 설계 2026-09-07 §10.2) ----
   대수·기준일·구획 번호처럼 크롬과 구획 머리에 사는 보조 정보의 공통 조판이다.
   숫자는 모노 tabular, 한글은 소형 + 자간 확장으로 회의록·의안 대장의 표기 문법을
   따른다. 값은 전부 기존 토큰이고 구분자는 가운뎃점 하나만 쓴다.
   대비: ink-500 on #FFFFFF = 5.26:1로 소형 텍스트 4.5:1을 통과한다.
   전례의 일반화다: .kind-label·.landing-step-num이 이미 이 문법의 사례이며 두 규칙은
   값이 근접해 무수정으로 둔다. 답변 본문(산문·카드) 조판에는 쓰지 않는다.
   파일 끝에 두는 이유: .sidebar-heading·.scope-note 같은 기존 규칙과 같은 특이도로
   병용되므로 뒤에 와야 값이 재조판된다. */
.meta-label {
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: 11px; font-weight: 500; letter-spacing: 0.05em;
  color: var(--ink-500);
}

/* ---- 층위 칩 (브랜드 웨이브 B2, 설계 2026-09-07 §10.5) ----
   등재 사실(DB 원문)과 종합분석(LLM 산문)의 층위 경계를 시각 어휘로 승격한 시그니처
   마이크로 컴포넌트다. 점선은 비확정·해석 층위라는 기존 어휘(.tier[data-tier="관련
   가능"]의 dashed)를 계승하므로 새 의미를 발명하지 않는다. 답변당 1개, 종합분석
   섹션 머리에만 산다(산문 중간 반복 삽입 없음).
   조판은 .meta-label 병용이라 여기서는 테두리·여백만 정한다. 선 색은 --border(=--rule,
   잉크 8% 알파)가 아니라 --ink-500이다: 저알파 헤어라인은 점선으로 끊기면 사실상
   보이지 않아 칩이 성립하지 않는다. 글자와 같은 잉크라 한 덩어리로 읽힌다.
   기존 고지 문장(.eval-note)은 무변경으로 그 아래 남는다. */
.provenance-chip {
  display: inline-block; margin: 0 0 12px; padding: 2px 8px;
  border: 1px dashed var(--ink-500); border-radius: var(--radius-tag);
}

/* ---- 아치 파생 오너먼트 (브랜드 웨이브 B3, 설계 2026-09-07 §10.3) ----
   브랜드 마크의 의사당 반원을 페이지 소품으로 내린 것이다. 규율: 아치는 장식일 때
   데이터를 흉내내지 않는다. 좌석으로 수를 표현하는 도형은 hemicycle 전용이라는 기존
   계약이 있으므로 파생 오너먼트는 도트를 쓰지 않고 채움 호로만 그리고, 마크업에서
   aria-hidden 순수 장식임을 명시한다. 텍스트 노드가 없어 금지어 스캔에도 무해하다.
   currentColor 채움이라 색은 여기서만 정한다. 신규 모션 0.
   2026-09-09(설계 §2.3 시그니처 집중): 랜딩 섹션 키커 앞 소형 호(.arc-mark)는
   사용처와 함께 걷었다. 아치는 브랜드 마크, 히어로 hemicycle, 404 오너먼트
   세 곳에만 남는다. */
.arc-ornament {
  display: block; width: 72px; height: 36px; margin: 0 0 18px;
  color: var(--ink-500); opacity: 0.3;
}

/* ---- 서기: 절차적 물리 구동 캐릭터 (오너 지시 2026-09-09) ----

   그림은 그대로다. 구동 층만 CSS 키프레임 클립에서 rAF 물리 엔진으로 옮겼다.

   그래서 이 파일에는 캐릭터 모션이 없다. 파츠의 transform은 cat.js가 매 프레임
   직접 쓴다(스프링-댐퍼 수렴값). 여기 남은 것은 (1) 자리와 크기, (2) 변형의
   기준점(transform-box/origin), (3) 색, (4) 말풍선과 소품처럼 캐릭터 밖의 것들뿐이다.

   키프레임을 지운 이유: 클립은 재생 중 끼어들 수 없고 상태가 바뀌면 자세가 한
   프레임에 튄다. 목표 자세를 스프링이 좇으면 언제 끼어들어도 현재 속도에서
   이어지므로 전환 스냅이 0이다.

   파츠에 transition을 걸면 안 된다. 루프가 매 프레임 쓰는 값을 전이가 다시
   보간해 두 겹으로 늦어지고, 물리적으로 맞던 속도가 어긋난다.

   맥거핀이다. 컨테이너째 aria-hidden이고 층 전체가 pointer-events: none이라
   본문·답변·컴포저의 클릭·선택·스크롤을 한 점도 가리지 않는다. z-index 9는 기존
   층 규율 그대로다(헤더 10 아래). 색은 전부 잉크 스케일이고 정당색은 오지 않는다. */

.cat-layer {
  position: fixed;
  inset: 0;
  z-index: 9;
  pointer-events: none;
  overflow: hidden;
  /* iOS 홈 인디케이터 영역. cat.js가 이 값을 읽어 바닥 여백에 더한다. */
  --cat-safe-bottom: env(safe-area-inset-bottom, 0px);
}

/* 자리는 left/top이다. 세로 기준이 top인 이유: 데스크톱에서 층이 문서에 고정되므로
   top이 곧 문서 좌표가 되고, 답변이 아래로 붙어도 앉아 있던 선반에서 안 밀린다. */
.cat-figure {
  position: absolute;
  left: 0;
  top: 0;
  width: 64px;
  height: 72px;
  pointer-events: auto;
  cursor: grab;
  touch-action: pan-y;
}

.cat-held { cursor: grabbing; }

/* 아래 다섯은 전부 변형의 기준점만 정한다. 값은 cat.js가 넣는다.
   transform-box: fill-box가 없으면 SVG 안에서 퍼센트 원점이 뷰박스 기준이 돼
   회전축이 엉뚱한 곳에 잡힌다. */
.cat-svg {
  display: block;
  width: 100%;
  height: auto;
  fill: var(--ink-900);
  transform-box: fill-box;
  transform-origin: 50% 100%;   /* 발밑 - 스쿼시가 바닥을 기준으로 눌린다 */
}

.cat-eyes {
  fill: var(--paper);
  transform-box: fill-box;
  transform-origin: 50% 50%;
}

.cat-pupils { fill: var(--ink-900); }

.cat-tail {
  transform-box: fill-box;
  transform-origin: 12% 88%;    /* 꼬리 밑동 */
}

.cat-head-group {
  transform-box: fill-box;
  transform-origin: 50% 100%;   /* 목 */
}

.cat-ear-l {
  transform-box: fill-box;
  transform-origin: 80% 100%;
}

.cat-ear-r {
  transform-box: fill-box;
  transform-origin: 20% 100%;
}

.cat-collar { fill: var(--accent); }

/* 말풍선은 캐릭터가 아니라 UI라 CSS가 그대로 맡는다. */
.cat-bubble {
  position: absolute;
  left: 50%;
  bottom: 74px;
  margin: 0;
  padding: 5px 10px;
  background: var(--paper);
  color: var(--ink-900);
  border: 1px solid var(--border);
  border-radius: var(--radius-bubble);
  box-shadow: var(--shadow-card);
  font-size: 13px;
  line-height: 1.2;
  white-space: nowrap;
  opacity: 0;
  visibility: hidden;
  /* 가로 위치는 고양이 중심 기준이고, --cat-bubble-shift가 화면 밖으로 넘칠 때
     안쪽으로 미는 보정값이다(cat.js가 실측해 넣는다). */
  transform: translateX(calc(-50% + var(--cat-bubble-shift, 0px)));
}

/* 대사(문장)는 줄바꿈을 허용한다. 의성어는 짧아 한 줄이면 되지만 문장까지
   nowrap으로 두면 말풍선이 화면 폭을 넘어간다. 320px에서도 들어오도록 vw로
   상한을 건다. */
.cat-bubble-wide {
  white-space: normal;
  width: max-content;
  max-width: min(230px, 66vw);
  text-align: center;
  line-height: 1.4;
}

.cat-bubble-on {
  visibility: visible;
  animation: cat-bubble-in 1700ms ease-out;
}

.cat-bubble-wide.cat-bubble-on { animation-duration: 3200ms; }

@keyframes cat-bubble-in {
  0% { opacity: 0; transform: translateX(calc(-50% + var(--cat-bubble-shift, 0px))) translateY(6px); }
  10% { opacity: 1; transform: translateX(calc(-50% + var(--cat-bubble-shift, 0px))) translateY(0); }
  88% { opacity: 1; transform: translateX(calc(-50% + var(--cat-bubble-shift, 0px))) translateY(0); }
  100% { opacity: 0; transform: translateX(calc(-50% + var(--cat-bubble-shift, 0px))) translateY(-4px); }
}

/* ---- 드럼통 ----
   앞판·뒷판으로 쪼개고 마크업 순서를 뒷판 < 고양이 < 앞판으로 둔다. 같은 쌓임
   맥락의 절대 배치 형제라 칠하는 순서가 곧 앞뒤이고, 고양이가 림 뒤로 내려가면
   앞판이 가려 "안에 들어갔다"가 성립한다. 자세는 cat.js가 목표 오프셋으로 준다. */
.cat-barrel-back,
.cat-barrel-front {
  position: absolute;
  width: 64px;
  height: 76px;
  opacity: 0;
  visibility: hidden;
  transform: translateY(16px);
  transition: opacity 260ms ease, transform 260ms ease;
}

.cat-barrel-on {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}

.cat-barrel-svg {
  display: block;
  width: 100%;
  height: auto;
  fill: var(--ink-900);
}

.cat-barrel-lip { fill: var(--ink-500); }
.cat-barrel-band { fill: var(--canvas); }

/* ---- 이름 없는 강아지 친구 ----
   식별 요소를 일절 붙이지 않는다: 이름표도 액세서리도 유채색도 없고 중성 잉크
   한 단계로만 그린다. 소품이라 물리 엔진에 넣지 않고 CSS로 둔다. */
.cat-dog {
  position: absolute;
  width: 72px;
  height: 60px;
  opacity: 0;
  visibility: hidden;
  transition: transform 1400ms linear, opacity 220ms ease;
}

.cat-dog-on {
  opacity: 1;
  visibility: visible;
}

.cat-dog-svg {
  display: block;
  width: 100%;
  height: auto;
  fill: var(--ink-700);
}

.cat-dog-flip .cat-dog-svg { transform: scaleX(-1); }
.cat-dog-eye { fill: var(--paper); }

.cat-dog-tail {
  transform-box: fill-box;
  transform-origin: 88% 88%;
  animation: cat-dog-wag 320ms ease-in-out infinite alternate;
}

.cat-dog-head {
  transform-box: fill-box;
  transform-origin: 30% 92%;
}

.cat-dog-playing .cat-dog-head { animation: cat-dog-tilt 900ms ease-in-out 2; }

@keyframes cat-dog-wag {
  from { transform: rotate(-16deg); }
  to { transform: rotate(20deg); }
}

@keyframes cat-dog-tilt {
  0%, 100% { transform: rotate(0deg); }
  45% { transform: rotate(13deg); }
}

/* ---- 모바일: 겹침 회피가 제1원칙 (오너 피드백 2026-09-09) ----
   좁은 화면은 1열이라 여백이 없고 손가락 입력에서는 드래그가 꺼져 있어 유저가
   치울 수 없다. 그래서 크기를 줄이고 cat.js가 우하단 코너에 고정한다.
   900px은 사이드바가 접히는 기존 경계다(새 경계를 만들지 않는다). */
@media (max-width: 900px) {
  .cat-figure { width: 46px; height: 52px; }

  .cat-bubble {
    bottom: 56px;
    padding: 4px 8px;
    font-size: 12px;
  }

  /* 좁은 화면에서는 상한을 더 조인다. 320px에서 66vw는 211px이라 말풍선이
     화면의 3분의 2를 덮는다. */
  .cat-bubble-wide { max-width: min(180px, 58vw); }
}

/* ---- 모션 최소화 ----
   cat.js가 루프를 아예 돌리지 않고 정적 자세만 세운다. 여기서는 소품 쪽 CSS
   모션과 말풍선 전이를 끈다. 클릭하면 말풍선만 뜨고 풀은 그대로다(오너 지시). */
@media (prefers-reduced-motion: reduce) {
  .cat-dog-tail,
  .cat-dog-playing .cat-dog-head { animation: none; }

  .cat-barrel-back,
  .cat-barrel-front,
  .cat-dog { transition: none; }

  .cat-bubble-on { animation: none; opacity: 1; }
}


/* ---- 관심 기록 담기·보관함 (설계 2026-09-08 watchlist-followup §4.6, W2) ----
   규율: 담기 토글은 고스트 버튼 계열이고 accent는 인터랙션 상태(hover·focus·담김)
   에만 닿는다. 신규 색·그림자 토큰은 만들지 않는다 - 전부 기존 토큰 참조다.
   소품 채움은 --canvas, 라벨류 조판은 .meta-label 병용이다. */

/* 카드 하단 어포던스 자리. 담기 버튼(로그인) 또는 유도 문구 1줄(비로그인)이
   progress.js 주입으로 들어온다. 서버 렌더 카드 HTML에는 이 노드가 없다
   (answer_html 동결 스냅샷 오염 금지). */
.watch-affordance { margin-top: 8px; }
.watch-login-note { margin: 0; }

/* 보관함 헤더 우측 복귀 링크. 사이드바 없는 독립 페이지라 명시 복귀가 필요하다. */
.header-return {
  font-size: 13px; color: var(--ink-500); text-decoration: none;
  white-space: nowrap; padding: 6px 0;
}
.header-return:hover, .header-return:focus-visible {
  color: var(--ink-900); text-decoration: underline; text-underline-offset: 3px;
}
.watch-toggle {
  font-family: inherit; font-size: 12px; line-height: 1;
  min-height: 26px; padding: 0 10px;
  color: var(--ink-700); background: none;
  border: 1px solid var(--border); border-radius: var(--radius-tag);
  cursor: pointer;
  transition: border-color .15s ease, color .15s ease, background-color .15s ease;
}
.watch-toggle:hover { border-color: var(--ink-500); }
.watch-toggle[aria-pressed="true"] {
  border-color: var(--accent); color: var(--accent); background: var(--canvas);
}
.watch-toggle:disabled { opacity: .55; cursor: default; }

/* 사이드바 보관함 링크. [새 대화] 버튼과 같은 행 높이·조판을 쓰되 배경 없는
   조용한 행이다(주 동작은 계속 [새 대화] 하나뿐). */
.sidebar-watch {
  display: flex; align-items: center; gap: 8px;
  min-height: 34px; margin-top: 6px; padding: 0 var(--space-3);
  font-size: 14px; color: var(--ink-700); text-decoration: none;
  border-radius: var(--radius-input);
  transition: background-color .12s ease;
}
.sidebar-watch:hover { background: var(--sidebar-row-hover); }
.sidebar-watch svg { flex: none; display: block; }
.sidebar-watch-badge {
  margin-left: auto; min-width: 18px; padding: 1px 6px;
  font-size: 11px; text-align: center;
  color: var(--primary-foreground); background: var(--accent);
  border-radius: var(--radius-tag);
}

/* 보관함 페이지. 채팅 표면과 달리 사이드바가 없는 단독 문서라 컨테이너 폭만 쓴다. */
.watch-main { padding-bottom: 48px; }
.watch-main h1 { margin-bottom: 4px; }
.watch-empty { margin-top: 24px; }
.watch-topic-form {
  margin: 24px 0 32px; padding: 14px 16px;
  background: var(--canvas); border-radius: var(--radius-input);
}
.watch-topic-form h2 { margin: 0 0 8px; }
.watch-topic-label { display: block; margin-bottom: 6px; font-size: 13px; color: var(--ink-700); }
.watch-topic-row { display: flex; gap: 8px; }
.watch-topic-input {
  flex: 1; min-height: 34px; padding: 0 10px; font-family: inherit; font-size: 14px;
  color: var(--foreground); background: var(--card);
  border: 1px solid var(--border); border-radius: var(--radius-input);
}
.watch-button {
  font-family: inherit; font-size: 13px; min-height: 34px; padding: 0 14px;
  color: var(--ink-700); background: var(--card);
  border: 1px solid var(--border); border-radius: var(--radius-input); cursor: pointer;
  transition: border-color .15s ease, color .15s ease;
}
.watch-button:hover { border-color: var(--ink-500); }
.watch-button:disabled { opacity: .55; cursor: default; }
.watch-section { margin-top: 32px; }
.watch-count { color: var(--ink-500); font-size: 14px; }
.watch-list { list-style: none; margin: 12px 0 0; padding: 0;
  display: flex; flex-direction: column; gap: 12px; }
.watch-item {
  padding: 14px 16px; background: var(--card);
  border: 1px solid var(--border); border-radius: var(--radius-input);
  box-shadow: var(--shadow-xs);
}
.watch-item-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px; }
.watch-item-label { flex: 1 1 240px; margin: 0; font-size: 15px; font-weight: 500; }
.watch-item-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.watch-unread-mark { color: var(--accent); }
.watch-timeline-label { display: block; margin: 14px 0 6px; }
.watch-timeline { list-style: none; margin: 0; padding: 0;
  display: flex; flex-direction: column; gap: 6px; }
.watch-event { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px;
  font-size: 14px; color: var(--ink-700); }
.watch-event .date { color: var(--ink-500); font-size: 12px; }
/* 미읽음 강조: 좌측 accent 바 + 소품 채움. 색 단독 전달이 아니다 - 항목 머리에
   "새 기록" 라벨이 함께 붙는다. */
.watch-event-unread {
  padding: 4px 8px; margin-left: -8px;
  background: var(--canvas); border-left: 2px solid var(--accent);
  border-radius: 0 var(--radius-tag) var(--radius-tag) 0;
}
.watch-event-source { font-size: 12px; }
