/* ============================================================================
   알파증류소 ui_v4 — 토큰 + 컴포넌트 레이어 (2026-10-19)
   원천: design_v4/tokens_v4.css 를 CRITIQUE M1·M2·M7·M9 + S-a·S-b·S-d·S-g·S-j 로 고친 최종본.
   배포: scripts/static/ui_v4.css → /static/ui_v4.css  (ui_v4_layer.apply 가 플래그 ui_v4 ON 일 때만 <link> 삽입)
   게이트: <body class="ui-v4" data-theme="dark">  (공개)  /  <body class="ui-v4" data-app="talisker">  (/live/*)

   규칙
   · 루트 셀렉터 선언 0. 토큰은 html body.ui-v4 (0,1,2) / body.ui-v4[data-theme=light] (0,2,1) / (prefers-color-scheme: light)
     body.ui-v4[data-theme=auto] (0,2,1) / body.ui-v4[data-app=talisker] (0,2,1) 네 블록에만 (M1 — 레거시 `html.dark body{--bg…}`
     는 (0,1,2) 라 기본 블록도 (0,1,2) 이어야 한다: 동률이면 </head> 직전 <link> 가 뒤라 v4 가 이기고, body.ui-v4 (0,1,1) 로 두면
     로드 순서와 무관하게 레거시가 이겨 페이지 배경이 #0f172a 로 남는다(2026-10-19 검증자 지적 수리). 분기·@supports 폴백 블록도 같은
     셀렉터. v4 를 켜지 않은 페이지로는 새지 않는다. tests_ui_v4_layer 가 '커스텀 속성 선언 특이성 ≥ (0,1,2)' 를 검사한다).
   · 리셋은 :where(.ui-v4) … 특이성 (0,0,1) (M2 — 레거시 bare 셀렉터만 이기고 클래스 규칙엔 진다).
   · 컴포넌트는 .v4-* 접두만. 레거시 클래스는 .ui-v4 .main-wrap(D01 스태킹 함정) 하나만 만진다.
   · 시맨틱: 상승·매수 --up(빨강) / 하락·매도 --dn(파랑) / 정상·적중 --ok / 경고 --warn(액센트와 분리) /
     오류·오프라인·빗나감 --bad (S-a). 액센트(앰버)는 활성·링크·포커스·주 버튼에만.
   · 숫자: 공개 사이트 인라인 숫자는 .v4-tnum(본문 글꼴 tabular), 모노 .v4-num 은 표·코드·탈리스커.
     단위(원·조·억·%)는 span 밖 또는 .v4-num .u (본문 글꼴) (S-d).
   · 틴트는 color-mix 로 파생(hex 증식 금지). 미지원 브라우저는 @supports not 블록의 hex 폴백 (S-j).
   · 모션 150ms 1종(투명도·위치), prefers-reduced-motion 이면 0.
   ========================================================================== */

/* ---------- 1. 토큰 — 다크(기본) — html body.ui-v4 (0,1,2) ≥ 레거시 html.dark body (M1) ---------- */
html body.ui-v4 {
  color-scheme: dark;

  /* 팔레트 원색 (이 파일 밖에서 직접 쓰지 않는다) */
  --c-ink-0: #0b0e14;   /* 페이지 */
  --c-ink-1: #11161f;   /* 표면·카드 */
  --c-ink-2: #1a2130;   /* 올라온 표면·hover·입력 */
  --c-line:  #27303f;   /* 선 */
  --c-fg:    #e6ebf3;   /* 본문  16:1 */
  --c-fg-2:  #a6afbe;   /* 보조  8.7:1 */
  --c-fg-3:  #7d8796;   /* 메타  5.3:1 (페이지 위) */
  --c-accent: #e3b45b;  /* 증류 앰버 10:1 */
  --c-up:     #ff6b6b;  /* 상승·매수 7:1 */
  --c-dn:     #5b9cff;  /* 하락·매도 7:1 */
  --c-ok:     #5ec98f;  /* 정상·적중 9.4:1 */
  --c-warn:   #ffd166;  /* 경고 — 액센트와 별도 토큰 (S-a·M9) */
  --c-bad:    #ff8a8a;  /* 오류·오프라인·빗나감 — 탈리스커 --bad 와 공유 */
  --tint-pct: 16%;      /* 시맨틱 틴트 농도 (라이트는 10% — S-b) */
  --tint-pct-soft: 14%; /* 액센트·경고·HOLD 틴트 농도 */

  /* 역할 토큰 */
  --bg:        var(--c-ink-0);
  --surface:   var(--c-ink-1);
  --surface-2: var(--c-ink-2);
  --line:      var(--c-line);
  --line-soft: rgba(39,48,63,.6);
  --fg:        var(--c-fg);
  --fg-2:      var(--c-fg-2);
  --fg-3:      var(--c-fg-3);

  --accent:      var(--c-accent);
  --accent-fg:   #1a1306;                                   /* 액센트 바탕 위 글자 */
  --accent-tint: color-mix(in srgb, var(--c-accent) var(--tint-pct-soft), var(--surface));
  --accent-line: color-mix(in srgb, var(--c-accent) 40%, var(--line));
  --focus:       var(--c-accent);

  --up:   var(--c-up);   --up-tint:   color-mix(in srgb, var(--c-up)   var(--tint-pct), var(--surface));
  --dn:   var(--c-dn);   --dn-tint:   color-mix(in srgb, var(--c-dn)   var(--tint-pct), var(--surface));
  --ok:   var(--c-ok);   --ok-tint:   color-mix(in srgb, var(--c-ok)   var(--tint-pct), var(--surface));
  --warn: var(--c-warn); --warn-tint: color-mix(in srgb, var(--c-warn) var(--tint-pct-soft), var(--surface));
  --bad:  var(--c-bad);  --bad-tint:  color-mix(in srgb, var(--c-bad)  var(--tint-pct), var(--surface));
  --hold: var(--c-fg-2); --hold-tint: color-mix(in srgb, var(--c-fg-2) var(--tint-pct-soft), var(--surface));

  /* 의견 배지 = 매수/매도 시맨틱 공유 (별도 hue 추가 금지) */
  --op-buy:  var(--up);   --op-buy-tint:  var(--up-tint);
  --op-sell: var(--dn);   --op-sell-tint: var(--dn-tint);
  --op-hold: var(--hold); --op-hold-tint: var(--hold-tint);

  /* 브리프 3장 슬롯 색 = '시각대' 표식(시맨틱 아님) — 채도 낮춤 */
  --slot-pre: #7cc4ff; --slot-mid: #8fd6a4; --slot-post: var(--c-accent);

  /* 타이포 */
  --font-body: "Pretendard Variable", Pretendard, "Noto Sans KR", -apple-system, "Apple SD Gothic Neo", "Malgun Gothic", system-ui, sans-serif;
  --font-display: var(--font-body);      /* 같은 가족, 굵기·자간으로 구분 (세리프 금지) */
  --font-data: "JetBrains Mono", "D2Coding", "Cascadia Mono", Consolas, ui-monospace, monospace;
  --fs-11: 0.6875rem; --fs-12: 0.75rem; --fs-13: 0.8125rem; --fs-14: 0.875rem;
  --fs-15: 0.9375rem; --fs-16: 1rem;    --fs-18: 1.125rem;  --fs-20: 1.25rem;
  --fs-24: 1.5rem;    --fs-28: 1.75rem; --fs-32: 2rem;
  --lh-tight: 1.25; --lh-snug: 1.4; --lh-body: 1.7; --lh-article: 1.85;
  --ls-display: -0.02em; --ls-body: -0.005em; --ls-caps: 0.06em;

  /* 간격·반경·그림자·선 */
  --sp-1: 4px; --sp-2: 8px; --sp-3: 12px; --sp-4: 16px; --sp-5: 20px;
  --sp-6: 24px; --sp-8: 32px; --sp-10: 40px; --sp-12: 48px; --sp-16: 64px;
  --r-1: 4px;   /* 칩·입력·배지 */
  --r-2: 8px;   /* 카드·버튼 */
  --r-3: 12px;  /* 패널·시트·모달 */
  --r-full: 999px;
  --shadow-1: 0 1px 0 rgba(255,255,255,.03), 0 2px 8px rgba(0,0,0,.35);
  --shadow-2: 0 12px 32px -8px rgba(0,0,0,.6), 0 0 0 1px rgba(255,255,255,.04);
  --hairline: 1px solid var(--line);

  /* 레이아웃 */
  --container: 1200px;
  --gutter: 24px;        /* 900↓ 16, 640↓ 12 */
  --page-x: 32px;        /* 900↓ 24, 640↓ 16 */
  --header-h: 56px;      /* 640↓ 52 */
  --spot-h: 48px;        /* 리포트 스팟 카드(sticky, 데스크톱) */
  --spot-mini-h: 40px;   /* 모바일 축약 1행 (M7) */
  --dock-h: 52px;        /* 모바일 챗 도크 */
  --tap: 44px;           /* 최소 터치 타깃 */

  /* 층위(z) — 단일 표. .main-wrap 은 스태킹 컨텍스트를 만들지 않는다 */
  --z-sticky: 80; --z-header: 100; --z-dock: 110; --z-overlay: 190; --z-sheet: 200; --z-dropdown: 300; --z-toast: 400;

  --motion: 150ms;
  --ease: cubic-bezier(.2,.7,.3,1);
}

/* ---------- 1b. 라이트 (헤더 '테마' 메뉴는 P5 전 노출 금지 — S-b) ---------- */
body.ui-v4[data-theme="light"] {
  color-scheme: light;
  --c-ink-0: #f4f6f9; --c-ink-1: #ffffff; --c-ink-2: #e9edf3; --c-line: #dfe4ec;
  --c-fg: #141a24; --c-fg-2: #4b5565; --c-fg-3: #636e7e;
  --c-accent: #8a5d0b; --c-up: #c62f31; --c-dn: #1f5fd6; --c-ok: #15724a; --c-warn: #9c4f00; --c-bad: #b42318;
  --accent-fg: #ffffff;
  --line-soft: rgba(223,228,236,.7);
  --tint-pct: 10%; --tint-pct-soft: 10%;      /* 12px 굵은 배지 글자 4.5:1 이상 (S-b) */
  --slot-pre: #1f6fbf; --slot-mid: #177a4c; --slot-post: #8a5d0b;
  --shadow-1: 0 1px 2px rgba(20,26,36,.06), 0 2px 8px rgba(20,26,36,.06);
  --shadow-2: 0 12px 32px -8px rgba(20,26,36,.25), 0 0 0 1px rgba(20,26,36,.04);
}
/* 자동: 시스템 설정 따름 — 값은 라이트 블록과 동일(복제 유지) */
@media (prefers-color-scheme: light) {
  body.ui-v4[data-theme="auto"] {
    color-scheme: light;
    --c-ink-0: #f4f6f9; --c-ink-1: #ffffff; --c-ink-2: #e9edf3; --c-line: #dfe4ec;
    --c-fg: #141a24; --c-fg-2: #4b5565; --c-fg-3: #636e7e;
    --c-accent: #8a5d0b; --c-up: #c62f31; --c-dn: #1f5fd6; --c-ok: #15724a; --c-warn: #9c4f00; --c-bad: #b42318;
    --accent-fg: #ffffff;
    --line-soft: rgba(223,228,236,.7);
    --tint-pct: 10%; --tint-pct-soft: 10%;
    --slot-pre: #1f6fbf; --slot-mid: #177a4c; --slot-post: #8a5d0b;
    --shadow-1: 0 1px 2px rgba(20,26,36,.06), 0 2px 8px rgba(20,26,36,.06);
    --shadow-2: 0 12px 32px -8px rgba(20,26,36,.25), 0 0 0 1px rgba(20,26,36,.04);
  }
}

/* ---------- 1c. 탈리스커: 다크 고정 + 밀도 높임 (라이트 요청 무시) — 라이트·자동 블록 뒤에 두어 이긴다 ---------- */
body.ui-v4[data-app="talisker"] {
  color-scheme: dark;
  --c-ink-0: #0b0e14; --c-ink-1: #11161f; --c-ink-2: #1a2130; --c-line: #27303f;   /* v4 값으로 통일 — live_v3/shell.py 토큰 블록(--card #11161f·--line #27303f 리터럴)과 같은 값 (M9·R9) */
  --c-fg: #e8edf6; --c-fg-2: #a6afbe; --c-fg-3: #8994a8;                            /* --dim 기존 값 유지 6.3:1 */
  --c-accent: #d9b45c; --c-up: #ff5c5c; --c-dn: #4d8dff; --c-ok: #7ee2a8; --c-warn: #ffd166; --c-bad: #ff8a8a;
  --accent-fg: #1a1306;
  --tint-pct: 16%; --tint-pct-soft: 14%;
  --line-soft: rgba(39,48,63,.6);
  --slot-pre: #7cc4ff; --slot-mid: #8fd6a4; --slot-post: var(--c-accent);
  --font-body: "Pretendard Variable", Pretendard, "Inter", system-ui, "Malgun Gothic", sans-serif;
  --fs-base: 13px; --r-2: 6px; --r-3: 8px; --container: 1280px; --page-x: 16px; --gutter: 10px;
  /* shell 토큰 매핑 (M9) — 매핑 소유자는 이 파일 하나(한 방향: shell 이름 → v4 역할 토큰). live_v3/shell.py 의
     html body[data-app=talisker] (0,1,2) 블록은 리터럴만 두고 v4 역할 토큰(--surface/--fg/--fg-3/--accent/--font-data/--font-body)을
     shell 이름으로 되매핑하지 않는다 — 되매핑하면 이 블록(0,2,1)이 이겨 --card↔--surface 등 5쌍이 순환, computed-value 단계에서 전부
     무효(.blk 배경 투명). tests_ui_v4_layer 가 두 파일 블록을 합쳐 순환을 검사한다. --warn·--bad 는 위 역할 토큰(별도 값). */
  --card: var(--surface); --tx: var(--fg); --dim: var(--fg-3); --gold: var(--accent);
  --mono: var(--font-data); --sans: var(--font-body);
}

/* 분기별 레이아웃 토큰 — 기본 블록과 같은 html body.ui-v4 (0,1,2) (탈리스커 블록 (0,2,1)은 특이성이 높아 --page-x 16 유지) */
@media (max-width: 900px) { html body.ui-v4 { --page-x: 24px; --gutter: 16px; } }
@media (max-width: 640px) { html body.ui-v4 { --page-x: 16px; --gutter: 12px; --header-h: 52px; } }

/* color-mix 미지원(삼성 인터넷 ≤20·iOS ≤15) hex 폴백 — 값은 위 color-mix 산식의 계산값 (S-j) */
@supports not (color: color-mix(in srgb, #000 50%, #fff)) {
  html body.ui-v4 { --accent-tint: #2e2c27; --accent-line: #72654a; --up-tint: #372429; --dn-tint: #1d2b43; --ok-tint: #1d3331;
    --warn-tint: #323029; --bad-tint: #372930; --hold-tint: #262b35; }
  body.ui-v4[data-theme="light"] { --accent-tint: #f3efe7; --accent-line: #bdae92; --up-tint: #f9eaea; --dn-tint: #e9effb;
    --ok-tint: #e8f1ed; --warn-tint: #f5ede6; --bad-tint: #f8e9e8; --hold-tint: #edeef0; }
  body.ui-v4[data-app="talisker"] { --accent-tint: #2d2c28; --accent-line: #6e654b; --up-tint: #372129; --dn-tint: #1b2943; --ok-tint: #223735; }
  .v4-hd, .v4-dock, .v4-spot, .v4-spot-mini { background: var(--bg); }
}
@supports not (backdrop-filter: blur(1px)) {
  .v4-hd, .v4-dock, .v4-spot, .v4-spot-mini { background: var(--bg); }
}

/* ============================================================================
   2. 기본·리셋 — body.ui-v4 + :where(.ui-v4) (0,0,1)
   ========================================================================== */
body.ui-v4 { background: var(--bg); color: var(--fg); font-family: var(--font-body); font-size: var(--fs-base, 16px);
  line-height: var(--lh-body); letter-spacing: var(--ls-body); -webkit-font-smoothing: antialiased;
  font-variant-numeric: tabular-nums; font-feature-settings: "tnum" 1; }
:where(.ui-v4) *, :where(.ui-v4) *::before, :where(.ui-v4) *::after { box-sizing: border-box; }
:where(.ui-v4) a { color: inherit; text-decoration: none; }
:where(.ui-v4) img { max-width: 100%; height: auto; }
:where(.ui-v4) input, :where(.ui-v4) textarea, :where(.ui-v4) select, :where(.ui-v4) button { font: inherit; color: inherit; }
:where(.ui-v4) input, :where(.ui-v4) textarea, :where(.ui-v4) select { font-size: max(16px, 1em); }   /* iOS 자동 확대 방지(D13) */
:where(.ui-v4) :focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; border-radius: var(--r-1); }
.ui-v4 .main-wrap { position: static; z-index: auto; }   /* D01 — 레거시 .main-wrap{z-index:60} 스태킹 함정 제거(의도적 레거시 덮어쓰기 1건) */
/* 숨김 유틸 — 서버가 v4 머리(스팟 카드·h1)와 중복되는 레거시 블록(제목 블록·KPI 카드·의견 배지·FAB)에 부여한다. 레거시 인라인 style/display 를 이기도록 !important
   (ui_v4_ask.js 도 ≤900 에서 도크가 뜨면 레거시 FAB #chat-open-fab 에 건다 — openMsgPanel/closeMsgPanel 이 fab.style.display 를 만져도 숨김 유지). */
.v4-hide { display: none !important; }
@media (prefers-reduced-motion: reduce) {
  :where(.ui-v4) *, :where(.ui-v4) *::before, :where(.ui-v4) *::after { transition: none !important; animation: none !important; scroll-behavior: auto !important; }
}

/* --- 글자 역할 --- */
.v4-display { font-family: var(--font-display); font-weight: 800; letter-spacing: var(--ls-display); line-height: var(--lh-tight); }
.v4-h1 { font-size: var(--fs-28); font-weight: 800; letter-spacing: var(--ls-display); line-height: var(--lh-tight); margin: 0; }
.v4-h2 { font-size: var(--fs-20); font-weight: 700; letter-spacing: -.015em; line-height: var(--lh-snug); margin: 0; }
.v4-h3 { font-size: var(--fs-16); font-weight: 700; margin: 0; }
.v4-eyebrow { font-size: var(--fs-12); font-weight: 600; letter-spacing: var(--ls-caps); color: var(--fg-3); text-transform: uppercase; }
.v4-meta { font-size: var(--fs-13); color: var(--fg-3); }
.v4-sub { font-size: var(--fs-14); color: var(--fg-2); }
/* 숫자 (S-d): 인라인은 본문 글꼴 tabular, 모노는 표·코드·탈리스커. 단위는 span 밖 또는 .u */
.v4-tnum { font-variant-numeric: tabular-nums; font-feature-settings: "tnum" 1; letter-spacing: 0; }
.v4-num, .v4-mono { font-family: var(--font-data); font-variant-numeric: tabular-nums; letter-spacing: 0; }
.v4-num { font-weight: 500; }
.v4-num .u { font-family: var(--font-body); font-weight: 400; font-size: .85em; margin-left: 1px; }
.v4-up { color: var(--up); } .v4-dn { color: var(--dn); } .v4-flat { color: var(--fg-2); }
.v4-ok { color: var(--ok); } .v4-warn { color: var(--warn); } .v4-bad { color: var(--bad); }
@media (max-width: 640px) { .v4-h1 { font-size: var(--fs-24); } .v4-h2 { font-size: var(--fs-18); } }

/* --- 컨테이너·그리드 (S-j: ≤900 은 3~6열을 2열로, ≤640 1열 — .two-m 은 모바일 2열 유지) --- */
.v4-container { max-width: var(--container); margin: 0 auto; padding: 0 var(--page-x); }
.v4-grid { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: var(--gutter); }
.v4-col-3 { grid-column: span 3; } .v4-col-4 { grid-column: span 4; } .v4-col-5 { grid-column: span 5; }
.v4-col-6 { grid-column: span 6; } .v4-col-7 { grid-column: span 7; } .v4-col-8 { grid-column: span 8; }
.v4-col-9 { grid-column: span 9; } .v4-col-12 { grid-column: 1 / -1; }
@media (max-width: 900px) {
  .v4-grid > .v4-col-7, .v4-grid > .v4-col-8, .v4-grid > .v4-col-9 { grid-column: 1 / -1; }
  .v4-grid > .v4-col-3, .v4-grid > .v4-col-4, .v4-grid > .v4-col-5, .v4-grid > .v4-col-6 { grid-column: span 6; }
}
@media (max-width: 640px) {
  .v4-grid > [class*="v4-col-"] { grid-column: 1 / -1; }
  .v4-grid.two-m > [class*="v4-col-"] { grid-column: span 6; }
}

/* --- 헤더 --- */
.v4-hd { position: sticky; top: 0; z-index: var(--z-header); height: var(--header-h);
  background: color-mix(in srgb, var(--bg) 88%, transparent); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
  border-bottom: var(--hairline); }
.v4-hd-in { height: 100%; display: flex; align-items: stretch; gap: var(--sp-2); }
.v4-logo { display: flex; align-items: center; gap: 8px; font-weight: 800; font-size: var(--fs-16); letter-spacing: -.01em; padding-right: var(--sp-3); }
.v4-logo img { width: 22px; height: 22px; }
.v4-nav { display: flex; align-items: stretch; gap: 2px; flex: 1; min-width: 0; overflow-x: auto; scrollbar-width: none; }
.v4-nav::-webkit-scrollbar { display: none; }
.v4-nav a { position: relative; display: flex; align-items: center; padding: 0 14px; color: var(--fg-2); font-size: var(--fs-14); font-weight: 500; white-space: nowrap; min-width: var(--tap); }
.v4-nav a:hover { color: var(--fg); }
.v4-nav a.on { color: var(--fg); font-weight: 700; }
.v4-nav a.on::after { content: ""; position: absolute; left: 10px; right: 10px; bottom: -1px; height: 2px; background: var(--accent); }
.v4-nav a.admin { color: var(--accent); }
.v4-nav a.admin::before { content: "●"; font-size: 8px; margin-right: 6px; vertical-align: 1px; }
.v4-hd-r { display: flex; align-items: center; gap: var(--sp-2); }
.v4-search-btn { display: inline-flex; align-items: center; gap: 8px; height: 36px; padding: 0 12px; border: var(--hairline); border-radius: var(--r-2); background: var(--surface); color: var(--fg-2); font-size: var(--fs-13); cursor: pointer; }
.v4-search-btn kbd { font-family: var(--font-data); font-size: 11px; border: 1px solid var(--line); border-radius: 3px; padding: 0 5px; color: var(--fg-3); }
.v4-login { display: inline-flex; align-items: center; height: 36px; padding: 0 14px; border: 1px solid var(--accent-line); border-radius: var(--r-2); color: var(--accent); font-size: var(--fs-13); font-weight: 600; }
.v4-avatar-pill { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; border-radius: 50%; background: var(--surface-2); border: var(--hairline); font-size: var(--fs-12); font-weight: 700; }
@media (max-width: 640px) {
  .v4-logo span { display: none; }
  .v4-search-btn span, .v4-search-btn kbd { display: none; }
  .v4-search-btn { width: 36px; padding: 0; justify-content: center; }
  .v4-nav a { padding: 0 10px; font-size: var(--fs-13); }
  .v4-nav a.admin { display: none; }   /* 모바일은 계정 메뉴에서 진입 */
}

/* --- 버튼·칩·배지 (S-g: 터치 타깃 — 칩 32 + ::before 확장, 아이콘·닫기 40) --- */
.v4-btn { display: inline-flex; align-items: center; justify-content: center; gap: 6px; height: 36px; padding: 0 14px;
  border: var(--hairline); border-radius: var(--r-2); background: var(--surface); color: var(--fg); font-size: var(--fs-14); font-weight: 600; cursor: pointer;
  transition: background var(--motion) var(--ease), border-color var(--motion) var(--ease); }
.v4-btn:hover { background: var(--surface-2); }
.v4-btn:disabled { opacity: .55; cursor: not-allowed; }
.v4-btn.primary { background: var(--accent); color: var(--accent-fg); border-color: var(--accent); }
.v4-btn.primary:hover { background: var(--accent); filter: brightness(1.06); }
.v4-btn.icon { width: 40px; height: 40px; padding: 0; }
.v4-btn.sm { height: 32px; padding: 0 10px; font-size: var(--fs-13); }
.v4-chip { position: relative; display: inline-flex; align-items: center; gap: 6px; min-height: 32px; padding: 0 12px; border: var(--hairline); border-radius: var(--r-full);
  background: var(--surface); color: var(--fg-2); font-size: var(--fs-13); white-space: nowrap; cursor: pointer; }
.v4-chip::before { content: ""; position: absolute; inset: -6px; }   /* 시각 32 → 터치 44 */
.v4-chip:hover { border-color: var(--fg-3); color: var(--fg); }
.v4-chip.on { border-color: var(--accent-line); background: var(--accent-tint); color: var(--fg); }
.v4-chip b { font-weight: 600; color: var(--fg); }
.v4-chip img { width: 20px; height: 20px; border-radius: 50%; object-fit: cover; margin-left: -4px; }
.v4-badge { display: inline-flex; align-items: center; height: 22px; padding: 0 8px; border-radius: var(--r-1); font-size: var(--fs-12); font-weight: 700; letter-spacing: .02em; white-space: nowrap; }
.v4-badge.buy  { background: var(--op-buy-tint);  color: var(--op-buy); }
.v4-badge.sell { background: var(--op-sell-tint); color: var(--op-sell); }
.v4-badge.hold { background: var(--op-hold-tint); color: var(--op-hold); }
.v4-badge.ok   { background: var(--ok-tint);   color: var(--ok); }     /* 적중·정상 */
.v4-badge.warn { background: var(--warn-tint); color: var(--warn); }   /* 주의·회고본 */
.v4-badge.bad  { background: var(--bad-tint);  color: var(--bad); }    /* 빗나감·오류 — 상승 빨강과 분리 (S-a) */
.v4-badge.neutral { background: var(--surface-2); color: var(--fg-2); font-weight: 600; }
/* 의견 1토큰: 배지 + 꼬리(괄호 안 태그) 한 줄 — 중복 표기 금지 (D03) */
.v4-op { display: inline-flex; align-items: center; gap: 6px; min-width: 0; }
.v4-op .tag { font-size: var(--fs-12); color: var(--fg-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* --- 카드·리스트 --- */
.v4-card { background: var(--surface); border: var(--hairline); border-radius: var(--r-2); padding: var(--sp-4); min-width: 0; }
.v4-card.flat { background: transparent; }
a.v4-card:hover { border-color: var(--accent-line); }
.v4-card-h { display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-2); margin-bottom: var(--sp-3); }
.v4-card-h h3 { font-size: var(--fs-13); font-weight: 700; color: var(--fg-2); letter-spacing: .02em; margin: 0; }
.v4-card-h a { font-size: var(--fs-12); color: var(--fg-3); }
.v4-list { list-style: none; margin: 0; padding: 0; }
.v4-list li { display: flex; align-items: center; gap: 10px; padding: 7px 0; border-top: 1px solid var(--line-soft); font-size: var(--fs-14); min-width: 0; }
.v4-list li:first-child { border-top: 0; padding-top: 0; }
.v4-list .rk { width: 16px; font-family: var(--font-data); font-size: var(--fs-12); color: var(--fg-3); text-align: right; }
.v4-list .nm { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.v4-list .z { font-family: var(--font-data); font-size: var(--fs-12); color: var(--fg-3); white-space: nowrap; }

/* --- 통계 타일 (값은 본문 글꼴 tabular — 단위는 .s 로) --- */
.v4-stat { min-width: 0; }
.v4-stat .l { font-size: var(--fs-12); color: var(--fg-3); }
.v4-stat .v { font-size: var(--fs-18); font-weight: 700; line-height: 1.3; font-variant-numeric: tabular-nums; }
.v4-stat .s { font-size: var(--fs-12); color: var(--fg-2); }

/* --- 입력(질문 상자·검색) --- */
.v4-input { display: flex; align-items: center; gap: 10px; height: 48px; padding: 0 8px 0 14px; border: var(--hairline); border-radius: var(--r-2); background: var(--surface); }
.v4-input:focus-within { border-color: var(--accent-line); box-shadow: 0 0 0 3px var(--accent-tint); }
.v4-input input { flex: 1; min-width: 0; border: 0; background: transparent; outline: 0; height: 100%; font-size: max(16px, 1em); }
.v4-input input::placeholder { color: var(--fg-3); }
.v4-input input:disabled { color: var(--fg-3); }
.v4-input .go { height: 34px; padding: 0 12px; border-radius: var(--r-1); background: var(--accent); color: var(--accent-fg); border: 0; font-weight: 700; font-size: var(--fs-13); cursor: pointer; }
.v4-input .go:disabled { background: var(--surface-2); color: var(--fg-3); cursor: not-allowed; }

/* --- 상태 점(챗 상태: ok 정상 / busy·late 지연 / off 오프라인) --- */
.v4-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: var(--fg-3); vertical-align: middle; flex: 0 0 auto; }
.v4-dot.ok { background: var(--ok); }
.v4-dot.busy, .v4-dot.late { background: var(--warn); }
.v4-dot.off { background: var(--bad); }
.v4-status { display: inline-flex; align-items: center; gap: 6px; font-size: var(--fs-12); color: var(--fg-3); white-space: nowrap; }
/* 상태점·문구 갱신 소유자 = static/ui_v4_ask.js(플래그 ui_v4_ask): /api/chat/health → .v4-dot[data-v4-health=dot] 클래스(ok|busy|off) +
   title(reason 툴팁), .v4-status-text[data-v4-health=text] 문구, [data-v4-ask] 의 data-v4-state. 페이지에 폴링(checkHealth/_rcCheckHealth →
   window._v4AskState)이 있으면 그 값을 받고, 없으면 30초 자체 폴링(document 'alpha-chat-health' 이벤트로도 공급 가능). */

/* --- 홈 질문 상자 .v4-ask-box — 검색 드롭다운 + 챗 단일 진입 (DESIGN §4.1 ②, CRITIQUE S-f: 타이핑=드롭다운 즉시, 종목 단독 Enter=이동, 문장=챗)
   마크업 계약(서버 작업자):
     <form class="v4-ask-box" id="search-form" data-v4-ask-box role="search" action="javascript:void(0)" onsubmit="return false;">
       <label class="v4-input" for="report-search">
         <span class="ic">(svg)</span>
         <input type="search" id="report-search" class="rc-search-input" placeholder="종목 · 키워드 · 질문" autocomplete="off" enterkeyhint="search">
         <span class="v4-status"><i class="v4-dot" data-v4-health="dot"></i></span>          ← 입력 안은 점만
         <button class="go" type="button" data-v4-ask-go>묻기</button>
       </label>
       <div class="v4-ask-dd" data-v4-ask-dd><div class="search-results" id="search-results" role="listbox"></div></div>   ← 드롭다운 자리
       <div class="v4-sugs"><button class="v4-chip" data-q="삼성전자">삼성전자</button> …
         <span class="v4-status"><i class="v4-dot" data-v4-health="dot"></i><span class="v4-status-text" data-v4-health="text">상태 확인 중</span></span></div>
     </form>
   · 입력이 기존 #report-search(+#search-form) 자체면 기존 리스너(드롭다운·Enter·화살표·'/' 단축키)가 그대로 돈다 — ui_v4_ask.js 는 '묻기'·칩만 배선.
   · 입력이 별도 요소면 ui_v4_ask.js 가 값을 #report-search 로 미러(input 이벤트)하고 #search-results 를 .v4-ask-dd 로 옮긴다(id·리스너 유지).
   · .v4-ask-dd 는 높이 0 의 기준 상자 — 레거시 .search-results{position:absolute; top:calc(100%+6px)} 가 입력 바로 아래 뜬다. z = --z-dropdown. */
.v4-ask-box { position: relative; margin: var(--sp-5) 0 0; min-width: 0; }
.v4-ask-box .v4-input { height: 54px; }
.v4-ask-box .v4-input .ic { display: flex; color: var(--fg-3); flex: 0 0 auto; }
.v4-ask-box .v4-input .v4-status { flex: 0 0 auto; }
.v4-ask-box .v4-input .v4-status .v4-status-text { display: none; }
.v4-ask-box .v4-input .go { height: 38px; padding: 0 14px; font-size: var(--fs-14); }
.v4-ask-dd { position: relative; height: 0; z-index: var(--z-dropdown); }
.v4-ask-dd > * { position: absolute; left: 0; right: 0; top: 4px; }
.v4-ask-box .v4-sugs { padding: 8px 0 0; align-items: center; }
.v4-ask-box .v4-sugs .v4-status { margin-left: auto; }
@media (max-width: 640px) {
  .v4-ask-box .v4-input { height: 48px; padding-left: 10px; }
  .v4-ask-box .v4-input .ic { display: none; }
  .v4-ask-box .v4-sugs .v4-status { margin-left: 0; flex-basis: 100%; }
}

/* --- 챗바(공용 1구현: 홈 질문상자 / 리포트 사이드 도크 / 데일리 인라인 / 모바일 시트) --- */
.v4-ask { border: var(--hairline); border-radius: var(--r-3); background: var(--surface); display: flex; flex-direction: column; min-width: 0; min-height: 0; }
.v4-ask-h { display: flex; align-items: center; gap: 10px; padding: 8px 8px 8px 12px; border-bottom: var(--hairline); flex: 0 0 auto; }
.v4-ask-h .av { width: 28px; height: 28px; border-radius: 50%; object-fit: cover; flex: 0 0 auto; }
.v4-ask-h .who { flex: 1; min-width: 0; font-size: var(--fs-13); }
.v4-ask-h .who b { display: block; font-weight: 700; }
.v4-ask-h .who span { color: var(--fg-3); font-size: var(--fs-12); }
.v4-ask-h .x { width: 40px; height: 40px; border: 0; background: transparent; color: var(--fg-2); font-size: 20px; line-height: 1; cursor: pointer; border-radius: var(--r-1); flex: 0 0 auto; }
.v4-ask-h .x:hover { background: var(--surface-2); color: var(--fg); }
.v4-ask-body { padding: 12px; display: flex; flex-direction: column; gap: 10px; overflow: auto; min-height: 0; overscroll-behavior: contain; }
.v4-msg { max-width: 92%; padding: 8px 12px; border-radius: var(--r-2); font-size: var(--fs-14); line-height: 1.6; overflow-wrap: anywhere; }
.v4-msg.ai { background: var(--surface-2); align-self: flex-start; border-bottom-left-radius: 2px; }
.v4-msg.me { background: var(--accent-tint); align-self: flex-end; border-bottom-right-radius: 2px; }
.v4-msg.err { background: var(--bad-tint); color: var(--bad); align-self: flex-start; }
.v4-msg.stream::after { content: "▍"; color: var(--accent); animation: v4blink 1s steps(2) infinite; }
@keyframes v4blink { 50% { opacity: 0; } }
.v4-think { display: flex; gap: 8px; align-items: center; font-size: var(--fs-12); color: var(--fg-3); }
.v4-think i { width: 6px; height: 6px; border-radius: 50%; background: var(--fg-3); animation: v4pulse 1.2s infinite; }
.v4-think i:nth-child(2) { animation-delay: .2s; } .v4-think i:nth-child(3) { animation-delay: .4s; }
@keyframes v4pulse { 0%, 80%, 100% { opacity: .25; } 40% { opacity: 1; } }
/* 스트리밍 중 표시 — .v4-typing 은 점 3개 '요소'(말풍선 앞·도크 안), .v4-streaming 은 컨테이너 '상태'(.v4-ask / .v4-dock / 레거시 호스트 .v4-ask-host).
   ui_v4_ask.js 가 레거시 #msg-send-btn[disabled] 를 관찰해 호스트·도크에 .v4-streaming 을 걸고 도크의 .v4-typing 을 보인다. 보내기 → ■ 는 .ic/.ic-stop 쌍. */
.v4-typing { display: inline-flex; gap: 4px; align-items: center; vertical-align: middle; }
.v4-typing i { width: 5px; height: 5px; border-radius: 50%; background: currentColor; animation: v4pulse 1.2s infinite; }
.v4-typing i:nth-child(2) { animation-delay: .2s; } .v4-typing i:nth-child(3) { animation-delay: .4s; }
.v4-typing[hidden] { display: none; }
.v4-streaming .v4-dot { animation: v4pulse 1.2s infinite; }
.v4-ask-in .send .ic-stop { display: none; }
.v4-ask.v4-streaming .v4-ask-in .send { background: var(--surface-2); color: var(--fg); }
.v4-ask.v4-streaming .v4-ask-in .send .ic { display: none; }
.v4-ask.v4-streaming .v4-ask-in .send .ic-stop { display: inline; }
.v4-sugs { display: flex; gap: 6px; flex-wrap: wrap; padding: 0 12px 10px; flex: 0 0 auto; }
.v4-ask-in { display: flex; align-items: center; gap: 8px; padding: 8px 8px 8px 12px; border-top: var(--hairline); flex: 0 0 auto; }
.v4-ask-in input, .v4-ask-in textarea { flex: 1; min-width: 0; border: 0; background: transparent; outline: 0; min-height: 36px; font-size: max(16px, 1em); resize: none; }
.v4-ask-in input::placeholder, .v4-ask-in textarea::placeholder { color: var(--fg-3); }
.v4-ask-in .send { width: 40px; height: 40px; border-radius: var(--r-1); border: 0; background: var(--accent); color: var(--accent-fg); font-weight: 700; cursor: pointer; flex: 0 0 auto; }
.v4-ask-in .send:disabled { background: var(--surface-2); color: var(--fg-3); cursor: not-allowed; }
.v4-ask-ft { display: flex; justify-content: space-between; align-items: center; gap: 8px; padding: 0 12px 8px; font-size: var(--fs-11); color: var(--fg-3); flex: 0 0 auto; }
.v4-ask.off .v4-ask-in input { color: var(--fg-3); }
/* 도킹 — 데스크톱: 사이드 4열 sticky 묶음(목차 아래, 최대 520), 본문 스크롤 잠금 없음 (D05)
   .v4-ask-dock 은 v4 네이티브 .v4-ask 의 '사이드 도킹' 변형에만 쓴다. 레거시 챗 컨테이너(#msg-panel = position:fixed 시트, #hero-chat-view)에
   붙이면 ≤900 에서 display:none·max-height 520 이 되어 열리지 않는다(2026-10-19 2단계 검증자 지적). 서버는 레거시 컨테이너에 마커 .v4-ask-host
   (이 파일에 레이아웃 규칙 0) + data-v4-ask / data-v4-mobile(sheet|inline) / data-v4-state 속성만 붙인다. 아래 :not(.v4-ask-host) 가드는 둘이
   실수로 같이 붙어도 레거시 패널을 건드리지 않게 한다(tests_ui_v4_layer 가 '.v4-ask-host 를 숨기는 규칙 0' 을 검사). */
.v4-aside-stack { position: sticky; top: calc(var(--header-h) + var(--spot-h) + 12px); display: flex; flex-direction: column; gap: var(--gutter);
  max-height: calc(100vh - var(--header-h) - var(--spot-h) - 24px); max-height: calc(100dvh - var(--header-h) - var(--spot-h) - 24px); }
.v4-aside-stack .v4-toc { position: static; flex: 0 0 auto; }
.v4-ask-dock:not(.v4-ask-host) { display: flex; flex-direction: column; max-height: 520px; min-height: 0; }
.v4-ask-dock .v4-ask-body { flex: 1 1 auto; min-height: 120px; }
.v4-ask-dock.folded .v4-ask-body, .v4-ask-dock.folded .v4-sugs, .v4-ask-dock.folded .v4-ask-in, .v4-ask-dock.folded .v4-ask-ft { display: none; }
/* 모바일: 하단 도크 52 → 시트 86dvh (머리줄 × 항상, 헤더보다 위 z200 — D01). 층위는 --z-* 표 하나: 헤더 100 < 도크 110 < 오버레이 190 < 시트 200 < 드롭다운 300.
   JS 계약(ui_v4_ask.js, 플래그 ui_v4_ask):
   · body.has-dock      — .v4-dock 이 DOM 에 있으면 건다(하단 여백). 소유자 ui_v4_ask.js.
   · body.v4-spot-scrolled — scrollY>120 축약 스팟(.v4-spot-mini). 소유자 서버 _V4_SPOT_MINI_JS(ui_v4_report_head) — ui_v4_ask.js 는 건드리지 않는다.
   · body.v4-sheet-open — 시트(레거시 #msg-panel.open 포함)가 열린 동안.
   · body.v4-kb-open + 인라인 --v4-vvh/--v4-vvt(px) — visualViewport 로 키보드가 열렸을 때(아래 .v4-sheet 규칙).
   · 레거시 호스트([data-v4-mobile=sheet] = #msg-panel)는 .v4-sheet 가 아니다: 도크 탭 → 기존 window.toggleMsgPanel/openMsgPanel 호출(중복 UI 금지),
     열림 판정은 #msg-panel.open. 도크 마크업이 서버에 없으면 ui_v4_ask.js 가 아래 런처 1행을 만든다:
       <div class="v4-dock" role="region" aria-label="리포트에 묻기">
         <button type="button" class="v4-dock-open" aria-haspopup="dialog"><img …><span class="t">김도훈에게 이 리포트 묻기</span>
           <span class="v4-typing" hidden><i></i><i></i><i></i></span><span class="v4-status"><i class="v4-dot" data-v4-health="dot"></i></span></button>
         <button type="button" class="v4-dock-go">묻기</button>
       </div> */
.v4-dock { display: none; position: fixed; left: 0; right: 0; bottom: 0; z-index: var(--z-dock); align-items: center; gap: 6px;
  min-height: calc(var(--dock-h) + env(safe-area-inset-bottom)); padding: 6px var(--page-x) calc(6px + env(safe-area-inset-bottom));
  background: color-mix(in srgb, var(--bg) 92%, transparent); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); border-top: var(--hairline); }
.v4-dock .act { display: flex; gap: 0; margin-right: 4px; }          /* 관심·저장·공유 아이콘 — 스팟 카드에서 내려옴 (M7) */
.v4-dock .act .v4-btn.icon { background: transparent; border-color: transparent; color: var(--fg-2); }
.v4-dock .v4-input { flex: 1; min-width: 0; height: 40px; padding-left: 8px; }
.v4-dock .v4-input img { width: 24px; height: 24px; border-radius: 50%; object-fit: cover; flex: 0 0 auto; }
.v4-dock-open { flex: 1; min-width: 0; display: flex; align-items: center; gap: 8px; height: 40px; padding: 0 10px 0 8px; border: var(--hairline); border-radius: var(--r-2);
  background: var(--surface); color: var(--fg-3); font-size: var(--fs-14); text-align: left; cursor: pointer; }
.v4-dock-open:hover { color: var(--fg); border-color: var(--fg-3); }
.v4-dock-open img, .v4-dock-open .av { width: 24px; height: 24px; border-radius: 50%; object-fit: cover; flex: 0 0 auto; }
.v4-dock-open .t { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.v4-dock-open .v4-typing { color: var(--accent); }
.v4-dock-go { height: 40px; padding: 0 14px; border: 0; border-radius: var(--r-2); background: var(--accent); color: var(--accent-fg); font-weight: 700; font-size: var(--fs-14); cursor: pointer; flex: 0 0 auto; }
.v4-sheet { position: fixed; inset: auto 0 0 0; z-index: var(--z-sheet); height: min(86vh, 720px); height: min(86dvh, 720px);
  display: flex; flex-direction: column; background: var(--surface); border: var(--hairline); border-bottom: 0; border-radius: var(--r-3) var(--r-3) 0 0;
  box-shadow: var(--shadow-2); transform: translateY(100%); visibility: hidden; overscroll-behavior: contain;
  transition: transform 200ms var(--ease), visibility 200ms; }
.v4-sheet.open { transform: none; visibility: visible; }
.v4-sheet > .v4-ask { flex: 1 1 auto; min-height: 0; border: 0; border-radius: 0; background: transparent; }
.v4-sheet .v4-ask-h { position: sticky; top: 0; z-index: 1; background: var(--surface); }           /* 머리줄 항상 보임 */
.v4-sheet .v4-ask-h .x { width: 44px; height: 44px; }                                                 /* 닫기 44 (S-g) */
.v4-sheet .v4-ask-body { flex: 1 1 auto; }
.v4-sheet .v4-ask-in { position: sticky; bottom: 0; background: var(--surface); padding-bottom: calc(8px + env(safe-area-inset-bottom)); }
/* 키보드 열림: 시트를 visualViewport 에 맞춘다(iOS·안드로이드 resizes-visual 기본값에서 fixed 바닥이 키보드 뒤로 가는 것 방지). 토큰은 JS 인라인. */
body.ui-v4.v4-kb-open .v4-sheet.open { top: var(--v4-vvt, 0px); bottom: auto; height: var(--v4-vvh, 100dvh); max-height: none; border-radius: 0; }
.v4-overlay { position: fixed; inset: 0; z-index: var(--z-overlay); background: rgba(0,0,0,.45); transition: opacity var(--motion) var(--ease); }
.v4-overlay[hidden] { display: none; }
@media (max-width: 900px) {
  .v4-aside-stack { position: static; max-height: none; }
  .v4-ask-dock:not(.v4-ask-host) { display: none; }            /* 사이드 챗 숨김 → 하단 도크 + 시트 (레거시 호스트는 제외) */
  .v4-dock { display: flex; }
  body.ui-v4.has-dock { padding-bottom: calc(var(--dock-h) + env(safe-area-inset-bottom)); }
}

/* --- 리포트 스팟 카드: 데스크톱 sticky 1행 48 / ≤900 비sticky 2행 + 스크롤 120px 뒤 축약 1행 40 sticky (M7) --- */
/* 10/19 QA 2차(주인): 상단 고정 띠는 큰 KPI 박스(.info-grid)와 따로 놀고 글자가 작다 → 스팟은 '스크롤 뒤에만 내려오는 요약 바'로.
   첫 화면은 레거시 KPI 박스(큰 숫자)가 담당, 120px 넘게 내리면 이 바가 헤더 아래로 내려온다(JS: body.v4-spot-scrolled). */
.v4-spot { position: fixed; left: 0; right: 0; top: var(--header-h); z-index: var(--z-sticky); margin: 0; border: 0; border-bottom: var(--hairline); border-radius: 0;
  background: color-mix(in srgb, var(--bg) 94%, transparent); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  transform: translateY(calc(-100% - 1px)); visibility: hidden; transition: transform var(--motion) var(--ease), visibility var(--motion); }
body.ui-v4.v4-spot-scrolled .v4-spot { transform: none; visibility: visible; }
.v4-spot-in { display: flex; align-items: center; flex-wrap: nowrap; gap: var(--sp-4); min-height: var(--spot-h); padding: 6px var(--page-x); min-width: 0; max-width: var(--page-max, 1200px); margin: 0 auto; }
.v4-spot .v3-optag { display: none; }   /* 10/19 QA: 배지 안에 이미 태그가 있어 '눌림 대기' 가 두 번 보이던 중복 */
.v4-spot .badge, .v4-spot .v3-opbadge-wrap { white-space: nowrap; flex: 0 0 auto; }
.v4-spot .nums { flex: 1 1 auto; }
@media (max-width: 640px) { .v4-spot .v3-opbadge-wrap { display: none; } }   /* 좁은 폭에선 배지가 세로로 깨져 바가 2~3줄이 되던 것 */
.v4-spot .who { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; }   /* 10/19 QA: min-width:0 이면 좁은 폭에서 종목명이 0폭으로 줄어 숫자와 겹침 */
.v4-spot .who img { width: 26px; height: 26px; border-radius: 50%; object-fit: cover; }
.v4-spot .who .stk { font-weight: 800; font-size: var(--fs-15); white-space: nowrap; }
.v4-spot .who .code { font-family: var(--font-data); font-size: var(--fs-12); color: var(--fg-3); }
.v4-spot .nums { display: flex; align-items: center; gap: var(--sp-4); min-width: 0; overflow-x: auto; scrollbar-width: none; }
.v4-spot .nums::-webkit-scrollbar { display: none; }
.v4-spot .n { display: flex; flex-direction: column; line-height: 1.15; white-space: nowrap; }
.v4-spot .n .l { font-size: 10px; color: var(--fg-3); letter-spacing: .04em; }
.v4-spot .n .v { font-size: var(--fs-14); font-weight: 600; font-variant-numeric: tabular-nums; }   /* 본문 글꼴 tnum (S-d) */
.v4-spot .act { margin-left: auto; display: flex; gap: 4px; }
.v4-spot .act .v4-btn.icon { background: transparent; border-color: transparent; color: var(--fg-2); }
.v4-spot .act .v4-btn.icon:hover { background: var(--surface-2); color: var(--fg); }
.v4-spot .base { font-size: var(--fs-12); color: var(--fg-3); white-space: nowrap; }
.v4-spot-mini { display: none; position: fixed; left: 0; right: 0; top: var(--header-h); z-index: var(--z-sticky); height: var(--spot-mini-h);
  align-items: center; gap: 10px; padding: 0 var(--page-x); font-size: var(--fs-13); white-space: nowrap; overflow: hidden;
  background: color-mix(in srgb, var(--bg) 94%, transparent); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); border-bottom: var(--hairline);
  transform: translateY(calc(-100% - 1px)); visibility: hidden; transition: transform var(--motion) var(--ease), visibility var(--motion); }
.v4-spot-mini .stk { font-weight: 700; }
.v4-spot-mini .v { font-weight: 600; font-variant-numeric: tabular-nums; }
.v4-spot-mini .sep { color: var(--line); }
.v4-spot-mini .v4-badge { height: 20px; padding: 0 6px; }
@media (max-width: 900px) {
  .v4-spot-in { padding: 6px 12px; gap: 8px 14px; }
  .v4-spot .nums { padding-right: 48px;
    mask-image: linear-gradient(to right, #000 calc(100% - 48px), transparent); -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 48px), transparent); }
  .v4-spot .act, .v4-spot .base { display: none; }   /* 액션은 .v4-dock .act 로 */
  .v4-spot-mini { display: none; }   /* 10/19 QA 2차: 축약 바 역할은 .v4-spot 하나가 전 폭에서 맡는다 */
}

/* --- 표 (다크 th 글자는 --fg-2 — S-b 4.43 미달 수리; scrollable 우측 페이드 힌트 D19) --- */
.v4-table-wrap { position: relative; overflow-x: auto; -webkit-overflow-scrolling: touch; border: var(--hairline); border-radius: var(--r-2); }
.v4-table-wrap.scrollable::after { content: ""; position: absolute; top: 0; right: 0; bottom: 0; width: 36px; pointer-events: none;
  background: linear-gradient(to right, transparent, var(--surface)); }
.v4-table { width: 100%; border-collapse: collapse; font-size: var(--fs-14); }
.v4-table th, .v4-table td { padding: 8px 12px; border-bottom: 1px solid var(--line-soft); text-align: left; white-space: nowrap; vertical-align: top; }
.v4-table th { font-size: var(--fs-12); font-weight: 600; color: var(--fg-2); background: var(--surface-2); }
.v4-table td.n, .v4-table th.n { text-align: right; font-family: var(--font-data); font-variant-numeric: tabular-nums; }
.v4-table tr:last-child td { border-bottom: 0; }

/* --- 목차 --- */
.v4-toc { position: sticky; top: calc(var(--header-h) + var(--spot-h) + 12px); font-size: var(--fs-13); }
.v4-toc .t { font-size: var(--fs-12); font-weight: 700; color: var(--fg-3); letter-spacing: var(--ls-caps); margin-bottom: 8px; }
.v4-toc a { display: block; padding: 5px 0 5px 10px; color: var(--fg-2); border-left: 2px solid var(--line); line-height: 1.45; }
.v4-toc a.on { color: var(--fg); border-left-color: var(--accent); }
.v4-toc a.locked { color: var(--fg-3); }
.v4-toc a.locked::after { content: ""; display: inline-block; width: 10px; height: 10px; margin-left: 6px; vertical-align: -1px;
  background: currentColor; -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='11' width='18' height='11' rx='2'/%3E%3Cpath d='M7 11V7a5 5 0 0 1 10 0v4'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='11' width='18' height='11' rx='2'/%3E%3Cpath d='M7 11V7a5 5 0 0 1 10 0v4'/%3E%3C/svg%3E") center / contain no-repeat; }   /* 🔒 이모지 대신 SVG (S-j) */

/* --- 스켈레톤 --- */
.v4-skel { display: block; height: 12px; border-radius: 3px; background: linear-gradient(90deg, var(--surface-2) 25%, var(--line) 50%, var(--surface-2) 75%); background-size: 200% 100%; animation: v4skel 1.2s infinite; }
@keyframes v4skel { to { background-position: -200% 0; } }

/* --- 기사 본문(리포트·데일리 공용) --- */
.v4-article { font-size: var(--fs-16); line-height: var(--lh-article); max-width: 72ch; }
.v4-article h2 { font-size: var(--fs-20); font-weight: 700; margin: var(--sp-10) 0 var(--sp-3); padding-top: var(--sp-4); border-top: var(--hairline); scroll-margin-top: calc(var(--header-h) + var(--spot-h) + 12px); }
.v4-article h3 { font-size: var(--fs-16); font-weight: 700; margin: var(--sp-6) 0 var(--sp-2); }
.v4-article p { margin: 0 0 var(--sp-4); }
.v4-article blockquote { margin: 0 0 var(--sp-4); padding: 10px 14px; border-left: 3px solid var(--accent); background: var(--accent-tint); border-radius: 0 var(--r-1) var(--r-1) 0; font-size: var(--fs-15); color: var(--fg); }
.v4-article blockquote.warn { border-left-color: var(--warn); background: var(--warn-tint); }   /* 캘리브레이션 경고 상자 — 액센트와 분리 (S-a) */
.v4-article strong { color: var(--fg); font-weight: 700; }
.v4-article ul, .v4-article ol { margin: 0 0 var(--sp-4); padding-left: 22px; }
.v4-article li { margin: 4px 0; }
.v4-article a { color: var(--accent); text-decoration: underline; text-decoration-color: var(--accent-line); text-underline-offset: 3px; }
.v4-article table { font-size: var(--fs-14); }
@media (max-width: 640px) { .v4-article { font-size: var(--fs-15); } }
/* 페이월 래퍼 (M4): 잠긴 본문 DOM 유지, 세로만 접는다 — 블러 본문 7,738px 폐기 */
.v4-tease { position: relative; max-height: 4.9em; overflow: hidden; filter: blur(4px); user-select: none; pointer-events: none; color: var(--fg-2);
  mask-image: linear-gradient(#000 40%, transparent); -webkit-mask-image: linear-gradient(#000 40%, transparent); }

/* --- 푸터 --- */
.v4-ft { margin-top: var(--sp-16); padding: var(--sp-8) 0 var(--sp-10); border-top: var(--hairline); color: var(--fg-3); font-size: var(--fs-12); }
.v4-ft .row { display: flex; flex-wrap: wrap; gap: var(--sp-4) var(--sp-8); justify-content: space-between; }
.v4-ft a { color: var(--fg-2); }

/* --- 데일리 슬롯 표식 --- */
.v4-slot { display: inline-flex; align-items: center; gap: 6px; font-size: var(--fs-12); font-weight: 700; letter-spacing: .02em; }
.v4-slot::before { content: ""; width: 3px; height: 12px; border-radius: 2px; background: currentColor; }
.v4-slot.pre { color: var(--slot-pre); } .v4-slot.mid { color: var(--slot-mid); } .v4-slot.post { color: var(--slot-post); }

/* --- 탈리스커 전용 (body.ui-v4[data-app="talisker"]) --- */
body.ui-v4[data-app="talisker"] { font-size: 13px; line-height: 1.5; }
body.ui-v4[data-app="talisker"] .v4-blk { background: var(--surface); border: var(--hairline); border-radius: var(--r-2); padding: 10px 12px; min-width: 0; }
body.ui-v4[data-app="talisker"] .v4-blk > h2 { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; flex-wrap: wrap; margin: 0 0 8px; font-size: 12px; font-weight: 600; color: var(--fg-3); letter-spacing: .04em; }
body.ui-v4[data-app="talisker"] .v4-blk > h2 b { color: var(--fg); }
body.ui-v4[data-app="talisker"] .v4-blk > h2 .asof { font-family: var(--font-data); font-size: 10px; color: var(--fg-3); }
body.ui-v4[data-app="talisker"] .v4-kv { display: grid; grid-template-columns: auto 1fr; gap: 2px 10px; font: 12px/1.5 var(--font-data); margin: 0; }
body.ui-v4[data-app="talisker"] .v4-kv dt { color: var(--fg-3); font-family: var(--font-body); font-size: 11px; }
body.ui-v4[data-app="talisker"] .v4-kv dd { margin: 0; text-align: right; }
body.ui-v4[data-app="talisker"] .v4-src { font: 10px/1 var(--font-data); border: 1px solid var(--line); border-radius: 3px; padding: 2px 5px; color: var(--fg-3); white-space: nowrap; }
body.ui-v4[data-app="talisker"] .v4-src.real { color: var(--accent); border-color: var(--accent-line); }
body.ui-v4[data-app="talisker"] .v4-alert { display: flex; flex-wrap: wrap; gap: 4px 8px; align-items: baseline; border: 1px solid var(--accent-line); border-radius: var(--r-2); padding: 7px 10px; font-size: 12px; margin: 0 0 6px; background: var(--warn-tint); color: var(--warn); }
body.ui-v4[data-app="talisker"] .v4-alert.bad { border-color: var(--bad); background: var(--bad-tint); color: var(--bad); }
body.ui-v4[data-app="talisker"] .v4-alert.fl { animation: v4fl 1.6s steps(2) infinite; }   /* 깜빡임 — reduced-motion 이면 위 규칙으로 0 */
@keyframes v4fl { 50% { opacity: .55; } }
