  :root, body[data-theme="dark"] {
    --bg:#0a0a0d; --panel:#17171d; --panel2:#20202a; --line:#2a2a34;
    --text:#f2f2f6; --dim:#9a9aa8;   /* 2026-08-19 밝게(구 #8a8a99) — "회색이 많아 눈 아프다"의 답은 회색을 줄이기보다 진하게 */ --up:#ff453a; --down:#0a84ff;
    /* 경고·이탈 전용 빨강 — 상승색(--up)과 다른 색이어야 둘을 헷갈리지 않는다 */
    --alert:#f26d6d;
    /* 구독 Pro 전용 파랑(구글 블루 계열) — **--down(하락)과 절대 겸용하지 않는다.**
       데이터 의미색을 UI 강조로 빌려 쓰면 파란 숫자가 "하락"인지 "유료"인지 헷갈린다 */
    --pro-1:#1a73e8; --pro-2:#4285f4; --pro-3:#8ab4f8;

    /* 무지갯빛 테두리 한 벌 — '특별한 것' 표시. 지금 두 곳이 쓴다: 추천코드 등록하기(.acctinvbtn)와
       넘버스&내러티브 프리셋(.preset.narrative). 값을 한 곳에 두어 둘이 갈리지 않게 (2026-08-30) */
    --rainbow:linear-gradient(96deg, #a8e063 0%, #ffd86b 26%, #ff9f7a 50%, #ff8fb1 74%, #c99bf0 100%);
    --accent:#34d399; --ai:var(--accent);   /* 모던 럭셔리 B + 브랜드=에메랄드 (docs/28 패스14) · --ai 보라 폐기 → 시그니처 청록 원톤 (사용자 최종 확정 2026-07-22 "메인 컬러 = 주비스 청록" — 구 #bf5af2·#c86fd4 계보 종료) */
    --radar:#c86fd4;     /* 재무 점수 오각형 엣지 = 밝은 자주빛 (사용자 지시 2026-07-22 "청록 말고 기존 자줏빛으로").
                            docs/28 §의미색 정본 — 네온(#bf5af2)도 연보라(#a68ddb)도 아닌 그 중간 */
    --pred:#dd8ae8;      /* 딥러닝 예측선 = 오각형보다 한 단계 밝은 자주 (사용자 지시 2026-07-22 "조금 더 밝게").
                            차트 위 얇은 선이라 면(오각형)보다 밝아야 같은 밝기로 읽힌다 */
    --mention:#38bdf8;   /* @멘션(진한 하늘색) — 대화에 첨부된 기업 컨텍스트 표시 (사용자 지시 2026-07-15) */
    --dim2:#a8a8b4;      /* '읽어야 하는' 보조 텍스트 — --dim은 라이트에서 3.97:1로 본문 기준(4.5) 미달이라
                            목록의 대화 이름처럼 내용을 담은 보조 글자는 이쪽을 쓴다 (실측 2026-07-29) */
    --pf-neon:#3cf5a8;   /* 포트폴리오 파이의 작은 조각 — 액센트보다 한 단계 형광 (사용자 지시 2026-08-13
                            "조금 더 형광 느낌으로"). 메뉴에서 유일한 색 포인트라 여기만 튄다 */
    --star:#f5b62c;      /* 관심종목 별 = 단색 노랑 (사용자 확정 2026-08-19). 보유는 색이 아니라 오로라로 가른다 */
    --shadow:0 1px 2px rgba(0,0,0,.5), 0 14px 34px rgba(0,0,0,.30);   /* 소프트 섀도 = 카드 레이어감 (B 핵심) */
    /* 카드가 놓이는 바닥 — 카드(--panel)가 바닥보다 **한 단 밝다**는 규칙 하나로 두 테마를
       관통한다(값은 connectors.html과 같은 짝). 라이트에서 --bg(#f5f5f7)는 흰 카드와
       구분이 안 돼 바닥 노릇을 못 한다 (2026-08-29). */
    --canvas:var(--bg);
  }
  body[data-theme="light"] {
    --bg:#f5f5f7; --panel:#ffffff; --panel2:#eceef1; --line:#e6e7ec;
    --text:#16161c; --dim:#63636e;   /* 2026-08-19 진하게(구 #74747f, 3.97:1 미달) — 흰 배경 5.2:1로 AA 통과 */ --up:#ff3b30; --down:#007aff;
    --alert:#d1443c;
    --pro-1:#1557d0; --pro-2:#1a73e8; --pro-3:#4285f4;

    /* 라이트는 흰 배경이라 파스텔이 날아간다 — 같은 색상환을 한 단계 진하게 */
    --rainbow:linear-gradient(96deg, #6fae2f 0%, #e0a411 26%, #e56a3f 50%, #e05586 74%, #8f5bc4 100%);
    --accent:#047857; --ai:var(--accent);   /* 라이트: 흰 카드 + 은은한 섀도 · 에메랄드는 딥(emerald-700) · --ai = 청록 원톤 (2026-07-22 최종) */
    --radar:#8e3a9e;     /* 라이트: 흰 배경 대비 확보한 딥 자주 (docs/28 정본 페어 #c86fd4/#8e3a9e) */
    --pred:#a855f7;      /* 라이트 예측선 — 기존 칩 하드코드(#a855f7)와 같은 값, 오각형보다 밝다 */
    --mention:#0284c7;   /* @멘션(진한 하늘색) — 라이트는 딥(sky-600)으로 흰 배경 대비 */
    --canvas:var(--panel2);   /* 흰 카드보다 한 단 어두운 바닥 (다크는 --bg, 위 주석 참조) */
    --dim2:#5c5c68;      /* 라이트 보조 — #eceef1 위 5.9:1 (AA 통과). --dim(#74747f)은 3.97:1 */
    --pf-neon:#00c983;   /* 라이트: 흰 배경에서도 형광으로 읽히되 글자 대비를 해치지 않는 선 */
    --star:#d98a00;      /* 라이트: 흰 배경에서도 노랑으로 읽히는 선까지 내린 값 */
    --shadow:0 1px 2px rgba(20,20,40,.06), 0 12px 30px rgba(20,20,40,.10);
  }
  /* ---------- 주비스 브랜드 팔레트 = 녹색머리풍금조 (사용자 확정 2026-08-04) ----------
     "구글이 4색을 갖듯, 주비스는 이 새의 색을 갖는다." 단색 시그니처(--accent 청록)는 불변이고,
     여러 색이 필요할 때(마스코트·일러스트·업종/카테고리 구분·빈 상태·온보딩) 이 팔레트가 주비스를 대표한다.
     ※ 데이터 의미색(--up 상승·--down 하락)은 이 팔레트와 무관하게 불변 — 섞지 말 것. */
  :root {
    --tg-turquoise:#45c9d8;   /* 머리 — 시그니처와 한 가족, 카테고리 1 */
    --tg-lime:#c3dc2b;        /* 목덜미 — 가장 밝은 하이라이트, 카테고리 2 */
    --tg-green:#6dbe45;       /* 등 — 중간 톤, 카테고리 3 */
    --tg-slate:#7e8fc6;       /* 날개깃 — 차분한 쿨톤, 카테고리 4 */
    --tg-petrol:#2c7285;      /* 꼬리 — 가장 깊은 색, 카테고리 5 */
    --tg-orange:#f2941b;      /* 깃 속 숨은 주황 줄무늬 — 화면당 1곳까지만(브랜드 모먼트) */
    /* ── 요금제 태그(Basic·Pro) 전용 5색 ────────────────────────────────
       사용자가 고른 시안 `figs_chatgpt/tag/{basic,pro}_tag.png`에서 **실측해 뽑은 값**이다
       (2026-08-29). 시안은 PNG였지만 화면에는 CSS로 옮겼다 — 이유는 셋: ① 두 장 합쳐 1.9MB라
       12px짜리 배지에 얹기엔 너무 무겁고 ② 글자가 그림에 구워져 있어 문구를 못 바꾸며
       ③ 배경이 투명이 아닌 흰색이라 다크 테마·색 있는 패널 위에서 흰 테가 뜬다.
       색·광택·모서리 금빛은 시안 그대로 재현했다. 카테고리 팔레트(--tg-*)와 별개 —
       이 다섯은 태그 두 개에만 쓴다. */
    /* Pro 배지 램프 — **한 단계 진하게** (머신러너님 지시 2026-08-31 "좀 없어 보인다,
       촌스러워 색감이"). 구조는 그대로 둔다(단일 대각 램프, 층 겹치기 금지 — 아래
       `.acctplan.pro` 주석의 두 번 반려된 방식). 바꾼 것은 **밝기와 채도**뿐이다:
       밝은 청록(#0192cc)과 옅은 샴페인(#d8cf95)이 작은 필 안에서 형광펜처럼 읽혔다.
       덤으로 대비도 좋아진다 — 흰 글자가 얹히는 가장 밝은 끝이 #f0c95c → #d9a63c다. */
    --tag-deep:#013f4d;       /* 좌측 심해 청록 — 태그의 바탕 (구 #03616e) */
    --tag-mid:#015a70;        /* 중간 — 청록에서 하늘빛으로 건너가는 다리 (구 #01768c) */
    --tag-azure:#0b6f9e;      /* 우측 하늘빛 — 여기서 밝아진다 (구 #0192cc, 네온기 제거) */
    --tag-aqua:#3f9aae;       /* 밝은 경유지 — 여전히 mid보다 밝다(탁한 연두 방지, 구 #63c2d6) */
    --tag-champ:#bda36b;      /* 샴페인 — 금빛 직전의 단계 (구 #d8cf95) */
    --tag-gold:#d9a63c;       /* 우측 하단 금빛 — Pro만 갖는 표식 (구 #f0c95c) */
    --tag-basic:#075563;      /* Basic = 그라데이션 없는 한 색 */
    --tg-ink:#17181c;         /* 눈가면·날개 띠 — 구조를 잡는 검정 */
    /* 메인이 쓰는 유일한 파생 (2026-08-04). **파스텔 4종(wash·line·soft)은 사용자 반려 — 재도입 금지**:
       메인 배경·괘선·아이콘에 파스텔 청록을 깔았더니 시그니처 에메랄드와 두 계열이 부딪쳐
       "색이 따로노는 느낌"이 됐다. 메인의 색은 시그니처 --accent 한 색으로 통일하고,
       풍금조 팔레트는 여러 색이 필요한 자리(카테고리 구분·일러스트)에만 쓴다. */
    --tg-veil:color-mix(in srgb, var(--accent) 8%, transparent);   /* 호버 틴트 — 행이 '떠오르는' 정도만 */
  }
  body[data-theme="light"] {   /* 흰 배경에서 글자·선으로 쓸 때 대비 확보 (--accent·--radar와 같은 관례) */
    --tg-turquoise:#0e8fa3; --tg-lime:#7f9410; --tg-green:#4a8f2c; --tg-orange:#c26a06;
    /* **테마마다 다시 선언해야 한다** — 커스텀 속성은 선언한 요소에서 치환이 끝나므로,
       :root에만 두면 다크 --accent(#34d399)가 박혀 라이트에서도 그 색이 나온다(실측 2026-08-06:
       틴트는 민트인데 같은 행의 좌측 바는 #047857로 계열이 어긋났다). 여기 선언하면
       이 요소의 --accent(#047857)로 풀린다. */
    --tg-veil:color-mix(in srgb, var(--accent) 8%, transparent);
  }
  /* ---------- 타이포 캐논 (사용자 확정 2026-08-19 "글씨가 너무 작아 안 보인다") ----------
     화면 글자 크기는 모듈마다 새로 정하지 않는다 — 여기 넷이 정본이고, 새 화면도 이걸 쓴다.
     ⚠ 10.5px 이하로 다시 내리지 마라. 그게 이번 지시의 원인이었다(표 컬럼 헤더 10.5px). */
  :root {
    --fs-th:13.5px;    /* 표 컬럼 헤더 — 읽는 글자다. 이름을 못 읽으면 열은 없는 것과 같다 */
    --fs-tbl:13px;     /* 표 본문 */
    --fs-sub:12.5px;   /* 부제·범례·각주 = **읽는 글자의 최소 크기** */
    --fs-body:13px;    /* 읽는 문장 */
    --fs-lab:12px;     /* 섹션 라벨·칩·필 — 읽는 문장이 아니라 표지판. 구 11/10.5px 전부 여기로 */
    --fs-badge:10.5px; /* 배지·위첨자 — 글자라기보다 마크. 구 10/9.5px 전부 여기로 (신규 더 작게 금지) */
    /* ── 제목 두 단 (사용자 지시 2026-08-19 "이게 이 모듈의 대표구나라는 이미지를 줬으면") ──
       그전엔 모듈 제목과 섹션 대제목이 **둘 다 17px**이었다. 크기가 같으면 위아래가 아니라
       나란히 읽혀, 화면에 들어와도 무엇이 이 모듈의 얼굴인지 눈이 못 고른다.
       화려하게가 아니라 **또렷하게** — 색·선·장식은 더하지 않고 크기와 자간만 벌린다.
       카드 제목(`.page h3` 15.5px)은 정본이라 건드리지 않는다. 사다리는 22 / 18 / 15.5. */
    --fs-title:22px;   /* 모듈 제목 — 화면당 하나뿐인 얼굴 (`.page h2`) */
    --fs-sect:18px;    /* 섹션 대제목 — 모듈 안의 큰 단락. 카드 제목보다 한 단 위 */
    --fgpad:18px;      /* 재무 셀(.fgcell) 좌우 패딩 — 셀 안쪽 내용의 들여쓰기 기준 */
  }
  :root { --zoom:1.2; overflow:hidden; }   /* 전역 확대 배율 (사용자 지시 2026-07-16 "120%를 기본처럼"). overflow:hidden = body를 transform:scale로 확대할 때 전광판(#tickerrail) 마퀴가 문서 밖으로 새어 나가 가로 스크롤 생기는 것 차단 (zoom→transform 전환 부작용) */
  /* 좁은 화면에서는 전역 확대를 끈다 (사용자 지시 2026-08-29 "모바일 화면 구성이 완벽하지 않다").
     위 1.2배는 큰 모니터를 위한 선택인데, body는 `width:100vw/1.2`로 줄지만 **`vw`는 그 나눗셈을
     안 받는다** — `vw`로 쓴 자리가 전부 body 상자보다 넓어진다.
     실측(375px 폰, 2026-08-29): body 레이아웃 폭 313px인데 `#chatpanel`이 `width:100vw`라 375px.
     제품의 메인 창이 제 상자보다 62px(화면의 17%) 넓었고, `:root{overflow:hidden}`이라 잘린
     오른쪽으로 스크롤도 못 갔다. 홈 한 화면에서만 이렇게 잘린 요소가 28개.
     1로 되돌리면 body 폭 = 화면 폭이라 `vw` 자리가 **한 번에** 맞는다 — 요소를 하나씩 때우는
     대신 버그의 종류를 없앤다(그 때우기의 흔적이 곳곳의 `calc(... / var(--zoom))` 보정이다).
     조건이 **폭 하나가 아닌 이유**(2026-08-29 실측): 처음엔 `max-width:900px`만 걸었더니
     델컴 크롬이 100%로 줄었다 — 데스크톱인데 창이 900px보다 좁았던 것이다(옆에 터미널을
     띄우거나 페이지 확대를 쓰면 CSS 뷰포트가 그만큼 줄어든다). 120%는 **책상에서 읽는
     취향**이라 창을 좁혔다고 뺏을 것이 아니다. 그래서 폭이 아니라 **입력 장치**로 가른다:
       · `(pointer:coarse) and (max-width:900px)` — 손가락으로 만지는 기기(폰·태블릿)
       · `(max-width:560px)` — 마우스든 뭐든 이 폭이면 확대가 해롭다(폴백)
     윈도 터치 PC는 주 포인터가 마우스라 `pointer:fine`으로 잡히므로 120%를 지킨다. */
  @media (pointer:coarse) and (max-width:900px), (max-width:560px) {
    /* **세로 스크롤을 푼다** (실측 2026-08-29 — 머신러너님 "손가락으로 쭉~ 안 내려가").
       위 `:root{overflow:hidden}`은 확대(scale) 때 전광판 마퀴가 문서 밖으로 새어 **가로**
       스크롤이 생기는 것을 막으려던 것이다. 그런데 세로까지 함께 막혀 있었다:
         html  overflow-y:hidden · 보이는 높이 812 · 내용 4155   ← 넘치는데 막힘
         body  overflow-y:auto   · 높이 4155      · 내용 4155   ← 자기는 안 넘쳐 무의미
       루트가 뷰포트의 스크롤 주체라, 여기가 hidden이면 **손가락이 아무리 밀어도 안 움직인다.**
       ⚠ `scrollTo()`는 hidden이어도 움직인다 — 그래서 프로그램 스크롤로 검증하면 통과로 보인다.
          실제로 그렇게 오판했다. 손가락 검증은 **실제 스크롤 이벤트**로 해야 한다.
       세로만 auto로 돌린다 — `overflow-x`는 위 규칙의 hidden이 그대로 살아 마퀴를 계속 막는다. */
    :root { --zoom:1; overflow-y:auto; }
    /* **`scale(1)`도 `position:fixed`를 망가뜨린다** (실측 2026-08-29). transform이 `none`이
       아니면 그 요소가 자손 fixed의 **기준 상자**가 된다 — 배율이 1이어도 그렇다.
       좁은 화면은 `body{height:auto}`(아래 @media 900)라 body가 내용만큼 길어지므로:
         · `#chatpanel`의 `top:0;bottom:0`이 화면(812)이 아니라 **body 높이(1162)** 기준이 돼
           높이가 1162px이 되고 입력창이 화면 아래 216px로 밀려났다 — 글을 못 썼다
         · 고정이어야 할 것이 **스크롤을 따라 움직였다**(실측: 400 굴리니 350px 이동).
           대화창만이 아니라 토스트·모달 등 fixed 전부가 그랬다
       확대가 꺼진 자리에서 `scale(1)`은 아무 일도 안 하면서 이 부작용만 남긴다. 그래서 지운다 —
       **보이는 것은 하나도 안 변하고**(배율 1) fixed만 제자리를 찾는다.
       ⚠ 확대가 살아 있는 좁은 창(마우스)에는 이 블록이 안 걸린다 — 거기선 transform이 배율을
       실제로 하는 일이라 지우면 안 된다. 조건이 `--zoom:1`과 한 몸인 이유다. */
    /* ⚠ body 재정의는 여기 두면 안 된다 — 기본 `body{transform:scale(...)}`(아래 144행)이
       **뒤에 있어 이긴다**(같은 특이도는 순서가 정한다). 그래서 그 규칙 **다음**으로 옮겼다. */
  }
  /* 폰을 눕히면 iOS·안드로이드가 **본문 글자를 제멋대로 키운다**(text autosizing). 그 순간
     글자 캐논(--fs-*)이 통째로 무너져 화면 문법이 깨진다. 100%로 못 박아 우리가 정한 크기를 지킨다.
     데스크톱 브라우저는 이 속성 자체를 쓰지 않으므로 **무동작**이다 — 그래서 @media 밖에 둔다. */
  html { -webkit-text-size-adjust:100%; text-size-adjust:100%; }
  * { box-sizing:border-box; margin:0; padding:0; }
  /* 키보드 포커스 링 (2026-07-29) — `:focus-visible`이라 **마우스 클릭에는 뜨지 않는다**.
     실측: 버튼 어디에도 포커스 표시가 없어 Tab으로 이동하면 지금 어디에 있는지 알 수 없었다
     (WCAG 2.4.7). 링 하나로 키보드 사용이 가능해진다. */
  :focus-visible { outline:2px solid var(--accent); outline-offset:2px; }
  /* 폰트 표준 (사용자 확정 2026-07-14): 영문·숫자=Google Sans(없으면 Roboto) · 한글=Noto Sans KR(기본)
     — Roboto엔 한글 글리프가 없어 한글만 Noto로 자연 폴백. 오프라인/미설치 시 Apple SD Gothic Neo(Mac)·맑은 고딕(Win).
     웹폰트는 index.html에서 Google Fonts 로드(display=swap — 로드 전에도 시스템 폰트로 즉시 표시) */
  body { background:var(--bg); color:var(--text);
    font:14px/1.55 "Google Sans",Roboto,"Noto Sans KR","Apple SD Gothic Neo","Malgun Gothic","Segoe UI",sans-serif;
    /* 전역 확대(120%). CSS zoom은 ECharts(zrender) 마우스 히트테스트를 깨뜨림 — zoom은 이벤트 offsetX를
       확대공간(예 292)으로 주는데 캔버스 좌표계는 비확대(244)라 어긋나 호버·툴팁·클릭 전부 먹통(2026-07-16 궤적 액션 실종 원인).
       transform:scale은 브라우저가 offsetX를 원좌표로 역매핑 → zrender 정상. origin top-left + 크기 /zoom 보정으로 100vw×100vh 정확히 채움 */
    transform:scale(var(--zoom)); transform-origin:top left;
    width:calc(100vw / var(--zoom)); height:calc(100vh / var(--zoom)); display:flex; overflow:hidden; }
  /* 확대를 끈 화면에서는 transform 자체를 걷는다 (사유는 위 --zoom 블록 주석).
     **반드시 위 body 규칙 뒤에 와야 한다** — 같은 특이도라 순서가 이긴다. 앞에 두면
     `transform:scale(1)`이 다시 이겨 규칙은 남은 채 효과만 죽는다(실측 2026-08-29에 한 번 밟았다).
     width/height도 함께 되돌린다 — 나눗셈이 필요 없어졌고, height는 아래 @media 900이 auto로 잡는다. */
  @media (pointer:coarse) and (max-width:900px), (max-width:560px) {
    body { transform:none; width:100%; }
  }

  /* **iOS는 16px 미만 입력창을 누르면 페이지를 확대한다 — 그리고 되돌리지 않는다.**
     실측 2026-08-29(머신러너님 폰 스크린샷): '3초 회원가입'의 추천코드 칸(`.lginvin` 13.5px)을
     누르자 화면이 확대되며 창이 오른쪽으로 밀려 '사용' 버튼이 잘렸다. 키보드가 올라온 게
     원인이 아니라 **글자 크기가 16px 미만**이라 사파리가 확대한 것이다.
     같은 조건인 칸이 더 있었다 — `#chatinput`·`#lndinput` 15.5 / `.pftrdform input` 12.5 /
     `.prask input` 12.5 / `.pfholdin input`. 하나씩 때우면 다음에 새로 만든 칸이 또 걸린다.
     그래서 **입력 요소 전부**를 한 규칙으로 올린다. 16px은 확대가 멈추는 정확한 경계다.

     ⚠ `#chathl`을 같은 규칙에 넣은 이유: 그건 `#chatinput` 위에 겹쳐 @기업·/스킬만 색칠하는
     투명 미러라 **글자 메트릭이 1px만 달라도 색칠이 밀린다**(`tests/js/test_composer_metrics.mjs`).
     따로 쓰면 언젠가 한쪽만 바뀐다 — 한 줄에 묶어 어긋날 수 없게 한다.
     ⚠ `!important`인 이유: `.pfholdin input`처럼 **클래스가 붙은 셀렉터가 특이도로 이긴다**.
     이건 취향이 아니라 브라우저 동작을 막는 불변식이라 순서·특이도에 맡기지 않는다.
     데스크톱은 이 블록이 안 걸리므로 기존 크기 그대로다. */
  @media (pointer:coarse) and (max-width:900px), (max-width:560px) {
    input, textarea, select, #chathl { font-size:16px !important; }
  }
  input, button, select, textarea { font:inherit; }   /* 폼 요소는 기본 미상속 — 표준 스택 강제 */

  /* ---------- 디자인 철학 공통 유틸 (docs/28 — 골격 제공, 모듈 재정의 금지) ---------- */
  /* [폐기 2026-08-16] 뷰 전환 캐스케이드(pagein) — 섹션이 위에서부터 순차로 떠오르던 효과.
     사용자 확정: "이 부드러움 효과가 더 느려 보이고 쾌적하지 않다. 그냥 페이지가 준비되면
     팍! 한번에 보이자." 실제로 마지막 요소가 자리잡는 데 최대 0.42초가 걸렸고(0.22s 재생 +
     0.2s 지연), 로더가 짧게 끝나는 전환에서는 그 꼬리가 그대로 보였다.
     이제 전환의 리듬은 **로더 → 빈 화면 90ms → 즉시 공개** 하나뿐이다. 재도입 금지. */
  /* 인터랙션 전환은 150ms — 튀지 않게 */
  #sidebar nav a, .vstabs a, .preset, .card, .repcard, .star, .qadd button { transition: background-color .15s ease, border-color .15s ease, color .15s ease; }
  /* 전역 로딩 바: fetch 진행 중 상단 금색 슬라이드 (core.js가 body.loading 토글, 120ms 지연 표시) */
  #loadbar { position:fixed; top:0; left:0; right:0; height:2px; z-index:99; pointer-events:none; opacity:0; transition:opacity .2s ease; overflow:hidden; }
  #loadbar::before { content:""; position:absolute; top:0; bottom:0; width:36%; border-radius:2px;
    background:var(--accent); animation:loadslide 1s ease-in-out infinite; }
  body.loading #loadbar { opacity:1; transition-delay:.12s; }
  @keyframes loadslide { 0% { left:-38%; } 70% { left:102%; } 100% { left:102%; } }
  /* 스켈레톤 로딩 (>300ms 예상 구간 필수): <div class="skel" style="height:__px"> — 내용과 같은 자리·높이로.
     숨쉬는 펄스 + 밝은 스윕, 스택은 행마다 시차(웨이브) */
  .skel { position:relative; overflow:hidden; background:var(--panel2); border-radius:8px; min-height:14px;
    animation: skelpulse 1.6s ease-in-out infinite; }
  .skel::after { content:""; position:absolute; inset:0; transform:translateX(-100%);
    background:linear-gradient(90deg, transparent 15%, rgba(150,170,200,.14) 50%, transparent 85%);
    animation:shimmer 1.1s ease-out infinite; }
  @keyframes shimmer { 100% { transform:translateX(100%); } }
  @keyframes skelpulse { 0%, 100% { opacity:1; } 50% { opacity:.7; } }
  .skel-stack { display:flex; flex-direction:column; gap:8px; }
  .skel-stack .skel:nth-child(2), .skel-stack .skel:nth-child(2)::after { animation-delay:.15s; }
  .skel-stack .skel:nth-child(3), .skel-stack .skel:nth-child(3)::after { animation-delay:.3s; }
  .skel-stack .skel:nth-child(n+4), .skel-stack .skel:nth-child(n+4)::after { animation-delay:.45s; }
  /* 접근성: 모션 최소화 설정 존중 */
  @media (prefers-reduced-motion: reduce) {
    .page:not([hidden]) > *, main, .skel, .skel::after, #loadbar::before { animation:none !important; }
  }
  /* 조용한 고급 디테일 (패스 7): 가는 스크롤바 + 앰버 선택 틴트 — 터미널 질감 */
  ::-webkit-scrollbar { width:12px; height:12px; }
  ::-webkit-scrollbar-track { background:transparent; }
  /* thumb: 잘 보이게 --dim (구 --line은 헤어라인색이라 흰 배경에 거의 안 보였음, 사용자 지시 2026-07-18) */
  ::-webkit-scrollbar-thumb { background:var(--dim); border-radius:6px; border:2px solid var(--bg); min-height:40px; }
  ::-webkit-scrollbar-thumb:hover { background:var(--text); }
  ::selection { background:color-mix(in srgb, var(--accent) 28%, transparent); }
  /* ---------- 브랜드 로더: 캔들 펄스 (배민 라이더식 로딩 모션 — docs/28 모션 ④, 사용자 지시 2026-07-17) ----------
     뷰 전환(showView) 때 core.js가 280ms 지연 후 노출(빠른 전환엔 안 뜸)·데이터 뜨면 숨김. #app 위 오버레이(사이드바는 안 가림). */
  /* 로더는 콘텐츠(메인) 영역만 덮는다 — 좌측 메뉴·AI 우측 드로어는 그대로 (사용자 지시 2026-07-18).
     left=사이드바 폭, right=AI 드로어 폭(--chat-w) 만큼 비운다. */
  #brandload { position:fixed; top:0; left:var(--nav-w); right:0; bottom:0; z-index:90; display:flex; flex-direction:column;
    align-items:center; justify-content:center; gap:20px;
    /* **불투명**하게 덮는다 (사용자 지시 2026-08-13). 반투명이면 뒤에서 조립 중인 화면이 비쳐
       "정신없다" — 로딩 중엔 아무것도 안 보이는 편이 오히려 쾌적하다. */
    background:var(--bg);
    /* 사라질 때 **페이드 없이 즉시**("팍!"). 부드러운 반전은 오히려 느려 보인다 —
       opacity에 transition을 걸지 않는다(폭 전환만 드로어와 맞춰 유지). */
    opacity:0; pointer-events:none; transition:left .18s ease, right .2s ease; }
  #brandload.on { opacity:1; pointer-events:auto; }
  /* 공개 직전 한 박자 — 로더(주가선·문구)만 지우고 불투명 배경은 남긴다 (사용자 지시 2026-08-16).
     이 짧은 정적이 "끝났다"는 신호가 되어, 로더에서 화면으로 곧장 튈 때보다 오히려 빨라 보인다. */
  #brandload.blank .blline, #brandload.blank .blmsg { visibility:hidden; }
  body.chat-open #brandload { left:calc(var(--nav-w) + var(--chat-w, 440px)); }   /* 좌측 AI 드로어 폭만큼 비움 */
  @media (max-width:900px) { #brandload { left:0; right:0; } }     /* 좁은 화면: 사이드바=상단 스트립 → 콘텐츠 전체 */
  /* 라이브 주가선 로더 (사용자 확정 2026-07-18 — 캔들 펄스 대체): 은은한 주가선 + 밝은 신호가 훑고,
     AI 스파클(✦, 주비스 AI 브리핑과 동일 모티프)이 선을 따라 흐른다. 색은 --accent(에메랄드) 유지. */
  #brandload .blline { width:132px; height:48px; overflow:visible; }
  #brandload .blbase { fill:none; stroke:var(--accent); stroke-width:2; stroke-linecap:round; stroke-linejoin:round; opacity:.26; }
  #brandload .blrun { fill:none; stroke:var(--accent); stroke-width:2.4; stroke-linecap:round; stroke-linejoin:round;
    stroke-dasharray:26 210; animation:blrun 1.8s linear infinite; }
  @keyframes blrun { from { stroke-dashoffset:236; } to { stroke-dashoffset:0; } }
  #brandload .blspark { fill:var(--accent); animation:blspark 1.8s ease-in-out infinite; }
  @keyframes blspark { 0%, 100% { opacity:.55; } 50% { opacity:1; } }
  #brandload .blmsg { font-size:13px; color:var(--dim); letter-spacing:.01em; }
  /* 로더 모션은 '동작 줄이기(prefers-reduced-motion)'에서도 유지 — 사용자가 로딩 액션을 명시 요청
     (2026-07-18 "전환 로딩에 액션이 없다"의 원인이 바로 이 억제였음) */
  /* [폐기 2026-08-13] 로더가 걷힐 때 콘텐츠가 순차로 떠오르던 진입 모션(.blreveal).
     사용자 지시: "스무스하게 보여주는 반전 효과가 오히려 쾌적함을 망친다 — 팍! 하고 그냥."
     완성된 화면을 즉시 드러내는 편이 실제로 더 빨라 보인다. 재도입 금지. */
  /* 공개(reveal) 모션도 '동작 줄이기'에서 유지 — "전환에 액션이 있어야 한다"는 사용자 지시 우선 */
  /* 브리핑 헤더 스파크 아이콘(이모지 대체) + 리스크 줄 점 마커 (docs/28) */
  /* 주비스 스파크 = 브랜드 모먼트라 시그니처 에메랄드 (2026-07-22 — 구 보라는 네온처럼 튐, docs/28 잔여항목 ② 해소) */
  /* 주비스 마크 = 심볼 이미지 (2026-08-04, 구 4각 별 SVG 폐기). svg로 남은 곳도 있어 stroke 속성은 유지 */
  .bico { width:15px; height:15px; fill:none; stroke:var(--accent); stroke-width:1.6; stroke-linejoin:round; flex-shrink:0; }
  img.bico { object-fit:contain; }
  .bsec .brisk::before { content:""; display:inline-block; width:6px; height:6px; border-radius:50%; background:var(--up); margin-right:6px; vertical-align:1.5px; }

  /* ---------- 좌측 사이드바 (불리고 벤치마킹) ---------- */
  /* --nav-w: 사이드바 폭 단일 변수 — 드로어(#chatpanel)·탭(#chattab)·로더(#brandload) 오프셋이 공유.
     196→172px 축소 + 챗 드로어 좌측 도킹(메뉴|챗|본문) — 사용자 지시 2026-07-21 (M0-2, docs/46) */
  body { --nav-w:172px; }
  /* 접힘 레일 62→76px (사용자 지시 2026-08-18 "거의 열지 않으니 조금 더 크게") —
     레일이 상시 상태이므로 아이콘이 작으면 매번 식별에 힘이 든다. */
  /* 76→61px (-20%, 사용자 지시 2026-08-18 "가로 너비가 너무 커").
     레일은 아이콘 하나가 지나가는 통로다 — 넓으면 본문을 그만큼 빼앗는다. */
  body.nav-collapsed { --nav-w:61px; }
  /* 폭 전환에 transition 금지 — width가 var(--nav-w)라 트랜지션이 멈춰 펼침이 62px에 갇히는 버그
     (2026-07-22 실측: transition 제거 시 62↔172 정상). 접힘/펼침은 즉시 전환한다. */
  #sidebar { position:relative; width:var(--nav-w); flex-shrink:0; background:var(--panel); border-right:1px solid var(--line); display:flex; flex-direction:column; padding:14px 10px 12px; gap:2px; }
  /* 브랜드 로크업 = 심볼 + 워드마크 (사용자 확정 2026-08-04). 접으면 심볼만 남아 레일에서도 정체성 유지 */
  /* 문패를 누르면 첫 화면(랜딩)으로 — core.js가 role=button을 달아 준다 (2026-08-30) */
  #sidebar .logo { display:flex; align-items:center; gap:9px; font-size:20px; font-weight:800; color:var(--accent); letter-spacing:1.5px; padding:2px 10px 14px; overflow:hidden; cursor:pointer; }
  #sidebar .logo:focus-visible { outline:2px solid var(--accent); outline-offset:2px; border-radius:8px; }
  #sidebar .logo .logomark { width:26px; height:26px; flex-shrink:0; object-fit:contain; display:block; }
  #sidebar .logo .logotext { min-width:0; }
  /* 접기 핸들 — **일부러 작게** (사용자 2026-08-02 "1레이어 모듈 펴기는 잘 쓰지 않게, 나중엔
     없앨 수도"): 뚜렷한 박스 문법은 포트 패널 핸들(#navbtn)에게 넘기고 여긴 가는 탭만 남긴다. */
  .navtoggle { position:absolute; right:-7px; bottom:104px; width:14px; height:32px; z-index:6;
    display:inline-flex; align-items:center; justify-content:center; padding:0;
    background:transparent; border:1px solid var(--line); border-radius:8px;
    color:var(--dim); opacity:.55; cursor:pointer;
    transition:right .18s ease, color .15s ease, opacity .15s ease, border-color .15s ease; }
  .navtoggle:hover { color:var(--text); opacity:1; background:var(--panel2); }
  .navtoggle svg { width:10px; height:10px; fill:none; stroke:currentColor; stroke-width:2; stroke-linecap:round; stroke-linejoin:round; transition:transform .18s ease; }
  #sidebar .logo small { display:block; color:var(--dim); font-weight:400; font-size:var(--fs-lab); letter-spacing:0; margin-top:2px; }
  #sidebar nav { display:flex; flex-direction:column; gap:2px; flex:1; }
  /* 글자 13.5→12.5px (사용자 지시 2026-08-18 "아이콘은 그대로, 글자를 좀 더 작게") —
     아이콘이 주인공이고 라벨은 이름표다. 아이콘 크기(18px)는 건드리지 않는다. */
  #sidebar nav a { display:flex; align-items:center; gap:9px; padding:9px 12px; border-radius:9px; color:var(--dim); text-decoration:none; font-size:12.5px; cursor:pointer; border:1px solid transparent; }
  /* 화면 스위치(plan.js jvApplyHiddenViews)가 `hidden`을 걸었을 때 **실제로 사라지게** 한다.
     `[hidden]{display:none}`은 UA 기본이라 위의 `#sidebar nav a{display:flex}`에 특이도로 진다 —
     속성만 걸고 렌더는 그대로인 상태가 되어, 감췄다고 믿은 메뉴가 화면에 계속 보였다
     (실측 2026-08-23: hidden=true인데 높이 53.6px). 코드가 아니라 렌더를 재야 잡힌다. */
  #sidebar nav a[hidden], #sidebar nav a.jvhide { display:none; }
  #sidebar nav a:hover { color:var(--text); background:var(--panel2); }
  #sidebar nav a.active { color:var(--accent); background:var(--panel2); border-color:var(--line); font-weight:700; }
  #sidebar nav a .ico { width:20px; display:inline-flex; align-items:center; justify-content:center; }
  /* 16→18px(2026-08-12) → **18→16.5px**(사용자 지시 2026-08-18 "조금만 작게").
     라벨을 13.5→12.5px로 줄인 뒤 아이콘만 커 보였다 — 둘의 균형을 다시 맞춘다.
     접힌 레일은 아이콘이 유일한 단서라 따로 키운다(아래 nav-collapsed 규칙, 23px). */
  #sidebar nav a .ico svg { width:16.5px; height:16.5px; fill:none; stroke:currentColor; stroke-width:1.8; stroke-linecap:round; stroke-linejoin:round; }
  /* 포트폴리오 = 파이 두 조각 중 **작은 조각만 청록**으로 (사용자 지시 2026-08-12 — 메뉴의 유일한 색 포인트).
     선은 currentColor 그대로라 활성·비활성 상태를 따라가고, 채움만 시그니처 색이다. */
  #sidebar nav a .ico svg .pfslice { fill:var(--pf-neon); stroke:none; }
  #sidebar nav a .soon { margin-left:auto; font-size:var(--fs-badge); color:var(--dim); border:1px solid var(--line); border-radius:8px; padding:1px 6px; }
  #sidebar .foot { display:flex; flex-direction:column; gap:8px; padding:8px 4px 0; border-top:1px solid var(--line); }
  #sidebar .ver { font-size:var(--fs-lab); color:var(--dim); text-align:center; }
  /* ---------- 접힌 레일 (아이콘만) — 사용자 지시 2026-07-17 ---------- */
  body.nav-collapsed #sidebar { width:var(--nav-w); padding-left:5px; padding-right:5px; }
  body.nav-collapsed #sidebar .logo { justify-content:center; padding:2px 0 14px; gap:0; }
  body.nav-collapsed #sidebar .logo .logotext { display:none; }   /* 접힘: 심볼만 (구: 로고 전체 숨김) */
  body.nav-collapsed #sidebar .sbhead { justify-content:center; }
  body.nav-collapsed .navtoggle svg { transform:rotate(180deg); }   /* 접히면 화살표가 펴기 방향 */
  body.nav-collapsed #sidebar nav a { justify-content:center; gap:0; padding:11px 0; font-size:0; }   /* 라벨 텍스트 숨김(아이콘 svg는 고정 px라 유지) */
  /* 접힘일 때만 아이콘을 키운다 — 펼친 상태는 글자와 균형이 맞아야 하므로 16.5px 유지 */
  body.nav-collapsed #sidebar nav a .ico { width:21px; }
  body.nav-collapsed #sidebar nav a .ico svg { width:20.7px; height:20.7px; }
  body.nav-collapsed #sidebar nav a .soon { display:none; }
  body.nav-collapsed #sidebar .ver { display:none; }

  #app { flex:1; display:flex; flex-direction:column; min-width:0; position:relative; transition:margin-left .2s ease; }
  /* 대화 드로어는 콘텐츠를 가리지 않고 옆으로 민다 (사용자 확정 2026-07-15 — push, not overlay).
     드로어가 좌측(사이드바 옆) 도킹으로 바뀌어 본문은 오른쪽으로 밀린다 (사용자 지시 2026-07-21). */
  body.chat-open #app { margin-left:var(--chat-w, 440px); }   /* 드로어 폭만큼 본문을 민다(=드로어 폭과 동일 변수) */
  @media (max-width:900px) { body.chat-open #app { margin-left:0; } }   /* 좁은 화면은 밀 공간 없음 → 덮기 */

  /* 상단 흐르는 시세 티커 (불리고 벤치마킹) */
  #ticker { height:32px; background:var(--panel); border-bottom:1px solid var(--line); overflow:hidden; position:relative; flex-shrink:0; }
  #ticker .rail { display:flex; gap:56px; position:absolute; white-space:nowrap; align-items:center; height:100%; padding-left:12px; animation:tickmove 50s linear infinite; will-change:transform; }
  /* 읽는 동안 세워 주는 배려 — **마우스가 있는 기기에서만** (머신러너님 지적 2026-08-30
     "전광판이 거의 멈춰 있다. 막 만지면 다시 흐른다").
     폰에는 호버가 없어서 브라우저가 **마지막으로 만진 요소에 `:hover`를 걸어 두고
     다른 곳을 만질 때까지 풀지 않는다.** 전광판은 화면 맨 위 가로 전체를 차지해
     스크롤하다 손가락이 걸리기 쉽고, 한 번 걸리면 계속 서 있었다. 다른 데를 누르면
     그제야 풀려 잠깐 흐른다 — 증상이 정확히 그랬다.
     터치에서 항목을 자세히 보고 싶으면 **탭하면 그 종목으로 간다**(onclick 그대로)이라
     멈춤을 빼도 잃는 기능이 없다. 잠금은 tests/test_css_sanity.py */
  @media (hover:hover) and (pointer:fine) {
    #ticker:hover .rail { animation-play-state:paused; }
  }
  @keyframes tickmove { from { transform:translateX(0); } to { transform:translateX(-50%); } }
  .titem { font-size:12.5px; color:var(--dim); cursor:pointer; flex-shrink:0; }
  .titem b { color:var(--text); margin-right:7px; font-weight:600; }
  .titem.idx b { color:var(--accent); }
  .titem .u { color:var(--up); } .titem .d { color:var(--down); }
  /* 낡은 항목의 기준일 — 값이 언제 것인지 말한다. 조용해야 하므로 한 단계 더 흐리게. */
  .titem .tsold { font-style:normal; font-size:11px; color:var(--dim);
    opacity:.62; margin-left:5px; letter-spacing:-.2px; }

  header { display:flex; align-items:center; gap:16px; padding:10px 18px; background:var(--panel); border-bottom:1px solid var(--line); flex-shrink:0; }
  /* 헤더 [요금제] — **로그인 없이 상품과 가격에 닿는 유일한 입구.**
     `margin-left:auto`로 오른쪽 끝에 붙인다. 검색이 주인공인 헤더라 눈에 띄되
     경쟁하지 않아야 해서, 테두리만 두르고 채우지 않는다(docs/28: 절제). */
  .hdrplan { margin-left:auto; flex:none; padding:6px 13px; border-radius:999px;
             border:1px solid var(--line); background:transparent; cursor:pointer;
             font:inherit; font-size:var(--fs-sub); color:var(--dim); }
  .hdrplan:hover { color:var(--text); border-color:var(--text); }
  /* [U0] 회원 — 사이드바 하단 계정 행 + 프로필 메뉴 (docs/31 · 스펙 B-6, 디자인 철학: 절제) */
  #authbox { position:relative; }
  .acctbtn { display:flex; align-items:center; gap:9px; width:100%; padding:7px 8px; background:var(--panel2); border:1px solid transparent; border-radius:9px; color:var(--text); cursor:pointer; text-align:left; transition:border-color .15s ease; }
  .acctbtn:hover { border-color:var(--line); }
  .acctav { width:26px; height:26px; border-radius:50%; flex-shrink:0; object-fit:cover; }
  .acctav-i { display:flex; align-items:center; justify-content:center; background:color-mix(in srgb, var(--accent) 16%, transparent); color:var(--accent); font-size:var(--fs-lab); font-weight:600; }
  /* 도형 아바타 (2026-08-29) — 원판 안이 곧 그림이라 배경·여백을 벗긴다 */
  .acctav-av { display:block; overflow:hidden; background:none; }
  .acctav-av svg { display:block; width:100%; height:100%; }
  .acctmeta { min-width:0; flex:1; display:flex; flex-direction:column; }
  .acctname { font-size:12.5px; color:var(--text); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .acctsub { font-size:var(--fs-lab); color:var(--dim); }
  .acctchev { color:var(--dim); flex-shrink:0; transition:transform .15s ease; }
  .acctbtn[aria-expanded="true"] .acctchev { transform:rotate(180deg); }

  /* 메뉴 — 위로 열린다(계정이 화면 맨 아래라). 접힌 레일보다 넓으므로 acctClampMenu가 뷰포트 안으로 민다.
     z-index는 앱 최상단(현행 최대 120)보다 위 — 아래로 깔리면 다른 레이어에 가려 잘려 보인다 */
  .acctmenu { position:absolute; bottom:calc(100% + 8px); left:0; width:270px; z-index:200; padding:5px; background:var(--panel); border:1px solid var(--line); border-radius:12px; box-shadow:var(--shadow); }
  .acctmhead { padding:7px 9px 8px; }
  .acctmemail { font-size:14px; color:var(--text); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .acctmnote { font-size:var(--fs-sub); line-height:1.6; color:var(--dim); }
  .acctbadge { display:inline-block; margin-top:6px; font-size:var(--fs-badge); padding:1px 7px; border-radius:5px; background:color-mix(in srgb, var(--accent) 14%, transparent); color:var(--accent); }
  .acctsep { height:1px; background:var(--line); margin:4px 5px; }
  /* 테마 = 라벨 + 2택 한 줄 (사용자 지시 2026-07-29 "너무 커! 작게 해" → "시스템은 없애라") */
  .acctrow { display:flex; align-items:center; gap:8px; padding:5px 9px; }
  .acctlabel { font-size:14px; color:var(--text); flex-shrink:0; }
  .acctseg.acctseg3 { grid-template-columns:repeat(3,1fr); }
  /* 아이콘이 16px로 커졌으니 칸도 함께 넓힌다 — 안 그러면 글리프가 칸 벽에 붙는다 */
  .acctseg.acctseg3 button { display:inline-flex; align-items:center; justify-content:center;
    padding:5px 11px; }
  .acctseg { display:grid; grid-template-columns:repeat(2,1fr); gap:1px; margin-left:auto; padding:2px; background:var(--bg); border-radius:6px; }
  .acctseg button { padding:3px 8px; font-size:var(--fs-sub); line-height:1.35; color:var(--dim); background:transparent; border:0; border-radius:4px; cursor:pointer; white-space:nowrap; }
  .acctseg button:hover { color:var(--text); }
  .acctseg button.on { background:var(--panel2); color:var(--text); }
  .acctitem { display:flex; align-items:center; gap:9px; width:100%; padding:8px 9px; font-size:14px; color:var(--text); background:transparent; border:0; border-radius:7px; cursor:pointer; text-align:left; }
  .acctitem:hover { background:var(--panel2); }
  /* '자세히 알아보기' — 클로드식 **우측 플라이아웃** (사용자 지시 2026-08-26).
     아래로 밀어내면 메뉴가 길어지고 로그아웃이 화면 밖으로 나간다. 옆은 비어 있다.
     기준은 감싸개(.acctmorewrap)이고, 항목의 **위쪽에 맞춰** 편다 — 메뉴가 위로 열리므로
     아래 정렬이면 플라이아웃이 화면 밖으로 내려간다. 꺾쇠는 열림 표시로만 회전한다. */
  .acctmorewrap { position:relative; }
  .acctmore .acctchev { margin-left:auto; color:var(--dim); transition:transform .15s ease; }
  .acctmore[aria-expanded="true"] .acctchev { transform:rotate(90deg); }
  .acctfly { position:absolute; left:calc(100% + 6px); top:-5px; min-width:172px; z-index:210;
    display:flex; flex-direction:column; padding:5px;
    background:var(--panel); border:1px solid var(--line); border-radius:10px;
    box-shadow:var(--shadow); }
  .acctfly[hidden] { display:none; }
  .acctflyitem { display:block; width:100%; padding:7px 10px; text-align:left;
    font-size:13px; color:var(--text); background:transparent; border:0; border-radius:7px;
    cursor:pointer; font-family:inherit; white-space:nowrap; }
  .acctflyitem:hover { background:var(--panel2); }
  .acctitem svg { color:var(--dim); flex-shrink:0; }
  .acctval { margin-left:auto; font-size:var(--fs-sub); color:var(--dim); }
  .acctrow svg { color:var(--dim); flex-shrink:0; }

  /* 약관·가격 안내 — 계정 메뉴에서만 열리는 읽기 전용 창 */
  .acctdocovl { position:fixed; inset:0; z-index:120; display:flex; align-items:center; justify-content:center; padding:24px; background:color-mix(in srgb, #000 38%, transparent); }
  .acctdoc { width:min(560px,100%); max-height:78vh; overflow:auto; padding:16px 18px 18px; background:var(--panel); border:1px solid var(--line); border-radius:12px; box-shadow:var(--shadow); }
  .acctdochead { display:flex; align-items:center; gap:10px; margin-bottom:10px; }
  .acctdochead h3 { flex:1; margin:0; font-size:15.5px; font-weight:700; color:var(--text); }
  .acctdocx { width:24px; height:24px; font-size:16px; line-height:1; color:var(--dim); background:transparent; border:0; border-radius:6px; cursor:pointer; }
  .acctdocx:hover { background:var(--panel2); color:var(--text); }
  /* 약관 모달 본문 — **pre-wrap을 걷었다** (사용자 지적 2026-08-26 "정렬이 엉망").
     그 규칙은 원문 텍스트를 그대로 뿌리던 시절의 잔재인데, 지금은 서버가 HTML로 렌더하므로
     (legal.to_html) 태그 사이의 줄바꿈·들여쓰기가 전부 공백으로 살아나 줄이 어긋났다.
     글자는 캐논 하한(--fs-sub 12.5px)을 지키고, 대신 **간격과 들여쓰기로** 위계를 세운다.
     h 단계는 to_html이 한 단 내려 준다: `##`(장)→h3 · `###`(조)→h4 · `####`(소제목)→h5. */
  .acctdocbody { font-size:var(--fs-sub); line-height:1.7; color:var(--text); word-break:keep-all; }
  .acctdocbody > :first-child { margin-top:0; }
  .acctdocbody h2, .acctdocbody h3 { font-size:13.5px; font-weight:700; color:var(--text);
    margin:16px 0 6px; padding-top:12px; border-top:1px solid var(--line); }
  .acctdocbody h4 { font-size:12.5px; font-weight:700; color:var(--text); margin:12px 0 4px; }
  /* 공문서체 (사용자 확정 2026-08-28): 법무 문서에 박스·색·기교 금지 — 독립 페이지
     (app.py _legal_page_html)와 같은 규칙. 한쪽만 고치면 두 표면이 어긋난다. */
  .acctdocbody h5 { font-size:12.5px; font-weight:600; color:var(--text); margin:10px 0 4px; }
  .acctdocbody p { margin:5px 0; }
  .acctdocbody ul, .acctdocbody ol { margin:5px 0; padding-left:1.5em; }
  .acctdocbody li { margin:3px 0; padding-left:2px; }
  .acctdocbody blockquote { margin:8px 0; padding:0 0 0 10px;
    border-left:2px solid var(--line); }
  .acctdocbody hr { border:0; border-top:1px solid var(--line); margin:14px 0; }
  .acctdocbody a { color:var(--text); text-decoration:underline; }
  /* 표는 좁은 모달에서 **가로로 흐르게** 둔다 — 억지로 줄바꿈하면 숫자 열이 어긋난다 */
  .acctdocbody table { display:block; overflow-x:auto; border-collapse:collapse;
    margin:8px 0; font-size:var(--fs-lab); }
  .acctdocbody th, .acctdocbody td { border:1px solid var(--line); padding:5px 8px;
    text-align:left; vertical-align:top; white-space:nowrap; }
  .acctdocbody th { font-weight:600; }
  .acctdocnote { font-size:var(--fs-sub); line-height:1.7; color:var(--dim); }
  .acctdocver { margin-top:12px; font-size:var(--fs-lab); color:var(--dim); }
  /* 약관 창 하단 — 문서끼리 오가는 줄 + 사업자 정보(전자상거래법 제10조 표시 의무).
     사업자 정보는 읽히기만 하면 되는 정보라 가장 낮은 위계로 둔다 — 본문보다 작고 흐리게. */
  .acctdocnav { display:flex; flex-wrap:wrap; gap:6px; margin-top:14px;
                padding-top:12px; border-top:1px solid var(--line); }
  .acctdocnav button { border:1px solid var(--line); background:transparent; cursor:pointer;
                       border-radius:999px; padding:4px 10px; font-size:var(--fs-lab);
                       color:var(--dim); font-family:inherit; }
  .acctdocnav button:hover { color:var(--text); border-color:var(--text); }
  .acctdocbiz { display:flex; flex-wrap:wrap; gap:2px 12px; margin-top:12px;
                font-size:var(--fs-lab); line-height:1.8; color:var(--dim); }
  /* 공정위 조회 링크 — 나머지 항목과 같은 줄에 섞이되 누를 수 있음이 보여야 한다 */
  .acctdocbiz a { color:var(--dim); text-decoration:underline; text-underline-offset:2px; }
  .acctdocbiz a:hover { color:var(--text); }

  /* 접힌 레일: 아바타만 (이름·꺾쇠 숨김), 메뉴는 레일 밖으로 나가야 하므로 왼쪽 정렬 유지 */
  body.nav-collapsed .acctmeta, body.nav-collapsed .acctchev { display:none; }
  body.nav-collapsed .acctbtn { justify-content:center; padding:7px 4px; }

  /* 로그인 안내 — 중립 톤. --up/--down은 상승·하락 전용이라 여기에 쓰지 않는다 */
  .autherr { font-size:var(--fs-sub); color:var(--dim); border:1px solid var(--line); border-radius:6px; padding:4px 8px; margin-bottom:6px; line-height:1.4; }

  /* ---- 프로필 창 (스펙 B-1~B-3) — 투자자 페르소나 3택 ---- */
  .pfdlg { position:fixed; inset:0; z-index:210; display:flex; align-items:center; justify-content:center; padding:24px; background:rgba(0,0,0,.42); }
  .pfpanel { width:min(640px, 100%); max-height:calc(100vh / var(--zoom, 1) - 48px); overflow:auto; padding:20px 22px 22px; background:var(--panel); border:1px solid var(--line); border-radius:16px; box-shadow:var(--shadow); }
  .pfhead { display:flex; align-items:center; margin-bottom:14px; }
  .pftitle { font-size:var(--fs-sect); color:var(--text); }
  .pfx { margin-left:auto; display:flex; padding:5px; color:var(--dim); background:transparent; border:0; border-radius:7px; cursor:pointer; }
  .pfx:hover { color:var(--text); background:var(--panel2); }
  .pfwho { display:flex; align-items:center; gap:8px; padding:10px 12px; margin-bottom:16px; background:var(--panel2); border-radius:10px; }
  .pfemail { font-size:var(--fs-sub); color:var(--text); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  /* 설정 v2 = 클로드 설정 문법: 좌측 메뉴 / 우측 내용 (사용자 확정 2026-07-26) */
  /* 창 크기는 pane을 바꿔도 고정 — 내용이 길면 좌측 메뉴와 우측 본문이 각자 스크롤한다
     (사용자 지시 2026-07-29 "선택했을 때 창 크기가 바뀌는 게 불편 · 길면 사이드바로 오르락내리락") */
  .pfpanel2 { width:min(780px, 100%); height:min(620px, calc(100vh / var(--zoom, 1) - 48px)); padding:0; overflow:hidden; display:flex; flex-direction:column; }
  .pfpanel2 .pfhead { margin:0; padding:14px 18px 12px; border-bottom:1px solid var(--line); flex:none; }
  .pfbody { display:flex; flex:1; min-height:0; }
  .pfnav { width:158px; flex:none; padding:10px 10px 12px; border-right:1px solid var(--line);
    display:flex; flex-direction:column; gap:1px; overflow-y:auto; }
  .pfnavg { padding:12px 12px 5px; font-size:var(--fs-sub); color:var(--dim); letter-spacing:.02em; }
  .pfnavg:first-child { padding-top:4px; }
  .pfnavi { padding:8px 12px; border-radius:8px; font-size:var(--fs-th); color:var(--text); cursor:pointer; }
  .pfnavi:hover { background:var(--panel2); }
  .pfnavi.on { background:var(--panel2); font-weight:700; }
  .pfpane { flex:1; min-width:0; overflow-y:auto; padding:18px 20px 20px; }
  /* 에이전트 3 pane = '에이전트' 창을 그대로 품는다 (2026-08-29) — 카드 2열 그리드가 들어오므로
     780px 창은 좁다. 그 pane에서만 창을 넓히고 패딩을 걷는다(안쪽 문서가 자기 여백을 갖는다). */
  .pfpanel2.pfwide { width:min(1040px, 100%); height:min(724px, calc(100vh / var(--zoom, 1) - 48px)); }
  /* 에이전트 3 pane은 **바닥이 회색**이다 (사용자 지시 2026-08-29 "회색으로 칠해서").
     안쪽 iframe이 배경을 투명으로 두므로 여기 한 줄이 창 가장자리까지 바닥을 깐다 —
     패딩 띠까지 같은 색이라야 "칠해진 영역"이 사각형으로 떨어진다. 다른 pane(일반·계정·
     스타일…)은 그대로 흰 바닥이다: 거기는 카드가 아니라 설정 '줄'이라 바닥을 깔 것이 없다. */
  .pfpane.pfembed { padding:14px 12px 10px 14px; overflow:hidden; background:var(--canvas); }
  .pfagwrap { height:100%; }
  #pfagframe { display:block; width:100%; height:100%; border:0; background:transparent; }
  .pfrow { display:flex; gap:14px; align-items:baseline; font-size:12.5px; padding:7px 0; }
  .pfrow > span:first-child { width:72px; flex:none; color:var(--dim); }
  /* 특징 필드 — 라벨 + 입력(회색 예시). 예시가 빈 칸 공포를 없앤다 */
  .pftrait { display:flex; align-items:center; gap:10px; margin-bottom:8px; }
  .pftrait label { width:80px; flex:none; font-size:var(--fs-sub); color:var(--dim); }
  .pftrait input { flex:1; min-width:0; background:var(--panel2); border:1px solid var(--line);
    border-radius:9px; padding:8px 11px; font:inherit; font-size:12.5px; color:var(--text); outline:none; }
  .pftrait input:focus { border-color:var(--accent); }
  .pftrait input::placeholder { color:var(--dim); opacity:.7; }
  /* 에이전트 pane 3종 목록 행 — 커넥터/스킬/플러그인 (2026-07-29) */
  .pfitem { display:flex; align-items:center; gap:12px; padding:9px 2px;
    border-bottom:1px solid var(--line); }
  .pfitem:last-child { border-bottom:0; }
  .pfitem-main { flex:1; min-width:0; display:flex; align-items:baseline; gap:8px; }
  .pfiname { font-size:var(--fs-th); font-weight:600; color:var(--text); white-space:nowrap; }
  .pfiname.pfmono { font-family:ui-monospace, Consolas, monospace; font-weight:700; }
  .pfisub { flex:1; min-width:0; font-size:var(--fs-sub); color:var(--dim);
    overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .pftag { flex:none; font-size:var(--fs-badge); color:var(--dim); border:1px solid var(--line);
    border-radius:999px; padding:1px 7px; white-space:nowrap; }
  .pfontag { flex:none; font-size:var(--fs-lab); color:var(--dim); }
  .pfbtn.pfbtn2 { padding:4px 11px; font-size:var(--fs-sub); }
  .pfitem .agsw { flex:none; cursor:pointer; }
  .pfsec { margin-bottom:12px; }
  .pfq { font-size:15.5px; font-weight:700; color:var(--text); }
  .pfhint { margin-top:4px; font-size:var(--fs-body); color:var(--dim); line-height:1.5; }
  /* 답변 길이 3택 — 페르소나 카드(.pfcards)와 달리 설명이 필요 없는 한 축이라 세그먼트로.
     .acctseg와 같은 문법이되 폭을 다 쓴다(설정 본문은 우측 넓은 판이라 오른쪽 정렬이 뜬다) */
  .pfseg { display:grid; grid-template-columns:repeat(3,1fr); gap:2px; padding:3px;
    background:var(--bg); border-radius:9px; }
  /* 안 고른 쪽 글자는 --dim만으로는 라이트에서 4.2:1이라 AA(4.5)에 못 미친다(실측
     2026-08-18). 셋 다 실제로 고를 수 있는 선택지라, 흐리게 두는 것이 목적이 아니다. */
  .pfseg button { padding:7px 10px; font:inherit; font-size:var(--fs-sub);
    color:color-mix(in srgb, var(--dim) 55%, var(--text));
    background:transparent; border:0; border-radius:7px; cursor:pointer;
    transition:color .15s ease, background-color .15s ease; }
  .pfseg button:hover { color:var(--text); }
  .pfseg button.on { background:var(--panel2); color:var(--text); font-weight:600; }
  .pfcards { display:grid; grid-template-columns:repeat(3, minmax(0,1fr)); gap:10px; }
  .pfcard { display:flex; flex-direction:column; padding:14px 12px 13px; background:var(--panel2); border:1px solid transparent; border-radius:12px; color:var(--dim); cursor:pointer; text-align:left; transition:border-color .15s ease; }
  .pfcard:hover { border-color:var(--line); }
  .pfcard.on { border-color:var(--accent); }
  /* 인물 그림이 들어오면 SVG 위를 덮고, 없으면 JS가 img를 지워 SVG가 그대로 남는다 */
  /* 그림은 정사각형으로 크게, 그 아래 이름·역할·한 줄 설명 (사용자 지시 2026-07-29) */
  /* 그림 3종은 scripts/make_persona_duotone.py 로 투명 배경 + 단색(#757982) 선화로 변환돼 있다.
     카드 배경이 그대로 비치므로 액자·감광 처리가 필요 없다(다크 전용 이미지도 불필요). */
  /* 바탕색은 **로드 중 빈 사각형을 위한 것**이다 (2026-08-23). 사진을 마크업에 바로
     심는 방식으로 바꾸면서(선그림 번쩍임 제거) 사진이 늦게 오는 찰나가 생겼는데,
     그때 카드가 뚫린 것처럼 보이지 않게 한다. aspect-ratio가 높이를 이미 잡아 둬서
     사진이 들어와도 자리가 흔들리지 않는다. */
  .pfartwrap { position:relative; display:block; width:100%; aspect-ratio:1/1; margin-bottom:11px; border-radius:9px; overflow:hidden; background:var(--panel2); }
  .pfart { position:absolute; inset:0; width:100%; height:100%; color:var(--text); }
  .pfphoto { position:absolute; inset:0; width:100%; height:100%; object-fit:cover; }
  .pfname { font-size:13px; color:var(--text); }
  /* .pftag는 에이전트 목록 배지(테두리 있음)와 이름이 겹쳐 상자가 생겼다 — 카드 전용 클래스로 분리 */
  .pfrole { margin-top:3px; font-size:var(--fs-lab); color:var(--accent); }
  .pfdesc { margin-top:7px; font-size:var(--fs-lab); color:var(--dim); line-height:1.5; }
  .pfsave { margin-top:12px; font-size:var(--fs-sub); color:var(--dim); }
  .pfsave.bad { color:var(--up); }
  /* 투자 스타일 판의 맨 아래 알림 — **자리를 미리 비워 둔다** (사용자 지시 2026-08-23).
     `hidden`으로 감춰 두면 문구가 뜨는 순간 판이 길어져서, 맨 아래까지 스크롤한 사람은
     [확인]을 누르고 **한 번 더 내려야** 문구를 본다. 높이를 먼저 잡아 두면 글자만 채워지므로
     누르는 즉시 그 자리에 나타난다. 두 줄까지 늘어나도 흔들리지 않게 min-height로 잡는다.
     (판 전체가 아니라 이 한 자리만 가운데 정렬 — 위쪽 설정 줄들은 좌측 정렬 그대로다.) */
  .pfsavefoot { display:flex; align-items:center; justify-content:center; text-align:center;
                min-height:2.6em; margin-top:16px; padding-bottom:4px; }

  /* AI 제공자 pane (오너 전용, docs/56 §6) — 4개가 항상 서 있고 키 없는 것은 '대기 중'.
     .pfitem은 한 줄 flex라 여기서는 블록으로 되돌린다(입력칸이 아래로 내려가야 한다). */
  .pfllm { display:block; padding:12px 2px; }
  .pfllmhead { display:flex; align-items:center; gap:8px; font-size:12.5px; color:var(--text); }
  .pfllmst { font-size:var(--fs-lab); border:1px solid var(--line); border-radius:999px;
    padding:1px 8px; color:var(--dim); }
  .pfllmst.ok { color:#38b28c; border-color:#38b28c55; }
  .pfllmst.bad { color:var(--up); border-color:color-mix(in srgb, var(--up) 40%, transparent); }
  .pfllmst.warn { color:var(--accent); border-color:color-mix(in srgb, var(--accent) 40%, transparent); }
  .pfllmuse { font-size:var(--fs-lab); color:var(--accent); }
  .pfllmact { font-size:var(--fs-lab); color:var(--dim); background:none; border:1px solid var(--line);
    border-radius:999px; padding:1px 8px; cursor:pointer; font-family:inherit; }
  .pfllmact:hover { color:var(--accent); border-color:var(--accent); }
  .pfllmrow { display:flex; gap:6px; margin-top:8px; align-items:center; }
  .pfllmrow .pfin { flex:1; min-width:0; background:var(--panel2); border:1px solid var(--line);
    border-radius:9px; padding:7px 11px; font:inherit; font-size:12.5px; color:var(--text); outline:none; }
  .pfllmrow .pfin:focus { border-color:var(--accent); }
  .pfllmrow .pfin::placeholder { color:var(--dim); opacity:.7; }
  .pfllmrow .pfbtn { flex:none; }
  .pfllmrow .pfbtn[disabled] { opacity:.4; cursor:default; }

  /* 나의 투자 스타일 — 말머리 칩 + 자유 서술 (설정 창 두 번째 단) */
  .pfsec2 { margin-top:22px; padding-top:18px; border-top:1px solid var(--line); }
  /* 두 번째 단인데 **줄은 긋지 않는 경우** (사용자 지시 2026-08-19 '일반' 탭).
     설정 행은 저마다 아래 선을 갖고 있어, 여기에 또 선을 그으면 선이 두 겹으로 겹친다.
     묶음을 가르는 건 선이 아니라 여백이면 충분하다. */
  .pfsec3 { margin-top:26px; }   /* 선을 뺀 만큼 여백이 구획을 가른다 (2026-08-29) */
  /* 회원 탈퇴 — 위험 구역 (사용자 지시 2026-08-26 "조금 어렵게").
     빨간 상자를 처음부터 펼쳐 두지 않는다. 설정을 열 때마다 경고문이 보이면 경고는
     배경이 되고, 정작 누를 때는 아무도 안 읽는다. 접힌 링크 하나로 두고, **편 사람에게만**
     붉은 테두리를 보여 준다. 색은 `--up`(상승 빨강)을 그대로 쓴다 — 경고색을 새로 만들면
     팔레트가 늘고 다크·라이트 대비를 따로 검증해야 한다. */
  /* 계정 탭의 **맨 아래** (사용자 지시 2026-08-29 "약간은 숨기고 싶어") — 위 목록과
     한 덩어리로 보이지 않게 여백을 넉넉히 띄운다. 자리 자체가 마찰의 한 단이다. */
  .pfdanger { margin-top:30px; }
  .pfdangeropen { padding:6px 0; font:inherit; font-size:var(--fs-body); color:var(--dim);
    background:transparent; border:0; cursor:pointer; text-decoration:underline;
    text-underline-offset:3px;
    text-decoration-color:color-mix(in srgb, var(--dim) 45%, transparent); }
  .pfdangeropen:hover { color:var(--up); }
  .pfdangerbox { margin-top:8px; padding:16px 18px; border-radius:12px;
    border:1px solid color-mix(in srgb, var(--up) 38%, var(--line));
    background:color-mix(in srgb, var(--up) 5%, transparent); }
  .pfdangerlead { margin:0; font-size:var(--fs-body); line-height:1.65; color:var(--text); }
  .pfdangerlist { margin:10px 0 0; padding-left:18px; font-size:var(--fs-sub);
    line-height:1.8; color:var(--dim); }
  .pfdangerask { margin:14px 0 0; font-size:var(--fs-body); line-height:1.65; color:var(--text); }
  .pfdangerrow { display:flex; gap:8px; margin-top:10px; }
  .pfdangerin { flex:1; }
  .pfdangergo { flex:none; padding:9px 18px; font:inherit; font-size:13.5px; font-weight:600;
    color:#fff; background:var(--up); border:1px solid var(--up); border-radius:10px;
    cursor:pointer; }
  .pfdangergo:disabled { opacity:.4; cursor:default; }
  .pfdangercancel { display:block; margin:12px auto 0; padding:4px 8px; font:inherit;
    font-size:var(--fs-sub); color:var(--dim); background:transparent; border:0; cursor:pointer; }
  .pfdangercancel:hover { color:var(--text); }
  .pfchips { display:flex; flex-wrap:wrap; gap:6px; margin-bottom:9px; }
  .pfchip { padding:4px 10px; font-size:var(--fs-lab); color:var(--dim); background:var(--panel2);
            border:1px solid transparent; border-radius:999px; cursor:pointer; white-space:nowrap; }
  .pfchip:hover { color:var(--accent); border-color:var(--accent); }
  .pfnote { display:block; width:100%; padding:11px 12px; font:inherit; font-size:12.5px;
            line-height:1.7; color:var(--text); background:var(--panel2); border:1px solid var(--line);
            border-radius:10px; resize:vertical; }
  .pfnote:focus { outline:none; border-color:var(--accent); }
  .pfnote::placeholder { color:var(--dim); }
  .pffoot { display:flex; align-items:center; gap:10px; margin-top:9px; }
  /* .pfnotecount(글자 수)는 없앴다 (사용자 지시 2026-08-23) — 세는 대신 maxlength로 막는다.
     숫자를 매 타이핑마다 다시 그리느라 화면이 눌렸다(profile.js settingsNoteCapInput 참고). */
  .pfbtn { margin-left:auto; padding:6px 16px; font-size:var(--fs-sub); color:var(--bg);
           background:var(--accent); border:0; border-radius:8px; cursor:pointer; }
  .pfbtn:hover { filter:brightness(1.08); }
  /* [확인] (2026-08-23) — **자동 저장을 대신하는 버튼이 아니다.** 저장은 이미 저절로 되고,
     이 버튼은 "다 됐다"를 확인받는 자리다. 조용한 저장은 안전하지만 쓰는 사람은 남았는지
     알 길이 없다 — 그 불안 하나를 없앤다.
     알림을 두 겹으로 준다: 버튼 자신이 1.8초간 바뀌고, 아래 줄에 문장이 남는다.
     눈이 버튼에 있든 글에 있든 하나는 본다. */
  #pfnoteok { display:inline-flex; align-items:center; gap:5px; }
  #pfnoteok.ok { cursor:default; animation:pfokpop .3s ease; }
  #pfnoteok[disabled] { cursor:default; }
  @keyframes pfokpop { 0% { transform:scale(.94); } 60% { transform:scale(1.04); }
                       100% { transform:scale(1); } }
  @media (prefers-reduced-motion:reduce) { #pfnoteok.ok { animation:none; } }

  /* 로그인 창 — 소셜 전용(2026-07-29). 입력란이 없다: 비밀번호를 받지 않으므로.
     각 버튼은 프로바이더 고유색을 쓴다(사용자가 눈으로 먼저 알아본다) — 인라인 style로 주입 */
  /* 로그인 창 — 중앙 정렬·큰 제목·알약형 중립 버튼 (사용자 확정 2026-08-06, ChatGPT 시안).
     버튼을 브랜드 색으로 칠하지 않는 이유: 흰·노랑·초록이 나란히 서면 요란하고,
     라이트 모드에선 흰 버튼이 흰 패널에 묻힌다. 식별은 로고가 맡는다. */
  /* 폭 480px (사용자 지시 2026-08-26 "너무 좁아 보여") — 2단계 흐름이 생겨 내용도 늘었다 */
  .lgpanel { position:relative; width:min(480px, 100%); padding:34px 34px 30px; text-align:center; }
  .lgx { position:absolute; top:14px; right:14px; margin:0; }
  .lgtitle { margin:0 0 10px; font-size:23px; font-weight:600; line-height:1.35; color:var(--text); }
  .lgintro { margin:0 0 24px; font-size:13px; line-height:1.65; color:var(--dim); }
  .lgbody { display:flex; flex-direction:column; gap:10px; }
  /* 초대 코드 — **회원가입 얼굴에서만** 뜬다 (문 분리 2026-08-29 4차).
     로그인 얼굴에는 아예 없다: 재로그인하는 회원에게 체험단 안내는 소음이다. */
  .lginv { margin:0 0 20px; text-align:left; }
  .lginv2 { margin:22px 0 0; }
  /* 회원가입·가입 마무리 얼굴은 코드 칸이 **맨 위**다 (문 분리 2026-08-29 4차) */
  .lginvtop { margin:0 0 16px; }
  .lginvlab { display:block; margin:0 0 6px; font-size:var(--fs-lab); color:var(--dim); }
  /* 체험단 환영 머리 — 마스코트(팻) + 두 줄 환영 문구 (사용자 지시 2026-08-29).
     팻은 픽셀아트라 보간되면 뭉개진다 — pixelated 필수 (.gpet과 같은 규칙).
     **소셜 버튼의 로고와 한 줄**: 크기 18px(로고와 동일), 왼쪽 들여쓰기 19px
     (버튼 테두리 1px + 안 여백 18px = 로고의 시작선), 간격 10px(.lgsocial gap과 동일). */
  .lginvhead { display:flex; align-items:center; gap:10px; margin:0 0 9px; padding-left:19px; }
  .lginvpet { width:18px; height:auto; flex:none; image-rendering:pixelated; }
  .lginvhead .lginvlab { margin:0; font-size:13.5px; font-weight:600; color:var(--text);
    line-height:1.55; }
  .lginvin { width:100%; box-sizing:border-box; padding:10px 14px; font:inherit;
             font-size:13.5px; letter-spacing:.08em; text-transform:uppercase;
             color:var(--text); background:var(--panel2); border:1px solid var(--line);
             border-radius:10px; transition:border-color .15s ease; }
  .lginvin:focus { outline:none; border-color:var(--accent); }
  .lginvin::placeholder { letter-spacing:normal; text-transform:none; color:var(--dim); }
  .lginverr { margin:8px 0 0; font-size:var(--fs-sub); color:var(--up); }
  /* 이메일 마무리 칸 (2026-08-30) — 코드 칸과 같은 부품이되 대문자·자간은 벗는다.
     이메일은 대문자로 보일 이유가 없고, 자간을 벌리면 주소가 문자열로 안 읽힌다. */
  .lgmailin { text-transform:none; letter-spacing:normal; }
  .lgmailwhy { margin:10px 0 0; font-size:var(--fs-sub); color:var(--dim); text-align:center; }
  /* 체험단 안내 상태(wantCode) — 칸 오류가 아니라 이 창에 온 **이유**라 한 급 크게,
     창의 중심축에 맞춰 가운데 (사용자 지시 2026-08-29). 칸 오류로 되돌 때 클래스도 벗는다. */
  .lginverr.lgnotice { font-size:13.5px; text-align:center; }
  /* 코드 입력 + [사용] 한 줄 — 확인돼야 계정 버튼이 열린다 (문 분리 2026-08-29 4차) */
  .lginvrow { display:flex; gap:8px; }
  .lginvrow .lginvin { flex:1; }
  /* [사용]은 중립으로 — 진한 액센트 채움은 이 창에서 제일 큰 소리가 돼 버린다
     (사용자 지시 2026-08-29 "너무 찐해"). 주 동선은 어디까지나 소셜 버튼이다. */
  .lginvgo { flex:none; padding:10px 18px; font:inherit; font-size:13.5px; font-weight:600;
    color:var(--dim); background:transparent; border:1px solid var(--line); border-radius:10px;
    cursor:pointer; transition:color .15s ease, border-color .15s ease; }
  .lginvgo:hover { color:var(--accent); border-color:var(--accent); }
  .lginvgo:disabled { opacity:.55; cursor:progress; }
  /* 가입 화면의 확인 칩 — 어떤 코드로 가입하는지 보이고, 수정으로 첫 화면 복귀 */
  .lgcodechip { display:flex; align-items:center; justify-content:center; gap:7px;
    margin:0 0 14px; padding:7px 12px; font-size:var(--fs-sub); color:var(--text);
    border:1px solid color-mix(in srgb, var(--accent) 32%, var(--line)); border-radius:9px;
    background:color-mix(in srgb, var(--accent) 7%, transparent); }
  .lgcodechip code { font-size:13px; letter-spacing:.08em; color:var(--accent); font-weight:700; }
  .lgcodechip button { padding:1px 7px; font:inherit; font-size:var(--fs-lab); color:var(--dim);
    background:transparent; border:1px solid var(--line); border-radius:6px; cursor:pointer; }
  .lgcodechip button:hover { color:var(--accent); border-color:var(--accent); }
  /* [폐지 2026-08-29 5차] .lgswap(얼굴 전환 링크)·.lglead.lgwait(잠김 머리글)·
     .lgsocial.hold(코드 확인 전 잠금) — 문을 하나로 되돌리면서 함께 사라졌다.
     코드가 관문이 아니라 Pro 열쇠가 되어 잠글 대상이 없다. 필요하면 git 이력에서. */
  /* 소셜 버튼 3개의 머리칸 — 여기서 끝난다는 신호. 위의 안내가 전부 흐린 회색이라
     버튼 앞에 **진한 볼드** 한 줄이 서야 시선이 조건 읽기에서 행동으로 넘어간다. */
  /* 좌측 정렬 + 한 단 위 (사용자 지시 2026-08-26) — 버튼 무리의 머리글이니 왼쪽에서 시작한다 */
  .lglead { margin:0 0 12px; font-size:15.5px; font-weight:700; color:var(--text);
    text-align:left; }
  .lgsocial { display:flex; align-items:center; gap:10px; padding:12px 18px;
              font:inherit; font-size:13.5px; font-weight:500; color:var(--text);
              background:transparent; border:1px solid var(--line); border-radius:999px;
              cursor:pointer; transition:background .15s ease, border-color .15s ease; }
  .lgsocial:hover:not(.off) { background:var(--panel2); border-color:var(--line-strong, var(--dim)); }
  .lgmark { display:flex; flex:none; }
  .lgtxt { flex:1; text-align:center; }
  /* 로고 폭(18px)+간격만큼 오른쪽을 비워 글자가 버튼 정중앙에 오게 한다 */
  .lgsocial:not(:has(.lgsoon)) .lgtxt { margin-right:28px; }
  .lgsoon { flex:none; font-size:var(--fs-lab); font-weight:400; color:var(--dim); }
  .lgsocial.off { cursor:default; opacity:.5; }
  .lgsocial.off .lgmark { filter:saturate(.2); }
  @media (max-width: 620px) { .pfcards { grid-template-columns:1fr; } }
  button.ghost { display:inline-flex; align-items:center; gap:6px; background:transparent; border:1px solid var(--line); color:var(--dim); border-radius:9px; padding:5px 12px; font-size:12.5px; cursor:pointer; transition:color .15s ease, border-color .15s ease; }
  button.ghost:hover { color:var(--text); border-color:var(--accent); }

  .page { flex:1; overflow-y:auto; padding:16px; }
  .page h2 { font-size:17px; margin-bottom:12px; }
  /* 모듈 대제목 전체 문법(가운데·헤어라인·여백)의 정본은 portfolio.css 한 곳
     (`#view-portfolio > h2` 공유 규칙, 2026-08-21로 전 모듈 확장) — 여기 있던 "크기만 키운"
     파일럿 규칙은 그리로 흡수했다. 이 .page h2는 아직 그 대제목 문법을 안 받은 화면(관심종목·
     데이터 상태 등)의 수수한 기본값으로만 남는다. */
  /* 주식 궤적: 차트가 남은 세로 공간만 채워 항상 한 화면에 (컨트롤이 몇 줄 접히든 무관 — 고정 calc 높이 대체) */
  #view-map:not([hidden]) { display:flex; flex-direction:column; }
  /* 궤적 phase 토글 (주식↔업종, docs/39) — 또렷한 세그먼트 컨트롤 (활성=에메랄드 필) */
  .cmphase { display:inline-flex; gap:2px; padding:3px; margin-right:10px;
    background:var(--panel2); border:1px solid var(--line); border-radius:11px; }
  .cmphase button { border:0; background:transparent; color:var(--dim); font:inherit;
    font-size:13px; font-weight:700; padding:5px 16px; border-radius:8px; cursor:pointer;
    transition:background .15s ease, color .15s ease; }
  /* 종목 vs 종목의 두 탭은 **같은 폭** (사용자 지시 2026-08-19) — '종목 비교'(5자)와
     '종목 스크리닝'(7자)은 글자 수가 달라, 폭을 안 맞추면 전환할 때마다 버튼이 움직인다. */
  #view-compare .vstabs .cmphase button, #view-screen .vstabs .cmphase button {
    min-width:132px; text-align:center; }
  .cmphase button:hover { color:var(--text); }
  .cmphase button.on { background:var(--accent); color:var(--bg); }
  /* 업종 선택 체크 칩 (기본=Σ시총 TOP10, 체크로 추가/제거) */
  .cmind .cmick { width:11px; height:11px; margin-right:5px; opacity:0; transition:opacity .12s ease; }
  .cmind.on .cmick { opacity:1; }
  /* 필터 행 */
  .cmfilt { display:flex; gap:8px; flex-wrap:wrap; align-items:center; margin-bottom:6px; }
  /* 시총 규모 = 체크박스 다중선택 드롭다운 (jvsel 버튼·패널 재사용 + 네모 체크박스, 사용자 확정 2026-07-18) */
  .jvchk-hd { font-size:var(--fs-lab); color:var(--dim); font-weight:700; padding:4px 10px 6px; letter-spacing:.03em; }
  .jvchk-hd span { font-weight:400; opacity:.7; }
  .jvchk-item { display:flex; align-items:center; gap:9px; width:100%; background:transparent; border:0;
    color:var(--text); text-align:left; font:inherit; font-size:13px; padding:8px 10px; border-radius:8px; cursor:pointer; }
  .jvchk-item:hover { background:var(--panel2); }
  .jvchk-box { width:15px; height:15px; border:1.6px solid var(--line); border-radius:4px; flex-shrink:0;
    display:inline-flex; align-items:center; justify-content:center; color:var(--bg);
    transition:background .12s ease, border-color .12s ease; }
  .jvchk-item.on .jvchk-box { background:var(--accent); border-color:var(--accent); }
  .jvchk-item:hover .jvchk-box { border-color:var(--accent); }
  .jvchk-ck { width:11px; height:11px; opacity:0; transition:opacity .1s ease; }
  .jvchk-item.on .jvchk-ck { opacity:1; }
  .jvchk-lb { display:flex; align-items:baseline; gap:7px; }
  .jvchk-rng { color:var(--dim); font-size:var(--fs-lab); }
  /* 궤적 상단 1행 2열: 좌=종목 선택 · 우=필터+후보 추천 (사용자 확정 2026-07-18) */
  #comettop { display:grid; grid-template-columns:3fr 5fr; gap:10px; margin-bottom:6px; align-items:stretch; }
  @media (max-width:1100px) { #comettop { grid-template-columns:1fr; } }
  .cmpanel { background:var(--panel); border:1px solid var(--line); border-radius:12px; padding:8px 10px; }
  .cmpanel-h { display:flex; align-items:center; gap:8px; font-size:var(--fs-sub); font-weight:700;
    color:var(--dim); letter-spacing:.03em; margin-bottom:6px; }
  .cmpanel-h .n { color:var(--accent); }
  .cmpanel-h .hint { font-weight:400; opacity:.8; }
  .cmrow { display:flex; gap:6px; flex-wrap:wrap; align-items:center; }
  .cmfoot { font-size:var(--fs-sub); color:var(--dim); opacity:.75; margin-top:8px; }
  /* 선택 종목 칩 — 궤적(1행2열)에선 더 작게 (사용자 확정 2026-07-18). S3 비교의 .cmpchip은 무변경 */
  #cometsel .cmpchip { padding:3px 9px; font-size:var(--fs-sub); border-radius:13px; gap:5px; }
  #cometsel .cmpchip .x { font-size:var(--fs-sub); }
  /* 미니 세그먼트 (시장 필터 등) — cmphase의 컴팩트판 */
  .cmseg { display:inline-flex; gap:2px; padding:2px; background:var(--panel2);
    border:1px solid var(--line); border-radius:9px; }
  .cmseg button { border:0; background:transparent; color:var(--dim); font:inherit; font-size:var(--fs-sub);
    font-weight:600; padding:4px 11px; border-radius:7px; cursor:pointer;
    transition:background .12s ease, color .12s ease; }
  .cmseg button:hover { color:var(--text); }
  .cmseg button.on { background:var(--accent); color:var(--bg); }

  /* 커스텀 드롭다운 (jvsel) — 브라우저 기본 select 대체, 모던 럭셔리(에메랄드 액센트·소프트 섀도·SVG) */
  .jvsel-wrap { position:relative; display:inline-flex; flex-direction:column; gap:3px; }
  .jvsel-wrap > .jvsel-lb { font-size:var(--fs-lab); color:var(--dim); letter-spacing:.02em; }
  .jvsel { display:inline-flex; align-items:center; justify-content:space-between; gap:10px;
    min-width:120px; background:var(--panel2); color:var(--text); border:1px solid var(--line);
    border-radius:9px; padding:7px 11px; font-size:13px; cursor:pointer;
    transition:border-color .15s ease, box-shadow .15s ease; }
  .jvsel:hover { border-color:var(--accent); }
  .jvsel[aria-expanded="true"] { border-color:var(--accent); box-shadow:0 0 0 3px rgba(52,211,153,.18); }
  .jvsel-cur { font-weight:600; white-space:nowrap; }
  .jvsel-chev { width:12px; height:12px; color:var(--dim); flex-shrink:0; transition:transform .18s ease; }
  .jvsel[aria-expanded="true"] .jvsel-chev { transform:rotate(180deg); }
  .jvsel-panel { position:absolute; top:calc(100% + 6px); left:0; z-index:60;
    min-width:210px; max-height:min(58vh,380px); overflow-y:auto;
    background:var(--panel); border:1px solid var(--line); border-radius:13px;
    box-shadow:var(--shadow); padding:6px; animation:jvpop .14s ease-out; }
  @keyframes jvpop { from { opacity:0; transform:translateY(-4px); } to { opacity:1; transform:none; } }
  .jvsel-gl { font-size:var(--fs-lab); color:var(--dim); font-weight:700; padding:9px 10px 4px; letter-spacing:.04em; }
  .jvsel-gl:first-child { padding-top:4px; }
  .jvsel-item { display:flex; align-items:center; justify-content:space-between; gap:12px; width:100%;
    background:transparent; border:0; color:var(--text); text-align:left; font:inherit; font-size:13px;
    padding:8px 10px; border-radius:8px; cursor:pointer; transition:background .12s ease; }
  .jvsel-item:hover { background:var(--panel2); }
  .jvsel-item.on { color:var(--accent); font-weight:600; }
  .jvsel-ck { width:14px; height:14px; flex-shrink:0; opacity:0; }
  .jvsel-item.on .jvsel-ck { opacity:1; }
  .todo-box { background:var(--panel); border:1px dashed var(--line); border-radius:12px; padding:28px; color:var(--dim); text-align:center; margin-top:10vh; }
  .todo-box b { color:var(--text); display:block; font-size:16px; margin-bottom:8px; }
  #statusgrid { display:grid; grid-template-columns:repeat(auto-fill,minmax(170px,1fr)); gap:8px; margin-bottom:14px; }
  .stbl { width:100%; border-collapse:collapse; background:var(--panel); border:1px solid var(--line); border-radius:10px; overflow:hidden; font-size:12.5px; }
  .stbl th, .stbl td { padding:7px 10px; border-bottom:1px solid var(--line); text-align:left; }
  .stbl th { color:var(--dim); font-weight:600; background:var(--panel2); }
  .stbl .ok { color:#38b28c; } .stbl .bad { color:var(--up); } .stbl .part { color:var(--accent); }
  /* 카드·섹션 대표 제목 = 전 화면 공통 캐논 (사용자 확정 2026-08-06 "크게·검정, 다른 페이지도 같은 규칙")
     — 화면마다 13px dim으로 흩어져 있던 제목을 하나로. 새 화면도 이 규칙을 그대로 쓴다. */
  /* 종목 화면(M2)은 `.page`가 아니라 `<main>` 아래에 산다 — 캐논이 닿지 않으면 브라우저 기본값
     1.17em(=16.38px)으로 떨어져 화면끼리 또 어긋난다 (실측 2026-08-06). 여백은 화면 사정이라
     `.page`에만 두고, 서체 규칙만 둘 다에 적용한다. */
  .page h3, main h3 { font-size:15.5px; font-weight:700; color:var(--text); letter-spacing:-.01em; }
  .page h3 { margin:18px 0 8px; }

  /* 홈 — 대표 10 바로가기 (docs/11 M1-C: 대시보드·뉴스·장식 금지) */
  .repgrid { display:grid; grid-template-columns:repeat(auto-fill,minmax(200px,1fr)); gap:10px; }
  .repcard { background:var(--panel); border:1px solid var(--line); border-radius:10px; padding:12px 14px; cursor:pointer; }
  .repcard:hover { border-color:var(--accent); }
  .repcard .nm { font-weight:700; }
  .repcard .cd { color:var(--dim); font-size:var(--fs-lab); margin-left:6px; }
  .repcard .px { font-size:15px; margin-top:4px; font-variant-numeric:tabular-nums; font-weight:600; }
  .repcard .sub { font-size:var(--fs-sub); color:var(--dim); margin-top:3px; }

  /* 결론 스트립 (P1 — 규칙 기반 한 줄, 단정 없음) */
  #conclusion { background:var(--panel); border:1px solid var(--line); border-left:3px solid var(--accent); border-radius:10px; padding:9px 14px; font-size:13px; }
  #conclusion b { color:var(--accent); font-weight:700; margin-right:2px; }
  #conclusion .warn { color:var(--up); }
  #conclusion .dim { color:var(--dim); }

  /* 오늘의 변화 (P1 — 평일에 여는 이유) */
  #homechanges .chgrow { display:flex; align-items:center; gap:10px; background:var(--panel); border:1px solid var(--line); border-radius:10px; padding:8px 14px; margin-bottom:6px; cursor:pointer; flex-wrap:wrap; }
  #homechanges .chgrow:hover { border-color:var(--accent); }
  #homechanges .nm { font-weight:700; min-width:90px; }
  #homechanges .px { font-variant-numeric:tabular-nums; color:var(--dim); }
  #homechanges .ev { font-size:12.5px; border:1px solid var(--line); border-radius:10px; padding:2px 9px; color:var(--dim); }
  #homechanges .ev.move-up { color:var(--up); border-color:var(--up); }
  #homechanges .ev.move-down { color:var(--down); border-color:var(--down); }
  #homechanges .ev.high { color:var(--accent); border-color:var(--accent); }

  /* 관심종목 (S2 — 투자 워크스페이스) */
  .wtbl { width:100%; border-collapse:collapse; background:var(--panel); border:1px solid var(--line); border-radius:10px; overflow:hidden; font-size:13px; }
  .wtbl th, .wtbl td { padding:9px 12px; border-bottom:1px solid var(--line); text-align:right; font-variant-numeric:tabular-nums; white-space:nowrap; }
  .wtbl th { color:var(--dim); font-weight:600; background:var(--panel2); }
  .wtbl th:nth-child(-n+2), .wtbl td:nth-child(-n+2) { text-align:left; }
  .wtbl tbody tr { cursor:pointer; }
  .wtbl tbody tr:hover td { background:var(--panel2); }
  .wtbl .up { color:var(--up); } .wtbl .down { color:var(--down); }
  .wtbl .na { color:var(--dim); font-size:var(--fs-sub); }
  .star { background:transparent; border:0; cursor:pointer; font-size:16px; color:var(--dim); padding:0 4px; line-height:1; }
  .star.on { color:var(--star); }                        /* 관심종목 = 단색 노랑 */
  .star:hover { color:var(--star); }
  /* 보유(포트폴리오) 별 = 오로라 (사용자 확정 2026-08-19 "조금 더 멋진 오로라풍").
     글자 자체에 그라데이션을 입히고 배경을 천천히 흘려 빛이 결을 타고 지나가게 한다.
     색은 브랜드 팔레트(녹색머리풍금조) — 화면에 새 색 계열을 들이지 않는다.
     ⚠ background-clip:text이므로 color가 아니라 -webkit-text-fill-color가 글자색을 정한다.
        .star:hover의 color가 이걸 이기지 못하도록 fill을 transparent로 못박아 둔다. */
  .star.held {
    background-image:linear-gradient(115deg, var(--tg-turquoise), var(--tg-lime), var(--accent),
                                     var(--tg-slate), var(--tg-petrol), var(--tg-turquoise));
    background-size:320% 100%;
    -webkit-background-clip:text; background-clip:text;
    color:transparent; -webkit-text-fill-color:transparent;
    filter:drop-shadow(0 0 5px color-mix(in srgb, var(--accent) 38%, transparent));
    animation:jvAurora 7s linear infinite;
    transform-origin:50% 50%;
  }
  /* 12초에 한 번 도는 '한 바퀴'는 **JS 타이머(jvStarSpinStart)**가 .spin을 얹어 재생한다.
     예전엔 12초짜리 키프레임 하나로 돌렸는데(88% 지점에서만 회전), 별이 다시 그려질 때마다
     애니메이션 시계가 0으로 되돌아가 회전 구간에 영영 닿지 못했다 — 그래서 "안 돈다"였다.
     짧은 1회성 애니메이션이면 시계가 리셋돼도 잃을 것이 없다. */
  .star.held.spin { animation:jvAurora 7s linear infinite, jvStarSpin 1.4s ease-in-out; }
  /* 호버하면 회전은 멈추고 글로우만 강해진다 — 아래 :hover의 filter가 keyframe에 지지 않도록
     animation을 오로라 하나로 되돌린다(진행 중인 애니메이션의 filter가 항상 이기기 때문). */
  .star.held:hover { color:transparent; -webkit-text-fill-color:transparent;
    animation:jvAurora 7s linear infinite;
    filter:drop-shadow(0 0 8px color-mix(in srgb, var(--accent) 58%, transparent)); }
  @keyframes jvAurora { from { background-position:0 0; } to { background-position:320% 0; } }
  @keyframes jvStarSpin {
    0%   { transform:rotate(0deg)   scale(1);
           filter:drop-shadow(0 0 5px color-mix(in srgb, var(--accent) 38%, transparent)); }
    45%  { transform:rotate(200deg) scale(1.34);
           filter:drop-shadow(0 0 13px color-mix(in srgb, var(--accent) 92%, transparent)); }
    100% { transform:rotate(360deg) scale(1);
           filter:drop-shadow(0 0 5px color-mix(in srgb, var(--accent) 38%, transparent)); }
  }
  @media (prefers-reduced-motion: reduce) {
    .star.held, .star.held.spin, .star.held:hover {
      animation:none; background-position:38% 0; transform:none; }   /* 색결은 남기고 움직임만 멈춘다 */
  }
  .w52wrap { display:inline-flex; align-items:center; gap:7px; }
  .w52bar { width:64px; height:6px; background:var(--panel2); border:1px solid var(--line); border-radius:3px; position:relative; }
  .w52bar i { position:absolute; top:-2px; width:3px; height:8px; background:var(--accent); border-radius:1px; }
  .emptywatch { background:var(--panel); border:1px dashed var(--line); border-radius:10px; padding:18px; color:var(--dim); font-size:13px; }
  .emptywatch .qadd { display:flex; gap:6px; flex-wrap:wrap; margin-top:10px; }
  .emptywatch .qadd button { background:var(--panel2); border:1px solid var(--line); color:var(--dim); border-radius:14px; padding:4px 12px; cursor:pointer; font-size:12.5px; }
  .emptywatch .qadd button:hover { color:var(--accent); border-color:var(--accent); }

  /* 3탭 카드 (사용자 확정 2026-08-30 "작은 기능 스위치가 아니라 큰 모듈") — 심리 .sntab 문법의
     축소판: 좌 대표 이미지(돋보기·주비스 마스코트·VS) + 제목·부제, 활성 = 에메랄드 테두리·틴트·상단 띠 */
  .vstabs { display:flex; margin:-2px 0 12px; }
  .vstabs-cards { display:grid; grid-template-columns:repeat(3, minmax(0, 1fr)); gap:6px; margin:6px 0 28px; }
  /* ⚠ 껍데기(테두리·바탕·눌림·선택 표시)는 **여기 없다** — 산업(#intab)·심리(.sntab)와 같은
     한 문법을 쓴다(파일 끝 "모듈 선택 탭" 블록). 여기 남는 것은 이 화면의 배치와 그림뿐. */
  .vscard { display:flex; align-items:center; gap:13px; text-align:left; padding:12px 15px; }
  .vsill { flex:0 0 auto; width:38px; height:38px; display:inline-flex; align-items:center; justify-content:center;
    color:var(--dim); }
  .vsill svg { width:34px; height:34px; fill:none; stroke:currentColor; stroke-width:3.2;
    stroke-linecap:round; stroke-linejoin:round; }
  /* 마스코트는 **작게** (사용자 지적 2026-08-26 "너무 커") — 돋보기·VS는 선 그림이라 같은 크기에서도
     가볍지만, 픽셀아트는 면이 꽉 차 혼자 두 배로 무거워 보인다. 눈에 보이는 무게를 맞춘다. */
  .vsill img { width:28px; height:28px; image-rendering:pixelated; }
  /* VS = **맞붙는 순간** (사용자 지적 2026-08-26 "밋밋하다 · 다이나믹하게"). 기울인 글자만 있던
     자리에 서로를 향해 파고드는 삼각 둘을 넣는다 — 왼쪽은 우리 색, 오른쪽은 잉크. */
  .vsill-vs svg { width:38px; height:38px; }
  /* VS = 글러브 터치 (사용자 재지시 2026-08-30 "대결하는 느낌") — 좌 에메랄드·우 회색 주먹이
     가운데서 맞붙고, 접점 위 임팩트 선 3가닥, 아래 VS. 실루엣 = 주먹 돔+엄지 로브+커프 */
  .vsill-vs .vsl { fill:var(--accent); stroke:none; }
  .vsill-vs .vsr { fill:color-mix(in srgb, var(--text) 42%, transparent); stroke:none; }
  .vsill-vs .vsx { fill:none; stroke:var(--dim); stroke-width:2.6; stroke-linecap:round; }
  .vsill-vs .vst { fill:var(--text); stroke:none; font-size:15px; font-weight:900; font-style:italic;
    letter-spacing:-.5px; text-anchor:middle; }
  .vscard.on .vsill, .vscard:hover .vsill { color:var(--accent); }
  .vscard:not(.on) .vsill img { opacity:.62; filter:saturate(.45); }
  .vscard-txt { display:flex; flex-direction:column; gap:2px; min-width:0; }
  .vscard-txt b { font-size:15.5px; font-weight:800; letter-spacing:-.3px; word-break:keep-all; }
  .vscard-txt i { font-style:normal; font-size:var(--fs-sub); color:var(--dim); word-break:keep-all; }
  @media (max-width:900px) { .vstabs-cards { grid-template-columns:1fr; } }

  /* 종목 스크리닝 (M6 v2, 2026-07-18) — 프리셋 hcard + 전광판 + 업종칩 + 정렬 테이블 + 펼침 */
  /* 프리셋 카드 — 균일 크기 그리드 + 대표 아이콘 (사용자 지시 2026-08-29: 크기 통일·폰트 확대·개행 깔끔) */
  /* 프리셋 = 탭 카드보다 한 단계 아래, **세로형 칩** (사용자 확정 2026-08-30 "가로는 짧게,
     세로는 길게 + 간격 여유"): 아이콘 위·제목·설명 세로 스택, 카운트는 우상단. 섀도 없음 */
  #scrpresets { display:grid; grid-template-columns:repeat(auto-fill, minmax(158px, 1fr)); gap:9px; margin-bottom:30px; }
  .preset { position:relative; display:flex; flex-direction:column; align-items:flex-start; gap:7px;
    text-align:left; background:var(--panel); border:1px solid var(--line); border-radius:11px;
    padding:13px 13px 12px; cursor:pointer; transition:border-color .15s, background .15s; }
  .preset:hover { border-color:var(--accent); }
  .preset.on { border-color:var(--accent); background:var(--panel2); }
  /* 넘버스&내러티브만 무지개 테두리 — 이 프리셋만 네러티브 리포트를 갖는 특별한 판이다
     (사용자 지시 2026-08-30). 색은 '추천코드 등록하기'(.acctinvbtn)와 같은 계보 한 벌.
     2px = 얇으면 색이 회색으로 뭉개져 안 보이고, 3px부터는 카드가 시끄럽다. */
  .preset.narrative { border:2px solid transparent; padding:12px 12px 11px;
    background:linear-gradient(var(--panel), var(--panel)) padding-box, var(--rainbow) border-box; }
  .preset.narrative.on { background:linear-gradient(var(--panel2), var(--panel2)) padding-box, var(--rainbow) border-box; }
  /* 호버·선택도 청록 테두리로 갈아타지 않는다 — 갈아타면 무지개가 사라져 딴 카드가 된다 */
  .preset.narrative:hover, .preset.narrative.on { border-color:transparent; }
  .preset.narrative:hover { filter:saturate(1.35) brightness(1.03); }
  .preset .pico { flex:0 0 auto; width:20px; height:20px; color:var(--dim); }
  .preset .pico svg { width:20px; height:20px; display:block; }
  .preset.on .pico, .preset:hover .pico { color:var(--accent); }
  .preset .ptxt { min-width:0; width:100%; }
  .preset .pcount { position:absolute; top:11px; right:12px; color:var(--dim);
    font-size:var(--fs-lab); font-weight:600; font-variant-numeric:tabular-nums; }
  .preset.on .pcount { color:var(--accent); }
  /* 말로하는 스크리닝 — 랜딩 프롬프트 문법 (사용자 지시 2026-08-30): 중앙 CI + 작은 인사말
     "말로 스크리닝 해보세요" + 큰 프롬프트 상자(#lndbox 축소판). 마스코트는 탭 카드가 담당 */
  .myscr-wrap { grid-column:1 / -1; max-width:680px; margin:22px auto 6px; text-align:center; }
  .myscr-ci { height:24px; width:auto; display:block; margin:0 auto 12px; }
  body[data-theme="dark"] .myscr-ci { content:url(/static/img/brand/joovis_ci_dark.png); }
  .myscr-hello { font-size:19px; font-weight:700; letter-spacing:-.01em; color:var(--text); margin-bottom:18px; }
  .myscr-box { position:relative; text-align:left; background:var(--panel); border:1px solid var(--line);
    border-radius:18px; padding:14px 14px 10px;
    box-shadow:0 10px 34px color-mix(in srgb, var(--tg-ink, #000) 14%, transparent);
    transition:border-color .15s ease; }
  .myscr-box:focus-within { border-color:color-mix(in srgb, var(--accent) 55%, var(--line)); }
  .myscr-box input { display:block; width:100%; box-sizing:border-box; border:0; background:transparent;
    outline:none; color:var(--text); font:inherit; font-size:15.5px; line-height:1.55; padding:2px 2px 10px; }
  .myscr-box input::placeholder { color:var(--dim); }
  .myscr-bar { display:flex; align-items:center; gap:10px; }
  .myscr-hint { margin-left:auto; font-size:var(--fs-lab); color:var(--dim); }
  .myscr-go { flex:none; display:inline-flex; align-items:center; justify-content:center;
    width:34px; height:34px; background:var(--accent); border:0; border-radius:10px; color:var(--bg); cursor:pointer; }
  /* 아이콘 = 랜딩 전송 버튼(#lndsend)과 같은 4각 별 fill (사용자 지시 2026-08-30) */
  .myscr-go svg { width:18px; height:18px; fill:currentColor; stroke:none; }
  .myscr-go:hover { filter:brightness(1.06); }
  .myscr-box.busy .myscr-go { pointer-events:none; }
  .myscr-box.busy .myscr-go svg { transform-origin:center; animation:myscrspin .9s linear infinite; }
  /* 실행 진행 카드 — 유튜브 요약 대기 자리(.pnytwait, portfolio.css) 문법을 스크리닝에 이식
     (사용자 지시 2026-08-30 "계산이 진행되고 있다는 느낌"): 스피너 + 단계 문구 + 스켈레톤 줄 */
  .myscr-run { max-width:680px; margin:26px auto 10px; padding:12px 14px 14px; text-align:left;
    border:1px dashed var(--line); border-radius:12px; user-select:none; }
  .myscr-runhead { display:flex; align-items:center; gap:8px; margin-bottom:10px;
    font-size:13px; font-weight:600; color:var(--text); }
  .myscr-runhead em { font-style:normal; font-weight:400; font-size:11.5px; color:var(--dim);
    overflow:hidden; text-overflow:ellipsis; white-space:nowrap; margin-left:auto; }
  .myscr-spin { flex:none; width:14px; height:14px; }
  .myscr-spin circle { fill:none; stroke:var(--accent); stroke-width:2.6; stroke-linecap:round;
    stroke-dasharray:40; stroke-dashoffset:26; transform-origin:center;
    animation:myscrspin .9s linear infinite; }
  @keyframes myscrspin { to { transform:rotate(360deg); } }
  .myscr-run .skel { min-height:12px; }
  /* 예시·저장 조건 칩 — 둘째 줄 전폭. 저장 칩은 이름 + 매치 수 흐름(prev→now) */
  .myscr-chips { display:flex; gap:6px; flex-wrap:wrap; align-items:center; justify-content:center; margin-top:14px; }
  .myscr-chips:empty { display:none; }
  .myscr-chips-lb { font-size:var(--fs-lab); color:var(--dim); }
  .myscr-chip { display:inline-flex; align-items:center; gap:6px; background:var(--panel2);
    border:1px solid var(--line); color:var(--dim); border-radius:14px; padding:4px 11px;
    font-size:var(--fs-lab); cursor:pointer; }
  .myscr-chip:hover { color:var(--accent); border-color:var(--accent); }
  .myscr-chip.saved { color:var(--text); }
  .myscr-chip i { font-style:normal; color:var(--accent); font-variant-numeric:tabular-nums; font-weight:600; }
  .myscr-chip .x { color:var(--dim); font-size:12px; opacity:0; transition:opacity .12s; }
  .myscr-chip:hover .x { opacity:1; }
  .myscr-chip .x:hover { color:var(--up); }
  .myscr-savebtn { background:transparent; border:1px solid var(--accent); color:var(--accent);
    border-radius:11px; padding:2px 10px; font-size:var(--fs-lab); cursor:pointer; margin-left:2px; }
  .myscr-savebtn:hover { background:color-mix(in srgb, var(--accent) 12%, transparent); }
  .myscr-savedok { color:var(--accent); font-size:var(--fs-lab); }
  .myscr-flow { color:var(--accent); font-weight:600; }
  .scrcond-unk { display:block; margin-top:5px; font-size:var(--fs-lab); color:var(--dim); }
  /* 선택 전 안내 — 박스·테두리 없이 또렷한 본문색 한 줄, 중앙 (사용자 확정 2026-08-30
     "점선 박스에 흐린 글씨가 제일 싫다 — 폰트 키우고 검정으로, 중앙에") */
  .scrwait { text-align:center; margin:84px 0; font-size:15.5px; font-weight:600; color:var(--text); }
  .preset b { display:block; font-size:var(--fs-th); white-space:nowrap; }  /* 칩형 제목 — 탭 카드(15.5)보다 한 단 아래 */
  .preset.on b { color:var(--accent); }
  /* 설명 1줄 말줄임 — 칩이 탭 카드보다 납작해야 위계가 산다(전체 설명은 카드 title 툴팁) */
  .preset small { display:block; color:var(--dim); font-size:var(--fs-sub); margin-top:1px;
    white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }

  /* 전광판 — 매치 수가 화면의 대형 타이포 앵커 + 자막 + 기준일 + 업종 스트립 (디자인 철학 docs/28) */
  .scrboard { border-top:2px solid color-mix(in srgb, var(--line) 90%, var(--text)); border-bottom:1px solid var(--line);
    padding:16px 2px 14px; margin-bottom:14px; }
  .scrboard-hero { display:flex; align-items:baseline; gap:8px; }
  .scrboard-n { font-size:42px; font-weight:700; letter-spacing:-1.5px; line-height:1; font-variant-numeric:tabular-nums; }
  .scrboard-u { font-size:16px; color:var(--dim); }
  .scrboard-dek { font-size:14px; color:var(--text); margin-top:6px; }
  .scrboard-meta { font-size:var(--fs-sub); color:var(--dim); margin-top:4px; }
  .scrind { display:flex; gap:6px; flex-wrap:wrap; margin-top:11px; align-items:center; }
  .indchip { background:var(--panel); border:1px solid var(--line); color:var(--text); border-radius:14px;
    padding:4px 10px; font-size:var(--fs-sub); cursor:pointer; display:inline-flex; gap:5px; align-items:center; transition:border-color .15s, color .15s; }
  .indchip span { color:var(--dim); font-variant-numeric:tabular-nums; }
  .indchip:hover { border-color:var(--accent); }
  .indchip.on { border-color:var(--accent); background:var(--panel2); color:var(--accent); }
  .indchip.on span { color:var(--accent); }
  .scrind-more { font-size:var(--fs-sub); color:var(--dim); }

  #scrconds { font-size:var(--fs-sub); margin:0 2px 12px; display:flex; gap:6px; flex-wrap:wrap; align-items:center; }
  .scrcond-lb { color:var(--dim); font-size:var(--fs-lab); letter-spacing:.08em; }
  .scrcond { color:var(--dim); background:var(--panel2); border-radius:10px; padding:2px 9px; }

  /* 결과 테이블 — 정렬 가능 헤더(▲▼), 동적 컬럼, 행 액션, 펼침 */
  .scrtblwrap { background:var(--panel); border:1px solid var(--line); border-radius:12px; overflow-x:auto; box-shadow:var(--shadow); }
  .scrtbl { width:100%; border-collapse:collapse; font-size:13px; }
  .scrtbl th, .scrtbl td { padding:9px 12px; border-bottom:1px solid var(--line); text-align:right; white-space:nowrap; font-variant-numeric:tabular-nums; }
  .scrtbl th { font-size:var(--fs-th); font-weight:600; color:rgba(255,255,255,.92); background:var(--accent); position:sticky; top:0; border-bottom:0; }
  .scrtbl th.l, .scrtbl td.l { text-align:left; }
  .scrtbl th.sort { cursor:pointer; user-select:none; }
  .scrtbl th.sort:hover { color:#fff; }
  .scrtbl th.sort.active { color:#fff; font-weight:700; }
  .scrtbl tbody tr.scrrow { cursor:pointer; }
  .scrtbl tbody tr.scrrow:hover td { background:var(--panel2); }
  .scrtbl tbody tr.scrrow.exp td { background:var(--panel2); }
  .scr-code { color:var(--dim); font-size:var(--fs-lab); }
  .scr-ind { color:var(--dim); font-size:var(--fs-sub); }
  .scr-star .star, .scr-exp { background:none; border:0; cursor:pointer; padding:2px 4px; font-size:14px; color:var(--dim); }
  .scr-star .star.on { color:var(--star); }
  .scr-exp { font-size:var(--fs-sub); }
  .scr-exp:hover { color:var(--text); }
  .scrtbl th.c, .scrtbl td.c { text-align:center; }   /* 추가하기·네러티브 열 — 중앙 (사용자 지시 2026-08-19) */
  .scr-actions { white-space:nowrap; }
  /* 선택된 버튼 우상단 ✕ = 빼기 (사용자 지시 2026-08-19 "추가만 하고 지울 순 없다") */
  .scr-actions button { position:relative; }
  .scr-actions .rmx { position:absolute; top:-7px; right:-7px; width:16px; height:16px;
    display:flex; align-items:center; justify-content:center; font-style:normal; font-size:10px;
    color:var(--dim); background:var(--panel); border:1px solid var(--line); border-radius:50%; }
  .scr-actions .rmx:hover { color:var(--down); border-color:var(--down); }
  /* 네러티브 셀 — 점수가 없으면 '리포트' 버튼, 있으면 점수 배지(클릭=리포트 열기) */
  .scr-nar { background:transparent; border:1px solid var(--line); color:var(--dim); border-radius:12px;
    padding:3px 11px; cursor:pointer; font-size:var(--fs-lab); }
  .scr-nar:hover { color:var(--ai); border-color:var(--ai); }
  /* 점수가 아니라 **문**이다 (사용자 지시 2026-08-30 "사람들이 이 점수를 클릭하게 해야 해").
     종전엔 넘버스 열과 똑같은 배지라 누를 수 있다는 신호가 0이었다 — 점수를 알약 안에 넣고
     '왜?'와 꺾쇠를 붙여 리포트로 가는 문임을 스스로 말하게 한다. */
  .scr-nar.has { display:inline-flex; align-items:center; gap:6px; border:1px solid color-mix(in srgb, var(--ai) 34%, transparent);
    padding:3px 8px 3px 4px; border-radius:7px; background:color-mix(in srgb, var(--ai) 7%, var(--panel2));
    transition:border-color .15s, background .15s, box-shadow .15s; }
  .scr-nar.has:hover { border-color:var(--ai); background:color-mix(in srgb, var(--ai) 14%, var(--panel2));
    box-shadow:0 1px 8px color-mix(in srgb, var(--ai) 22%, transparent); }
  .scr-nar.has .scrscore { min-width:32px; height:23px; font-size:13.5px; padding:0 7px; border-radius:5px; }
  /* 리포트 아이콘 — 말 대신 그림으로 "여기 읽을 게 있다" (사용자 지시 2026-08-30 "왜? 말고 리포트 느낌의 아이콘") */
  .scr-nar.has svg { width:15px; height:15px; color:var(--ai); opacity:.85; flex:none; }
  .scr-nar.has:hover svg { opacity:1; }
  /* 점수가 아직 없는 리포트 — 아이콘만. '준비 전'이라 잠그지 않는다 (사고 2026-08-30) */
  .scr-nar.has.noscore { padding:5px 8px; }
  /* 열 머리도 스스로 '리포트'라고 말한다 */
  .scrtbl th.narth svg { width:12px; height:12px; vertical-align:-1px; margin-left:4px; opacity:.6; }
  /* 표 위 한 줄 — 무엇을 누르면 무엇이 열리는지. 넘버스&네러티브 프리셋에만 나온다 */
  .scrnarhint { display:flex; align-items:center; gap:8px; margin:0 0 10px; padding:8px 12px;
    border:1px solid color-mix(in srgb, var(--ai) 26%, transparent); border-radius:8px;
    background:color-mix(in srgb, var(--ai) 6%, var(--panel2));
    font-size:var(--fs-sub); color:var(--dim); line-height:1.45; }
  .scrnarhint svg { width:16px; height:16px; flex:none; color:var(--ai); }
  .scrnarhint b { color:var(--text); font-weight:700; }
  /* 준비 전 = 버튼이 아니다 — 생성은 주간 배치 전용이라 사용자가 누를 게 없다 (2026-08-28) */
  .scr-nar.wait { border:0; background:transparent; cursor:help; font-size:var(--fs-badge); }
  .scr-nar.wait:hover { color:var(--dim); border-color:transparent; }
  .scr-actions button { background:var(--panel2); border:1px solid var(--line); color:var(--dim); border-radius:12px;
    padding:3px 9px; font-size:var(--fs-sub); cursor:pointer; margin-left:4px; transition:color .15s, border-color .15s; }
  .scr-actions button:hover { color:var(--accent); border-color:var(--accent); }
  .scr-actions button.on { color:var(--accent); border-color:var(--accent); background:color-mix(in srgb, var(--accent) 12%, transparent); }
  /* AI 스코어 배지 — 포트폴리오 학점 색 기준 (사용자 지시 2026-08-29, portfolio.css .bk.sA~sF 동일 앵커):
     A보라 #6d28d9 · B연두 #65a30d · C주황 #d97706 · D빨강 #b91c1c · F(판정불가) 회색.
     배경은 JS(scoreColor)가 등급 내 위치로 진하기 72~100%를 보간해 인라인으로 준다 —
     납작한 5단이 아니라 결이 있는 5색 계열 (같은 A라도 95가 76보다 진하다). */
  .scrscore { display:inline-flex; align-items:center; justify-content:center; min-width:38px; height:26px;
    padding:0 9px; border-radius:8px; font-weight:700; font-size:14.5px; font-variant-numeric:tabular-nums;
    color:#fff; border:1px solid transparent; }
  .scrscore.gF { background:color-mix(in srgb, #3f3f46 55%, var(--panel2)); color:var(--dim);
    font-weight:600; font-size:var(--fs-sub); }
  .scrmore { font-size:var(--fs-sub); color:var(--dim); text-align:center; margin-top:8px; }

  /* 펼침 행 — 재무·기술 대형 점수(히트색) + 재무 5축 맥락 + AI 내러티브 해석(온디맨드) */
  .scr-detail td { background:var(--panel2); }
  .scrdet { display:flex; gap:28px; align-items:center; flex-wrap:wrap; padding:8px 2px 10px; text-align:left; white-space:normal; }
  .scrdet-score-wrap { display:flex; align-items:center; gap:12px; flex-shrink:0; }
  .scrdet-lb { font-size:var(--fs-lab); letter-spacing:.06em; color:var(--dim); line-height:1.3; }
  .scrdet-lb small { display:block; font-size:var(--fs-badge); opacity:.75; }
  .scrdet-score { display:inline-flex; align-items:center; justify-content:center; min-width:52px; height:44px;
    padding:0 12px; border-radius:10px; font-size:26px; font-weight:800; font-variant-numeric:tabular-nums;
    letter-spacing:-1px; color:#fff; }
  .scrdet-score.gF { background:color-mix(in srgb, #3f3f46 55%, var(--panel2)); color:var(--dim); }
  .scrdet-tnote { font-size:var(--fs-sub); color:var(--dim); }
  .scrdet-axes { display:inline-flex; gap:14px; flex-wrap:wrap; }
  .scrax { display:inline-flex; align-items:center; gap:6px; font-size:var(--fs-sub); }
  .scrax-l { color:var(--dim); min-width:44px; }
  .scrax-bar { width:56px; height:5px; background:var(--panel); border-radius:3px; overflow:hidden; }
  .scrax-bar i { display:block; height:100%; background:var(--accent); border-radius:3px; }
  .scrax-v { color:var(--text); font-variant-numeric:tabular-nums; font-weight:600; min-width:18px; }
  .scrdet-ai { flex:1; min-width:260px; }
  .scrai-btn { background:var(--panel); border:1px solid var(--accent); color:var(--accent); border-radius:12px; padding:5px 12px; font-size:var(--fs-sub); cursor:pointer; }
  .scrai-btn:hover { background:color-mix(in srgb, var(--accent) 12%, transparent); }
  .scrai-none, .scrai-load { font-size:12.5px; color:var(--dim); }
  .scrai { font-size:13px; line-height:1.6; }
  .scrai-h { display:flex; align-items:center; gap:6px; font-size:var(--fs-sub); letter-spacing:.06em; color:var(--accent); margin-bottom:5px; }
  .scrai-h svg { width:14px; height:14px; fill:var(--accent); }
  .scrai p { margin:0 0 6px; color:var(--text); }
  .scrai-basis { font-size:var(--fs-lab); color:var(--dim); margin-top:4px; }

  #screxcluded { margin-top:14px; color:var(--dim); font-size:var(--fs-sub); }
  #screxcluded summary { cursor:pointer; font-size:12.5px; padding:4px 0; }
  #screxcluded li { margin:3px 0 3px 18px; }

  /* 종목비교 (S3) */
  #cmpsel { display:flex; gap:8px; flex-wrap:wrap; align-items:center; margin-bottom:14px; }
  .cmpchip { display:inline-flex; align-items:center; gap:6px; background:var(--panel); border:1px solid var(--accent); color:var(--text); border-radius:16px; padding:5px 12px; font-size:13px; }
  .cmpchip b { color:var(--accent); }
  .cmpchip .x { cursor:pointer; color:var(--dim); font-size:14px; }
  .cmpchip .x:hover { color:var(--up); }
  #cmpsearchwrap { position:relative; }
  #cmpsearch { width:220px; padding:6px 12px; background:var(--panel2); border:1px solid var(--line); border-radius:16px; color:var(--text); font-size:13px; outline:none; }
  #cmpsearch:focus { border-color:var(--accent); }
  #cmpsuggest { position:absolute; top:36px; left:0; width:280px; background:var(--panel2); border:1px solid var(--line); border-radius:8px; z-index:50; display:none; max-height:260px; overflow-y:auto; }
  #cmpsuggest div { padding:8px 12px; cursor:pointer; display:flex; justify-content:space-between; font-size:13px; }
  #cmpsuggest div:hover { background:var(--panel2); }
  .cmpqadd { display:inline-flex; gap:6px; flex-wrap:wrap; }
  .cmpqadd button { background:var(--panel2); border:1px solid var(--line); color:var(--dim); border-radius:14px; padding:5px 13px; cursor:pointer; font-size:var(--fs-body); }
  .cmpqadd button:hover { color:var(--accent); border-color:var(--accent); }
  /* 비교 v2 (2026-07-18): VS 마스트헤드 + 자막 + 그룹 테이블·우세 ● + 레이더 + 업종 추천 */
  #cmphdr { display:grid; gap:0; background:var(--panel); border:1px solid var(--line); border-radius:12px;
    padding:16px 0 14px; margin-bottom:10px; text-align:center; }
  .cmphdr-co { cursor:pointer; padding:0 12px; }
  .cmphdr-co.vsline { border-left:1px solid var(--line); position:relative; }
  .cmphdr-co.vsline::before { content:"vs"; position:absolute; left:-11px; top:50%; transform:translateY(-50%);
    background:var(--panel); color:var(--dim); font-size:var(--fs-lab); padding:2px 4px; }
  .cmphdr-nm { font-size:21px; font-weight:700; letter-spacing:-.01em; }
  .cmphdr-nm:hover { text-decoration:underline; text-underline-offset:3px; }
  .cmphdr-px { font-size:14px; margin-top:4px; font-variant-numeric:tabular-nums; }
  .cmphdr-px .cmplive { color:var(--accent); font-size:8px; margin-left:6px; vertical-align:2px; }
  .cmphdr-mt { font-size:var(--fs-sub); color:var(--dim); margin-top:3px; }
  #cmpdek { text-align:center; color:var(--text); font-size:15px; margin:2px 0 6px; }
  #cmpdek .na { font-size:var(--fs-body); color:var(--dim); }
  /* 우측 = 레이더(위)+축별 가로 막대(아래) 2단, 폭 300px — 표가 더 넓게 (사용자 확정 2026-07-18) */
  #cmptop { display:grid; grid-template-columns:1fr 320px; gap:18px; align-items:stretch; margin-bottom:4px; }
  #cmptop #cmptblwrap { margin-bottom:0; }
  #cmpside { display:flex; flex-direction:column; gap:18px; }
  #cmpside #cmpradar { flex:1.35; min-height:270px; }
  #cmpside #cmpaxbars { flex:1; min-height:200px; }
  @media (max-width:1100px) { #cmptop { grid-template-columns:1fr; }
    #cmpside #cmpradar { height:280px; } #cmpside #cmpaxbars { height:210px; } }
  #cmptbl tr.grp td { padding:14px 16px 6px; font-size:13.5px; font-weight:700; letter-spacing:.06em; color:var(--dim);
    border-bottom:none; background:transparent; }
  #cmptbl .win { color:var(--accent); font-size:11px; vertical-align:1.5px; margin-right:6px; }
  #cmppeers { flex-basis:100%; display:flex; gap:8px; flex-wrap:wrap; align-items:center; margin-top:2px; }
  .cmppeers-lb { font-size:var(--fs-body); color:var(--dim); }
  .cmppeers-lb b { color:var(--text); font-weight:600; }
  #cmptblwrap { background:var(--panel); border:1px solid var(--line); border-radius:10px; padding:4px 0 0; overflow-x:auto; margin-bottom:12px; }
  #cmptbl { width:100%; border-collapse:collapse; font-size:15px; }
  #cmptbl th, #cmptbl td { padding:11px 16px; border-bottom:1px solid var(--line); text-align:right; font-variant-numeric:tabular-nums; white-space:nowrap; }
  #cmptbl th:first-child, #cmptbl td:first-child { text-align:left; color:var(--text); }
  #cmptbl thead th { font-size:16px; font-weight:700; background:var(--panel2); cursor:pointer; }
  #cmptbl thead th:hover { color:var(--accent); }
  #cmptbl .na { color:var(--dim); font-size:var(--fs-body); }
  /* 빽빽함의 원인 셋을 함께 푼다 (사용자 지시 2026-08-19 "너무 복잡하고 보기도 싫다"):
       ① 칸을 넓히고(340→400) 사이를 벌린다(10→18)  ② 높이를 230→300으로 키운다
       ③ 제목을 캔버스 밖(.cmplab)으로 빼 범례와 다투지 않게 한다 */
  #cmpcharts { display:grid; grid-template-columns:repeat(auto-fit,minmax(400px,1fr)); gap:18px; }
  .cmpmini { background:var(--panel); border:1px solid var(--line); border-radius:10px; height:300px;
    padding:14px 16px 12px; display:flex; flex-direction:column; min-width:0; }
  .cmpmini .cmplab { font-size:15.5px; font-weight:700; color:var(--text); letter-spacing:-.01em;
    margin-bottom:2px; word-break:keep-all; }                      /* 중제목 캐논 */
  .cmpmini .cmplab small { font-size:var(--fs-sub); font-weight:400; color:var(--dim); margin-left:6px; }
  .cmpmini .cmpcv { flex:1; min-height:0; }
  /* 레이더·막대는 캔버스가 곧 패널이라 padding이 없어야 한다 (제목이 캔버스 안에 있음) */
  #cmpside .cmpmini { padding:0; display:block; }

  /* V차트 섹션 소제목 (docs/14 §3 — 탭 없이 시각 구분만) */
  .sect { font-size:12.5px; color:var(--accent); font-weight:700; margin:12px 4px 2px; padding-top:10px; border-top:1px dashed var(--line); }
  .sect small { color:var(--dim); font-weight:400; margin-left:8px; }

  /* 연간 요약 테이블 (docs/13 §7 — 장기 연간, 2015~) */
  #annualwrap { background:var(--panel); border:1px solid var(--line); border-radius:10px; padding:12px 14px; }
  #annualwrap h3 { margin:0 0 8px; }
  #annualwrap .scroll { overflow-x:auto; }
  #annualtbl { width:100%; border-collapse:collapse; font-size:12.5px; white-space:nowrap; }
  #annualtbl th, #annualtbl td { padding:5px 10px; border-bottom:1px solid var(--line); text-align:right; font-variant-numeric:tabular-nums; }
  #annualtbl th:first-child, #annualtbl td:first-child { text-align:left; }
  #annualtbl th { color:var(--dim); font-weight:600; background:var(--panel2); }
  #annualtbl .neg { color:var(--down); }
  #annualtbl .na { color:var(--dim); font-size:var(--fs-sub); }
  .searchwrap { position:relative; width:340px; }
  #search { width:100%; padding:8px 12px; background:var(--panel2); border:1px solid var(--line); border-radius:8px; color:var(--text); font-size:14px; outline:none; }
  #search:focus { border-color:var(--accent); }
  #suggest { position:absolute; top:40px; left:0; right:0; background:var(--panel2); border:1px solid var(--line); border-radius:8px; z-index:50; display:none; max-height:300px; overflow-y:auto; }
  #suggest div { padding:8px 12px; cursor:pointer; display:flex; justify-content:space-between; }
  /* 선택 강조 — 구 규칙은 배경(--panel2)과 **같은 색**이라 호버가 보이지 않았다.
     `.on` = 키보드 선택(↑↓·기본 맨 위), `:hover` = 마우스. 둘이 같은 표시여야 Enter가 무엇을 고를지 읽힌다. */
  #suggest div:hover, #suggest div.on { background:var(--tg-veil); }
  #suggest div.on { box-shadow:inset 2px 0 0 var(--accent); }
  /* 씨앗 목록 머리 — 이건 고를 수 있는 항목이 아니라 목록의 이름이다. `#suggest div` 규칙이
     모든 div에 커서·호버를 주므로 여기서 되돌린다(아니면 못 눌리는 줄이 눌릴 것처럼 보인다).
     `_sgRows()`는 `div[data-code]`만 세므로 ↑↓·Enter 대상에는 애초에 들어가지 않는다. */
  #suggest .sghead { cursor:default; padding:7px 12px 6px; font-size:11.5px; color:var(--dim);
    border-bottom:1px solid var(--line); letter-spacing:.02em; }
  #suggest .sghead:hover { background:transparent; }
  #recent { display:flex; gap:6px; flex-shrink:0; }
  /* 칩은 글자가 절대 두 줄로 안 깨지게 — nowrap + 안 찌그러짐(flex-shrink:0). 좁아지면 칩이 넘칠 뿐, 줄바꿈 금지 (사용자 지시 2026-07-18) */
  #recent button { background:var(--panel2); border:1px solid var(--line); color:var(--dim); border-radius:14px; padding:2px 10px; cursor:pointer; font-size:var(--fs-lab); white-space:nowrap; flex-shrink:0; }
  #recent button:hover { color:var(--text); border-color:var(--accent); }

  /* AI 패널 = 전 화면 공용 드로어로 이동 (2026-07-15 사용자 지시 — 파일 끝 [공통] AI 대화 드로어 참조)
     본문은 1컬럼 복귀. 대화 로직(chat.js)·구독 연결(docs/29 §5-1)은 불변 */
  main { flex:1; display:grid; grid-template-columns:1fr; gap:10px; padding:10px; min-height:0; overflow:hidden; }
  #left { display:flex; flex-direction:column; gap:14px; min-width:0; overflow-y:auto; }

  /* 스크롤을 내려도 **위에 남는다** (사용자 확정 2026-08-14) — 아래로 한참 내려가도
     지금 보는 기업이 무엇인지 계속 보이게. 스크롤 컨테이너는 #left이고 이 밴드는 그 직계 자식.
     배경이 불투명해야 아래 내용이 비쳐 보이지 않는다(--panel 이미 지정). */
  #stockhead { position:sticky; top:0; z-index:20;
    background:var(--panel); border:1px solid var(--line); border-radius:10px; padding:10px 14px; display:flex; align-items:baseline; gap:12px; flex-wrap:wrap;
    box-shadow:var(--shadow); }
  #stockhead .nm { font-size:18px; font-weight:800; }
  #stockhead .cd { color:var(--dim); font-size:13px; }
  #stockhead .mc { color:var(--accent); font-size:14px; font-weight:700; margin-left:auto; }
  /* 기업 프로필 (사용자 확정 2026-07-17, FnGuide 스타일): [WICS 업종] 사업요약 ······ 결산·홈페이지 */
  #stockhead .hprof { display:flex; align-items:baseline; gap:10px; flex:1 1 320px; min-width:0; }
  #stockhead .hprof:empty { display:none; }
  #stockhead .hwics { flex:none; font-size:var(--fs-lab); color:var(--accent); border:1px solid var(--line); border-radius:8px; padding:1px 8px; cursor:help; }
  #stockhead .hsum { flex:1 1 auto; min-width:0; font-size:12.5px; color:var(--dim); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
  #stockhead .hmeta { flex:none; font-size:var(--fs-sub); color:var(--dim); white-space:nowrap; }
  #stockhead .hmeta a { color:var(--accent); text-decoration:none; }
  #stockhead .hmeta a:hover { text-decoration:underline; }
  #perf { display:flex; gap:6px; flex-wrap:wrap; }
  #perf span { background:var(--panel); border:1px solid var(--line); border-radius:8px; padding:4px 10px; font-size:var(--fs-sub); color:var(--dim); }
  #perf b { margin-left:5px; font-variant-numeric:tabular-nums; }
  #periods { display:flex; justify-content:space-between; padding:2px 6px 4px; }
  #periods .grp { display:flex; gap:4px; }
  #periods button { background:transparent; border:1px solid var(--line); color:var(--dim); border-radius:6px; padding:2px 9px; font-size:var(--fs-sub); cursor:pointer; }
  #periods button.on, #periods button:hover { color:var(--accent); border-color:var(--accent); }
  #vcharts { background:var(--panel); border:1px solid var(--line); border-radius:10px; padding:12px 10px; }
  #vcharts h3 { margin:0 4px 6px; }
  .vtab { background:transparent; border:1px solid var(--line); color:var(--dim); border-radius:6px; padding:2px 10px; font-size:var(--fs-sub); cursor:pointer; margin-left:4px; }
  .vtab.on, .vtab:hover { color:var(--accent); border-color:var(--accent); }
  .mini { height:215px; width:100%; }

  /* 종목 카드 행 — ①최대한 한 줄 ②그래도 안 되면 **균형 있게** 나눈다 (사용자 지시 2026-08-01).
     칸 수는 6(카드 6개) 또는 7(시간외 있으면 종가가 2칸). auto-fill은 폭이 모자랄 때 마지막 1개만
     덜렁 내려보내므로, 좁아지면 **열 수를 명시**해 4+3 / 3+3 / 2+2+2로 고르게 접는다.
     기준은 뷰포트가 아니라 **패널 폭**(#left) — 챗 도크가 열리면 뷰포트는 그대로인데 패널만 좁아지기 때문(컨테이너 쿼리). */
  #left { container-type:inline-size; container-name:leftcol; }
  /* auto-fit(=fill 아님): 남는 열은 붕괴돼 카드가 폭을 나눠 갖는다 → 넓은 화면에서 빈 칸·과도한 여백 없음 */
  #cards { display:grid; grid-template-columns:repeat(auto-fit, minmax(104px, 1fr)); gap:8px; }
  @container leftcol (max-width:860px) { #cards { grid-template-columns:repeat(4, 1fr); } }      /* 7칸 → 4+3 */
  @container leftcol (max-width:620px) { #cards { grid-template-columns:repeat(3, 1fr); } }      /* 6칸 → 3+3 */
  @container leftcol (max-width:420px) { #cards { grid-template-columns:repeat(2, 1fr); } }      /* 6칸 → 2+2+2 */
  .card { background:var(--panel); border:1px solid var(--line); border-radius:10px; padding:10px 12px; }
  .card .k { font-size:var(--fs-lab); color:var(--dim); margin-bottom:3px; }
  .card .v { font-size:16px; font-weight:700; white-space:nowrap; }
  .card .s { font-size:var(--fs-lab); color:var(--dim); }

  #chartbox { background:var(--panel); border:1px solid var(--line); border-radius:10px; padding:6px; height:520px; flex-shrink:0; }
  /* #chartbox 안에 기간 토글(#periods ≈30px)이 함께 있으므로 그만큼 뺀다 (인라인 style에서 이관) */
  #chart { width:100%; height:calc(100% - 30px); }

  #disc { background:var(--panel); border:1px solid var(--line); border-radius:10px; padding:14px 16px; }
  #disc h3 { margin-bottom:8px; }
  #disc a { color:var(--text); text-decoration:none; display:flex; gap:10px; padding:3px 0; font-size:13px; }
  #disc a:hover { color:var(--accent); }
  #disc .d { color:var(--dim); flex-shrink:0; font-variant-numeric:tabular-nums; }
  /* 최근 공시 | 최근 주요 뉴스 — 2열 + 세로 구분선 (사용자 확정 2026-07-17) */
  #disc .discsplit { display:grid; grid-template-columns:1fr 1fr; align-items:start; }
  #disc .disccol { min-width:0; }
  #disc .disccol + .disccol { border-left:1px solid var(--line); margin-left:20px; padding-left:20px; }
  #disc h3 small { font-weight:400; color:var(--dim); opacity:.7; }
  #disc .dt { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  #disc .dsrc { color:var(--dim); font-size:var(--fs-lab); margin-left:7px; }
  #disc .dnone { color:var(--dim); font-size:13px; }
  /* 더보기 — 목록의 일부지 별개 조작이 아니라, 버튼 티를 내지 않고 한 줄로 앉힌다
     (사용자 요청 2026-08-07 "3개인데 더보기로 5개 추가해 최대 8개"). */
  #disc .dmorebtn { display:block; margin-top:5px; padding:3px 0; border:0; background:none;
    color:var(--dim); font-size:var(--fs-sub); font-family:inherit; cursor:pointer; text-align:left; }
  #disc .dmorebtn:hover { color:var(--accent); }
  #asof { font-size:var(--fs-sub); color:var(--dim); padding:0 4px 8px; }

  #chatpanel { background:var(--panel); border:1px solid var(--line); border-radius:10px; display:flex; flex-direction:column; min-height:0; }
  /* AI 백엔드 배지 — 내 Claude(연결)/Claude 연결(버튼)/API 를 정직하게 표기 (docs/29 §5-1) */
  #aibk { font-size:var(--fs-lab); color:var(--ai); border:1px solid var(--ai); border-radius:9px; padding:1px 8px; margin-left:8px; vertical-align:2px; font-weight:400; cursor:pointer; transition:background-color .15s ease; }
  #aibk:empty { display:none; }
  #aibk:hover { background:color-mix(in srgb, var(--ai) 14%, transparent); }
  #aibk.off { color:var(--accent); border-color:var(--accent); font-weight:600; }   /* 미연결 = 연결 유도 */
  /* Pro = 계정 메뉴 `.acctplan.pro`와 같은 오로라 필 (사용자 확정 2026-08-28 "상단 Pro는 이런 모양").
     상태 배지라 눌러도 아무 일 없다 — 호버 틴트·포인터도 벗긴다. 완전 둥근 필은 캡처 그대로. */
  #aibk.pro { color:#fff; border-color:transparent; border-radius:999px; padding:1px 10px;
    font-weight:700; cursor:default;
    background:linear-gradient(124deg, var(--tag-deep) 0%, var(--tag-mid) 34%, var(--tag-azure) 58%,
               var(--tag-aqua) 76%, var(--tag-champ) 90%, var(--tag-gold) 100%);
    background:linear-gradient(124deg in oklab, var(--tag-deep) 0%, var(--tag-mid) 34%, var(--tag-azure) 58%,
               var(--tag-aqua) 76%, var(--tag-champ) 90%, var(--tag-gold) 100%);
    box-shadow:inset 0 1px 0 rgba(255,255,255,.30), inset 0 -1px 0 rgba(0,0,0,.12), 0 1px 6px color-mix(in srgb, var(--tag-azure) 30%, transparent); }
  #aibk.pro:hover { background:linear-gradient(124deg, var(--tag-deep) 0%, var(--tag-mid) 34%, var(--tag-azure) 58%,
                     var(--tag-aqua) 76%, var(--tag-champ) 90%, var(--tag-gold) 100%);
          background:linear-gradient(124deg in oklab, var(--tag-deep) 0%, var(--tag-mid) 34%, var(--tag-azure) 58%,
                     var(--tag-aqua) 76%, var(--tag-champ) 90%, var(--tag-gold) 100%); }
  #aibk.off:hover { background:color-mix(in srgb, var(--accent) 16%, transparent); }
  #chathead { padding:10px 14px; border-bottom:1px solid var(--line); font-weight:700; color:var(--ai); font-size:14px; }
  #chathead small { color:var(--dim); font-weight:400; display:block; margin-top:2px; }
  /* 좌우 여백 12 → 18px (사용자 지시 2026-08-21 "너무 빽빽해서 답답한 느낌").
     위아래는 그대로 — 답답한 쪽은 글이 벽에 붙는 가로였다. */
  #chatlog { flex:1; overflow-y:auto; padding:12px 18px; display:flex; flex-direction:column; gap:10px;
    overscroll-behavior:contain; }

  /* ---------- 스크롤 성능 (사용자 지시 2026-08-21 "3~5턴인데 벌써 버벅거려") ----------

     앱 전체가 `body { transform:scale(1.2) }` 안에 있다(전역 확대, 2026-07-16 — CSS zoom은
     ECharts 히트테스트를 깨뜨려 transform으로 갔다). 스케일된 레이어 안에서 스크롤하면
     브라우저가 **매 프레임 다시 래스터**한다. 답변 서너 개만 쌓여도 그 비용이 눈에 보인다.

     전역 확대를 되돌릴 수는 없으니(ECharts가 거기 걸려 있다) **일하는 양을 줄인다.**
     클로드·ChatGPT가 긴 대화에서 안 버벅이는 이유도 같은 원리다 — 화면 밖 메시지는
     그리지 않는다.

       · content-visibility:auto — 화면 밖 답변은 레이아웃·페인트를 **통째로 건너뛴다**
       · contain-intrinsic-size:auto — 건너뛴 높이를 기억해 스크롤바가 튀지 않게 한다
         (`auto` 없이 고정값만 주면 스크롤 위치가 흔들린다)
       · contain:layout style — 메시지 하나가 바뀌어도 형제들을 다시 계산하지 않는다

     **사용자 말풍선에는 걸지 않는다.** `/스킬` 필의 설명 툴팁(.slashtip)이 말풍선 위로
     빠져나가는데, content-visibility가 붙이는 paint 격리가 그걸 잘라낸다. 답변 쪽이
     길고 무거운 쪽이라 효과는 거기서 거의 다 나온다. */
  .msg.ai { content-visibility:auto; contain-intrinsic-size:auto 280px; }
  /* 화면 밖으로 나가도 **쓰는 중인 답**은 건너뛰지 않는다 — 타이핑이 멈춘 것처럼 보인다 */
  .msg.ai.streaming { content-visibility:visible; }
  /* 접힌 메시지 — 내용은 떼어 보관하고 **높이만** 자리를 지킨다(chat.js foldOld).
     인라인 height가 정본이므로 여기서 크기를 정하지 않는다. 화면에 닿기 전에
     IntersectionObserver가 되살리므로 사용자는 빈 자리를 보지 못한다. */
  .msg.folded { overflow:hidden; contain:strict; }
  .msg.folded .msgact { display:none; }
  /* 메시지 — 클로드 벤치마킹 (docs/33): AI는 프로즈(버블 제거), 사용자는 서브틀 컨테이너 */
  /* 13.5 → 15px (사용자 지시 2026-08-20 "답변한 폰트가 내 기준엔 좀 작아").
     입력창(15.5px)과 **거의 같은 크기로 모은다** — 묻는 글과 답하는 글의 크기가
     크게 다르면 한 대화가 두 문서처럼 읽힌다. 아래 제목·중첩목록도 같은 비율로
     올린다: 안 올리면 h5(13.5)가 본문(15)보다 **작아져 위계가 뒤집힌다.** */
  /* contain:layout style — 메시지 하나가 바뀌어도 형제들을 다시 계산하지 않는다.
     paint는 넣지 않는다: /스킬 툴팁(.slashtip)이 말풍선 위로 빠져나가야 해서
     잘리면 안 된다. 자세한 배경은 아래 '스크롤 성능' 블록. */
  .msg { max-width:100%; font-size:15px; word-break:break-word; contain:layout style; }
  /* 슬래시 명령 필 (사용자 2026-08-02, 클로드 /simplify 문법) — 하늘색 토큰 + 호버 설명 툴팁.
     툴팁 배경은 필보다 한 단계 옅은 하늘색, 설명 아래 '스킬' 라벨. */
  .msg .slashcmd { position:relative; display:inline-block; color:var(--mention); font-weight:600;
    background:color-mix(in srgb, var(--mention) 13%, transparent); border-radius:6px;
    padding:0 5px; cursor:default; }
  .msg .slashtip { display:none; position:absolute; bottom:calc(100% + 7px); left:-4px;
    width:max-content; max-width:280px; white-space:normal;
    background:color-mix(in srgb, var(--mention) 7%, var(--panel));
    border:1px solid color-mix(in srgb, var(--mention) 32%, var(--line));
    border-radius:10px; padding:9px 11px; font-size:var(--fs-sub); font-weight:400;
    color:var(--text); line-height:1.55; box-shadow:var(--shadow); z-index:20; }
  .msg .slashtip small { display:block; margin-top:6px; color:var(--dim2); font-size:var(--fs-lab); }
  .msg .slashcmd:hover .slashtip { display:block; }
  .msg.user { align-self:flex-end; max-width:86%; }
  .msg.user .msgbody { background:color-mix(in srgb, var(--accent) 14%, var(--panel));
    padding:9px 12px; border-radius:14px 14px 4px 14px; white-space:pre-wrap; }
  .msg.ai { align-self:stretch; }
  .msg.ai .msgid { display:flex; align-items:center; gap:6px; margin-bottom:4px;
    font-size:var(--fs-lab); font-weight:700; color:var(--ai); letter-spacing:.02em; }
  /* msgid 스파크 마크 제거 (사용자 지시 2026-07-22 "중복 느낌") — 마크는 생각 중(jvthink)에만 */
  /* 행간 1.65 → 1.8 (머신러너님 지시 2026-08-31 "전체적으로 행간을 좀 더").
     답이 1,200자를 넘기 시작했다(같은 날 실측 · 착수 전 921자) — 길어진 글에
     같은 행간을 두면 벽처럼 읽힌다. 폰 세로에서 특히 그렇다. */
  .msg.ai .msgbody { white-space:normal; line-height:1.8; }
  /* AI 답변 마크다운 프로즈 — 인라인 위젯 = 주비스의 얼굴 (사용자 지시 2026-07-26 "클로드 것을 그대로 따르자").
     클로드 답변 타이포 문법: 표=가로 구분선만(격자·헤더배경 없음)·숫자 우측정렬, 참고문=작은 회색 캡션,
     섹션 라벨=절제된 오버라인, 넉넉한 수직 리듬. 장식 없이 위계와 여백으로만 읽히게. */
  .msg.ai .msgbody > :first-child { margin-top:0; }
  .msg.ai .msgbody > :last-child { margin-bottom:0; }
  /* 제목 위 여백 16 → 22px. 소제목은 **앞 문단과 떨어져야** 구간의 시작으로 읽힌다. */
  .msg.ai .msgbody h4, .msg.ai .msgbody h5, .msg.ai .msgbody h6 { margin:22px 0 8px; font-weight:700; line-height:1.4; color:var(--text); letter-spacing:-.01em; }
  /* **답변 제목 3단 사다리** (머신러너님 지시 2026-08-31 2차 — "아래 내용에 나오는 폰트
     크기와는 구분되어야 하지 않을까"). mdlite가 `#→h4 · ##→h5 · ###→h6`로 한 단씩 내리므로
     화면의 실제 위계는 이 셋이다. 본문 15px 기준으로 사다리를 벌린다:

         h4 (`#`)   22px  답 전체의 대제목 — 이 답이 무엇에 관한 것인가 (교리에서 첫 줄로 강제)
         h5 (`##`)  18px  구간 소제목 — 답변에서 가장 흔하다
         h6 (`###`) 16px  그 아래 갈래
         본문       15px

     종전 19/17/14.5는 **h5와 본문이 2px 차이**라 굵기 하나로 버텼고, 폰에서는 그것도 안
     갈렸다. h6은 14.5px + `--dim`이라 본문보다 **작고 흐렸다** — 제목인데 캡션으로 읽혔다.
     그래서 h6은 본문 위로 올리고 색도 본문색으로 돌린다. 제목은 제목처럼 보여야 한다. */
  .msg.ai .msgbody h4 { font-size:22px; font-weight:800; margin-top:26px; }
  /* 18 → 19px (머신러너님 2026-08-31 3차 "폰트가 좀 더 커야해"). 구간 소제목이
     답변에서 가장 흔한 제목이라, 여기가 본문과 확실히 갈려야 훑어보기가 된다. */
  .msg.ai .msgbody h5 { font-size:19px; }
  .msg.ai .msgbody h6 { font-size:16px; }
  /* 문단 간격 8 → 12px — 행간(1.8×15≈27px)보다 커야 문단이 문단으로 읽힌다. */
  .msg.ai .msgbody p { margin:12px 0; }
  .msg.ai .msgbody b { color:var(--text); font-weight:700; }
  .msg.ai .msgbody a { color:var(--ai); text-decoration:underline; text-underline-offset:2px; word-break:break-all; }
  .msg.ai .msgbody ul, .msg.ai .msgbody ol { margin:12px 0; padding-left:19px; }
  .msg.ai .msgbody li { margin:6px 0; }
  .msg.ai .msgbody li::marker { color:var(--dim); }
  .msg.ai .msgbody blockquote { margin:10px 0; padding:2px 0 2px 12px; border-left:2px solid var(--line); color:var(--dim); }
  .msg.ai .msgbody code { background:var(--panel); border:1px solid var(--line); border-radius:4px; padding:0 4px; font-size:var(--fs-sub); font-variant-numeric:tabular-nums; }
  .msg.ai .msgbody pre { position:relative; background:var(--panel); border:1px solid var(--line); border-radius:8px; padding:10px 12px; margin:10px 0; overflow-x:auto; }
  .msg.ai .msgbody pre .lang { position:absolute; top:6px; left:10px; font-size:var(--fs-badge); color:var(--dim); letter-spacing:.06em; text-transform:uppercase; }
  .msg.ai .msgbody pre code { background:none; border:0; padding:0; font-size:var(--fs-sub); line-height:1.5; display:block; white-space:pre; }
  .msg.ai .msgbody pre .codecopy { position:absolute; top:6px; right:6px; width:24px; height:24px; background:var(--panel2); border:1px solid var(--line); color:var(--dim); border-radius:6px; display:inline-flex; align-items:center; justify-content:center; cursor:pointer; opacity:0; transition:opacity .15s ease; }
  .msg.ai .msgbody pre:hover .codecopy { opacity:1; }
  .msg.ai .msgbody pre .codecopy svg { width:13px; height:13px; fill:none; stroke:currentColor; stroke-width:2; }
  /* 표 — 클로드식: 세로선·외곽선·헤더 배경 없음, 가로 구분선만. 헤더는 작고 흐리게, 본문 아래 얇은 선.
     숫자 셀(.num)은 우측 정렬 + tabular-nums(자릿수 정렬). 좁은 드로어에서 넘치면 표만 가로 스크롤(.tblwrap). */
  .msg.ai .msgbody .tblwrap { overflow-x:auto; margin:10px 0; }
  .msg.ai .msgbody table { border-collapse:collapse; width:100%; margin:0; }
  .msg.ai .msgbody th { border:0; border-bottom:1px solid var(--line); background:none;
    padding:5px 10px 6px 0; font-size:var(--fs-sub); font-weight:600; color:var(--dim); text-align:left; letter-spacing:.02em; white-space:nowrap; }
  .msg.ai .msgbody td { border:0; border-bottom:1px solid color-mix(in srgb, var(--line) 55%, transparent);
    padding:6px 10px 6px 0; font-size:12.5px; text-align:left; vertical-align:top; font-variant-numeric:tabular-nums; }
  .msg.ai .msgbody tr > :last-child { padding-right:0; }
  .msg.ai .msgbody tbody tr:last-child td { border-bottom:0; }   /* 마지막 행 선 제거 — 표가 프로즈에 스며들게 */
  .msg.ai .msgbody th.num, .msg.ai .msgbody td.num,
  .msg.ai .msgbody th.al-right, .msg.ai .msgbody td.al-right { text-align:right; }
  .msg.ai .msgbody th.al-center, .msg.ai .msgbody td.al-center { text-align:center; }
  .msg.ai .msgbody th.al-left, .msg.ai .msgbody td.al-left { text-align:left; }
  .msg.ai .msgbody td:first-child { color:var(--text); }
  .msg.ai .msgbody hr { border:0; border-top:1px solid var(--line); margin:14px 0; }
  /* 기울임·취소선 (마크다운 v3) — 절제: 기울임은 색을 바꾸지 않고, 취소선은 흐리게 */
  .msg.ai .msgbody i { font-style:italic; }
  .msg.ai .msgbody s { color:var(--dim); }
  /* 체크 항목 (`- [ ]` / `- [x]`) — SVG 체크박스, 이모지 금지 (docs/28) */
  .msg.ai .msgbody li.mdtask { list-style:none; display:flex; align-items:flex-start; gap:7px; margin-left:-19px; }
  .msg.ai .msgbody li.mdtask .mdck { width:14px; height:14px; flex-shrink:0; margin-top:3px;
    fill:none; stroke:var(--dim); stroke-width:2; stroke-linecap:round; stroke-linejoin:round; }
  .msg.ai .msgbody li.mdtask.on .mdck { stroke:var(--accent); }
  .msg.ai .msgbody li.mdtask.on > span { color:var(--dim); }
  /* 중첩 목록 — 위계는 들여쓰기로만, 마커는 한 단계 더 흐리게 */
  .msg.ai .msgbody li > ul, .msg.ai .msgbody li > ol { margin:3px 0 0; }
  .msg.ai .msgbody li li { font-size:13.5px; }
  /* 섹션 라벨 (데이터/해석/결론/판단/리스크) — 본문과 구분되는 절제된 오버라인 (굵은 본문 글씨 아님) */
  .msg.ai .msgbody .mdlabel { margin:14px 0 3px; font-size:var(--fs-lab); font-weight:700; letter-spacing:.09em; color:var(--dim); }
  .msg.ai .msgbody .mdlabel:first-child { margin-top:0; }
  /* 참고·기준일·면책 — 작은 회색 캡션 (사용자 지시 2026-07-26 "참고사항이면 조금 작은 글씨로 회색") */
  .msg.ai .msgbody .mdnote { margin:10px 0 0; font-size:var(--fs-sub); line-height:1.55; color:var(--dim); }
  .msg.ai .msgbody .mdnote + .mdnote { margin-top:2px; }

  /* ══════════ 인라인 위젯 (```joovis + JSON → 살아있는 카드, chat.js jvWidget · docs/33)
     사용자 지시 2026-07-28 "클로드 코워크처럼 인라인 위젯이 작동해야 해".
     프로즈에 박히는 데이터 조각 — 표와 같은 문법(장식 없이 위계·여백)이되 한 겹 카드로 떠 있다.
     라이브러리 0, 순수 SVG/CSS (타이핑 재렌더에 무상태로 견디게). 이모지 금지. */
  .jvw { margin:12px 0; padding:12px 14px; background:var(--panel); border:1px solid var(--line); border-radius:12px; }
  .jvw .whead { display:flex; align-items:baseline; gap:8px; margin-bottom:10px; }
  .jvw .wtitle { font-size:var(--fs-sub); font-weight:700; letter-spacing:.01em; color:var(--text); }
  .jvw .wasof { margin-left:auto; font-size:var(--fs-lab); color:var(--dim); white-space:nowrap; font-variant-numeric:tabular-nums; }
  .jvw .wnote { margin-top:9px; font-size:var(--fs-lab); line-height:1.5; color:var(--dim); }
  /* 톤 = 의미색. up=빨강·down=파랑(국내 관례, 메인 화면과 통일) · good=에메랄드 · bad=경고 · flat=중립 */
  .jvw .t-up { color:var(--up); } .jvw .t-down { color:var(--down); }
  .jvw .t-good { color:var(--accent); } .jvw .t-bad { color:#f59e0b; } .jvw .t-flat { color:var(--text); }
  .jvw i.t-up { background:var(--up); } .jvw i.t-down { background:var(--down); }
  .jvw i.t-good { background:var(--accent); } .jvw i.t-bad { background:#f59e0b; } .jvw i.t-flat { background:var(--dim); }
  /* ① 지표 타일 — 값 + 비교값(절대값 단독 금지를 형태로 강제) */
  .jvw .wmetrics { display:grid; grid-template-columns:repeat(auto-fit, minmax(96px, 1fr)); gap:1px;
    background:var(--line); border-radius:9px; overflow:hidden; }
  .jvw .wm { background:var(--panel); padding:9px 11px 10px; display:flex; flex-direction:column; gap:2px; min-width:0; }
  .jvw .wml { font-size:var(--fs-lab); color:var(--dim); letter-spacing:.02em; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
  .jvw .wmv { font-size:19px; font-weight:700; line-height:1.15; letter-spacing:-.02em; font-variant-numeric:tabular-nums; }
  .jvw .wms { font-size:var(--fs-lab); color:var(--dim); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
  /* ② 수평 바 — 점수·업종 대비. 음수가 섞이면 0 기준선에서 좌우로 뻗는다(--wz = 0의 위치) */
  .jvw .wbars { display:flex; flex-direction:column; gap:7px; }
  .jvw .wb { display:flex; align-items:center; gap:9px; }
  /* 76px은 한글 5~6자다 — `이수페타시스`가 안 들어가 말줄임으로 잘렸다(신고 2026-09-02).
     한 위젯 = 한 지표(answer.md ②)라 라벨은 대상 이름뿐이지만, 긴 종목명은 늘 있다. */
  .jvw .wbl { flex:0 0 124px; font-size:var(--fs-sub); color:var(--dim); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
  .jvw .wbt { position:relative; flex:1; min-width:0; height:7px; background:var(--panel2); border-radius:4px; }
  .jvw .wbt.zero::before { content:""; position:absolute; left:var(--wz, 50%); top:-2px; bottom:-2px;
    width:1px; background:var(--line); }
  .jvw .wbt i { position:absolute; top:0; height:7px; min-width:2px; border-radius:4px; }
  .jvw .wbv { flex:0 0 auto; min-width:44px; text-align:right; font-size:var(--fs-sub); font-weight:600;
    color:var(--text); font-variant-numeric:tabular-nums; }
  /* ③ 미니 라인 — 시리즈별 독립 정규화(주가와 실적의 '관계'가 보이게, 아이투자 V차트 사상) */
  .jvw .wline { position:relative; }
  .jvw .wlsvg { display:block; width:100%; height:64px; overflow:visible; }
  .jvw .wlsvg polyline { fill:none; stroke-width:1.6px; stroke-linejoin:round; stroke-linecap:round; }
  .jvw .wlx { display:flex; justify-content:space-between; margin-top:4px; font-size:var(--fs-badge); color:var(--dim);
    font-variant-numeric:tabular-nums; }
  .jvw .wleg { display:flex; flex-wrap:wrap; gap:12px; margin-top:8px; }
  .jvw .wlg { display:inline-flex; align-items:center; gap:5px; font-size:var(--fs-lab); color:var(--dim); }
  .jvw .wlg i { width:11px; height:2px; border-radius:1px; flex-shrink:0; }
  .jvw .wlg i.dash { background:none !important;
    background-image:repeating-linear-gradient(to right, currentColor 0 3px, transparent 3px 5px) !important; }
  .jvw .wlg i.solid { height:8px; width:8px; border-radius:2px; background:var(--accent); }
  .jvw .wlg i.estl { height:8px; width:8px; border-radius:2px; background:color-mix(in srgb, var(--accent) 34%, transparent);
    border:1px solid color-mix(in srgb, var(--accent) 55%, transparent); }
  /* ④ 분기 막대 — 확정=솔리드 / 추정=반투명 (컨센서스 차트 문법과 통일, 사용자 확정) */
  .jvw .wq { --wqgap:3px; }
  .jvw .wqrow, .jvw .wqlabs { display:flex; gap:var(--wqgap); }
  .jvw .wqrow { position:relative; height:74px; align-items:flex-end; }
  .jvw .wqc { position:relative; flex:1; min-width:0; height:100%; }
  .jvw .wqbar { position:absolute; left:12%; right:12%; border-radius:3px 3px 0 0; background:var(--accent); min-height:1px; }
  .jvw .wqbar.neg { border-radius:0 0 3px 3px; background:var(--down); }
  .jvw .wqbar.est { background:color-mix(in srgb, var(--accent) 32%, transparent);
    border:1px solid color-mix(in srgb, var(--accent) 60%, transparent); }
  .jvw .wqbar.est.neg { background:color-mix(in srgb, var(--down) 32%, transparent);
    border-color:color-mix(in srgb, var(--down) 60%, transparent); }
  .jvw .wqzero { position:absolute; left:0; right:0; bottom:var(--wz, 0); height:1px; background:var(--line); }
  .jvw .wqlabs { margin-top:5px; }
  .jvw .wql { flex:1; min-width:0; text-align:center; font-size:var(--fs-badge); color:var(--dim);
    white-space:nowrap; overflow:hidden; text-overflow:clip; }
  /* ⑤ 판단 카드 — 헌장(docs/48)의 심장: 반증 없는 판단은 판단이 아니다 */
  .jvw-verdict { border-color:color-mix(in srgb, var(--accent) 26%, var(--line)); }
  .jvw .wv { display:flex; align-items:baseline; gap:10px; flex-wrap:wrap; }
  .jvw .wvb { font-size:20px; font-weight:800; letter-spacing:-.02em; }
  .jvw .wvs { font-size:var(--fs-sub); color:var(--dim); line-height:1.5; }
  .jvw .wvsec { margin-top:11px; }
  .jvw .wvl { display:block; font-size:var(--fs-badge); font-weight:700; letter-spacing:.09em; color:var(--dim); margin-bottom:4px; }
  .jvw .wvsec ul { margin:0; padding-left:15px; }
  .jvw .wvsec li { margin:3px 0; font-size:var(--fs-sub); line-height:1.55; }
  .jvw .wvsec li::marker { color:var(--dim); }
  .jvw .wvsec.falsify li::marker { color:var(--accent); }
  .jvw .wvmiss { margin-top:11px; padding:7px 10px; border-radius:8px; font-size:var(--fs-lab); line-height:1.5;
    color:#f59e0b; background:color-mix(in srgb, #f59e0b 10%, transparent);
    border:1px solid color-mix(in srgb, #f59e0b 30%, transparent); }
  /* ⑥ 신호등 — 축별 판정. 색은 **왼쪽 띠 하나**로만 말한다(읽는 문장은 검정 유지).
     본문에 이모지를 뿌리던 것을 대체한다 (사용자 지시 2026-08-08). */
  .jvw .wsig { display:flex; flex-direction:column; }
  .jvw .wsr { display:grid; grid-template-columns:3px 78px auto 1fr; align-items:baseline;
    gap:0 10px; padding:7px 0; border-top:1px solid var(--line); }
  .jvw .wsr:first-child { border-top:0; padding-top:2px; }
  .jvw .wsr > i { grid-row:1; align-self:stretch; border-radius:2px; min-height:15px; }
  .jvw .wsk { font-size:var(--fs-sub); color:var(--dim); }
  .jvw .wsv { font-size:12.5px; font-weight:700; white-space:nowrap; }
  .jvw .wsn { font-size:var(--fs-sub); color:var(--dim); line-height:1.5; text-align:right;
    font-variant-numeric:tabular-nums; }
  /* 결측 행 — 판정처럼 보이지 않게 흐리게 (하드 규칙 6: 사유 있는 N/A) */
  .jvw .wsr.na .wsv { color:var(--dim); font-weight:400; }
  .jvw .wsr.na > i { opacity:.35; }
  /* ⑦ 위치 게이지 — 밴드 안 현재 위치. "높다/낮다"를 글자 대신 자리로 */
  .jvw .wg { display:flex; flex-direction:column; gap:12px; }
  .jvw .wgh { display:flex; align-items:baseline; gap:8px; margin-bottom:5px; }
  .jvw .wghl { font-size:var(--fs-sub); color:var(--dim); }
  .jvw .wghv { margin-left:auto; font-size:13px; font-weight:700;
    font-variant-numeric:tabular-nums; }
  .jvw .wgt { position:relative; height:5px; border-radius:3px; background:var(--panel2);
    border:1px solid var(--line); }
  .jvw .wgt > i { position:absolute; top:50%; width:9px; height:9px; border-radius:50%;
    transform:translate(-50%, -50%); border:2px solid var(--panel); }
  .jvw .wge { display:flex; justify-content:space-between; margin-top:4px;
    font-size:var(--fs-lab); color:var(--dim); font-variant-numeric:tabular-nums; }
  @media (max-width: 460px) {
    .jvw .wsr { grid-template-columns:3px 1fr auto; }
    .jvw .wsn { grid-column:2 / -1; text-align:left; margin-top:2px; }
    /* 데스크톱 124px을 폰에 그대로 두면 **막대가 설 자리가 없다** — 375px에서
       라벨 124 + 값 44 + 여백을 빼면 막대가 100px 남짓이다. 라벨을 줄여 막대를 살린다.
       (한 위젯 = 한 지표라 라벨은 대상 이름뿐이므로 92px로도 대개 들어간다) */
    .jvw .wbl { flex:0 0 92px; }
  }
  /* 타이핑 중(펜스 미닫힘) 스켈레톤 · 스펙 오류 낙하 — 어느 쪽도 답변 전체를 잃지 않는다 */
  .jvw.wskel { display:flex; flex-direction:column; gap:7px; }
  .jvw.wskel .skel { height:11px; border-radius:5px; background:var(--panel2); }
  .jvw.wskel .skel:last-child { width:62%; }
  .jvw.wbad { font-size:var(--fs-sub); color:var(--dim); background:none; border-style:dashed; padding:9px 12px; }
  /* 메시지 액션 — 호버 시 복사·다시 생성 (SVG, 이모지 금지) */
  /* 질문 수정 — 말풍선 자리에서 바로 (2026-08-18). 상자가 말풍선을 대체하므로 폭·여백을
     말풍선에 맞추고, 편집 중에는 호버 액션을 감춘다(수정 버튼을 또 누를 일이 없다). */
  .msg.editing .msgact { display:none; }
  /* 편집 중에는 말풍선을 넓힌다 — 86%짜리 좁은 자리에서 여러 줄을 고치기 어렵다.
     말풍선 배경도 벗긴다: 상자 안에 상자가 겹쳐 보이지 않게. */
  .msg.user.editing { max-width:100%; align-self:stretch; }
  .msg.user.editing .msgbody { background:transparent; padding:0; }
  .msgedit textarea { display:block; width:100%; min-height:52px; max-height:40vh; resize:none;
    font:inherit; font-size:13px; line-height:1.6; color:var(--text); background:var(--panel);
    border:1px solid var(--accent); border-radius:10px; padding:9px 11px; outline:none;
    overflow-y:auto; }
  .msgeditrow { display:flex; align-items:center; gap:6px; margin-top:7px; }
  .msgeditnote { margin-right:auto; font-size:var(--fs-lab); color:var(--dim); }
  .msgeditrow button { font:inherit; font-size:var(--fs-sub); padding:5px 12px; border-radius:999px;
    border:1px solid var(--line); background:transparent; color:var(--dim); cursor:pointer;
    transition:background-color .15s ease, color .15s ease; }
  .msgeditrow button:hover { background:var(--panel2); color:var(--text); }
  .msgeditrow button.go { border-color:var(--accent); color:var(--panel);
    background:var(--accent); font-weight:600; }
  .msgeditrow button.go:hover { filter:brightness(1.06); color:var(--panel); }
  .msgact { display:flex; gap:2px; margin-top:5px; opacity:0; transition:opacity .15s ease; }
  .msg.user .msgact { justify-content:flex-end; }
  .msg:hover .msgact, .msg .msgact:focus-within { opacity:1; }
  .msgact button { width:26px; height:26px; background:transparent; border:0; color:var(--dim); border-radius:6px;
    display:inline-flex; align-items:center; justify-content:center; cursor:pointer; transition:color .15s ease, background-color .15s ease; }
  .msgact button:hover { color:var(--ai); background:var(--panel2); }
  .msgact button.ok { color:var(--accent); }
  .msgact button svg { width:14px; height:14px; fill:none; stroke:currentColor; stroke-width:2; stroke-linecap:round; stroke-linejoin:round; }
  /* 대기 모션 — 답변 자리에서 로고 단독 가속 회전, 문구 없음 (사용자 지시 2026-07-22
     "로고가 가속도로 회전하면서 진행, '분석중' 문구 빼고" — 클로드식 미니멀).
     회전 자체는 chat.js addThinking의 WAAPI가 구동 (CSS 스큐 무관) — 여기는 크기·색만 */
  .jvthink { display:inline-flex; align-items:center; padding:3px 0; }
  /* ---------- 대기 모션 = 팻이 파닥이며 폴짝 + 문구 빔 (사용자 지시 2026-08-05) ----------
     구 심볼 WAAPI 회전은 폐기. 몸통은 웅크림→도약→착지, 날개는 그보다 3배 빠르게 파닥인다. */
  .jvthink .jvpet { flex-shrink:0; display:block; }
  /* 5프레임 스프라이트 애니메이션 (사용자 제공 joovis_code_1~5, 마젠타 크로마키 제거 후 스트립화).
     프레임 안에 날개 폄·접힘·도약이 이미 그려져 있어 CSS로 덧댈 게 없다 — "붙인 티" 문제 해소.
     5장을 **합집합 bbox 동일 크롭**으로 잘라 프레임 전환 시 튀지 않는다. */
  /* 스프라이트는 **날개·꼬리 변화만** 담고(원본의 세로 26px 통짜 이동은 추출 때 상쇄),
     상하 부유는 CSS가 매끄럽게 보간한다 — steps()로 세로까지 옮기면 8단계로 뚝뚝 끊겨
     "부자연스럽다"(사용자 지적 2026-08-05). 부유 주기 = 프레임 주기라 둘이 한 몸으로 움직인다. */
  .jvthink .jvpet { width:33px; height:29px; margin-right:10px;
    background:url(/static/img/brand/joovis_pet_strip8.png) 0 0 / 264px 29px no-repeat;
    image-rendering:pixelated;
    animation:jvframes 1.25s steps(8) infinite, jvfloat 1.25s cubic-bezier(.36,0,.3,1) infinite; }
  @keyframes jvframes { from { background-position:0 0; } to { background-position:-264px 0; } }
  /* 상하 부유 진폭 = **전체가 통째로 뜬다**는 게 읽힐 만큼 (사용자 지적 2026-08-05
     "위아래로 늘어나는 느낌이라 이상하다"). 스프라이트 8프레임에는 세로 이동이 0px이고
     (실측: 몸통 중심 y가 8프레임 모두 동일) 발·날개 모양만 바뀐다 — 그래서 2px 부유로는
     '몸이 뜬다'가 아니라 '다리가 늘었다 줄었다'로만 보였다. 5px(캐릭터 높이의 17%)로 키우고
     곡선도 도약처럼: 빠르게 솟았다가 천천히 내려앉는다. 세로 크기는 건드리지 않는다
     (scale 금지 — 그게 진짜 '늘어남'이 된다). */
  @keyframes jvfloat { 0%, 100% { transform:translateY(1px); } 46% { transform:translateY(-4px); } }
  /* 문구 빔 (ChatGPT 문법): 밝은 띠가 글자 위를 좌→우로 훑는다.
     배경 위치는 100%→0%이어야 하이라이트가 왼쪽에서 오른쪽으로 지나간다(반대로 하면 역방향). */
  .jvthink .jvtx { font-size:13px; font-weight:500;
    background:linear-gradient(100deg, var(--dim) 34%, var(--text) 50%, var(--dim) 66%);
    background-size:260% 100%; -webkit-background-clip:text; background-clip:text;
    -webkit-text-fill-color:transparent; color:transparent;
    animation:jvbeam 1.05s linear infinite; }   /* 빔 속도 ↑ (사용자 지시 2026-08-05: 1.7s→1.05s) */
  @keyframes jvbeam { 0% { background-position:130% 0; } 100% { background-position:-30% 0; } }
  /* 문구·물결 점(jvtx·jvdot) 제거 — 로고 단독 회전(WAAPI, JS가 reduce-motion 판정)으로 대체 (2026-07-22) */
  #quickq { display:flex; flex-wrap:wrap; gap:5px; padding:0 12px 8px; }
  /* 추천 프롬프트는 대화 시작 전(빈 챗)에만 — 메시지가 하나라도 생기면 숨김 (사용자 지시 2026-07-22).
     :has()라 전송·포트 이어보기·도구 카드 등 모든 진입 경로를 JS 수정 없이 커버, 챗 초기화 시 자동 복귀 */
  #chatpanel:has(#chatlog .msg) #quickq { display:none; }
  /* 인사 화면에는 이미 추천 카드 4장이 서 있다. 그 아래 칩까지 두면
     같은 역할이 두 번 보이고 화면이 무거워진다 (사용자 지적 2026-08-18:
     "추천 프롬프트 4개가 주어지면 그 아래에는 주어질 필요 없다"). */
  #chatpanel:has(#chatlog .greet) #quickq { display:none; }
  #quickq button { background:transparent; border:1px solid var(--line); color:var(--dim); border-radius:12px; padding:3px 9px; font-size:var(--fs-sub); cursor:pointer; }
  #quickq button:hover { color:var(--ai); border-color:var(--ai); }
  /* 컴포저(#chatform·#chatbox·#chatinput·#chatsend·.chatctx) 스타일은 아래 드로어 블록에 통합 정의 */
  .thinking { color:var(--dim); font-style:italic; }
  #empty { color:var(--dim); text-align:center; margin-top:24vh; font-size:15px; }

  /* 좁은 화면(모바일·좁은 창): 사이드바를 상단 가로 스트립으로, 본문 세로 스택 */
  @media (max-width: 900px) {
    body { overflow-y:auto; height:auto; flex-direction:column; }
    #sidebar { width:100%; flex-direction:row; align-items:center; padding:8px 10px; gap:6px; border-right:0; border-bottom:1px solid var(--line); overflow-x:auto; }
    #sidebar .logo { padding:0 8px 0 2px; font-size:16px; }
    #sidebar .logo small { display:none; }
    #sidebar nav { flex-direction:row; flex:initial; }
    #sidebar nav a { padding:6px 10px; white-space:nowrap; }
    #sidebar nav a .soon { display:none; }
    /* **접힘 상태가 가로 스트립을 이기던 것** (실측 2026-08-29, 폰 랜딩 스크린샷).
       위 `#sidebar{width:100%}`(특이도 0,1,0)보다 `body.nav-collapsed #sidebar`(0,2,1, app.css:262)가
       세서 폭이 61px로 남았다. 그 결과 375px 폰에서 사이드바가 **61x74 상자로 잘려** 홈·포트폴리오
       두 아이콘만 보이고 나머지 메뉴(x=61~226)와 로그인 버튼이 상자 밖에서 사라졌다.
       같은 선택자를 여기 다시 써서 **순서로** 이긴다(특이도가 같으면 뒤엣것이 이긴다).
       접기 버튼은 감춘다 — 가로 스트립에는 '접는다'는 개념이 없고, 실제로 y=-75(화면 위)로
       벗어나 있었다. */
    body.nav-collapsed #sidebar { width:100%; padding-left:10px; padding-right:10px; }
    #navtoggle { display:none; }
    #sidebar .foot { border-top:0; padding:0; margin-left:auto; flex-direction:row; }
    #sidebar .ver { display:none; }
    header { flex-wrap:wrap; gap:8px; }
    .searchwrap { width:100%; order:3; }
    main { grid-template-columns:1fr; overflow:visible; }
    #left { overflow:visible; }
    /* #cards 열 수는 위 컨테이너 쿼리(leftcol)가 담당 — 뷰포트 기준 재정의는 균형 규칙을 깨므로 두지 않는다 */
    #chartbox { height:420px; }
    /* #chatpanel 높이는 여기서 못 정한다 — 아래 드로어 규칙의 height:auto가
       같은 특이도로 더 뒤에 있어 늘 이긴다(실측 2026-08-31). 드로어는 top:0·bottom:0으로
       화면 높이를 다 쓴다. 옛 인페이지 레이아웃 시절의 480px은 죽은 줄이었다. */
    #empty { margin-top:8vh; }
  }

/* 메모 (고도화 5단계) + 시장 온도계 */
.memo { background:transparent; border:0; cursor:pointer; font-size:13px; color:var(--line); padding:0 3px; }
.memo.on, .memo:hover { color:var(--accent); }
.memotxt { color:var(--dim); font-size:var(--fs-sub); margin-left:4px; font-style:italic; }
#marketline .up { color:var(--up); } #marketline .down { color:var(--down); }
#marketline b { color:var(--text); }

/* AI 주식 시장 브리핑 — 홈 전용, 스타일은 [디자인 패스 5] 섹션의 .bsec */

/* ---------- [디자인 패스 1: 메인] docs/28 파일럿 — 승인 시 타 모듈 확산 ---------- */
/* 숫자는 고정폭(tabular) — 가격·등락이 흔들리지 않고 정렬됨 (전역, 고급 터미널 문법) */
body { font-variant-numeric: tabular-nums; }
/* 읽기 폭 제한 + 섹션 라벨: 작고 넓은 자간의 조용한 표지판 */
#view-home { max-width:1120px; padding:30px 32px; font-family:'Inter',-apple-system,'Noto Sans KR','Apple SD Gothic Neo',sans-serif; }   /* 패스13 애플-심플: 본문 SF 대체(Inter), 한글은 Noto 폴백 */
/* **배경 틴트 재도입 금지** (사용자 반려 2026-08-04 "색이 따로노는 느낌 · 배경은 이전 회색으로").
   메인 배경에 파스텔 청록을 깔았더니 시그니처 에메랄드와 청록 두 계열이 부딪쳤다.
   메인의 색은 **시그니처 한 색(--accent)만** — 배경은 중립 --bg 그대로 둔다. */
/* 섹션 라벨: 라벨이 오른쪽으로 괘선을 여는 편집 문법 (패스 7) — 구분이 분명해지고 조용히 고급 */
#view-home h3 { display:flex; align-items:center; gap:12px; font-size:var(--fs-sub); font-weight:700;
  letter-spacing:.12em; color:var(--dim); margin:30px 0 10px; }
#view-home h3::after { content:""; flex:1; height:1px; background:var(--line); }
/* 섹션 라벨 우측 링크 (라벨—괘선—링크 순): 관심종목 → 전체 화면 */
#view-home h3 .h3link { order:1; font-size:var(--fs-lab); font-weight:400; letter-spacing:.02em;
  color:var(--dim); cursor:pointer; transition:color .15s ease; }
#view-home h3 .h3link:hover { color:var(--accent); }
/* 크레도 — 주비스 철학의 한 줄 (사실/해석 구분·판단은 사용자, docs/28·29). 화면 맨 아래 조용히 */
#homecredo { text-align:center; font-size:var(--fs-sub); color:var(--dim); letter-spacing:.02em; margin:30px 0 8px; }
#homecredo b { color:var(--accent); font-weight:700; letter-spacing:.14em; margin-left:12px; }
/* ---------- [디자인 패스 11: 메인 단아·모던] 작업 존을 통일 카드로 — 구분 명확 + 여백 (2026-07-15 사용자 지시) ----------
   지수+브리핑은 열린 히어로(page bg), 후보·AI픽·관심종목은 동일한 카드 표면으로 담아 경계를 확실히.
   카드 안엔 박스를 겹치지 않는다(중첩 금지 — 패스 5 교훈). 존 사이 넉넉한 여백. */
.hcard { background:var(--panel); border:.5px solid var(--line); border-radius:16px; overflow:hidden; margin-top:22px; box-shadow:var(--shadow); }   /* 패스14 모던 럭셔리 B: 카드 레이어 + 은은한 소프트 섀도(깊이) */
.hcard-h { display:flex; align-items:center; gap:10px; padding:14px 20px 13px; font-size:var(--fs-sub); font-weight:700;
  letter-spacing:.12em; color:var(--dim); border-bottom:1px solid var(--line); }
.hcard-h .hcard-sub { font-weight:400; letter-spacing:.02em; font-size:var(--fs-lab); color:var(--dim); opacity:.85; }
.hcard-h .hcard-meta, .hcard-h .h3link { margin-left:auto; font-weight:400; letter-spacing:.02em; font-size:var(--fs-lab); color:var(--dim); }
.hcard-h .h3link { cursor:pointer; transition:color .15s ease; }
.hcard-h .h3link:hover { color:var(--accent); }
/* 히어로(브리핑)와 첫 카드 사이는 넉넉히 — 존 전환을 여백으로 */
.bdek + .hcard { margin-top:42px; }
/* 관심종목 표는 카드 안에서 테두리 없이 흐른다 (카드가 경계 제공) */
.hcard-watch #homewatch .wtbl { border:0; border-radius:0; background:transparent; }
.hcard-watch #homewatch .wtbl tbody tr:last-child td { border-bottom:0; }
.hcard-watch #homewatch .emptywatch { border:0; padding:18px 20px; }
/* ---------- [디자인 패스 5: 메인 탈AI] 카드·그라데이션 제거 → 마스트헤드+플랫 섹션 (docs/28 체크리스트 준수) ---------- */
/* 지수 전광판 = 마스트헤드: 신문 1면 문법 — 박스 없이 확실히 구분.
   상단은 굵은 룰+가는 룰 이중 괘선(패스 7 — 고전 편집 디자인의 고급 디테일), 하단 단일 헤어라인.
   볼드·중앙정렬 대형 숫자는 유지(사용자 확정) — 화면 유일의 대형 타이포 앵커 */
/* 패스 10: 신문 날짜줄 — 마스트헤드 위 오늘 날짜 (사람 손길의 에디토리얼 디테일, 친근함 ⑥) */
/* 날짜줄 = 날짜(조금 크게) + 옆에 지수 업데이트 시각(분 단위) — 사용자 지시 2026-07-22 */
#homehero .hdate { text-align:center; font-size:14px; font-weight:500; color:var(--text);
  letter-spacing:.02em; margin-bottom:10px; }
#homehero .hnow { font-size:var(--fs-sub); font-weight:400; color:var(--dim); letter-spacing:.02em; margin-left:10px; }
#homehero .hnow::before { content:"·"; margin-right:10px; color:var(--line); }
/* 패스 9: 지수 대형 전광판 복원 — 메인의 대표는 지수 (사용자 최종 확정 2026-07-15, 불변).
   이중 괘선 마스트헤드 + 볼드·중앙 42px. 타입 스케일 42(지수)→21(AI 헤드라인)→13.5(본문)→11(라벨) */
/* **지수 박스·그라데이션 재도입 금지** (사용자 반려 2026-08-04 "촌스럽다 · 에메랄드 박스가 형편없다").
   시그니처 그라데이션 박스(라운드 18 + 3색 그라데이션 + 섀도)를 씌웠다가 즉시 되돌렸다 —
   전광판은 **박스 없는 마스트헤드**가 정답이다(패스13 애플-심플 이후 유지된 형태).
   docs/28 §색 "그라데이션 금지"에 예외는 없다. */
#homehero .hwrap { display:flex; align-items:flex-end; justify-content:center; gap:46px; flex-wrap:wrap;
  position:relative; border-bottom:1px solid var(--line); padding:24px 8px 24px; }
#homehero .hwrap::before { display:none; }   /* 패스13 애플-심플: 에디토리얼 이중 괘선 제거 — 장식 덜어내고 여백으로 (사용자 "심플=고급" 지시, 구 시그니처#1 수정) */
#homehero .hcell { text-align:center; }
#homehero .hdiv { width:1px; align-self:stretch; background:var(--line); margin:8px 0; }
#homehero .hk { font-size:var(--fs-th); letter-spacing:.14em; color:var(--dim); font-weight:700; margin-bottom:5px; }   /* KOSPI·KOSDAQ 라벨 — 대문의 주인공 이름이라 한 단 위(사용자 지시 2026-08-20 "조금 더 키우자") */
#homehero .hv { font-size:23px; font-weight:700; line-height:1.1; letter-spacing:-.02em; }
#homehero .big .hv { font-size:52px; font-weight:700; letter-spacing:-.024em; }   /* 항목1(2026-07-16): KOSPI·KOSDAQ 42→52px 확대 (지수=대표, 더 크게) */
#homehero .hc { font-size:12.5px; margin-top:5px; font-weight:600; }
#homehero .hc.up { color:var(--up); } #homehero .hc.down { color:var(--down); }
/* 지수 스파크라인 (사용자 지시 2026-08-14) — 선 + 아래로 사라지는 그라데이션.
   **색은 등락색 그대로**: 오르면 --up(빨강) 내리면 --down(파랑). 여기서 색을 정하는 게 아니라
   `color`만 정하고, 선(stroke)·면(그라데이션 stop)이 currentColor로 그 색을 따라간다.
   이건 데이터를 그리는 면이라 §그라데이션 금지(장식용 표면)와 별개다 — 차트의 area fill 문법.
   폭은 셀을 꽉 채우고 높이만 고정 → 숫자 아래 얇은 띠로 앉는다. */
#homehero .hspwrap { margin-top:12px; min-height:56px; }   /* 비동기로 채워지므로 자리를 미리 잡는다(레이아웃 시프트 방지) */
#homehero .hspwrap.empty { margin-top:0; min-height:0; }   /* 당일 점이 없으면(장 전·휴장) 자리째 걷는다 — 빈 띠 금지 */
#homehero .hspark { display:block; width:100%; height:56px; }   /* 30px는 "너무 플랫"해 반려 (2026-08-14) */
#homehero .hspark.up { color:var(--up); }
#homehero .hspark.down { color:var(--down); }
#homehero .hspark.flat { color:var(--dim); }
#homehero .hspline { stroke:currentColor; stroke-width:1.6; stroke-linejoin:round; stroke-linecap:round; }
/* AI 주식 시장 브리핑 = 좌측 대형 헤드라인 + 옆 설명 (항목2 2026-07-16 — 중앙 자막에서 좌측 에디토리얼로).
   "큰 문구를 왼쪽에, 그 옆에 설명" — 헤드라인(사실 압축)이 주인공, 가이드(해석)가 조연. */
.bsec { margin-top:0; }
/* 마스트헤드 = 좌측 대형 키워드 명패(라운드 패널, 안 B 사용자 확정 2026-07-16) | 우측 내용(헤드라인·해석·팩트) */
.bsec .bdek { display:grid; grid-template-columns:200px minmax(0,1fr); gap:28px; align-items:start;
  text-align:left; padding:26px 0 0; }
.bsec .bplate { background:var(--panel2); border-radius:12px; padding:16px 18px 18px; }
.bsec .bico { width:20px; height:20px; }
.bsec .bwm { font-size:25px; font-weight:700; letter-spacing:-.02em; line-height:1.16; color:var(--text); margin:9px 0 0; }
.bsec .bwac { display:block; width:26px; height:3px; background:var(--accent); margin:11px 0 0; }
.bsec .bmeta { display:block; font-size:var(--fs-sub); font-weight:400; color:var(--dim); cursor:help; margin:10px 0 0; }
.bsec .bcontent { min-width:0; }
.bsec .bheadline { font-size:26px; font-weight:700; letter-spacing:-.02em; line-height:1.24; margin:0; }
.bsec .bguide { font-size:14px; color:var(--dim); line-height:1.5; margin-top:9px; }
@media (max-width:820px) { .bsec .bdek { grid-template-columns:1fr; gap:14px; } .bsec .bheadline { font-size:22px; } }
/* 후보 카드 에디토리얼 넘버링 01·02·03 (패스 9) — 데이터가 아닌 조판의 손길 */
.bsec .bnum { font-size:var(--fs-lab); color:var(--dim); letter-spacing:.08em; font-weight:400; }
/* ---------- 주비스의 한마디 (사용자 지시 2026-07-22 — 애플식 절제) ----------
   메인은 지수 + 이 한 줄이 전부. 카드·테두리 없이 여백 위 타이포만 (문장 하나에 상자를 두르지 않는다).
   질문 입력은 좌측 대화 드로어, 시장 심리는 심리 메뉴 — 메인에 두지 않는다. */
.jsay { max-width:680px; margin:52px auto 0; text-align:center; }
/* 인삿말 글자는 본문색(검정) — 시그니처는 **아이콘만** (사용자 확정 2026-08-04).
   한 문장을 통째로 액센트로 칠했더니 과했다: 브랜드 색은 '가리키는 자리'(아이콘)에만 두고
   읽는 글은 본문색으로 둔다. .saytext에 color 지정 금지. */
/* 여러 줄(한 문장 = 한 줄, 2026-08-04): 1.65는 문단용이라 줄이 흩어져 보인다 → 1.5로 조여
   세 줄이 하나의 덩어리로 읽히게. `text-wrap:balance`는 각 줄이 길어 접힐 때 좌우를 고르게 나눈다. */
.jsay .saytext { font-size:20px; font-weight:500; line-height:1.5; letter-spacing:-.012em; margin:0;
  text-wrap:balance; }
/* [폐지 2026-08-31] .jsay .saypet — 인삿말 앞 마스코트. 화면 구석의 AI 버튼(#chattab)이
   같은 마스코트를 달고 떠 있어 한 화면에 주비스가 둘이 됐다 (머신러너님 지시). git 이력에 있다. */
@media (max-width:820px) { .jsay { margin-top:36px; } .jsay .saytext { font-size:17.5px; } }
/* ---------- 3레이어: 오늘, 함께 볼까요 (사용자 지시 2026-07-22 — 지능화=AI 자율 생성, 하루 1회) ----------
   카드 없이 헤어라인 행 3줄. 클릭 → 해당 화면으로 이동. 호버는 시그니처 에메랄드. */
.jtoday { max-width:680px; margin:44px auto 0; }
.jtoday .jtlab { font-size:var(--fs-lab); font-weight:700; letter-spacing:.12em; color:var(--dim); text-align:center; margin-bottom:10px; }
/* 슬롯 라벨 (2026-07-28) — 시각 대신 '장 초반/장 마감'만. 지나간 시각은 표기하지 않는다 */
.jtoday .jtslot { font-weight:400; letter-spacing:.02em; opacity:.7; margin-left:7px; }
.jtoday .jtrow { display:flex; align-items:center; gap:12px; width:100%; padding:15px 8px; text-align:left;
  background:transparent; border:0; border-top:1px solid var(--line); color:var(--text);
  font:inherit; font-size:15px; line-height:1.45; cursor:pointer;
  transition:color .15s ease, background-color .15s ease; }
.jtoday .jtrow:last-child { border-bottom:1px solid var(--line); }
/* 호버 = 색 + 아주 옅은 청록 베일 (2026-08-04) — 행이 '떠오르는' 정도, 칠하는 게 아니다 */
.jtoday .jtrow:hover { color:var(--accent); background:var(--tg-veil); }
/* 행 아이콘 = 좌측 메뉴 아이콘 복제 (2026-07-22) — 어디로 가는지 한눈에.
   색은 시그니처 --accent (사용자 지시 2026-08-04 "그 아래의 느낌도 시그니처 컬러로") —
   인삿말과 같은 한 색으로 묶어 메인이 하나의 계열로 읽히게 한다. */
.jtoday .jtico { width:22px; flex-shrink:0; display:inline-flex; align-items:center; justify-content:center;
  color:var(--accent); }
/* ↑ **transition:color 금지** (실측 2026-08-04). 값이 var(--토큰)인 속성에 전이를 걸면 테마를 바꿨을 때
   색이 옛 테마 값에 얼어붙는다(1.5초 뒤에도 옛 값 유지, 전이를 끄면 즉시 새 값). 브랜드 색이
   테마 전환 후 안 바뀌는 것으로 보이므로 재도입 금지 — 호버 감각은 아래 svg opacity·화살표 전이가 맡는다. */
.jtoday .jtico svg { width:18px; height:18px; fill:none; stroke:currentColor; stroke-width:1.8;
  stroke-linecap:round; stroke-linejoin:round; opacity:.9; transition:opacity .15s ease; }
.jtoday .jtrow:hover .jtico { color:var(--accent); }
.jtoday .jtrow:hover .jtico svg { opacity:1; }
.jtoday .jtx { flex:1; min-width:0; }
/* 시인성 (2026-07-29): 앞 '사실'은 또렷하게, 뒤 '권유'는 조용하게 · 숫자는 굵기로만 강조(색 금지) */
.jtoday .jtx .jtq { color:var(--dim); }
.jtoday .jtx .jtn { font-weight:700; font-variant-numeric:tabular-nums; }
.jtoday .jtarrow { width:15px; height:15px; flex-shrink:0; fill:none; stroke:currentColor;
  stroke-width:2; stroke-linecap:round; stroke-linejoin:round; opacity:.45; transition:opacity .15s ease, transform .15s ease; }
.jtoday .jtrow:hover .jtarrow { opacity:1; transform:translateX(2px); }
@media (max-width:820px) { .jtoday { margin-top:32px; } .jtoday .jtrow { font-size:14px; } }

/* 시장 심리 요약 스트립 (2026-07-16 단일 출처): 심리(M9) 고스톱 5지표 축약 — 홈·심리 값 항상 일치.
   종합(N고 M스톱·구간) + 지표별 고/스톱 칩. 클릭 → 심리 모듈. 고=상승색·스톱=하락색(심리와 동일 규약) */
.bsent { margin-top:22px; padding-top:18px; border-top:1px solid var(--line); cursor:pointer; }
.bsent .bsenthead { display:flex; align-items:baseline; gap:12px; flex-wrap:wrap; }
.bsent .bsk { font-size:var(--fs-lab); letter-spacing:.1em; color:var(--dim); font-weight:700; }
.bsent .bscomp { font-size:15px; font-weight:700; }
.bsent .bsband { font-size:var(--fs-lab); color:var(--dim); border:1px solid var(--line); border-radius:6px; padding:1px 8px; }
.bsent .bsmore { margin-left:auto; font-size:var(--fs-lab); color:var(--dim); transition:color .15s ease; }
.bsent:hover .bsmore { color:var(--accent); }
.bsent .bsentchips { display:flex; flex-wrap:wrap; gap:8px 20px; margin-top:12px; }
.bsent .sstat { font-size:12.5px; color:var(--dim); }
.bsent .sst-go { color:var(--up); font-weight:700; margin-left:2px; }
.bsent .sst-stop { color:var(--down); font-weight:700; margin-left:2px; }
.bsent .sst-x { color:var(--dim); font-weight:600; margin-left:2px; }
/* (구) 팩트 스트립 .bboard — 심리 스트립으로 대체됨, 규칙은 하위호환용 잔존 */
.bsec .bboard { display:flex; flex-wrap:wrap; justify-content:flex-start; row-gap:12px; margin-top:22px;
  padding-top:18px; border-top:1px solid var(--line); }
.bsec .bstat { display:flex; flex-direction:column; align-items:flex-start; gap:3px; padding:0 24px;
  border-left:1px solid var(--line); }
.bsec .bstat:first-child { border-left:0; padding-left:0; }
.bsec .bk { font-size:var(--fs-lab); letter-spacing:.1em; color:var(--dim); font-weight:700; }
.bsec .bv { font-size:14px; display:flex; align-items:center; gap:6px; }
.bsec .up { color:var(--up); } .bsec .down { color:var(--down); }
.bsec .bbar { display:inline-flex; width:84px; height:4px; border-radius:2px; overflow:hidden; background:var(--line); }
.bsec .bbar .u { background:var(--up); } .bsec .bbar .d { background:var(--down); }
/* AI vs AI — 4파전 순위 스트립 (항목4 2026-07-16): 순위·로고·누적·전적, 1위 강조. 단순명료. */
.apstand { display:flex; flex-direction:column; }
.apstand .apst { display:flex; align-items:center; gap:10px; padding:10px 20px; border-bottom:1px solid var(--line); font-size:12.5px; }
.apstand .apst.lead { background:color-mix(in srgb, var(--accent) 7%, transparent); }
.apstand .aprk { width:16px; text-align:center; font-weight:700; color:var(--dim); font-size:var(--fs-sub); }
.apstand .apst.lead .aprk { color:var(--accent); }
.apstand .apst img { width:20px; height:20px; border-radius:50%; background:#eef0f4; }
.apstand .apnm { font-weight:600; min-width:78px; }
.apstand .apcum { font-weight:700; min-width:56px; }
.apstand .apcum.up { color:var(--up); } .apstand .apcum.down { color:var(--down); }
.apstand .apwl { color:var(--dim); font-size:var(--fs-lab); margin-left:auto; }
/* 1위의 이번 주 픽 — 소제목 줄 */
.apleadhead { display:flex; align-items:center; gap:7px; padding:13px 20px 11px; font-size:12.5px; color:var(--dim); border-bottom:1px solid var(--line); background:var(--panel2); }
.apleadhead img { width:18px; height:18px; border-radius:50%; background:#eef0f4; }
.apleadhead b { color:var(--text); font-weight:600; }
.apleadhead .aplhmeta { margin-left:auto; font-size:var(--fs-lab); }
.aprows .aprow { display:flex; align-items:baseline; gap:12px; padding:11px 20px;
  border-bottom:1px solid var(--line); cursor:pointer; transition:background-color .15s ease; }
.aprows .aprow:last-child { border-bottom:0; }
.aprows .aprow:hover { background:var(--panel2); }
.aprows .aprow b { font-size:13px; min-width:96px; }
.aprows .apsec { color:var(--dim); font-size:var(--fs-lab); min-width:84px; }
.aprows .apreason { color:var(--dim); font-size:12.5px; flex:1; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
/* 행 스파크라인: 최근 3개월 종가 — 축·면 없는 단순 곡선 1개, 색은 중립(등락색은 수익률 숫자가 담당) */
.aprows .apspark { width:90px; flex-shrink:0; align-self:center; display:inline-flex; }
.aprows .apspark svg { width:90px; height:22px; display:block; }
.aprows .apspark polyline { fill:none; stroke:var(--dim); stroke-width:1.5;
  stroke-linejoin:round; stroke-linecap:round; opacity:.9; transition:stroke .15s ease; }
.aprows .aprow:hover .apspark polyline { stroke:var(--text); }
.aprows .ret { font-size:12.5px; font-weight:600; }
.aprows .ret.up { color:var(--up); } .aprows .ret.down { color:var(--down); }
/* 오늘의 후보 = 카드 안 3칼럼(세로 헤어라인 구분) — 채운 카드 나열 폐기(중첩 금지, 패스 11) */
/* 패스13 애플-심플: 후보 3칼럼 → iOS 그룹 인셋 리스트(세로, 좌측 인셋 헤어라인 + 우측 쉐브론) */
.bsec .bgrid { display:flex; flex-direction:column; }
/* 패스14 모던 럭셔리 B: 후보 = 카드 안 리스트 행 (쉐브론 제거 — B엔 없음), 인셋 헤어라인 구분 */
.bsec .bcard { position:relative; background:transparent; border:0; border-radius:0;
  padding:15px 20px; cursor:pointer; transition:background-color .15s ease; }
.bsec .bcard:not(:first-child)::before { content:""; position:absolute; top:0; left:20px; right:0; height:.5px; background:var(--line); }
.bsec .bcard:hover { background:var(--panel2); }
.bsec .bhead { display:flex; align-items:baseline; gap:8px; margin-bottom:8px; }
.bsec .bhead b { font-size:14.5px; }
/* 선정 기준(왜) 태그 — emerald 액센트 틴트 칩 (항목3: 왜 골랐는지 명시) */
.bsec .bwhy { margin-left:auto; font-size:var(--fs-lab); font-weight:600; color:var(--accent);
  background:color-mix(in srgb, var(--accent) 12%, transparent); border-radius:6px; padding:3px 9px; letter-spacing:.01em; white-space:nowrap; }
/* 근거(그 이유) — 전체 나열, 칩형 라인 (항목3) */
.bsec .breasons { display:flex; flex-wrap:wrap; gap:6px 10px; }
.bsec .breasons .bra { font-size:var(--fs-sub); color:var(--text); opacity:.82; }
.bsec .breasons .bra:not(:last-child)::after { content:"·"; margin-left:10px; color:var(--dim); opacity:.6; }
.bsec .brisk { font-size:var(--fs-sub); color:var(--up); margin-top:8px; }
/* 좁은 화면: 후보 3칼럼 → 세로 스택(가로 헤어라인) */
@media (max-width:820px) {
  .bsec .bgrid { grid-template-columns:1fr; }
  .bsec .bcard { border-left:0; }
  .bsec .bcard:first-child { border-top:0; }
}
/* 오늘의 변화: 박스 나열 → 한 패널 + 헤어라인 (조용한 표) */
#view-home #homechanges { background:var(--panel); border:1px solid var(--line); border-radius:12px; overflow:hidden; }
#view-home #homechanges .skel-stack { padding:8px; }
#view-home #homechanges .chgrow { background:transparent; border:0; border-radius:0; margin:0; padding:10px 16px; border-bottom:1px solid var(--line); transition:background-color .15s ease; }
#view-home #homechanges .chgrow:last-child { border-bottom:0; }
#view-home #homechanges .chgrow:hover { background:var(--panel2); }
#view-home #homechanges .chgrow .nm { font-weight:600; min-width:104px; }
#view-home #homechanges .chgrow .px { min-width:96px; text-align:right; font-size:13.5px; }
/* 이벤트 칩: 테두리 → 은은한 틴트 면 */
#view-home #homechanges .ev { border:0; border-radius:6px; padding:3px 9px; font-size:var(--fs-sub); background:var(--panel2); }
#view-home #homechanges .ev.move-up { color:var(--up); background:color-mix(in srgb, var(--up) 13%, transparent); }
#view-home #homechanges .ev.move-down { color:var(--down); background:color-mix(in srgb, var(--down) 13%, transparent); }
#view-home #homechanges .ev.high { color:var(--accent); background:color-mix(in srgb, var(--accent) 15%, transparent); }
#view-home .emptywatch { border-style:solid; }
/* 당일 공시 칩 (관심종목 테이블 종목명 옆 — 구 '오늘의 변화'의 고유 정보 통합) */
.disc-chip { font-size:var(--fs-lab); color:var(--accent); background:color-mix(in srgb, var(--accent) 14%, transparent); border-radius:5px; padding:1px 7px; margin-left:4px; cursor:help; white-space:nowrap; }
/* 기준일 풋터: 카드 4장 → 헤어라인 위 한 줄 */
/* [제거 2026-08-23] .homelegal 일가 — 홈 하단 사업자 표기는 랜딩 푸터로 이관
   (사용자 지시 "랜딩엔 넣지만 홈에선 없앤다" · 초기화면=랜딩, auth.js 주석 참조) */

.homefoot { border-top:1px solid var(--line); margin-top:28px; padding:12px 2px 4px; font-size:var(--fs-sub); color:var(--dim); }
.homefoot .warn { color:var(--down); font-weight:600; }
/* 누구에게 보이는 줄인지 밝히는 꼬리표 — 경고보다 한 단 약하게 (2026-08-16 사용자 확정) */
.homefoot .warnwho { color:var(--dim2); font-weight:400; margin-left:6px; }

/* AI 스코어 (아이투자 통합진단 벤치 — 카테고리별 지표 진단 목록, 행 클릭 → 주식 궤적) */
#scorebox { background:var(--panel); border:1px solid var(--line); border-radius:10px; padding:14px 16px; }
#scorebox h3 { margin:0 0 8px; }   /* 제목은 대제목(.jsect)으로 패널 밖에 나갔다 — 잔여 h3 대비용 */
#scorebox h3 .tag { float:right; font-size:var(--fs-lab); color:var(--dim); border:1px solid var(--line); border-radius:10px; padding:1px 8px; font-weight:400; cursor:help; }
/* 고정 3열 → 카드 5개 = 3줄+2줄 안정 배치 (사용자 확정 2026-07-19 "3-2가 기본, 안정적"). 좁은 화면만 2·1열 */
.scgrid { display:grid; grid-template-columns:repeat(3,1fr); gap:10px; }
@media (max-width:820px) { .scgrid { grid-template-columns:1fr 1fr; } }
@media (max-width:560px) { .scgrid { grid-template-columns:1fr; } }
/* 3열 subgrid — 카드 안에서 숫자를 한 열로 맞추고(우측 정렬) 설명을 그 뒤에 (사용자 확정 2026-07-19).
   라벨 1fr | 숫자 max-content | 설명 minmax(0,max-content). subgrid로 행마다 같은 열 트랙 공유 → 숫자 세로 정렬. */
.sccat { border:1px solid var(--line); border-radius:8px; overflow:hidden; align-self:start;
         display:grid; grid-template-columns:1fr max-content minmax(0,max-content); }
.schead { grid-column:1/-1; font-size:var(--fs-sub); font-weight:700; color:var(--accent); padding:6px 10px; background:var(--panel2); border-bottom:1px solid var(--line); }
.schead small { color:var(--dim); font-weight:400; margin-left:6px; }
.scrow { grid-column:1/-1; display:grid; grid-template-columns:subgrid; align-items:baseline;
         padding:5px 0; border-bottom:1px solid var(--line); font-size:12.5px; cursor:default; }
.scrow:last-child { border-bottom:0; }
.scrow .lb { padding-left:10px; padding-right:8px; color:var(--text); white-space:nowrap; }
/* 신호등 자리를 **항상** 비워 둔다 — 점이 금액 뒤에 붙어 흐르던 탓에 점 있는 행(현금흐름 3종)과
   없는 행(FCF·오너어닝)의 숫자 끝이 어긋났다 (사용자 지적 2026-08-07 "금액 세로 방향 맞춰라").
   점을 절대배치하면 유무와 관계없이 숫자 오른쪽 끝이 한 줄에 선다. */
.scrow .vl { position:relative; padding-right:13px;
  text-align:right; font-variant-numeric:tabular-nums; white-space:nowrap; }
.scrow .sb { padding-left:6px; padding-right:10px; color:var(--dim); font-size:var(--fs-lab); line-height:1.3; }
.scrow .vl.pos { color:var(--up); } .scrow .vl.neg { color:var(--down); }
.scrow .vl.warn { color:var(--up); }
.scrow .vl.na { color:var(--dim); font-size:var(--fs-sub); white-space:normal; }
/* 현금흐름 부호 신호등 — 항목마다 건강한 부호가 다르다(영업+ / 투자·재무−). 음수라도 건강하면 초록,
   주의할 방향이면 빨강 (사용자 확정 2026-07-26 "긍정은 마이너스더라도 초록, 부정이면 빨강"). 이모지 금지 → CSS 원형 */
/*  점은 금액 오른쪽 (사용자 확정 2026-07-26). 설명은 카드 안쪽 아래 범례(.scleg)가 맡는다. */
.scrow .vl .sig { position:absolute; right:0; top:50%; margin-top:-3.5px;
  width:7px; height:7px; border-radius:50%; flex:none; }
.scrow .vl .sig-good, .scleg .sig-good { background:#22c55e; box-shadow:0 0 0 2px color-mix(in srgb, #22c55e 18%, transparent); }
.scrow .vl .sig-bad,  .scleg .sig-bad  { background:#ef4444; box-shadow:0 0 0 2px color-mix(in srgb, #ef4444 18%, transparent); }
/* 상태 배지 (흑자전환·적자지속) — 숫자 옆 작은 알약. 색은 판정색 계열 (사용자 확정 2026-07-26) */
.scrow .vl .bdg { margin-left:5px; font-size:var(--fs-badge); font-weight:700; letter-spacing:-.01em; padding:1px 5px;
  border-radius:8px; vertical-align:1.5px; white-space:nowrap;
  color:var(--up); background:color-mix(in srgb, var(--up) 13%, transparent); }
.scrow .vl .bdg.warn { color:var(--down); background:color-mix(in srgb, var(--down) 13%, transparent); }
.scrow .vl .bdg.na { color:var(--dim); background:var(--panel2); }
/* 신호등 범례 — 표 아래 한 줄, 쉬운 말로 (사용자 지시 2026-07-26). 점은 범례에선 글 앞에 */
/* 범례 = 카드 그리드와 같은 3열 트랙 → 항목이 카드 좌측선에 정렬 (사용자 지시 2026-07-26 "줄 정렬 맞춰라") */
/* 범례 = 신호가 있는 카드 안쪽 아래, 카드 좌측선(10px)에 정렬 (사용자 확정 2026-07-26) */
.scleg { grid-column:1/-1; display:flex; flex-direction:column; gap:5px; padding:8px 10px 9px;
  border-top:1px solid var(--line); font-size:var(--fs-lab); color:var(--dim); line-height:1.5; }
.scleg > span { min-width:0; }
/* wrap = 좁은 폭(챗 드로어 열림·2열 접힘)에서 부호 조합이 잘리지 않고 다음 줄로 내려가게 */
.sclegr { display:flex; align-items:center; gap:6px; flex-wrap:wrap; row-gap:2px; }
.sclegd { color:var(--line); flex:none; }
.scleg b { color:var(--text); font-weight:700; }        /* "초록불은 긍정적" 앞머리 강조, 뒤 설명은 옅게 */
.scleg .sig { display:inline-block; width:7px; height:7px; border-radius:50%; flex:none; }
/* 부호 3종(영업·투자·재무) — "정상 방향" 같은 빈 말 대신 **조합 자체**를 보여준다 (사용자 2026-08-03).
   ⊕/⊖ 글리프는 폰트마다 굵기가 달라 CSS 원으로 그린다. 색은 그 줄의 판정(초록/빨강)을 따른다. */
.cftrio { font-style:normal; display:inline-flex; align-items:center; gap:8px; white-space:nowrap;
  color:var(--text); font-weight:600; letter-spacing:.01em; }
.cfs { display:inline-flex; align-items:center; justify-content:center; width:15px; height:15px; margin-left:4px;
  border:1px solid currentColor; border-radius:50%; font-style:normal; font-size:var(--fs-lab); font-weight:700;
  line-height:1; flex:none; }
.sclegr.good .cfs { color:#22c55e; }
.sclegr.bad  .cfs { color:#ef4444; }
/* 물음표 글리프는 없앴다 (사용자 지시 2026-08-19 "그냥. 너무 복잡해") — 부호 조합이 이미
   판정을 말하고 있어서 그 옆의 ?는 한 겹 더였다. 설명(CF_SIGN_HELP)은 지우지 않고
   범례 줄 자체의 호버 툴팁으로 내렸다: 화면엔 판정만, 알고 싶으면 얹으면 나온다(docs/28). */
.sclegr[data-tip] { cursor:help; }
.scrow.miss > .lb { grid-column:1/-1; color:var(--dim); font-size:var(--fs-lab); padding-right:10px; white-space:normal; }

/* 성장률 테이블 (아이투자 Growth 벤치) + 수익성 박스 + 투자맵 */
#growth { background:var(--panel); border:1px solid var(--line); border-radius:10px; padding:10px 14px; }
#growth h3 { margin:0 0 6px; }
#growth table { width:100%; border-collapse:collapse; font-size:13px; }
#growth th, #growth td { padding:5px 10px; text-align:right; font-variant-numeric:tabular-nums; border-bottom:1px solid var(--line); }
#growth tr:last-child td { border-bottom:0; }
#growth th:first-child, #growth td:first-child { text-align:left; color:var(--text); font-weight:600; }
#growth th { color:var(--dim); font-weight:600; }
#growth .pos { color:var(--up); } #growth .neg { color:var(--down); }
#growth .na { color:var(--dim); font-size:var(--fs-sub); }
#profitbox { background:var(--panel); border:1px solid var(--line); border-radius:10px; padding:12px 10px; }
#profitbox h3 { margin:0 4px 6px; }
#mapchart { background:var(--panel); border:1px solid var(--line); border-radius:10px; }

/* [M2] AI 종목 발굴 — 기술적/재무적 모드 전환 + 기술적 AI 분석 (docs/25 §2, docs/26 M2)
   2026-07-14 개선: S/R 3열 히어로(대형 타이포 앵커) + 헤어라인 팩트 + 접이식 진단 (docs/28) */
/* 폭 = 아래 **재무 점수 카드(#finherobox)의 바깥 테두리**에 맞춘다 (사용자 지시 2026-08-20
   "재무 점수의 좌-우 길이를 맞춰라"). 카드가 #left의 전폭을 쓰므로 모드바도 전폭이다.

   ⚠ 앞선 시도(2026-08-19)는 카드의 **콘텐츠 폭**(테두리 1 + 패딩 18 = 19px 안쪽)에 맞췄었다.
   그러면 총평 칸(.radarwrap 3열 `calc(50% - 4px)`)과는 좌우가 맞지만 **카드 바깥선과는
   19px씩 어긋난다** — 화면에서 눈에 걸리는 건 이쪽이었다. 둘은 19px 차이라 **동시에 맞출 수
   없다**: 총평 칸은 카드 안쪽에 있고 패딩을 음수로 밀지 않는 한 카드 바깥선에 닿지 못한다.
   바깥 프레임(카드 = 버튼)을 택했다 — 총평 칸이 카드 안쪽으로 들어가 보이는 것은 자연스럽고,
   버튼이 카드보다 좁은 것은 어긋나 보인다. */
/* 배치 = 산업 트렌드(#intab)와 같은 2단 그리드. **껍데기는 파일 끝 "모듈 선택 탭"이 쥔다**
   (사용자 지시 2026-08-21 "대표 모듈 구분 버튼은 다 이 스타일로 가고 있다").
   폭은 전폭 — 아래 재무 점수 카드와 좌우가 맞는다(2026-08-20 정렬 결정 유지). */
#stockmode { display:grid; grid-template-columns:1fr 1fr; gap:8px; }
#stockmode button { display:flex; align-items:center; justify-content:center; gap:12px;
  text-align:left; padding:13px 15px; }
@media (max-width:900px) { #stockmode { grid-template-columns:1fr; } }
/* 부제(`지지/저항 · 이동평균 · MDD`)는 뺐다 (2026-08-21) — 옮겨간 탭 문법은 **그림이 부제를
   대신한다**. 그림과 부제를 함께 두면 한 줄에 세 가지를 말하게 돼 아무것도 안 읽힌다.
   무엇을 보는지는 고른 뒤 화면이 말한다. */
/* (M5 #mnmode 전용 껍데기는 2026-08-28에 지웠다 — M5도 그림 있는 탭 문법으로 옮겼다.
   모양은 파일 끝 "모듈 선택 탭" 선택자가, 배치는 아래 `#mnmode`가 맡는다.) */
/* 모드 전환 (사용자 지시 2026-07-14): 주가-이익 차트(#chartbox)는 기본적 분석 전용 — 기술적 모드에선 숨김.
   공시·기준일은 어느 모드에서든 유지. (차트 제거 아님 — 기본적 모드에 오버레이·모드 전환 그대로) */
/* 주가-이익 그래프(#chartbox)는 기본적 AI 분석 전용 (사용자 확정 2026-07-14 — 기술적 모드의 주가 차트는 대표 차트가 담당) */
/* 결론 요약·AI 스코어(#conclusion·#scorebox)는 재무 콘텐츠 → 기술적 모드에선 숨김 (사용자 확정 2026-07-16) */
#left.mode-tech #growth, #left.mode-tech #chartbox, #left.mode-tech #vcharts, #left.mode-tech #profitbox, #left.mode-tech #annualwrap,
#left.mode-tech #conclusion, #left.mode-tech #scorebox,
#left.mode-tech #disc, #left.mode-tech #quartable, #left.mode-tech #quartitle { display:none !important; }   /* 공시·분기표는 재무 모드 전용 (2026-07-16) */
#techbox { display:none; background:var(--panel); border:1px solid var(--line); border-radius:10px; padding:12px 14px; }
#left.mode-tech #techbox { display:block; }
#techbox h3 { margin:0 2px 8px; }
#techbox h3 .tag { float:right; font-size:var(--fs-lab); color:var(--dim); border:1px solid var(--line); border-radius:10px; padding:1px 8px; font-weight:400; cursor:help; }
/* AI 스코어: 정적 목록 — 행 클릭 제거 (기존 .scrow 클래스는 두고 동작만 오버라이드) */
.scrow { cursor:default; }
.scrow:hover { background:transparent; }
/* ① 지지·저항 히어로 — 화면의 대형 타이포 앵커 (지지=파랑 · 저항=빨강, 현재가 중앙 최대) */
.trhero { display:grid; grid-template-columns:1fr 1.15fr 1fr; gap:8px; text-align:center; align-items:end; padding:12px 6px 2px; }
.trhero .lab { font-size:var(--fs-sub); letter-spacing:.12em; color:var(--dim); margin-bottom:3px; }
.trhero .num { font-size:29px; font-weight:300; line-height:1.12; font-variant-numeric:tabular-nums; white-space:nowrap; }
.trhero .cur .num { font-size:35px; font-weight:400; color:var(--text); }
.trhero .sup .num { color:var(--down); }
.trhero .res .num { color:var(--up); }
.trhero .num.none { color:var(--dim); font-weight:300; }
.trhero .sub { font-size:var(--fs-sub); color:var(--dim); margin-top:3px; font-variant-numeric:tabular-nums; }
.trhero .basis { border:1px solid var(--line); border-radius:9px; padding:0 7px; font-size:var(--fs-lab); margin-left:5px; cursor:help; white-space:nowrap; }
/* 현재가 위치 바 — 1차 지지↔1차 저항 사이 */
.trbar { position:relative; height:4px; background:linear-gradient(90deg, var(--down), var(--up)); opacity:.85; border-radius:2px; margin:12px 12% 2px; }
.trbar i { position:absolute; top:-4px; width:12px; height:12px; border-radius:50%; background:var(--text); border:2px solid var(--panel); transform:translateX(-50%); }
.trsecond { text-align:center; font-size:var(--fs-sub); color:var(--dim); margin:8px 0 4px; font-variant-numeric:tabular-nums; }
.trsecond .sep { margin:0 10px; color:var(--line); }
/* 기본적 AI 분석 = 2×2 대시보드 + 분기 테이블 (사용자 확정 2026-07-15, 아이투자 종목분석 참조) */
/* 기술적 모드: 대시보드·서술 숨김 (기술 화면은 techbox가 담당) */
#left.mode-tech #fingrid, #left.mode-tech #findiag { display:none !important; }
/* 재무적 모드: 레거시 산재 섹션 정리 → 대시보드로 대체. AI 스코어(#scorebox)만 재무 콘텐츠로 유지(그리드 편입) */
#left:not(.mode-tech) #vcharts,
#left:not(.mode-tech) #profitbox, #left:not(.mode-tech) #annualwrap, #left:not(.mode-tech) #growth,
#left:not(.mode-tech) #perf, #left:not(.mode-tech) #asof { display:none !important; }
/* 결론 요약(#conclusion)은 삭제 (사용자 확정 2026-07-16) — 양 모드 모두 숨김 */
#conclusion { display:none !important; }

/* 셀 사이 간격 12 → 18 (사용자 확정 2026-08-05 "재무적 AI 분석도 답답하다").
   카드 안쪽 패딩도 함께 키워야 숨통이 트인다 — 아래 .fgcell padding 참조. */
/* ── 제목 3단 정본 (사용자 확정 2026-08-19 "대제목/중제목/소제목을 통일하자") ──────────
   대제목 `.jsect`  18px(--fs-sect) 700 검정 — 화면 안의 큰 단락. **패널 밖**에 놓고 위로
                    넉넉히 띄운다. 여백이 "여기서 내용이 바뀐다"를 말한다.
   중제목 `.fglab` / `h3`  15.5px 700 검정 — 단락 안의 차트·카드 제목.
   소제목 `.fglab small`   12.5px(--fs-sub) 400 회색 — **데이터 사실만**(2026E·24개사 등).
                    산식·풀이 같은 설명문은 화면에서 빼고 툴팁으로 내린다.
   간격 원칙: 맥락이 같으면 그대로 두고(#fingrid gap), 내용이 바뀌는 경계만 크게 벌린다(.jsect). */
.jsect { display:flex; align-items:baseline; gap:10px; word-break:keep-all;
  font-size:var(--fs-sect); font-weight:700; color:var(--text); letter-spacing:-.01em;
  margin:14px 2px 8px; }                               /* + #left gap 14 = 경계 28px */
/* 그리드 안에서는 위아래로 gap 20이 이미 붙는다 — margin으로 그만큼 되돌려 제목이 자기 단락에 붙게 */
#fingrid > .jsect { grid-column:1/-1; margin:6px 2px -10px; }
#quartitle { margin-bottom:-6px; }                     /* 표는 제목에 붙인다 (+ #left gap 14 = 8px) */

#fingrid { display:grid; grid-template-columns:1fr 1fr; gap:20px; }
/* AI 스코어(#scorebox) = 그리드 전체폭 셀 (재무점수·주가이익 아래) — 자체 패널 스타일 유지 */
#fingrid > #scorebox { grid-column:1/-1; margin:0; }
#fingrid .fgmeta { grid-column:1/-1; font-size:var(--fs-lab); color:var(--dim); padding:2px 0 2px; font-variant-numeric:tabular-nums; }
#fingrid .fgmeta span { cursor:help; } #fingrid .fgmeta small { font-size:var(--fs-badge); opacity:.85; }
#fingrid .fgmeta .dot { margin:0 8px; color:var(--line); cursor:default; }
#fingrid .fgmeta .soon { color:var(--accent); font-weight:600; }
#fingrid .fgcell { background:var(--panel); border:1px solid var(--line); border-radius:10px; padding:16px var(--fgpad); min-width:0; }
#fingrid #chartcell { padding:8px 6px 6px; }
#fingrid #margincell { padding:8px 6px 6px; }   /* (1,1)과 동일 패딩 — x축 세로 정렬 (사용자 확정 2026-07-18) */
#fingrid #margincell .fglab { margin:0 6px 10px; }
/* 높이 = (1,2) 컨센서스 차트(#conschart 248px)와 동일 — 좌우 두 차트가 같은 크기라야 정렬돼 보인다
   (사용자 확정 2026-08-04 "우측 그래프 크기가 기준"). 겉 박스는 그리드가 같은 높이로 늘린다.
   **높이는 #chartbox가 아니라 캔버스(#chart)에 준다** — #chartbox 안에는 기간 토글(#periods)이
   함께 들어 있어 박스에 주면 캔버스가 그만큼(36px) 작아진다 (실측 2026-08-05). */
#fingrid #chartcell #chartbox { display:block; border:0; padding:0; height:auto; background:transparent; }
#fingrid #chartcell #chart { height:248px; }
/* Row1 = 기술적 #techbox 상단과 동일 포맷 (사용자 확정 2026-07-16): 외곽 흰 박스 → 헤더(기준일 메타 + 규칙기반 태그)
   → [라벤더 서술 | 투명 재무점수]. 통일감. */
#fingrid #finherobox { grid-column:1/-1; }
/* 헤더 (기술적 #techbox h3와 통일): 메타 왼쪽 · 규칙기반 태그 오른쪽 */
#finherobox .fhhead { display:flex; align-items:baseline; gap:8px; margin:0 2px 14px; }
/* 기준일 메타 = 모든 숫자가 언제 것인지 말하는 줄 — 옅은 회색으로 묻어 두면 안 읽힌다.
   본문색·12.5px로 올린다(사용자 확정 2026-08-04, "과도하게 크게는 아니게"). */
#finherobox .fhhead .fhmeta { font-size:12.5px; color:var(--text); font-variant-numeric:tabular-nums; }
#finherobox .fhhead .fhmeta .dot { margin:0 8px; color:var(--line); } #finherobox .fhhead .fhmeta .soon { color:var(--accent); font-weight:600; }
#finherobox .fhhead .tag { margin-left:auto; font-size:var(--fs-lab); color:var(--dim); border:1px solid var(--line); border-radius:10px; padding:1px 8px; font-weight:400; cursor:help; }
/* 내부 2열: [라벤더 서술 | 투명 재무점수] — 기술적 #techtop과 동일(왼쪽 서술 박스, 오른쪽 투명 콘텐츠) */
/* 서술 패널(#diagcell) 제거 → 단일 컬럼 (사용자 확정 2026-07-19 "설명 빼자·한눈에 복잡해 보이면 안 된다") */
#finherobox #finherorow { display:grid; grid-template-columns:1fr; gap:16px; align-items:start; }
#finherobox #radarpane { min-width:0; background:transparent; }   /* 3열(오각형|막대|총평)이 전폭 사용 — 820px 상한은 우측 공백('?')을 만들어 제거 (2026-08-02) */
#radarpane .fglab .fghelp { margin-left:6px; font-size:var(--fs-badge); font-weight:600; color:var(--dim); cursor:help;
  border:1px solid var(--line); border-radius:50%; padding:0 5px; }
#radarpane .fglab .fghelp:hover { color:var(--ai); border-color:var(--ai); }
/* 주비스의 재무적 AI 분석 = 라벤더 박스 (기술적 #techdiagcell과 폰트·크기 동일): panel2 + 보라 왼줄 flush */
#finherobox #diagcell { background:var(--panel2); border:1px solid var(--line); border-left:3px solid var(--ai);
  border-radius:10px; padding:12px 14px; min-width:0; }
#finherobox #diagcell #findiag { background:transparent; border:0; padding:0; display:block; }
#finherobox #diagcell .tdiag { margin-top:0; border-left:0; padding:0; }
/* 재무적 서술 폰트 = 기술적 상단 박스(주비스 코멘트)와 통일 — 조금 작게 (사용자 확정 2026-07-16) */
#finherobox #diagcell .sum { font-size:12.5px; }
#finherobox #diagcell .tnarr { font-size:13.5px; line-height:1.8; }
#finherobox #diagcell summary { font-size:var(--fs-sub); }
#finherobox #diagcell .sg { font-size:var(--fs-sub); }
/* 분기 재무 테이블 = 그리드 밖 · 최근 공시 아래 · 가장 아래 (사용자 확정 2026-07-16) */
.fgtable { background:var(--panel); border:1px solid var(--line); border-radius:10px; padding:14px 16px; }
#fingrid .fgtable { grid-column:1/-1; }
#quartable { margin-top:0; }   /* 경계 여백은 #quartitle(.jsect)가 담당 */
/* word-break:keep-all — 좁아지면 **어절 단위로** 끊는다. 기본값은 글자 단위라
   '밸류에이션 밴드'가 '밸류에이 / 션 밴드'로 잘렸다 (사용자 지적 2026-08-07). */
.fglab { display:flex; align-items:baseline; gap:6px; font-size:15.5px; letter-spacing:-.01em; color:var(--text); font-weight:700; margin-bottom:12px; word-break:keep-all; }
.fglab small { font-weight:400; letter-spacing:0; font-size:var(--fs-sub); color:var(--dim); }
/* 1x1 오각 레이더 — 차트 + 축별 점수 리스트 (항목 대표색 매칭, 사용자 확정 2026-07-15) */
/* 3열: 오각형(좌) | 점수 막대(중) | 총평(우) — 전폭 사용·넉넉한 간격 (사용자 확정 2026-08-02 "공간감 있게·막대 길게") */
/* 2026-08-03 재배치: 오각형·막대를 조금 줄여 **총평 칸을 넓힌다**(사용자 지시 — 점수는 이미 좌측
   오각형과 등급으로 읽히므로 폭은 AI 서술에 준다). 1열 0.85fr · 2열 0.72fr · 3열 1.5fr. */
/* 총평 칸의 **왼쪽 모서리를 위 모드바("기술적 | 재무적")의 경계선에 맞춘다** (사용자 확정 2026-08-04
   "중앙선에 맞춰 균형감 있게"). 모드바는 카드 전폭에 1fr 1fr + gap 8 → 두 번째 버튼의 왼쪽 =
   카드폭/2 + 4. ⚠ **gap을 바꾸면 이 4px도 함께 바꿔야 한다**(gap의 절반이다). 카드의 테두리 1 + 패딩(--fgpad)을 빼고 풀면 3열 폭 = 콘텐츠폭/2 − 4.
   ⚠ 오른쪽 끝은 카드 **안쪽**이라 버튼의 오른쪽 끝(카드 바깥선)보다 그만큼 들어와 있다 —
   패딩을 음수로 밀지 않는 한 둘은 동시에 맞출 수 없다(2026-08-20 판단). 좌측 2열은 남은 폭을 비율로. */
/* ⚠ 1열은 **반드시 1fr** — 0.78fr이면 총평 칸이 왼쪽으로 밀린다 (실측 2026-08-28).
   2열이 최소폭(188px)에 걸려 얼면 남은 flex 합이 0.78 < 1이 되고, 그리드는 이때 fr을
   `남은공간 × 0.78`만 나눠 준다(합이 1 미만이면 비율 그대로 쓰는 규칙). 남은 22%(실측 46px)가
   **그리드 오른쪽 끝에 죽은 여백으로 고이고** 3열이 통째로 왼쪽으로 밀려 모드바 경계선과 어긋났다.
   1fr이면 합이 정확히 1이라 남는 폭을 오각형이 전부 가져간다 → 정렬 복원 + 오각형 확대 (사용자 지시). */
.radarwrap { display:grid; grid-template-columns:minmax(0,1fr) minmax(188px,0.64fr) calc(50% - 4px);
  gap:22px; align-items:center; }
/* 학점 배지 A~D — 둥근 정사각, 점수 우측 (사용자 확정 2026-08-02) */
.rscore-row { display:flex; align-items:center; gap:9px; margin-bottom:4px; }
.rscore-row .rscore { margin-bottom:0; }
.rgrade { width:31px; height:31px; border-radius:8px; display:inline-flex; align-items:center; justify-content:center;
  font-size:16.5px; font-weight:800; cursor:help; flex:none; }
.rgrade.gA { color:var(--accent); background:color-mix(in srgb, var(--accent) 14%, transparent); border:1px solid color-mix(in srgb, var(--accent) 45%, transparent); }
.rgrade.gB { color:#3d9bff; background:rgba(61,155,255,.12); border:1px solid rgba(61,155,255,.4); }
.rgrade.gC { color:#e8943a; background:rgba(232,148,58,.12); border:1px solid rgba(232,148,58,.4); }
.rgrade.gD { color:#ef4444; background:rgba(239,68,68,.12); border:1px solid rgba(239,68,68,.4); }
/* 재무적 AI 분석 총평 — AI 수급 동향 분석 카드와 동일 문법(초록 좌보더). 오각형 높이에 어울리는 세로 크기 */
#radarsum { min-width:0; align-self:center; }
/* 카드 높이에 상한 — 아래 '딥러닝 기업 가치 분석' 버튼 위치를 **결정론적으로** 만든다.
   본문만 남는 높이를 먹고(.rsum-text가 flex:1) 넘치면 그 안에서 스크롤 → 출처·버튼·푸터는 항상 보인다.
   총평 길이·칸 폭이 바뀌어도 버튼이 접힘 아래로 밀리지 않는다 (사용자 확정 2026-08-04). */
/* **글은 절대 가리지 않는다** (사용자 확정 2026-08-06 "세로가 길어지더라도 가려지지 않도록").
   앞서 아래 '딥러닝 기업 가치 분석' 버튼을 첫 화면에 붙들려고 상한 300px + 본문 스크롤을 뒀는데,
   글씨를 13.5px로 키우자 본문이 잘려 읽히지 않았다. 읽히는 것이 먼저다 — 상한을 푼다.
   (버튼은 그만큼 아래로 밀린다. 그건 감수한다.) */
.rsum { background:var(--panel2); border:1px solid var(--line); border-left:3px solid var(--accent);
  border-radius:10px; padding:13px 16px; min-height:170px;
  display:flex; flex-direction:column; justify-content:center; }
.rsum-h { font-size:13px; font-weight:700; color:var(--accent); margin-bottom:8px; }
/* 12px/1.7 — 칸을 중앙선에 맞추며 폭이 줄어 줄 수가 늘었다. 같은 높이에 더 담아 스크롤을 줄인다
   (사용자 확정 2026-08-04 정렬 우선). 카드 상한이 버튼 위치를 잡고, 폰트가 본문 손실을 줄인다. */
.rsum p { margin:0; font-size:13.5px; line-height:1.8; }
.rsum-f { margin-top:9px; padding-top:8px; border-top:1px solid var(--line); font-size:var(--fs-sub); color:var(--dim);
  line-height:1.6; font-variant-numeric:tabular-nums; }
.rsum-f b { color:var(--text); }
.rsum-f .dim { opacity:.8; }
.rsum-f .rsum-gen { opacity:.75; }
/* 온디맨드 AI 총평 — 버튼·리즈닝은 **이 칸 안에서만** (사용자 확정 2026-08-03) */
/* min-height:0 = flex 자식이 콘텐츠보다 작아질 수 있게(스크롤 성립 조건). 바닥값은 .rsum이 맡는다 */
.rsum-body { flex:1 1 auto; min-height:0; display:flex; flex-direction:column; justify-content:center; }
/* 스크롤은 **본문에만** — body에 걸면 출처 배지·버튼까지 갇혀 잘린다(사용자 지적 2026-08-04).
   높이는 고정값이 아니라 카드가 남긴 공간(flex:1) — 카드 상한이 곧 본문 상한이 된다. */
/* 스크롤 없음 — 본문은 있는 그대로 다 보인다 (위 .rsum 주석 참조) */
.rsum-text { flex:0 0 auto; }
.rsum-btn { align-self:flex-start; margin-top:9px; display:inline-flex; align-items:center; gap:6px;
  background:var(--panel); border:1px solid var(--accent); color:var(--accent); border-radius:8px;
  padding:5px 12px; font-size:13px; font-weight:700; cursor:pointer; transition:background .15s, color .15s; }
.rsum-btn:hover { background:var(--accent); color:#fff; }
.rsum-wait { display:flex; flex-direction:column; align-items:center; gap:8px; padding:6px 0; text-align:center; }
.rsum-wait .pl-ring { width:30px; height:30px; }
.rsum-wait .pl-txt { font-size:13.5px; }
.rsum-wait .pl-sub { font-size:12.5px; }   /* 10.5px는 읽히지 않는다 (2026-08-06) */
.rsum-ai { margin:0; }
/* AI 답변 문단 나눔 (사용자 지시 2026-08-05 "개행을 적절히") — jvParas가 <p>로 쪼개고 여기서 사이를 띄운다.
   첫 문단은 위 여백 0이라 기존 레이아웃이 밀리지 않는다. */
.rsum-ai p, .tnarr p { margin:0; }
.rsum-ai p + p, .tnarr p + p, .rsum p + p { margin-top:.36em; }
/* 출처 배지 — 웹 검색으로 반영한 사실의 **검증 링크**(사용자 확정 2026-08-03 "검색 AI처럼").
   본문을 밀어내지 않도록 작게, 도메인이 아니라 사람이 읽는 이름으로. */
.rsum-src { display:flex; flex-wrap:wrap; gap:5px; margin-top:9px; }
/* 배지는 카드(panel2) 위에 **흰 알약**으로 떠 있게 — 배경이 같으면 링크로 안 보인다
   (사용자 확정 2026-08-04). --panel = 라이트에선 흰색, 다크에선 그에 맞는 밝은 면. */
/* 출처 배지는 본문이 아니라 **각주**다 — 12px는 읽는 문장과 같은 크기라 눈이 그리로 끌렸다
   (사용자 지적 2026-08-07 "폰트가 너무 커"). 알약도 함께 줄여 비율을 지킨다. */
.rsum-src a { display:inline-flex; align-items:center; gap:3px; max-width:100%; padding:1.5px 7px;
  border:1px solid var(--line); border-radius:999px; background:var(--panel);
  color:var(--dim); font-size:var(--fs-lab); line-height:1.45; text-decoration:none;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; transition:color .15s, border-color .15s; }
.rsum-src a:hover { color:var(--accent); border-color:var(--accent); }
.rsum-src a svg { flex:0 0 auto; width:9px; height:9px; color:var(--dim); }
/* 완료 표시 — 버튼 자리를 그대로 이어받는 정적 칩. 다음 날이 되면 다시 버튼으로 바뀐다. */
.rsum-done { align-self:flex-start; margin-top:9px; display:inline-flex; align-items:center; gap:5px;
  color:var(--dim); font-size:var(--fs-sub); font-weight:600; letter-spacing:.01em; }
.rsum-done svg { color:var(--accent); }
/* 시총 다이얼 분석 마커 — 종목명 우상단. 계산 중=회색 깜빡임 / 완료·미확인=주비스 청록 점
   (사용자 확정 2026-08-03: 확인하면 사라짐). 칩 레이아웃을 밀지 않도록 absolute. */
#marcapdial .mdit { position:relative; }
#marcapdial .mdit.sn-run::after, #marcapdial .mdit.sn-new::after {
  content:""; position:absolute; top:2px; right:2px; width:6px; height:6px; border-radius:50%; }
#marcapdial .mdit.sn-run::after { background:var(--dim); animation:sn-blink 1.1s ease-in-out infinite; }
#marcapdial .mdit.sn-new::after { background:var(--accent); box-shadow:0 0 0 2px color-mix(in srgb, var(--accent) 25%, transparent); }
@keyframes sn-blink { 0%,100% { opacity:.25; } 50% { opacity:1; } }
#radarcell { height:218px; }   /* 250 → 218: 오각형을 조금 줄여 총평 폭을 확보 (사용자 2026-08-03) */
/* 점수 리스트 — 2026-08-03 축소: 좌측 오각형과 등급 배지가 이미 같은 정보를 주므로 막대는 보조 역할.
   (2026-07-16의 확대분을 되돌리는 게 아니라, 3열 배분을 총평 쪽으로 옮기는 것) */
.radarlist { display:flex; flex-direction:column; gap:11px; }
.radarlist .rscore { font-size:28px; font-weight:300; font-variant-numeric:tabular-nums; line-height:1; margin-bottom:4px; }
.radarlist .rscore small { font-size:var(--fs-sub); color:var(--dim); margin-left:2px; }
.radarlist .rrow { display:flex; align-items:center; gap:7px; font-size:var(--fs-sub); cursor:help; }
.radarlist .rl { width:46px; flex-shrink:0; font-weight:600; }
.radarlist .rbar { flex:1; height:9px; background:var(--panel2); border-radius:5px; overflow:hidden; }
.radarlist .rbar i { display:block; height:100%; border-radius:5px; }
.radarlist .rv { width:25px; text-align:right; font-variant-numeric:tabular-nums; font-weight:700; font-size:12.5px; }
.radarlist .rv.na { color:var(--dim); font-weight:400; font-size:var(--fs-lab); }
/* 예측(버튼 ON) 시 — 막대 아래 축별 델타(→값 ▲/▼), 대표 델타 */
.radarlist .rrow.hasfut { flex-wrap:wrap; row-gap:1px; }
.radarlist .rrow .rdelta { flex-basis:100%; text-align:right; font-size:var(--fs-lab); font-weight:700; font-variant-numeric:tabular-nums; }
.radarlist .rsdelta { display:flex; align-items:baseline; gap:5px; margin-top:3px; }
.radarlist .rsdelta small { color:var(--dim); font-size:var(--fs-badge); font-weight:400; }
.radarlist .rsdelta .rdelta { font-size:12.5px; font-weight:700; font-variant-numeric:tabular-nums; }
/* 2x2 컨센서스 셀 — 정돈된 지표 그리드 + 추정 요약 + 일봉 차트 (사용자 확정 2026-07-15) */
/* 차트 묶음을 셀 **바닥에** 붙인다 — 좌우 차트가 같은 높이이므로 바닥이 맞으면 상단도 맞는다.
   (위 콘텐츠 양이 좌우가 달라 위에서부터 쌓으면 113px 어긋났다 — 실측 2026-08-04) */
/* 좌우 차트 바닥선 정렬의 **단일 규칙** (사용자 확정 2026-08-05 "세로 정렬이 엄밀해야 한다"):
   2x2 네 셀을 모두 flex column으로 두고 ①차트를 바닥에 붙이고(margin-top:auto)
   ②padding-bottom을 6px로 통일한다. 차트 높이가 모두 248이므로 바닥이 같으면 상단도 같다.
   한 셀만 빠지면 그 셀의 콘텐츠가 짧을 때 차트가 붕 뜬다 — #chartcell 누락으로 109px 어긋났던 실측. */
#fingrid #chartcell, #fingrid #conscell, #fingrid #margincell, #fingrid #bandcell {
  display:flex; flex-direction:column; padding-bottom:6px; }
#fingrid #chartcell #chartbox, #fingrid #conscell .rvwrap,
#fingrid #margincell #marginchart, #fingrid #bandcell #bandchart { margin-top:auto; }
#conscell .fglab .cvtoggle { margin-left:auto; display:flex; gap:4px; }
#conscell .cvtoggle .ct { background:transparent; border:1px solid var(--line); color:var(--dim); border-radius:6px; padding:1px 8px; font-size:var(--fs-lab); cursor:pointer; }
#conscell .cvtoggle .ct.on, #conscell .cvtoggle .ct:hover { color:var(--accent); border-color:var(--accent); }
.cgrid { display:grid; grid-template-columns:repeat(auto-fit,minmax(120px,1fr)); gap:8px 18px; padding:2px 0 8px; border-bottom:1px dashed var(--line); }
.cgrid .ci { display:flex; flex-direction:column; }
.cgrid .ci small { color:var(--dim); font-size:var(--fs-lab); }
.cgrid .ci b { font-size:17px; font-weight:600; font-variant-numeric:tabular-nums; margin-top:1px; }
.cgrid .ci b .pos, .cgrid .ci b .neg { font-size:var(--fs-sub); }
.cgrid .ci i { font-style:normal; font-size:var(--fs-lab); color:var(--dim); margin-top:1px; }
.cgrid .ci i .pos { color:var(--up); font-weight:600; } .cgrid .ci i .neg { color:var(--down); font-weight:600; }
.cgrid .pos { color:var(--up); } .cgrid .neg { color:var(--down); }
.cest { font-size:var(--fs-sub); color:var(--text); margin:8px 0 2px; }
.cest .ck { color:var(--dim); font-size:var(--fs-lab); margin-right:4px; }
.cest .sep { margin:0 10px; color:var(--line); }
/* 컨센서스 섹션 라벨 (Forward 컨센서스 · 어닝서프라이즈) — 사용자 확정 2026-07-16 */
.csect { font-size:var(--fs-lab); font-weight:700; letter-spacing:.04em; color:var(--dim); margin:10px 0 5px; }  /* 간격 압축 (2026-07-17) */
.csect:first-of-type { margin-top:4px; }
.csect small { font-weight:400; letter-spacing:0; opacity:.9; }
/* 어닝서프라이즈 행 — 지표 · 서프라이즈% · 잠정 vs 컨센 */
.csur { display:flex; align-items:baseline; gap:10px; font-size:12.5px; padding:5px 0; border-bottom:1px solid var(--line); }
.csur:last-of-type { border-bottom:0; }
.csur-m { font-weight:600; min-width:52px; }
.csur-p { font-weight:700; font-variant-numeric:tabular-nums; }
.csur-p.pos { color:var(--up); } .csur-p.neg { color:var(--down); }
.csur-d { margin-left:auto; color:var(--dim); font-size:var(--fs-lab); font-variant-numeric:tabular-nums; }
.csur-none { font-size:var(--fs-sub); color:var(--dim); padding:4px 0; }
/* 최신 실적 카드 — 확정 재무제표보다 앞선 분기 실적 (사용자 확정 2026-07-31). 지표와 숫자를 섞지 않고 별도 영역 */
.lac { border:1px solid var(--line); border-radius:9px; padding:9px 11px; background:var(--panel2); }
.lac.fresh,
/* 좌측 '최근 이익'도 같은 테두리로 (사용자 지적 2026-08-07 "우측처럼 좌측도"). 좌우 두 요약
   박스는 나란히 짝지어 읽히는데 한쪽만 회색이면 둘이 다른 종류로 보인다. `fresh`는 '확정보다
   최신'이라는 뜻이라 좌측(확정 재무)에 붙일 수 없어, 선택자로만 같은 색을 준다. */
#chartinfo .lac { border-color:color-mix(in srgb, var(--accent) 45%, var(--line)); }
.lacr { display:flex; align-items:baseline; gap:10px; padding:3px 0; }
.lacr-m { font-size:var(--fs-sub); color:var(--dim); min-width:62px; }
.lacr-v { font-size:15px; font-weight:700; font-variant-numeric:tabular-nums; }
.lacr-s { margin-left:auto; font-size:var(--fs-sub); font-weight:700; font-variant-numeric:tabular-nums; }
.lacr-s.pos { color:var(--up); } .lacr-s.neg { color:var(--down); }
.lac-foot { margin-top:7px; padding-top:7px; border-top:1px solid var(--line); font-size:var(--fs-lab); color:var(--dim); line-height:1.5; }
/* 헤더 메타 배지 — "2Q 실적 발표 07-07" */
#finherobox .fhhead .fhmeta .fresh { color:var(--accent); font-weight:700; cursor:help; }
/* 우선주 배지 — 이 화면의 재무가 본주 것이라는 사실을 알린다. 다른 메타보다 한 눈 먼저
   읽혀야 해서 면으로 채운다(나머지는 글자만). 사용자 확정 2026-08-07 */
#finherobox .fhhead .fhmeta .pref { color:var(--accent); font-weight:700; cursor:help;
  background:color-mix(in srgb, var(--accent) 11%, transparent);
  border-radius:7px; padding:1px 7px; }
/* 2x1 성장 궤적 */
#growcell { height:250px; }
/* 분기 재무 테이블 (숫자 나열) */
.qtwrap { overflow-x:auto; }
.qtbl { width:100%; border-collapse:collapse; font-size:var(--fs-sub); white-space:nowrap; }
.qtbl th, .qtbl td { padding:5px 9px; border-bottom:1px solid var(--line); text-align:right; font-variant-numeric:tabular-nums; }
.qtbl th { color:var(--dim); font-weight:600; background:var(--panel2); }
.qtbl th.qh, .qtbl td:first-child { text-align:left; color:var(--dim); position:sticky; left:0; background:var(--panel); }
.qtbl th.qh { background:var(--panel2); }
.qtbl td:first-child { font-weight:600; }
.qtbl .neg { color:var(--down); } .qtbl .na { color:var(--dim); }
/* 주요 재무지표 표 (iTooza 스타일, 사용자 확정 2026-07-16): 연간/분기 토글 + 지표명 열 폭 */
.fglab .tbltoggle, .jsect .tbltoggle { margin-left:auto; display:flex; gap:4px; }
.fglab .tbltoggle .ct, .jsect .tbltoggle .ct { background:transparent; border:1px solid var(--line); color:var(--dim); border-radius:6px; padding:1px 9px; font-size:var(--fs-lab); cursor:pointer; }
.fglab .tbltoggle .ct.on, .fglab .tbltoggle .ct:hover,
.jsect .tbltoggle .ct.on, .jsect .tbltoggle .ct:hover { color:var(--accent); border-color:var(--accent); }
.fintbl th.qh, .fintbl td.qh { min-width:96px; }
.fintbl td.qh .uni { font-size:0.82em; font-weight:400; color:var(--dim); }  /* 지표명 끝 괄호 단위 작게 */
/* 가장 최신 기간 열 — 은은한 음영 + '최근' 딱지 (사용자 확정 2026-07-17) */
.fintbl th.recent { background:color-mix(in srgb, var(--accent) 12%, var(--panel2)); }
.fintbl td.recent { background:color-mix(in srgb, var(--accent) 6%, transparent); }
.rcbadge { display:inline-block; margin-left:5px; font-size:8.5px; font-weight:700; letter-spacing:0;
  color:var(--accent); border:1px solid var(--accent); border-radius:5px; padding:0 3px; vertical-align:1px; }
@media (max-width:1000px) { #fingrid { grid-template-columns:1fr; } .radarwrap { grid-template-columns:1fr; }
  #finherobox #finherorow { grid-template-columns:1fr; }
  #valpredchip .vpwrap { grid-template-columns:1fr; }
  #valpredchip .vp-perf { grid-column:1; grid-row:auto; border-left:0; padding-left:0; border-top:1px solid var(--line); padding-top:10px; }
  #valpredchip .vp-expl { border-left:0; border-top:1px solid var(--line); padding-left:0; padding-top:10px; } }
/* Forward 컨센서스 — 박스 없이 섹션 소제목(.sect 문법)과 크기 위계로 강조 (휴먼 패스 2026-07-15) */
.fwd { border-top:1px dashed var(--line); padding:10px 2px 2px; margin:14px 0 4px; }
.fwd.none { color:var(--dim); font-size:12.5px; }
.fwd .fhead { font-size:12.5px; font-weight:700; color:var(--accent); cursor:help; }
.fwd .fhead small { color:var(--dim); font-weight:400; margin-left:8px; }
.fwd .fitems { display:flex; gap:30px; flex-wrap:wrap; margin-top:9px; }
.fwd .fi { display:flex; flex-direction:column; }
.fwd .fi small { color:var(--dim); font-size:var(--fs-lab); }
.fwd .fi b { font-size:19px; font-weight:600; font-variant-numeric:tabular-nums; margin-top:1px; }
.fwd .fi i { font-style:normal; font-size:var(--fs-lab); color:var(--dim); margin-top:1px; }
.fwd .fi i.pos { color:var(--up); font-size:var(--fs-sub); font-weight:600; } .fwd .fi i.neg { color:var(--down); font-size:var(--fs-sub); font-weight:600; }
/* 컨센서스 리비전 미니 차트 (주간 추정 추이 — "전망이 오르는 중인가") */
.rvwrap { margin-top:10px; border-top:1px dashed var(--line); padding-top:8px; }
/* flex 고정 — float:right는 캡션이 길어지면 토글이 아랫줄(차트 범례 위)로 떨어져 겹쳤다 (사용자 지적 2026-08-01) */
.rvcap { font-size:var(--fs-sub); color:var(--dim); display:flex; align-items:center; gap:8px; }
.rvcap small { flex:1 1 auto; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.rvcap b { margin-left:6px; font-variant-numeric:tabular-nums; }
.rvcap b.pos { color:var(--up); } .rvcap b.neg { color:var(--down); }
.rvcap .rvlast { margin-left:8px; font-size:var(--fs-lab); color:var(--dim); font-variant-numeric:tabular-nums; }
.rvcap .cmtoggle { flex:none; margin-left:auto; display:flex; gap:4px; }
.rvcap .cmtoggle .ct { background:transparent; border:1px solid var(--line); color:var(--dim); border-radius:6px; padding:0 8px; font-size:var(--fs-lab); cursor:pointer; }
.rvcap .cmtoggle .ct.on, .rvcap .cmtoggle .ct:hover { color:var(--accent); border-color:var(--accent); }
#revchart { height:118px; margin-top:4px; }
#conschart { height:248px; margin-top:4px; }  /* 상단 요약 줄 제거로 회수 + 확대 — 차트가 주인공 (사용자 확정 2026-07-17) */
/* 2x2 하단 행 — (2,1) 이익률 · (2,2) 밸류에이션 밴드 (사용자 확정 2026-07-17) */
/* 네 차트 모두 같은 높이(248) — 2x2 격자가 한 판으로 읽힌다 (사용자 확정 2026-08-04).
   하단행도 상단행과 같이 **바닥선 정렬**: 셀을 flex column으로 두고 차트를 바닥에 붙인다
   (라벨·캡션 줄 수가 좌우로 달라 위에서 쌓으면 28px 어긋났다 — 실측). */
#marginchart, #bandchart { height:248px; margin-top:6px; }
#fingrid #margincell, #fingrid #bandcell { display:flex; flex-direction:column; padding-bottom:6px; }
#fingrid #margincell #marginchart, #fingrid #bandcell #bandchart { margin-top:auto; }
/* '오늘'로 붙는 자석 (사용자 요청 2026-08-16 "현재 근처라 가면 자석처럼 살짝 탁 하면서").
   붙는 순간 세로선이 브랜드 청록으로 켜진다. 트랜지션은 아주 짧게 — 길면 자석이 아니라
   페이드가 되어 '탁' 걸리는 감각이 사라진다. 커서를 가리지 않도록 이벤트는 통과시킨다. */
#bandchart { position:relative; }
.bandsnap { position:absolute; top:30px; bottom:24px; width:0; z-index:3;
            border-left:1.6px solid var(--accent); opacity:0; pointer-events:none;
            transition:opacity .1s ease-out; }
.bandsnap.on { opacity:1; }
/* 리사이즈 지연 중 캔버스가 이웃 셀을 침범하지 않게 클리핑 (사용자 지적 2026-07-18) */
#fingrid .fgcell { overflow:hidden; }
/* 딥러닝 가치 예측 (docs/41, 사용자 확정 2026-07-18) — 칩은 재무 점수 아래 흐름 카드 */
#radarpane .fglab { display:flex; align-items:baseline; }
/* 버튼 = **레이더 아래 중앙**(사용자 확정 2026-08-03). 헤더 우측 구석에선 존재를 인지하지 못한다 —
   "첫 화면에서 보여야 하고, 스크롤을 내려서 보게 하면 안 된다". 위아래 여백으로 눈에 띄게 띄운다. */
/* 버튼 위아래로 흰 박스를 넉넉히 — 카드 바닥에 붙어 있으면 답답하다(사용자 지적 2026-08-04).
   아래 여백은 버튼 '뒤'라 첫 화면 노출 조건(버튼 bottom)에는 영향이 없다. */
/* 여백은 기술적 분석의 #predrow와 같은 값으로 — 두 '딥러닝 …' 버튼이 같은 자리 문법을 쓴다
   (사용자 지시 2026-08-06 "재무 쪽 버튼 위아래도 조금 더 여유를") */
#valpredrow { display:flex; justify-content:center; margin:22px 0 20px; }
#radarpane .fglab { margin-bottom:6px; }
#finherobox .radarwrap { position:relative; }
/* 칩 = 재무 점수(레이더+바) 아래 흐름 카드 — 절대배치 오버레이가 겹쳐 글자 뒤섞이던 것 원천 차단
   (사용자 지적 2026-07-18 "겹쳐서 보기 안좋다"). 드래그 아님 · 폭 100% */
#valpredchip { position:static !important; width:auto; margin-top:12px; animation:pl-in .35s ease; }
#valpredchip .pchip-h { cursor:default; }
#valpredchip .vpax { display:inline-block; font-weight:700; font-size:var(--fs-sub); margin-right:8px; white-space:nowrap; }
#valpredchip .pcr-v { white-space:normal; text-align:left; }   /* 축 여러 개면 줄바꿈 허용 */
#valpredchip .predmsg { font-size:var(--fs-sub); color:var(--dim); padding:8px 4px; }
/* 1년·2년 예측 2열 카드 (직관 설명 박스) */
/* 칩 본문 2열: 좌=예측 카드(1·2년), 우=분석 결과 요약 (사용자 확정 2026-07-19 남는 우측에 설명) */
#valpredchip .vpwrap { display:grid; grid-template-columns:minmax(0,1.5fr) minmax(0,1fr); gap:16px; align-items:stretch; margin-bottom:10px; }
#valpredchip .vp-left { grid-column:1; display:flex; flex-direction:column; min-width:0; }     /* 카드 + POCF 한 묶음 */
#valpredchip .vp2 { display:grid; grid-template-columns:repeat(2, minmax(0,1fr)); gap:8px; }   /* 1·2년 카드 2열 (박스 낮게 유지) */
#valpredchip .vp-mk { color:var(--text); font-weight:800; }                          /* '멀티플' 볼드 강조 */
#valpredchip .vp-cur { font-size:14px; color:var(--dim); font-weight:600; font-variant-numeric:tabular-nums; }   /* 현재값을 예측 옆에 병기 — 12px는 너무 작았다 (사용자 확정 2026-08-21) */
/* 모델 검증 성적 (우측 세로 전체) — 산점: 예측 vs 실제, 이 종목 점 강조 (사용자 확정 2026-08-21) */
#valpredchip .vp-perf { grid-column:2; grid-row:1 / 3; border-left:1px solid var(--line); padding-left:16px;
  display:flex; flex-direction:column; min-width:0; }
#valpredchip .vp-perf-h { font-size:var(--fs-badge); font-weight:700; color:var(--dim); letter-spacing:.03em;
  margin-bottom:6px; display:flex; align-items:center; justify-content:space-between; }
#valpredchip .vp-perf-tg { display:inline-flex; gap:4px; }
#valpredchip .vp-perf-tg button { font-size:var(--fs-lab); line-height:1; padding:4px 11px; border-radius:999px;
  border:1px solid var(--line); background:none; color:var(--dim); cursor:pointer; }
#valpredchip .vp-perf-tg button.on { color:var(--accent); border-color:var(--accent); font-weight:700; }
#valpredchip .vp-perf-chart { height:200px; min-width:0; flex:none; }
#valpredchip .vp-perf-note { font-size:var(--fs-sub); color:var(--dim); line-height:1.6; margin-top:6px; word-break:keep-all; }
#valpredchip .vp-perf-note p { margin:0 0 .3em; font-size:var(--fs-sub); line-height:1.6; }
#valpredchip .vp-perf-note p:last-child { margin-bottom:0; }
#valpredchip .vp-perf-me { color:#7cb342; font-weight:700; }   /* 산점의 이 종목 점과 같은 초록·연두 */
#valpredchip .vp-expl { grid-column:1; border-top:1px solid var(--line); padding-top:10px; display:flex; flex-direction:column; }
#valpredchip .vp-expl-h { font-size:var(--fs-badge); font-weight:700; color:var(--dim); letter-spacing:.03em; margin-bottom:7px; }
/* 읽는 글은 **기술적 AI 서술과 같은 규격**(13.5px/1.8, 사용자 확정 2026-08-06).
   `.tdiag .tnarr`·`.flowdiag .tnarr`·`#diagcell .tnarr`가 정본이고, 여기만 11.5/1.55로
   작아 같은 성격의 글인데 화면마다 다르게 읽혔다. 문단 간격도 .tnarr과 같은 .36em으로. */
#valpredchip .vp-expl p { margin:0 0 .36em; font-size:13.5px; line-height:1.8; }
#valpredchip .vp-expl p:last-child { margin-bottom:0; }
#valpredchip .vp-expl-sub { font-size:var(--fs-lab); color:var(--dim); line-height:1.5; margin-top:auto; padding-top:6px; }
/* 산업·거시 맥락 한 줄 — 근거 아래 옅게 (사용자 확정 2026-07-19 "거시·산업 통찰 추가, 글밥은 과하지 않게") */
#valpredchip .vp-expl-ctx { font-size:var(--fs-lab); color:var(--dim); line-height:1.5; margin-top:auto; padding-top:7px; border-top:1px solid var(--line); }
/* AI 해설 (온디맨드) — 규칙 3줄 자리를 대체. 대기 문구는 옅게 (docs/43 §7.5) */
#valpredchip .vp-expl-ai { font-size:13.5px; line-height:1.8; color:var(--text); }
#valpredchip .vp-expl-wait { font-size:var(--fs-lab); color:var(--dim); }
/* 모델값·조정 병기 — 무엇이 검증된 예측이고 무엇이 내러티브 조정인지 숨기지 않는다 (docs/43 §7.7) */
#valpredchip .vp-src { font-size:var(--fs-badge); color:var(--dim); margin-top:3px; font-variant-numeric:tabular-nums; }
#valpredchip .vp-o { opacity:.55; }
#valpredchip .vp-expl-adj { font-size:var(--fs-lab); color:var(--dim); line-height:1.5; margin-top:auto; padding-top:7px;
  border-top:1px solid var(--line); }
#valpredchip .vp-tier { color:var(--dim); font-weight:600; margin-left:1px; }
#valpredchip .vpcard { background:var(--panel2); border:1px solid var(--line); border-radius:9px; padding:9px 11px; min-width:0; }
#valpredchip .vp-hz { font-size:var(--fs-lab); color:var(--dim); font-weight:700; margin-bottom:3px; }
#valpredchip .vp-exp { display:flex; align-items:center; gap:3px; font-size:20px; font-weight:800; line-height:1.1; font-variant-numeric:tabular-nums; }
#valpredchip .vp-exp .vp-arw { flex:none; }
#valpredchip .vp-rng { font-size:var(--fs-lab); color:var(--dim); margin-top:5px; font-variant-numeric:tabular-nums; }
#valpredchip .vp-win { display:flex; align-items:center; gap:6px; margin-top:5px; font-size:var(--fs-lab); color:var(--dim); }
#valpredchip .vp-win i { display:block; height:5px; min-width:2px; max-width:66px; flex:1; background:var(--ai); border-radius:3px; opacity:.5; }
#valpredchip .vp-win span { flex:none; white-space:nowrap; }
#valpredchip .vp-na { display:flex; flex-direction:column; justify-content:center; }
#valpredchip .vp-na-t { font-size:13px; font-weight:700; color:var(--dim); }
#valpredchip .vp-na small { font-size:var(--fs-badge); color:var(--dim); margin-top:2px; line-height:1.3; }
#valpredchip .vp-why { display:flex; flex-direction:column; gap:6px; flex:none; min-width:118px; }
#valpredchip .vp-wr { display:flex; align-items:baseline; gap:8px; flex-wrap:wrap; font-size:var(--fs-sub); }
#valpredchip .vp-wl { flex:none; font-size:var(--fs-badge); font-weight:700; letter-spacing:.02em; }
#valpredchip .vp-wl.vp-up { color:var(--up); }
#valpredchip .vp-wl.vp-dn { color:var(--down); }
/* 절대 멀티플(현재 PER → 예측) + 하단 2열([가치 근거] | [재평가 불릿]) */
#valpredchip .vp-mult { margin-top:2px; }
#valpredchip .vp-mult-lab { font-size:var(--fs-badge); color:var(--dim); font-weight:600; }
#valpredchip .vp-mult-val { display:flex; align-items:baseline; gap:5px; margin-top:3px; }
#valpredchip .vp-mult-val b { font-size:21px; font-weight:800; line-height:1.05; font-variant-numeric:tabular-nums; }
#valpredchip .vp-mult-val small { font-size:var(--fs-sub); font-weight:700; }
#valpredchip .vp-mult-cur { font-size:var(--fs-lab); color:var(--dim); font-variant-numeric:tabular-nums; margin-top:1px; }
#valpredchip .vp-lower { display:flex; gap:16px; flex-wrap:wrap; border-top:1px solid var(--line); padding-top:9px; margin-top:2px; }
#valpredchip .vp-rr { flex:1; min-width:150px; }
#valpredchip .vp-rr-h { font-size:var(--fs-badge); font-weight:700; color:var(--dim); margin-bottom:5px; letter-spacing:.02em; }
#valpredchip .vp-bullets { list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:4px; }
#valpredchip .vp-bullets li { font-size:var(--fs-lab); line-height:1.35; padding-left:10px; position:relative; font-variant-numeric:tabular-nums; }
#valpredchip .vp-bullets li::before { content:"–"; position:absolute; left:0; color:var(--dim); }
#valpredchip .vb-o { color:var(--dim); font-weight:400; margin:0 1px; }
#valpredchip .vb-up { color:var(--up); }
#valpredchip .vb-dn { color:var(--down); }
#valpredchip .vp-fincav { font-size:var(--fs-sub); line-height:1.5; color:var(--dim); background:var(--panel2); border:1px solid var(--line); border-radius:9px; padding:10px 12px; margin-bottom:10px; }
#valpredchip .vp-fincav b { color:var(--text); font-weight:700; }
/* 딥러닝 분석 한 줄 (자연어) */
#valpredchip .vp-analysis { border-top:1px solid var(--line); padding-top:9px; margin-top:2px; font-size:13.5px; line-height:1.8; color:var(--text); }
#valpredchip .vp-analysis b { font-weight:700; }
#valpredchip .vp-ai-tag { display:inline-block; font-size:var(--fs-badge); font-weight:700; color:var(--ai); border:1px solid var(--ai); border-radius:5px; padding:0 5px; margin-right:6px; letter-spacing:.02em; opacity:.9; }
#valpredchip .vp-rr { margin-top:9px; }
#chartinfo { margin:0 6px 2px; }
#chartinfo .csur { padding:4px 0; }
/* `.fglab`은 flex 컨테이너라 **float이 무시된다** — 버튼이 그냥 나열돼, 부제 길이가
   바뀌면(탭 전환) 제목을 밀어 한 줄↔두 줄로 접히고 버튼이 위아래로 움직였다
   (사용자 지적 2026-08-17 "두 버튼은 그대로 있어야지 막 바뀌면 어떻게하니").
   margin-left:auto가 flex에서 '오른쪽 끝 고정'의 정답이다. */
.fglab .cmtoggle { margin-left:auto; flex:0 0 auto; display:flex; gap:4px; align-items:center; }
.fglab .cmtoggle .ct { background:transparent; border:1px solid var(--line); color:var(--dim); border-radius:6px; padding:0 9px; font-size:var(--fs-lab); cursor:pointer; white-space:nowrap; }
.fglab .cmtoggle .ct.on, .fglab .cmtoggle .ct:hover { color:var(--accent); border-color:var(--accent); }
.fglab .cmtoggle .ct:disabled { opacity:.4; cursor:default; }
.fglab .cmtoggle .tsep { width:1px; background:var(--line); margin:2px 4px; }

/* 밸류에이션 밴드 머리줄 — 제목은 자리를 내주지 않고(줄어들면 접힌다), 부제만 늘고 줄며,
   버튼은 오른쪽 끝에 고정된다. 그래야 탭을 바꿔도 버튼이 제자리에 있다.
   좁은 화면에서 제목이 두 줄로 접히면 **가운데로 모은다** (사용자 지시 2026-08-17
   "밸류에이션 / 밴드 이렇게 중간정렬되어야 한다 둘다"). */
.fglab.bandlab { align-items:center; }
.fglab.bandlab .fgtit { flex:0 0 auto; text-align:center; }
.fglab.bandlab small { flex:1 1 auto; min-width:0; }
/* 시총 순 내비 (사용자 확정 2026-07-15): 순위 표시 + 위·아래 종목 이동 */
/* 기술적 차트 위 상단 — 서술을 없앤 뒤(2026-07-22) 온도계 히어로 단독 전체폭 */
#techtop { display:grid; grid-template-columns:1fr; gap:12px; align-items:start; margin:10px 2px 6px; }
#techtop #heroarea { min-width:0; }
/* ② 대표 차트 (1행 명칭 — 사용자 확정 2026-07-14) + 온도계 모드 토글(.gsel, 2026-07-15) */
.tctl { display:flex; align-items:center; gap:4px; margin:8px 2px 0; }
/* 섹션 제목 = 심리 메뉴 키워드 대제목(.snax)과 동일 포맷 (사용자 확정 2026-07-17 일관성) */
.tctl .tlabel { margin-right:auto; font-size:16.5px; letter-spacing:-.2px; color:var(--text); font-weight:700; }
.tctl .ct, .gsel .ct { background:transparent; border:1px solid var(--line); color:var(--dim); border-radius:6px; padding:2px 10px; font-size:var(--fs-sub); cursor:pointer; }
.tctl .ct.on, .tctl .ct:hover, .gsel .ct.on, .gsel .ct:hover { color:var(--accent); border-color:var(--accent); }
/* 봉 전환 셀렉터 (사용자 확정 2026-07-29) — 캔들 토글 옆, 활성=액센트(.ct 상속) */
.tfseg { display:inline-flex; gap:2px; margin-left:4px; }
.tfseg .tfbtn { padding:2px 9px; }
/* 기간 셀렉터 (연중/1/2/3/5년) — 봉 셀렉터와 구분 위해 좌측에 얇은 구분선 */
.rgseg { display:inline-flex; gap:2px; margin-left:8px; padding-left:8px; border-left:1px solid var(--line); }
.rgseg .rgbtn { padding:2px 8px; }
/* 선↔캔들 전환 버튼 (사용자 확정 2026-07-17, 기술적 분석 전용) — SVG 아이콘 정렬 */
#candlebtn { display:inline-flex; align-items:center; gap:5px; margin-right:6px; padding:3px 10px; }
.gsel { display:flex; justify-content:flex-end; gap:4px; margin:2px 2px 0; }
/* 기술적 차트 (사용자 확정 2026-07-16: 조금 축소 + 휠로 시계열 확대/축소) */
#techchartwrap { position:relative; }
#techchart { height:500px; margin:2px 0 4px; }
/* 머신러닝 계산 중 오버레이 (fancy 연출 — 사용자 확정 2026-07-16) */
#predloading { position:absolute; inset:0 0 4px 0; display:flex; align-items:center; justify-content:flex-end;
  padding-right:8%; z-index:20; border-radius:8px; pointer-events:none;
  background:linear-gradient(90deg, transparent 55%, color-mix(in srgb, var(--radar) 12%, transparent) 100%); }
#predloading[hidden] { display:none; }
.pl-card { display:flex; flex-direction:column; align-items:center; gap:9px; padding:20px 26px; text-align:center;
  background:var(--panel2); border:1px solid var(--radar); border-radius:14px; box-shadow:0 10px 34px rgba(0,0,0,.28);
  animation:pl-in .3s ease; }
/* 가치 예측 칩 안에서는 결과 카드 자리에 그대로 뜨므로 이중 카드 방지(테두리·배경 제거) */
#valpredchip .pl-card { background:transparent; border:0; box-shadow:none; padding:22px 12px; }
@keyframes pl-in { from { opacity:0; transform:translateY(6px) scale(.97); } }
.pl-ring { width:38px; height:38px; animation:pl-rot .9s linear infinite; }
.pl-ring circle { fill:none; stroke:var(--radar); stroke-width:3.5; stroke-linecap:round; stroke-dasharray:66 46; opacity:.9; }
@keyframes pl-rot { to { transform:rotate(360deg); } }
.pl-txt { font-size:13px; font-weight:700; color:var(--text); }
.pl-txt .pl-dots i { animation:pl-blink 1.1s infinite; } .pl-txt .pl-dots i:nth-child(2){ animation-delay:.18s; } .pl-txt .pl-dots i:nth-child(3){ animation-delay:.36s; }
@keyframes pl-blink { 0%,100%{ opacity:.2; } 50%{ opacity:1; } }
.pl-sub { font-size:var(--fs-lab); color:var(--dim); }
/* 머신러닝 주가 예측 버튼 + 결과 (사용자 확정 2026-07-16) */
/* 딥러닝 예측 버튼 = 엣지 자주빛(--radar), 시그니처 청록 아님 (사용자 지시 2026-07-22 "청록 말고 기존 자줏빛") */
.predbtn { display:inline-flex; align-items:center; gap:6px; background:var(--panel2); border:1px solid var(--radar);
  color:var(--radar); border-radius:8px; padding:4px 12px; font-size:var(--fs-sub); font-weight:700; cursor:pointer;
  transition:background .15s ease, color .15s ease; }
.predbtn:hover { background:var(--radar); color:#fff; }
.predbtn.on { background:var(--radar); color:#fff; }
.predbtn:disabled { opacity:.6; cursor:default; }
#predbox { margin:7px 2px 0; }
.predmsg { font-size:12.5px; color:var(--dim); padding:6px 2px; }
/* ==== 딥러닝 차트 분석 — 버튼은 52주 온도계와 '기술적 분석' 사이(한눈에 보이는 자리,
   사용자 확정 2026-08-06 "핵심이라 아래에 있으면 안 좋다"), 결과 1×2 해설은 차트 아래.
   차트 위에 떠다니던 칩은 폐기 — 차트를 가리지 않는다. ==== */
#predrow { display:flex; justify-content:center; margin:18px 0 16px; }
/* 추세선 버튼 — 차트 범례 줄 좌측. 위 기간 버튼(.ct)과 **같은 규격, 색만 검정**
   (사용자 확정 2026-08-04). ECharts 범례로 만들었을 땐 텍스트가 silent라 :hover가 통째로
   죽어 있었다(사용자 지적 2026-08-07) — 진짜 버튼이라야 호버가 확실히 먹는다. */
#techchartwrap { position:relative; }
/* top·left는 alignTrendBtn()이 범례(MA20) 자리를 실측해 채운다 (아래 값은 첫 페인트용 근사) */
#trendbtn, #mntrendbtn { position:absolute; top:4px; right:210px; z-index:6;
  background:transparent; border:1px solid var(--line); color:var(--dim);
  border-radius:6px; padding:2px 10px; font-size:var(--fs-sub); font-family:inherit; line-height:1.55;
  cursor:pointer; transition:color .15s ease, border-color .15s ease; }
#trendbtn:hover, #mntrendbtn:hover { color:var(--text); border-color:var(--text); }   /* 회색 → 검정 */
#trendbtn.on, #mntrendbtn.on { color:var(--text); border-color:var(--text); font-weight:600; }
/* 월봉·연봉 = 조용히 비활성. 경고 문구 없이 '지금은 못 쓴다'만 보이게 (사용자 확정 2026-08-07) */
#trendbtn.off, #mntrendbtn.off { opacity:.35; cursor:default; }
#trendbtn.off:hover, #mntrendbtn.off:hover { color:var(--dim); border-color:var(--line); }
#deeppanel[hidden] { display:none; }
/* **1행 2열 + 2행 통합** (사용자 확정 2026-08-17 "조금 복잡한 느낌이야").
   종전엔 2×2라 해설도 좌우로 갈려 있었다. 같은 종목의 한 이야기를 두 칸으로 나눠 읽히니
   같은 말이 양쪽에 겹치고, 눈이 좌우를 오가야 했다. **재료는 둘, 결론은 하나**로 바꾼다.

     1행  [ 과거 유사한 차트 모양 ] [ 주가 흐름 예측 ]   ← 서로 다른 재료
     2행  [        통합 차트 분석 해설 (전폭)        ]   ← 둘을 합친 결론 */
.dpanel { display:grid; grid-template-columns:1fr 1fr; gap:0;
  margin-bottom:6px; background:var(--panel2); border:1px solid var(--line);
  border-left:3px solid var(--radar); border-radius:10px; animation:pl-in .35s ease; }
.dpanel .dp-cell { padding:14px 18px; min-width:0; }
.dpanel .dp-top { padding-bottom:16px; }
/* 중앙 세로 점선 = 1행의 두 칸이 한 카드 안의 두 재료임을 보이게 */
.dpanel .dp-top + .dp-top { border-left:1px dashed var(--line); }
/* 2행 = 두 열을 가로지른다. 전폭이라 가로선 하나가 곧 '여기부터 결론'이 된다 */
.dpanel .dp-wide { grid-column:1 / -1; }
@media (max-width:900px) {
  /* 1열 폴백 — 자연 순서가 곧 읽는 순서(모양 → 흐름 → 해설)라 재배치가 필요 없다 */
  .dpanel { grid-template-columns:1fr; }
  .dpanel .dp-top + .dp-top { border-left:0; border-top:1px dashed var(--line); }
}
/* 제목 = **카드 제목 단**(15.5px). 종전 13px은 본문(13.5px)보다도 작아 제목으로 안 읽혔다
   (사용자 지시 2026-08-17 "지금 너무 작아"). 캐논 사다리 22 / 18 / 15.5의 셋째 칸이다 */
.dp-h { font-size:15.5px; font-weight:700; color:var(--radar); margin-bottom:12px;
  letter-spacing:-.2px; }
.dp-body, .dp-say { font-size:13.5px; }
/* 주비스의 말은 **양쪽 다 아래로 밀어** 바닥을 맞춘다 (사용자 지시 2026-08-06 "정렬이 잘돼야
   이해하기 편하다"). 위 블록의 줄 수가 달라도 두 칸의 해설·각주가 같은 선에서 시작한다. */
.dp-say { border-top:1px solid var(--line); padding-top:12px; margin-top:2px; }
.dp-body p, .dp-say p { margin:0; font-size:13.5px; line-height:1.8; }
.dp-body p + p, .dp-say p + p { margin-top:.36em; }   /* 벌어지면 벽처럼 읽힌다 */
.dp-body p b, .dp-say p b { font-weight:700; }
/* 지금 상태 = 큰 그림(좌) / 큰 숫자(우) 하나. 두 칸의 첫 블록 높이를 맞춘다. */
.dp-now { display:flex; flex-direction:column; align-items:center; gap:5px;
  min-height:96px; justify-content:center; margin-bottom:8px; }
.dp-now .dp-gl { display:block; }
.dp-nowt { display:flex; align-items:center; gap:7px; font-size:15px; font-weight:700; }
.dp-nowc { font-size:var(--fs-sub); color:var(--dim); }
/* 우측 큰 숫자의 이름표 — 좌측 `.dp-arrow span`과 **같은 규격·같은 청록**
   (머신러너님 지시 2026-08-31 "상단의 청록색 볼드처럼 하단도"). 두 칸이 같은 문법으로
   말해야 「과거엔 이런 모양 / 이런 자리」가 한 쌍으로 읽힌다. */
.dp-nowk { font-size:13.5px; font-weight:600; color:var(--accent); text-align:center; }
/* 두 달을 어떻게 지나왔나 — 숫자 블록과 표 사이에 낮게 깐다. 끝값의 각주 같은 자리다. */
.dp-shape { font-size:12.5px; line-height:1.6; color:var(--dim); text-align:center;
  margin:-2px 0 12px; padding:0 4px; cursor:help; }
.dp-big { font-size:30px; font-weight:800; letter-spacing:-.01em; font-variant-numeric:tabular-nums;
  line-height:1.1; }
.dp-now .ccfam { flex:none; font-size:var(--fs-sub); font-weight:700; border:1px solid; border-radius:6px; padding:1px 7px; }
/* 현재 → 이후. 화살표가 두 블록의 관계를 말한다(글로 설명하지 않는다). */
/* 화살표·캡션은 주비스 시그니처 청록 (사용자 확정 2026-08-07) — 두 블록을 잇는 이 한 줄이
   좌측 칸의 이야기가 꺾이는 지점이라, 회색으로 두면 그냥 지나친다. */
.dp-arrow { display:flex; flex-direction:column; align-items:center; gap:3px;
  margin:8px 0 8px; color:var(--accent); cursor:help; }
.dp-arrow span { font-size:13.5px; font-weight:600; }
/* 이후 모양 3개 — 확률 내림차순. 그림이 먼저 읽히고 이름은 그다음이다. */
.dp-next { display:grid; grid-template-columns:repeat(3, 1fr); gap:7px; }
.dp-nx { border:1px solid var(--line); border-radius:9px; padding:9px 5px 8px;
  display:flex; flex-direction:column; align-items:center; gap:3px; background:var(--panel); }
.dp-nx .dp-gl { display:block; }
.dp-nxp { font-size:15px; font-weight:800; font-variant-numeric:tabular-nums; line-height:1.1; }
.dp-nxk { font-size:12.5px; font-weight:700; text-align:center; line-height:1.25; }
.dp-nxc { font-size:var(--fs-lab); color:var(--dim); text-align:center; line-height:1.25; }
/* 판단 근거 — 줄마다 하나. 한 문단에 이어 붙이면 "…했어요 …했어요"로 읽힌다 */
.dp-ev { margin:22px 0 12px; }
.dp-evh { display:block; font-size:var(--fs-sub); font-weight:700; color:var(--dim); margin-bottom:4px; }
.dp-evl { display:block; font-size:13px; line-height:1.7; padding-left:11px; position:relative; }
.dp-evl::before { content:""; position:absolute; left:0; top:.62em; width:4px; height:4px;
  border-radius:50%; background:var(--dim); }
.dp-cls { display:flex; align-items:center; gap:7px; margin-bottom:10px; font-size:14px; font-weight:700; }
.dp-cls .ccfam { flex:none; font-size:var(--fs-sub); font-weight:700; border:1px solid; border-radius:6px; padding:1px 7px; }
.dp-conf { font-size:var(--fs-sub); color:var(--dim); font-weight:600; }
/* 숫자를 먼저 줄 단위로 세우고(개행), 주비스의 말은 그 아래 (사용자 지시 2026-08-06) */
.dp-rows { margin-bottom:12px; }
.dp-row { display:flex; align-items:baseline; justify-content:space-between; gap:12px;
  padding:7px 0; font-size:12.5px; border-bottom:1px solid var(--line); }
.dp-row:last-child { border-bottom:0; }
/* 항목 이름은 본문색 (사용자 확정 2026-08-07) — 회색이면 무슨 항목인지부터 안 읽힌다 */
.dp-rl { color:var(--text); flex:none; }
.dp-rl[title] { cursor:help; }
.dp-rl small { color:var(--dim); }
.dp-rv { text-align:right; font-variant-numeric:tabular-nums; white-space:nowrap; }
.dp-rv b { font-size:14px; font-weight:700; }
/* 곁들이는 숫자는 **작은 회색 주석이 아니라 괄호 안 본문색** (사용자 확정 2026-08-07).
   중요한 숫자를 10.5px 회색으로 흘려두면 읽히지도 않고 주저리주저리로만 보인다.
   설명 문구는 화면에서 빼고 툴팁으로 — 여기 남는 건 숫자뿐이다. */
.dp-rv small { font-size:13.5px; color:var(--text); font-weight:400; }
/* 값 칸에 들어가는 작은 패턴 그림 — baseline 정렬이라 살짝 내려 글자 가운데에 맞춘다 */
.dp-rv .dp-gl { display:inline-block; vertical-align:-3px; margin-right:2px; }
.dp-f { margin-top:11px; padding-top:8px; border-top:1px solid var(--line);
  font-size:var(--fs-sub); color:var(--dim); line-height:1.65; }
.dp-f .dim { opacity:.8; }
/* 차트 예측 영역 작은 박스 (사용자 확정 2026-07-16) — 보라색(예측선과 통일), 드래그·접기 */
/* 차트 커서 (사용자 확정 2026-07-18): 기본 = 손바닥 팬 · 쥐면 grabbing · 휠클릭 범위 모드 = 십자.
   ECharts가 루트 div에 인라인 커서를 쓰므로 !important로 모드별 오버라이드 */
#techchart:not(.boxzoom) > div { cursor:grab !important; }
#techchart.grabbing:not(.boxzoom) > div { cursor:grabbing !important; }
#techchart.boxzoom > div { cursor:crosshair !important; }
#predchip, .predchip, #svchip { position:absolute; top:36px; right:12px; z-index:15; width:272px;   /* 차트 유형 섹션 수용(docs/53) — 238이면 기저율 줄이 4줄로 꺾인다 */
  background:var(--panel2); border:1px solid var(--line); border-left:3px solid var(--radar); border-radius:10px;
  padding:9px 11px; box-shadow:0 6px 20px rgba(168,85,247,.22); animation:pl-in .35s ease; user-select:none; }
#predchip[hidden], .predchip[hidden], #svchip[hidden] { display:none; }
#predchip.folded, .predchip.folded, #svchip.folded { padding-bottom:8px; }
#predchip.folded .pchip-body, .predchip.folded .pchip-body, #svchip.folded .pchip-body { display:none; }
#predchip.folded .pchip-h, .predchip.folded .pchip-h, #svchip.folded .pchip-h { margin-bottom:0; }
/* 헤더 한 줄 고정 — 제목이 "딥러닝 예/측"으로 꺾이지 않게 (사용자 확정 2026-07-18 정리정돈) */
#predchip .pchip-h, .predchip .pchip-h, #svchip .pchip-h { font-size:var(--fs-lab); font-weight:700; color:var(--radar); margin-bottom:7px;   /* 딥러닝 칩 헤더 = 엣지 자줏빛(--radar) — 시그니처 청록 아님 (사용자 지시 2026-07-22) */
  display:flex; align-items:center; cursor:move; white-space:nowrap; }
#predchip .pchip-h small, .predchip .pchip-h small, #svchip .pchip-h small { overflow:hidden; text-overflow:ellipsis; }
#predchip .pchip-h small, .predchip .pchip-h small, #svchip .pchip-h small { color:var(--dim); font-weight:400; margin-left:3px; }
/* 접기 버튼 — 잘 보이게 크게 (사용자 확정 2026-07-17) */
#predchip .pchip-fold, .predchip .pchip-fold, #svchip .pchip-fold { margin-left:auto; background:none; border:1px solid var(--line); border-radius:6px;
  color:var(--dim); cursor:pointer; font-size:15px; line-height:1; padding:3px 8px;
  transition:transform .2s ease, background .15s ease, color .15s ease; }
#predchip .pchip-fold:hover, .predchip .pchip-fold:hover, #svchip .pchip-fold:hover { color:var(--radar); border-color:var(--radar); background:color-mix(in srgb, var(--radar) 14%, transparent); }
#predchip.folded .pchip-fold, .predchip.folded .pchip-fold, #svchip.folded .pchip-fold { transform:rotate(-90deg); }
#predchip .pchip-i, .predchip .pchip-i, #svchip .pchip-i { margin-left:6px; color:var(--dim); cursor:help; border:1px solid var(--line); border-radius:50%; padding:0 4.5px; font-size:var(--fs-badge); }
/* 판정 줄 아래 헤어라인으로 단락 구분 — 이후 행들은 일정한 리듬 (사용자 확정 2026-07-18) */
#predchip .pchip-verdict, .predchip .pchip-verdict, #svchip .pchip-verdict { font-size:15px; font-weight:800; margin:2px 0 0;
  padding-bottom:9px; border-bottom:1px solid var(--line); }
#predchip .pchip-bar, .predchip .pchip-bar, #svchip .pchip-bar { display:flex; align-items:center; gap:6px; margin-top:4px; font-size:var(--fs-lab); }
#predchip .pcb-l, .predchip .pcb-l, #svchip .pcb-l { color:var(--dim); flex:none; width:56px; }
#predchip .pcb-track, .predchip .pcb-track, #svchip .pcb-track { flex:1; height:7px; background:var(--line); border-radius:4px; overflow:hidden; }
#predchip .pcb-track i, .predchip .pcb-track i, #svchip .pcb-track i { display:block; height:100%; border-radius:4px; transition:width .5s ease; }
#predchip .pcb-v, .predchip .pcb-v, #svchip .pcb-v { flex:none; width:34px; text-align:right; font-weight:700; font-variant-numeric:tabular-nums; }
#predchip .pchip-lstm, .predchip .pchip-lstm, #svchip .pchip-lstm { display:flex; align-items:center; gap:5px; font-size:var(--fs-lab); color:var(--dim); margin-top:8px; padding-top:7px; border-top:1px solid var(--line); }
#predchip .pchip-lstm b, .predchip .pchip-lstm b, #svchip .pchip-lstm b { font-variant-numeric:tabular-nums; }
#predchip .pchip-lstm small, .predchip .pchip-lstm small, #svchip .pchip-lstm small { color:var(--dim); }
#predchip .pcl-dot, .predchip .pcl-dot, #svchip .pcl-dot { width:12px; height:3px; border-radius:2px; background:var(--pred); box-shadow:0 0 6px var(--pred); flex:none; }   /* 예측선 범례 = 차트의 예측선과 같은 토큰 */
/* 종목 역사 학습 요약 행 (사용자 확정 2026-07-17 — ±9% 배리어 막대 대체) */
#predchip .pchip-row, .predchip .pchip-row, #svchip .pchip-row { display:flex; align-items:baseline; justify-content:space-between; gap:10px;
  margin-top:8px; font-size:var(--fs-lab); line-height:1.4; }
#predchip .pcr-l, .predchip .pcr-l, #svchip .pcr-l { white-space:nowrap; }
#predchip .pcr-v, .predchip .pcr-v, #svchip .pcr-v { white-space:nowrap; }   /* 값 줄바꿈 금지 — "+354.9% vs 보유 +208.9%" 한 줄 */
#predchip .pcr-l, .predchip .pcr-l, #svchip .pcr-l { color:var(--dim); flex:none; }
#predchip .pcr-v, .predchip .pcr-v, #svchip .pcr-v { font-weight:700; font-variant-numeric:tabular-nums; text-align:right; }
#predchip .pcr-v small, .predchip .pcr-v small, #svchip .pcr-v small { color:var(--dim); font-weight:400; }
#predchip .pchip-verdict small, .predchip .pchip-verdict small, #svchip .pchip-verdict small { font-size:var(--fs-lab); font-weight:600; }
#predchip .pchip-foot, .predchip .pchip-foot, #svchip .pchip-foot { font-size:var(--fs-badge); color:var(--dim); margin-top:9px; padding-top:7px; border-top:1px solid var(--line); }
/* ②-b 2열 패널: RSI(과열/침체) | 고점 대비 낙폭 곡선 — 박스 없이 헤어라인 구획 (휴먼 패스 2026-07-15) */
/* 섹션 사이 숨 쉴 틈 (사용자 확정 2026-08-05 "너무 따닥따닥 붙어 답답하다").
   구분선 위 24 / 아래 22 — 선은 경계일 뿐이고, 읽는 눈은 그 앞뒤의 여백에서 쉰다. */
.trow2 { display:grid; grid-template-columns:repeat(auto-fit,minmax(320px,1fr)); gap:28px; margin:24px 0 6px; border-top:1px dashed var(--line); padding-top:22px; }
/* 수급 동향 패널 (사용자 확정 2026-07-17) — 외국인·기관·개인 누적 순매수 + 주가 오버레이, RSI·MDD 아래 전폭 */
/* ⚠ 이 요소는 class="tpanel tflow"다. 아래 `.tpanel { padding:0 2px }`가 **축약형**이라
   같은 특이도면서 뒤에 오므로 padding-top을 덮는다(실측 2026-08-05: 22px 지정이 0px로 죽음).
   그래서 좌우 패딩은 tpanel에 맡기고, 위 여백만 `.tpanel.tflow`로 특이도를 올려 잡는다. */
.tflow { margin:28px 0 6px; border-top:1px dashed var(--line); }
.tpanel.tflow { padding-top:22px; }
#flowchart { height:300px; }
/* 수급 패널의 두 행은 **같은 열 정의를 공유**한다 (사용자 지적 2026-08-03 "그래프 선을 위 박스 선에 맞춰라").
   각자 다른 비율(1.25fr vs 2fr)을 쓰다 보니 위·아래 경계가 어긋나 난잡해 보였다.
   변수 하나로 묶어 두 행이 구조적으로 같은 세로선을 쓰게 한다 — 다시 어긋날 수 없다. */
.tflow { --flowcols: minmax(0, 2fr) minmax(330px, 1fr); --flowgap: 22px; }
/* 상단 행 (사용자 확정 2026-07-18): AI 수급 분석(좌) | 주도 세력 전광판(우) */
.tflow .flowtop { display:grid; grid-template-columns:var(--flowcols); gap:var(--flowgap); align-items:stretch; margin:14px 0 22px; }
@media (max-width:900px) { .tflow .flowtop { grid-template-columns:1fr; } }
.tflow .flowdiag { background:var(--panel2); border:1px solid var(--line); border-left:3px solid var(--ai);
  border-radius:10px; padding:12px 16px; margin:0; }
.tflow .flowdiag .sum { font-size:13.5px; font-weight:700; color:var(--ai); cursor:help; }
.tflow .flowdiag .tnarr { font-size:13.5px; line-height:1.8; margin:6px 0 0; max-width:76em; }
/* 하단 행 (사용자 확정 2026-07-18): 동행 차트(좌) | 기간별 순매수 테이블(우) */
.tflow .flowgrid { display:grid; grid-template-columns:var(--flowcols); gap:var(--flowgap); align-items:center; }   /* 상단 행과 동일 열 = 세로선 정렬. 표가 5열이라 우측 최소폭 330px (2026-07-29) */
@media (max-width:900px) { .tflow .flowgrid { grid-template-columns:1fr; } }
/* 주도 세력 전광판 — 박스 없이 평면 (사용자 확정 2026-07-18 "회색 박스 없애라") */
/* 전광판: 블록은 공간 정중앙, 내부 텍스트는 좌측 정렬 — 주체별 동행도와 같은 축 (사용자 확정 2026-07-18) */
.tflow .flowlead { padding:12px 0 6px; display:flex; flex-direction:column;
  justify-content:center; align-items:center; text-align:left; height:100%; }
.tflow .fl-t, .tflow .fl-name, .tflow .fl-sub { width:100%; max-width:370px; }
/* 기간별 순매수 테이블 */
.tflow .flowtable { padding:4px 2px; }
.tflow .ft-t { font-size:var(--fs-lab); font-weight:700; color:var(--dim); letter-spacing:.04em; margin-bottom:7px; }
.tflow .ft-t small { font-weight:400; }
.tflow .flowtable table { width:100%; border-collapse:collapse; font-size:var(--fs-sub); }
.tflow .flowtable th { font-weight:600; color:var(--dim); text-align:right; padding:6px 4px; border-bottom:1px solid var(--line); }
.tflow .flowtable tbody th { text-align:left; }
.tflow .flowtable td { text-align:right; padding:7px 4px; border-bottom:1px solid var(--line); font-variant-numeric:tabular-nums; font-weight:600; }
.tflow .flowtable tbody tr:last-child th, .tflow .flowtable tbody tr:last-child td { border-bottom:0; }
/* 딥러닝 차트 분석 — 예측 칩 하단의 차트 유형 섹션 (docs/53, 상시 패널 #ccpanel은 폐기) */
#predchip .pcc-div { height:1px; background:var(--line); margin:9px -2px 8px; }
#predchip .ccfam { flex:none; font-size:var(--fs-badge); font-weight:700; border:1px solid; border-radius:5px; padding:0 5px; }
#predchip .pcc-row { display:flex; align-items:baseline; gap:6px; flex-wrap:wrap; }
#predchip .pcc-name { font-size:13px; font-weight:700; letter-spacing:-.2px; }
#predchip .pcc-why { margin-top:4px; font-size:var(--fs-lab); line-height:1.55; color:var(--dim); }
#predchip .pcc-stat { margin-top:5px; font-size:var(--fs-lab); line-height:1.55; color:var(--dim); font-variant-numeric:tabular-nums; }
#predchip .pcc-stat b { color:var(--text); font-weight:600; }
#predchip .pcc-hold { font-size:var(--fs-lab); color:var(--dim); }
/* 합의 판정 — 일치=방향색 왼줄, 엇갈림=보라 왼줄 (판정이 아니라 주의 신호) */
#predchip .pcc-verdict { margin-top:7px; padding:5px 8px; font-size:var(--fs-lab); line-height:1.55;
  border-left:2px solid var(--dim); background:color-mix(in srgb, var(--dim) 7%, transparent); border-radius:0 6px 6px 0; }
#predchip .pcc-agree_up { border-left-color:var(--up); }
#predchip .pcc-agree_down { border-left-color:var(--down); }
#predchip .pcc-mixed { border-left-color:var(--pred); }
/* 당일 열이 아직 집계 전일 때 — 값도 헤더도 옅게(사유 있는 N/A, 사용자 확정 2026-07-29) */
.tflow .flowtable .ft-na { color:var(--dim); opacity:.55; font-weight:400; }
/* 5열(당일~3개월) — 여백 축소 + 줄바꿈 금지('외국인'이 외/국/인으로 쪼개지던 문제) */
.tflow .flowtable th, .tflow .flowtable td { padding:6px 3px; white-space:nowrap; }
.tflow .flowtable tbody th { padding-right:8px; }
.tflow .fl-t { font-size:var(--fs-lab); font-weight:700; color:var(--dim); letter-spacing:.08em; }
.tflow .fl-name { font-size:34px; font-weight:800; letter-spacing:-.5px; margin:9px 0 4px; }
.tflow .fl-name.fl-none { font-size:19px; color:var(--dim); font-weight:700; }
.tflow .fl-sub { font-size:var(--fs-sub); color:var(--dim); margin-bottom:18px; }
.tflow .fl-sub b { color:var(--text); font-size:13px; }
/* 주체별 동행도 위젯 — 다이버징 바: 0 중심, 우=동행 · 좌=반대.
   막대는 열 전체가 아니라 적당한 길이로 (사용자 확정 2026-07-18 "길이 조금 줄이자") */
.tflow .fcorr { width:100%; max-width:370px; cursor:help; text-align:left; }   /* 막대 2배 (트랙 ~113→220px대) */
.tflow .fc-t { margin-bottom:7px; }
.tflow .fc-row { margin-top:6px; }
.tflow .fc-t { font-size:var(--fs-lab); font-weight:700; color:var(--dim); letter-spacing:.04em; margin-bottom:5px; }
.tflow .fc-q { border:1px solid var(--line); border-radius:50%; padding:0 4px; font-size:var(--fs-badge); font-weight:400; }
.tflow .fc-row { display:flex; align-items:center; gap:5px; margin-top:4px; font-size:var(--fs-lab); }
.tflow .fc-l { flex:none; width:38px; font-weight:600; }
.tflow .fc-track { position:relative; flex:1; height:8px; background:var(--line); border-radius:4px; overflow:hidden; }
.tflow .fc-track::after { content:""; position:absolute; left:50%; top:0; bottom:0; width:1px; background:var(--dim); opacity:.55; }
.tflow .fc-track i { position:absolute; top:0; bottom:0; border-radius:4px; }
.tflow .fc-v { flex:none; width:44px; text-align:right; font-variant-numeric:tabular-nums; }
/* '주도' 배지 슬롯 — 모든 행에 고정폭으로 확보해 숫자 열 정렬 유지 (사용자 확정 2026-07-17),
   배지는 숫자 오른쪽. 색은 주도 주체 색을 인라인으로 받음 */
.tflow .fc-b { flex:none; width:30px; font-size:var(--fs-badge); font-weight:700; text-align:center; }
.tflow .fc-b:not(:empty) { border:1px solid; border-radius:5px; padding:1px 0; }
.tpanel { padding:0 2px; }
/* 두 패널 사이 세로 구분선 — 밸류에이션 좌우 2열(#mnvalref .mnvalcol)과 같은 신호.
   auto-fit이라 좁아지면 1열로 접히는데, 그때 세로선은 뜻이 없어 가로선으로 바꾼다. */
.trow2 > .tpanel + .tpanel { border-left:1px solid var(--line); padding-left:28px; }
@media (max-width:820px) {
  .trow2 > .tpanel + .tpanel { border-left:0; padding-left:2px; border-top:1px solid var(--line); padding-top:22px; }
}
/* 무엇인지 분명하게 (사용자 확정 2026-07-16): 제목 + 한 줄 설명, 값은 크게 우측 */
.tpanel .ph { display:flex; align-items:flex-start; gap:8px; }
/* 항상 떠 있던 설명 한 줄(.pdesc)은 '?' 배지로 대체 (사용자 확정 2026-07-22 "한눈에 복잡해 보이면 안 된다")
   — 제목과 '?'가 한 줄, 설명은 올려놨을 때만 */
.tpanel .pk-wrap { display:flex; align-items:center; gap:6px; min-width:0; }
/* 패널 제목 = 심리 메뉴 .snax와 동일 포맷 16.5px/700 (사용자 확정 2026-07-17 일관성) */
.tpanel .pk { font-size:16.5px; letter-spacing:-.2px; color:var(--text); font-weight:700; }
/* '?' 도움말 배지 — 평소엔 조용한 점, 올려놓으면 설명 말풍선. 브라우저 기본 title은 1초 지연이라 직접 그린다 */
/* 밸류에이션 밴드 툴팁 — 선마다 금액을 적던 것을 **괴리율**로 바꿨다(사용자 지적 2026-08-07
   "숫자가 너무 많아 복잡"). 여섯 자리 숫자 여섯 줄은 어느 것을 읽어야 할지 알려주지 못한다.
   금액은 주가 한 줄뿐이고, 머리의 실효 배수가 "지금 몇 배인가"에 바로 답한다. */
.bt { min-width:132px; }
.bt-d { font-size:var(--fs-badge); color:var(--dim); }
.bt-h { display:flex; align-items:baseline; gap:6px; margin-top:2px;
  font-size:13px; font-weight:600; font-variant-numeric:tabular-nums; }
.bt-h em { font-style:normal; font-size:var(--fs-lab); font-weight:500; color:var(--dim); }
.bt-c { margin:6px 0 3px; padding-top:5px; border-top:1px solid var(--line);
  font-size:var(--fs-badge); color:var(--dim); }
.bt-r { display:flex; justify-content:space-between; gap:14px; line-height:1.65;
  font-size:var(--fs-lab); color:var(--dim); font-variant-numeric:tabular-nums; }
.bt-r b { font-weight:600; color:var(--text); }
.bt-r.ref, .bt-r.ref b { color:var(--accent); font-weight:600; }

/* 공용 툴팁(#jvtip) — core.js가 body 직속에 하나만 만들어 재사용한다.
   body 직속이라 카드의 overflow·z-index에 잘리지 않는다.
   **규격 셋** (사용자 확정 2026-08-07 "규격화된 설명 크기를 미리 정해두고 골라 쓰자"):
     s 190px — 한 줄 설명   ·   m 280px — 보통   ·   l 380px — 계산식까지 붙는 긴 설명
   길이에 맞는 상자를 고르면 어느 쪽이든 한 화면에 서너 줄로 읽힌다. */
#jvtip { display:none; position:fixed; z-index:400; padding:9px 12px; border-radius:9px;
  background:var(--panel2); border:1px solid var(--line); box-shadow:0 8px 24px rgba(0,0,0,.35);
  font-size:var(--fs-sub); font-weight:400; line-height:1.6; color:var(--text);
  text-align:left; white-space:pre-line; word-break:keep-all; overflow-wrap:anywhere;
  opacity:0; transition:opacity .1s; pointer-events:none; }
#jvtip.on { opacity:1; }
#jvtip.sz-s { width:190px; }
#jvtip.sz-m { width:280px; }
#jvtip.sz-l { width:380px; }

.phelp { position:relative; flex:none; width:15px; height:15px; border-radius:50%;
  border:1px solid var(--line); color:var(--dim); background:transparent;
  font-size:var(--fs-badge); font-weight:700; line-height:1; cursor:help;
  display:inline-flex; align-items:center; justify-content:center; transition:color .12s, border-color .12s; }
.phelp:hover { color:var(--ai); border-color:var(--ai); }
/* 말풍선은 #jvtip 공용 엔진이 그린다 — 여기 있던 ::after 판은 폭이 264px로 못 박혀 있었고
   카드 overflow에 잘렸다. `.phelp`의 data-tip을 그대로 쓰므로 마크업은 바뀌지 않는다. */
.tpanel .pv { margin-left:auto; display:flex; align-items:baseline; gap:7px; font-size:24px; font-weight:400; font-variant-numeric:tabular-nums; white-space:nowrap; }
.tpanel .pv b { font-weight:600; }
.tpanel .zone { font-size:var(--fs-lab); font-weight:600; border:1px solid var(--line); border-radius:9px; padding:1px 8px; color:var(--dim); align-self:center; }
.tpanel .zone.hot { color:var(--up); border-color:var(--up); }
.tpanel .zone.cold { color:var(--down); border-color:var(--down); }
/* 패널 부제 = **실측 사실 한 줄**이지 캡션이 아니다 (사용자 지시 2026-08-17 "전혀 안 느껴진다").
   종전 12.5px × --dim은 '약한 회색 × 작은 크기'의 곱이라, 값 자체는 중요한데 눈에 안 걸렸다.
   'RSI 49.2'는 오늘 하루지만 '1년 중 29%가 과매수'는 **한 해 전체의 성질**이다 —
   오히려 큰 숫자보다 오래 남는 정보라 본문색으로 올린다.
   크기는 캐논의 '읽는 글자' 칸(13.5px). 15.5로 올리면 패널 제목(16.5px)과 붙어 위계가 무너진다. */
/* 박스로 감싼다 (사용자 지시 2026-08-17 "분명히 중요한 데이터이기 때문이다").
   'RSI 49.2'는 오늘 하루지만 '1년 중 29%가 과매수'는 **한 해 전체의 성질**이라 오래 남는다.
   그런데도 제목과 차트 사이에 낀 한 줄이라 눈이 그냥 지나쳤다.
   틴트는 브랜드 에메랄드(--accent) 10% — 판정색(빨강·파랑)을 쓰면 '나쁜 값'으로 오독된다.
   **글자는 검정 그대로** 둔다. 배경과 같은 계열로 물들이면 오히려 덜 읽힌다 —
   틴트는 '여기를 보라'는 표지, 검정은 '읽는 글자'로 역할을 나눈다.
   `inline-block`인 이유 — 전폭 띠로 깔면 배지가 아니라 **구획**이 돼서 제목과 차트를 갈라 놓는다
   (사용자 지시 2026-08-17 "해당 글자만 감싸는 박스"). 글자 폭만큼만 차지해야 표지로 읽힌다. */
.tpanel .ps { display:inline-block;          /* **글자만** 감싼다 — 전폭 띠는 패널을 갈라 놓는다 */
  font-size:var(--fs-th); color:var(--accent); font-weight:600;
  margin:5px 0 0; padding:2px 8px; border-radius:5px; line-height:1.5;
  background:color-mix(in srgb, var(--accent) 10%, transparent);
  border:1px solid color-mix(in srgb, var(--accent) 22%, transparent);
  letter-spacing:-.1px; font-variant-numeric:tabular-nums; }
/* 라이트에서는 **액센트보다 한 단 진한 초록**(emerald-900)을 쓴다.
   같은 계열 위에 글자를 얹으면 대비가 깎이는데, 라이트의 --accent(#047857)를 그대로 쓰면
   채움 rgb(230,242,238) 위에서 4.78:1 — AA(4.5) 턱걸이다. 지금 틴트를 조금만 옅게 하거나
   액센트를 조금만 밝게 하는 날 바로 깨진다. #064e3b는 **8.47:1**로 AAA고 초록으로도 또렷하다.
   다크는 --accent(#34d399)가 채움 rgb(26,42,41) 위에서 7.76:1이라 그대로 쓴다.
   (`.pxbadge.nxt`와 같은 관례 — 흰 배경에서 글자로 쓸 땐 한 단 깊은 색으로) */
body[data-theme="light"] .tpanel .ps { color:#064e3b; }
/* RSI·MDD = 좌우 대칭 쌍둥이 (사용자 확정 2026-08-05 "높이와 위치를 같게") — 둘 다 상단 44px
   주가 스트립 + 본 지표. 같은 280px·같은 그리드(pxStrip 공용)라 구조적으로 어긋날 수 없다 */
#rsichart, #ddchart { height:280px; margin-top:8px; }
.pempty { display:flex; align-items:center; justify-content:center; color:var(--dim); font-size:var(--fs-sub); }
/* ③ 핵심 팩트 — 헤어라인 행 (카드 나열 금지) */
.tfacts { border-top:1px solid var(--line); margin-top:6px; }
.tfacts .row { display:flex; gap:12px; align-items:baseline; padding:8px 4px; border-bottom:1px solid var(--line); font-size:12.5px; }
.tfacts .k { color:var(--dim); width:76px; flex-shrink:0; }
.tfacts .v { margin-left:auto; text-align:right; font-variant-numeric:tabular-nums; }
.tfacts .v b { font-weight:700; }
.tfacts .na { color:var(--dim); font-size:var(--fs-sub); }
/* 재무적 최근 공시: 전체폭 블록 — 서술은 대시보드로 올라가고 공시만 남음 (사용자 확정 2026-07-16) */
#finbottom { margin-top:0; }   /* 경계 여백은 .jsect가 담당 */
#left.mode-tech #finbottom { display:none; }                      /* 재무적 하단은 기술적 모드에서 숨김 */
#finbottom #disc { margin:0; min-width:0; }                       /* 공시 패널 (자체 패널 스타일 유지) */
/* Forward-PER 카드의 1A+3E 태그 (주비스 정의 표식) — 우상단 코너 배치로 라벨 줄바꿈 방지 (사용자 확정 2026-07-16) */
#cardfwd { position:relative; }
#cardfwd .fwtag { position:absolute; top:9px; right:11px; margin:0; font-size:9px; font-weight:600; color:var(--accent); border:1px solid var(--line); border-radius:6px; padding:0 4px; cursor:help; letter-spacing:0; }
/* 밸류 카드 부제 (사용자 확정 2026-07-16): 지표 한글명(.mnm) + 백분위(.mpc) — 두 줄 붙여서. 52주는 신고가/신저가 2줄 */
.card .s .mnm { color:var(--dim); }
.card .s .mpc { margin-top:2px; color:var(--dim); }
/* 전 종목 대비 상위 백분위 (사용자 확정 2026-07-17) — 시총 1위처럼 순위 감각, 상위%는 액센트 */
.card .s .mxs { margin-top:2px; color:var(--dim); cursor:help; }
.card .s .mxs b { color:var(--accent); font-weight:700; }
/* 상단 카드 하단 정렬 (사용자 확정 2026-07-17) — 순위/상위% 줄을 카드 바닥에 맞춰 한 줄로 정렬 */
#cards .card { display:flex; flex-direction:column; }
#cards .card .s { display:flex; flex-direction:column; flex:1 1 auto; min-height:0; }
#cards .card .s .mxs { margin-top:auto; }   /* 상위%·시총순위를 카드 맨 아래로 → 카드 간 한 줄 정렬 */

/* 현재가/종가 카드 — KRX·NXT 2블록 나란히 (사용자 레퍼런스 2026-07-21).
   시간외(NXT)가 있을 때만 .pxwide로 2칸 차지 — 없으면 기존 1칸 그대로. */
#cards .card.pxwide { grid-column:span 2; }
/* 좁아지면 종가 카드도 1칸으로 — 7칸이면 3열에서 [2,3,1]로 깨진다. 6칸이 되어야 3+3 / 2+2+2로 고르게 접힘
   (사용자 지시 2026-08-01 "균형 있게 재배치"). 이 규칙은 위 span 2 뒤에 와야 이긴다 — 특이성 동일·순서 승부. */
@container leftcol (max-width:620px) { #cards .card.pxwide { grid-column:span 1; } }
.pxwrap { display:flex; gap:16px; align-items:flex-end; }   /* 하단 정렬 — NXT 블록이 작아도 바닥선 일치 (사용자 지시 2026-07-21) */
.pxblk { flex:1 1 0; min-width:0; }
.pxblk .pxv { font-size:18px; font-weight:700; letter-spacing:-.3px; white-space:nowrap; }
.pxblk .pxd { display:flex; align-items:center; gap:5px; margin-top:2px;
              font-size:var(--fs-sub); font-weight:600; white-space:nowrap; }
/* 날짜·시각은 볼드 해제 (사용자 지시 2026-07-21) — .card .v의 font-weight:700 상속을 끊는다 */
.pxblk .pxt { margin-top:3px; font-size:var(--fs-lab); font-weight:400; color:var(--dim); white-space:nowrap; }
.pxbadge { padding:1px 5px; border-radius:4px; font-size:var(--fs-badge); font-weight:700; letter-spacing:.4px;
           background:var(--panel2); color:var(--dim); border:1px solid var(--line); }
/* 배지는 상승률 옆 (사용자 지시 2026-07-22 — 가격 옆에서 이동). .pxd가 flex라 gap 5px가 간격을 준다 */
.pxblk .pxd .pxbadge { flex:none; }
.pxblk.sm .pxv { font-size:15px; font-weight:600; }
.pxblk.sm .pxd { font-size:var(--fs-lab); }
/* NXT(시간외·대체거래소) 배지 = 하늘색 (사용자 지시 2026-07-21) — 다크/라이트 각각 가독 톤.
   등락 파랑(--down)과 혼동되지 않도록 색 단독이 아닌 배지 형태(테두리+틴트)로만 사용 */
.pxbadge.nxt { color:#38bdf8; border-color:#38bdf8; background:color-mix(in srgb, #38bdf8 12%, var(--panel2)); }
body[data-theme="light"] .pxbadge.nxt { color:#0284c7; border-color:#7dd3fc; background:color-mix(in srgb, #0284c7 10%, var(--panel2)); }
@media (max-width:720px) {                   /* 좁은 화면: 2블록을 위아래로 */
  .pxwrap { flex-direction:column; gap:8px; }
}

/* 시총 다이얼 (헤더 우측, 사용자 확정 2026-07-16) — 앞뒤 종목 슬쩍 보며 ‹ ›·←/→로 하나씩 넘기기.
   현재 종목=가운데 강조 칩, 앞뒤=흐려지는 미리보기(페이드), 넘길 때 방향대로 슬라이드(다이얼 느낌) */
#marcapdial { display:none; align-items:center; gap:5px; margin-left:auto; min-width:0; }
/* authbox가 사이드바 하단으로 이동(스펙 B-6)하면서 다이얼이 헤더 우측 끝을 차지한다 */
header.has-dial #marcapdial { margin-left:auto; }
#marcapdial .mdch { display:inline-flex; align-items:center; justify-content:center; width:26px; height:26px; flex:none;
  border:1px solid var(--line); border-radius:8px; background:var(--panel); color:var(--dim); cursor:pointer; }
#marcapdial .mdch:hover:not([disabled]) { color:var(--accent); border-color:var(--accent); }
#marcapdial .mdch[disabled] { opacity:.3; cursor:default; }
#marcapdial .mdch svg { width:15px; height:15px; fill:none; stroke:currentColor; stroke-width:2; stroke-linecap:round; stroke-linejoin:round; }
#marcapdial .mddisc { display:flex; align-items:baseline; gap:9px; overflow:hidden; }
#marcapdial .mdit { white-space:nowrap; font-size:var(--fs-sub); color:var(--dim); background:none; border:0; padding:0; font-family:inherit; cursor:pointer; }
#marcapdial .mdit.pk:hover { color:var(--accent); }
#marcapdial .mdit.d1 { opacity:.7; }
#marcapdial .mdit.d2 { opacity:.4; font-size:var(--fs-lab); }
#marcapdial .mdit.gh { width:22px; cursor:default; }
#marcapdial .mdit.cur { display:inline-flex; align-items:baseline; gap:5px; padding:3px 11px; cursor:pointer;
  border:1px solid var(--line); border-radius:8px; background:var(--panel2); font-family:inherit; }
#marcapdial .mdit.cur b { font-size:13px; font-weight:700; color:var(--text); }
#marcapdial .mdit.cur i { font-size:var(--fs-lab); font-style:normal; color:var(--accent); font-variant-numeric:tabular-nums; }
#marcapdial .mdit.cur:hover { border-color:var(--accent); }
/* 미리보기 중(스크롤로 훑는 중) 센터 강조 — "클릭하면 이동" 신호 (사용자 확정 2026-07-16) */
#marcapdial.previewing .mdit.cur { border-color:var(--accent); box-shadow:0 0 0 2px rgba(52,211,153,.22); }
.mddisc.dir-next { animation:mdNext .22s ease; }
.mddisc.dir-prev { animation:mdPrev .22s ease; }
@keyframes mdNext { from { transform:translateX(16px); opacity:.5; } to { transform:none; opacity:1; } }
@keyframes mdPrev { from { transform:translateX(-16px); opacity:.5; } to { transform:none; opacity:1; } }
/* 좁아져도 다이얼 자체는 유지(사용자 확정 2026-07-16: 고정) — 미리보기(±2→±1)만 접고 화살표+현재 종목은 남김 */
@media (max-width:1240px) { #marcapdial .d2 { display:none; } }
@media (max-width:1040px) { #marcapdial .d1 { display:none; } }
@media (max-width:560px)  { #marcapdial { display:none !important; } }   /* 진짜 모바일에서만 숨김 */

/* 최근 조회 칩 삭제 × (사용자 확정 2026-07-16) — 칩 hover 시 우상단 코너에 나타남, 클릭=제거 */
#recent .rchip { position:relative; }
#recent .rc-del { position:absolute; top:-6px; right:-6px; display:none; align-items:center; justify-content:center;
  width:15px; height:15px; border-radius:50%; background:var(--panel2); border:1px solid var(--line);
  color:var(--dim); font-size:var(--fs-lab); line-height:1; cursor:pointer; }
#recent .rchip:hover .rc-del { display:flex; }
#recent .rc-del:hover { color:#fff; background:var(--down); border-color:var(--down); }

/* ⑤ 주비스의 AI 분석 서술 — 보라 왼줄 하나로만 표시 (화면 유일의 아이덴티티 색, 휴먼 패스) */
.tdiag { border-left:3px solid var(--ai); padding:2px 0 2px 14px; margin-top:16px; }
.tdiag .sum { font-size:13.5px; font-weight:700; color:var(--ai); cursor:help; }
.tdiag .sum .tag { float:right; font-size:var(--fs-lab); color:var(--dim); border:1px solid var(--line); border-radius:10px; padding:1px 8px; font-weight:400; cursor:help; }
.tdiag .tnarr { font-size:13.5px; line-height:1.8; margin-top:6px; max-width:76em; }
.tdiag summary { cursor:pointer; color:var(--dim); font-size:var(--fs-sub); margin-top:6px; }
.tdiag summary:hover { color:var(--text); }
.tdiag .sg { display:flex; gap:8px; font-size:12.5px; padding:4px 0; flex-wrap:wrap; }
.tdiag .sg .f { color:var(--text); }
.tdiag .sg .it { color:var(--dim); }
.tdiag .tdisc { color:var(--dim); font-size:var(--fs-lab); margin-top:8px; }

/* ---------- [M9] 심리 — 주비스 고스톱 (docs/25 §5-1, 자체 전용 sn- 접두) ----------
   심리 패스 1 (2026-07-15 "3초 바이너리 판독"): 존1 판정 전광판(이중 괘선 마스트헤드 —
   42px 앵커 + 5축 신호등 스트립 + 주비스 자막) / 존2 근거 그리드. 틴트 면 = 패스 1 문법. */
/* 고/스톱 판정색 (2026-07-15 사용자 확정) — 시장 등락색(빨강/파랑)과 구분되는 신호등 의미색:
   고=고급 초록(신호등 GO)·스톱=차분한 파랑. 이 화면 전용, 전역 --up/--down은 건드리지 않는다. */
/* 고/스톱 대표색 = 메인 홈 시장심리 스트립(.sst-go/.sst-stop)과 통일 — 고=빨강(--up) 스톱=파랑(--down)
   (2026-07-16 사용자 확정). body 스코프로 선언해 --up/--down의 테마별(라이트/다크) 값을
   .sst-go와 동일하게 물려받는다(:root 선언 시 다크값에 고정되는 문제 회피). */
body { --sn-go:var(--sn-adr-up); --sn-stop:var(--sn-adr-down); }   /* 2026-08-21 사용자: 쨍한 --up/--down 대신 ADR 소프트 팔레트로 통일 */
/* 상승/하락 막대 세련색 (2026-07-15 사용자 "빨강/파랑 더 세련되게") — 채도 낮춘 깊은 로즈/슬레이트
   + 20일 이평선 밝은 주황(사용자 확정, 빨강/파랑 위 대비·50% 위아래 판독) */
/* ADR 면 = 로즈/스틸블루(등락 방향). 20일 이평선은 흰색, 중앙 50%는 에메랄드(sentiment.js).
   2026-08-01 재조합: 두 색의 '밝기를 맞추고' 남색기를 뺐다 — 명도가 어긋나면(구 #3f66b8은
   로즈보다 어두운 남색) 파랑만 앞으로 튀어나와 대결이 아니라 한쪽의 압도로 보인다.
   실제 옅기는 여기가 아니라 areaStyle.opacity가 만든다(툴팁 글자색은 이 원색 그대로 써야 읽힌다). */
:root, body[data-theme="dark"] { --sn-adr-up:#dd6f77; --sn-adr-down:#6d97da; }
body[data-theme="light"] { --sn-adr-up:#cf5761; --sn-adr-down:#5580c9; }
/* 오늘의 대결 전광판 (ADR 카드, 파도 바로 위) — **가운데 모인 하나의 판**.
   사용자 재지시 2026-08-16: 좌우 끝으로 벌리면 전광판이 아니라 그냥 양쪽 숫자다.
   숫자를 VS 곁으로 모으고 판(틀) 안에 넣는다. 양쪽 min-width를 같게 잡아
   자릿수가 달라져도(569 vs 1,969) VS가 정중앙에 머문다 + tabular-nums로 폭 고정. */
/* 상승/하락 전광판 — **질문 박스 안에 산다** (사용자 지시 2026-08-19 "두 박스를 하나의 박스로").
   그전엔 질문 상자와 전광판 상자가 따로 서서, 같은 이야기를 두 덩어리로 끊어 읽게 했다.
   합쳤으니 전광판은 제 테두리·배경을 버린다 — 상자 안의 상자는 상자가 아니다. */
.snboardwrap { display:flex; justify-content:center; padding:12px 0 2px; margin-top:11px;
  border-top:1px dashed var(--line); }
.snboard { display:inline-flex; align-items:center; gap:22px; }
.snboard .snb-side { display:flex; flex-direction:column; align-items:center; gap:2px; min-width:104px; }
.snboard .snb-side.up { color:var(--sn-adr-up); }
.snboard .snb-side.down { color:var(--sn-adr-down); }
/* 숫자 위 라벨 = 이 전광판이 무엇을 세는지 말하는 자리 — 12px 표지판으로는 작았다
   (사용자 지시 2026-08-19 "상승/하락 폰트를 키워줘") */
.snboard .snb-k { font-size:15px; font-weight:700; letter-spacing:.02em; opacity:1; }
.snboard .snb-v { font-size:30px; font-weight:800; line-height:1.06;
  font-variant-numeric:tabular-nums; letter-spacing:-.01em; }
.snboard .snb-p { font-size:var(--fs-sub); font-weight:600; opacity:.78; font-variant-numeric:tabular-nums; }
.snboard .snb-vs { font-size:var(--fs-sub); font-weight:700; color:var(--dim); letter-spacing:.1em; }
.snwrap { max-width:1080px; }
/* 카드 그리드: 행당 2개 (사용자 지시) — 구분은 헤어라인, 테두리 박스 금지 */
.sngrid { display:grid; grid-template-columns:1fr 1fr; column-gap:32px; row-gap:34px; }
/* 상승/하락은 좌측 반쪽에 그대로 둔다 — 우측 빈칸은 비워 둔 채로(사용자 지시 2026-08-16,
   그 자리 용도는 나중에 정한다). 전폭으로 늘렸다가 되돌린 자리다. */
/* 변동성 = 옆칸 공포탐욕의 시각화 블록과 **위아래 끝을 정확히 맞춘다** (사용자 지시 2026-08-19).
   270 = 게이지 201.8(폭 캡 245px × viewBox 229/278) + 타임라인 여백 5 + 타임라인 63.
   둘 다 .snqbox 아래 margin-top:10px에서 시작하므로 위쪽은 저절로 맞고, 이 높이가 아래를 맞춘다.
   ⚠ .sngauge의 max-width나 .snkfng-tl의 height를 바꾸면 이 값도 함께 고쳐야 한다.

   355 → 270 (사용자 지시 2026-08-23): 추세·빚투·변동성은 **성격이 같은 꺾은선**인데 210 vs 355로
   세로가 145px이나 벌어져 한 그리드 안에서 남남처럼 보였다. 공포탐욕 칸에 키를 맞추느라
   변동성만 홀로 커진 것이 원인이다. 이제 넷을 **270 한 값**으로 모은다 —
   위 두 장은 늘리고(210→270) 아래 두 장은 줄여서(355→270) 가운데서 만난다. */
#snchart-vol { height:270px; }
/* 종합 패널 (2026-07-16 사용자 확정): (1,1)판정+(1,2)해설을 하나의 카드로 묶어 이어 읽게.
   좌=판정 전광판, 우=AI 분석. 사이 세로 헤어라인 하나로 "한 유닛" — 아래 근거는 오픈 카드로 대비. */
/* 전광판 강조 (2026-07-16 사용자 지시): 모던 럭셔리 B 카드 레이어 — 소프트 섀도로 아래 오픈 카드보다
   확실히 떠 보이게. 상단에 무드색 액센트 바로 오늘의 장세를 한 번 더 각인. */
.snsummary { position:relative; display:grid; grid-template-columns:1fr 1fr; background:var(--panel);
  border:.5px solid var(--line); border-radius:18px; overflow:hidden; margin-bottom:34px; box-shadow:var(--shadow); }
.snsummary::before { content:""; position:absolute; inset:0 0 auto 0; height:3px; z-index:1;
  background:var(--accent); }   /* 상단 띠 = 브랜드 대표색 에메랄드 (2026-07-16 사용자 지시) */
.snsum-verdict, .snsum-analysis { padding:24px 24px 26px; min-width:0; }
.snsum-analysis { border-left:1px solid var(--line); }
/* 좌 판정: 대표 장세 키워드가 주인공 — 중앙 정렬, 세로 균형 */
.snsum-verdict { display:flex; flex-direction:column; align-items:center; justify-content:center; text-align:center; }
.snsum-verdict .snsum-label { align-self:center; }
.snsum-regime { font-size:44px; font-weight:800; letter-spacing:-1.6px; line-height:1.05; margin-top:9px; }
.snsum-label { font-size:13.5px; letter-spacing:.06em; color:var(--dim); font-weight:700;
  display:flex; align-items:center; gap:5px; }
.snsum-label.ai { color:var(--ai); }
.snsum-label svg { width:13px; height:13px; fill:none; stroke:currentColor; stroke-width:1.6; stroke-linejoin:round; }
/* 좌: 판정 전광판 — 5축 고/스톱을 원형 토큰(신호등 램프)으로 (2026-07-16 사용자 지시: 각 칩을 동그라미) */
.snsum-verdict .snstrip { display:flex; width:100%; margin-top:20px; gap:6px; }
.snchip { border:0; background:none; cursor:pointer; padding:0;
  flex:1; min-width:0; display:flex; flex-direction:column; align-items:center; justify-content:flex-end;
  gap:9px; font:inherit; color:var(--text); text-align:center; }
.snchip .ax { font-size:13.5px; font-weight:600; color:var(--dim); letter-spacing:0; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; max-width:100%; }
/* 원형 토큰 = 솔리드 필(판정색 배경 + 흰 글씨)로 또렷·강하게 (2026-07-23 사용자 지시).
   근거 배지와 같은 강한 문법 — 고=빨강 배경·스톱=파랑 배경, 글자는 진한 흰색. */
.snchip .word { display:flex; align-items:center; justify-content:center;
  width:58px; height:58px; border-radius:50%; margin:0 auto; color:#fff;
  font-size:23px; font-weight:800; line-height:1; letter-spacing:-1px; white-space:nowrap;
  transition:box-shadow .15s ease, transform .15s ease; }
.snchip.go .word { background:var(--sn-go); box-shadow:0 2px 7px color-mix(in srgb, var(--sn-go) 34%, transparent); }
.snchip.stop .word { background:var(--sn-stop); box-shadow:0 2px 7px color-mix(in srgb, var(--sn-stop) 34%, transparent); }
.snchip.na .word { background:none; color:var(--dim); border:1.6px dashed var(--dim); box-shadow:none; }
.snchip:hover .word { transform:translateY(-1px); }
.snchip.go:hover .word { box-shadow:0 4px 12px color-mix(in srgb, var(--sn-go) 46%, transparent); }
.snchip.stop:hover .word { box-shadow:0 4px 12px color-mix(in srgb, var(--sn-stop) 46%, transparent); }
/* "3고 2스톱" 집계 — 대표 요약답게 크게 (2026-07-16 사용자 지시) */
.snsum-tally { margin-top:18px; font-size:22px; font-weight:600; color:var(--dim); font-variant-numeric:tabular-nums; letter-spacing:.01em; }
.snsum-tally b.go { color:var(--sn-go); font-weight:800; } .snsum-tally b.stop { color:var(--sn-stop); font-weight:800; }
.snsum-tally .sep { margin:0 8px; }
/* 우: AI 심리 종합 분석 — 온도계 + 센티멘탈 코멘터리 (무드 워드 줄은 2026-07-16 제거, 온도바가 대체) */
.snsum-tally b.mood-bull, .snsum-analysis .mood-bull { color:var(--up); }
.snsum-tally b.mood-bear, .snsum-analysis .mood-bear { color:var(--down); }
.snsum-tally b.mood-mid, .snsum-analysis .mood-mid { color:var(--accent); }
/* 근거 섹션 라벨 = 대제목 캐논(.jsect)을 그대로 쓴다 (사용자 지시 2026-08-19 "대제목으로 키우기") */
.snsect { margin:6px 2px 2px; }
.snsect .lg-go { color:var(--sn-go); } .snsect .lg-stop { color:var(--sn-stop); }
/* 좁은 화면: 종합 패널도 1열(판정 위, 해설 아래 — 헤어라인 상단으로) */
@media (max-width: 1150px) {
  .snsummary { grid-template-columns:1fr; }
  .snsum-analysis { border-left:0; border-top:1px solid var(--line); }
}
.sncard { border-top:1px solid var(--line); padding:12px 0 12px; cursor:help; min-width:0; }
.sncard .snhead { display:flex; align-items:baseline; gap:9px; }
.sncard .snax { font-size:16.5px; font-weight:700; letter-spacing:-.2px; }  /* 키워드 대제목 — 부각 */
.sncard .snname { font-size:16.5px; font-weight:700; white-space:nowrap; }   /* 분석 카드 제목 */
.sncard .snhead > svg { width:16px; height:16px; fill:none; stroke:var(--ai); stroke-width:1.6;
  stroke-linejoin:round; flex-shrink:0; align-self:center; }
.sncard .snmeta { margin-left:auto; color:var(--dim); font-size:var(--fs-sub); text-align:right; }
.sncard .snmeta .tgo { color:var(--sn-go); font-weight:700; } .sncard .snmeta .tstop { color:var(--sn-stop); font-weight:700; }
/* 주비스 AI 고스톱 — 육각형 레이더 카드 */
/* 주비스 AI 고스톱 — 시장 심리 온도계 (레이더 대체, 2026-07-15) */
.sncard.sntemp { display:flex; flex-direction:column; }
.sntemp .mood-bull { color:var(--up); } .sntemp .mood-bear { color:var(--down); } .sntemp .mood-mid { color:var(--accent); }
.sntemp .sntemp-bar { margin-top:16px; }
.sntemp .sntemp-na { color:var(--dim); font-size:var(--fs-sub); padding:14px 0; }
.sntemp .sntemp-phrase { display:flex; gap:7px; align-items:flex-start; margin-top:16px;
  padding:10px 12px; border:1px solid var(--line); border-left:3px solid var(--ai); border-radius:8px;
  font-size:12.5px; line-height:1.6; color:var(--text); }
.sntemp .sntemp-phrase svg { width:14px; height:14px; fill:none; stroke:var(--ai); stroke-width:1.6;
  stroke-linejoin:round; flex-shrink:0; margin-top:2px; }
/* 우측 종합 코멘터리 — 총평(lead)·드라이버·마무리(tail) 위계 (2026-07-16) */
.sntemp .snsum-comment { margin-top:17px; display:flex; flex-direction:column; gap:10px; }
.sntemp .snsum-comment p { margin:0; font-size:14.5px; line-height:1.75; color:var(--text);
  letter-spacing:-.1px; }
.sntemp .snsum-comment p.lead { font-size:16.5px; font-weight:700; letter-spacing:-.3px; }
.sntemp .snsum-comment p.tail { font-size:12.5px; color:var(--dim); padding-top:9px;
  border-top:1px solid var(--line); }
.sncard .snmeta .unc, .sncard .sndate .unc { border:1px solid var(--line); border-radius:8px; padding:0 6px; }
.sncard .sndate { margin-left:auto; color:var(--dim); font-size:var(--fs-lab); text-align:right; }
/* 질문+지금 상태 = 한 어두운 박스로 구분 (2026-07-16 사용자 지시: 조금 어두운 색상 박스) */
.sncard .snqbox { margin-top:10px; padding:11px 13px; background:var(--panel2);
  border:1px solid var(--line); border-radius:10px; }
.sncard .snq { font-size:14px; font-weight:600; margin-top:0; }
.sncard .snq[title] { cursor:help; }                 /* 판정 규칙은 툴팁으로 내렸다 */
.sncard .snq .how { color:var(--dim); font-weight:400; }
.sncard .snval { font-size:14.5px; margin-top:7px; font-variant-numeric:tabular-nums; }
.sncard .snval b { font-weight:700; }
.sncard .snval .tgo { color:var(--sn-go); } .sncard .snval .tstop { color:var(--sn-stop); }
.sncard .snval .na { color:var(--dim); font-size:var(--fs-sub); }
.sncard .snchart { height:270px; margin-top:10px; }   /* 넷을 한 키로 (2026-08-23) — 위 주석 참조 */
/* ③ K-공포와 탐욕 — 세련된 반원 게이지(위) + 1년 타임라인(아래) 스택 (2026-07-16 참조 스타일) */
.snkfng { display:flex; flex-direction:column; margin-top:10px; }
/* 키 270은 그대로 두고 **속도계만 키운다** (사용자 지시 2026-08-23).
   두 갈래로 키웠다: ① SVG viewBox에서 죽은 여백을 잘라 그림이 상자를 꽉 채우게(+22%)
   ② 폭 캡을 225→245로(+9%). 그만큼 타임라인을 77→63으로 줄여 합이 270을 넘지 않게 한다.
   이 둘을 만지면 #snchart-vol과 sentiment.js의 viewBox도 함께 고친다. */
.snkfng .sngauge { width:100%; max-width:245px; margin:0 auto; }
.snkfng .snkfng-tl { height:63px; margin-top:5px; }
.kfgauge { width:100%; height:auto; display:block; }
/* 구간 라벨 = 두툼한 밴드 '안'에 같은 굴곡(textPath) · 흰 글씨로 또렷하게 (2026-07-19 사용자 지시) */
.kfgauge .gg-seglbl { fill:#fff; font-size:13px; font-weight:700; letter-spacing:-.3px; }
.kfgauge .gg-tick { fill:var(--dim); font-size:var(--fs-badge); font-weight:600; font-variant-numeric:tabular-nums; }
/* 속도계 눈금 — 소/대 두 단계 (밴드 안쪽) */
.kfgauge .gg-tk-min { stroke:var(--dim); stroke-width:1.2; opacity:.45; }
.kfgauge .gg-tk-maj { stroke:var(--dim); stroke-width:2.2; opacity:.8; stroke-linecap:butt; }
/* 구간 경계 구분선 — 연속 그라데이션 위에 밴드를 가로지르는 얇은 흰 선 */
.kfgauge .gg-sep { stroke:#fff; stroke-width:2; opacity:.8; }
.kfgauge .gg-val { fill:var(--text); font-size:30px; font-weight:800; letter-spacing:-.8px; font-variant-numeric:tabular-nums; }
/* 현재 상태 = 크고 선명하게 (공포권은 붉게) */
.kfgauge .gg-zone { font-size:20px; font-weight:800; letter-spacing:.02em; }
/* 주비스의 메모 — 고스톱 우측 1×2, AI 문법(tdiag·briefing 톤): 보라 왼줄 + 스파크, 규칙 기반 */
.sncard.snmemo { border-left:3px solid var(--ai); padding-left:14px; cursor:help; }
.snmemo .snhead svg { width:15px; height:15px; fill:none; stroke:var(--ai); stroke-width:1.6;
  stroke-linejoin:round; flex-shrink:0; align-self:center; }
.snmemo .snname { color:var(--ai); }
.snmemo-obs { margin-top:8px; }
.snmemo-obs .obs { display:flex; gap:8px; align-items:baseline; padding:5px 0;
  border-bottom:1px solid var(--line); font-size:12.5px; line-height:1.5; }
.snmemo-obs .obs:first-child { border-top:1px solid var(--line); }
.snmemo-obs .k { flex-shrink:0; width:58px; font-size:var(--fs-sub); font-weight:600; }
.snmemo-obs .k.go { color:var(--sn-go); } .snmemo-obs .k.stop { color:var(--sn-stop); }
.snmemo-obs .k.na { color:var(--dim); }
.sncard .snchart.snempty { display:flex; align-items:center; justify-content:center;
  color:var(--dim); font-size:var(--fs-sub); }
/* 판정 배지 — 스트립과 같은 틴트 면 문법 (테두리 칩 → 의미색 틴트, 패스 1) */
/* 고/스톱 배지 강조 (2026-07-16 사용자 지시): 은은한 틴트 → 솔리드 필 + 흰 글씨로 또렷·강하게 */
.snbadge { font-size:var(--fs-sub); font-weight:800; border-radius:999px; padding:2.5px 13px; flex-shrink:0;
  letter-spacing:.02em; box-shadow:0 1px 3px rgba(0,0,0,.14); }
.snbadge.go { color:#fff; background:var(--sn-go); }
.snbadge.stop { color:#fff; background:var(--sn-stop); }
.snbadge.na { color:var(--dim); background:var(--panel2); font-weight:600; box-shadow:none; }
.snbadge.ai { color:var(--ai); background:color-mix(in srgb, var(--ai) 12%, transparent); box-shadow:none; }
/* 밸류에이션(KOSPI PER) 카드 배지 — 고/스톱 판정과 구분되는 중립 톤(테두리 칩) */
.snbadge.neu { color:var(--dim); background:transparent; border:1px solid var(--line); font-weight:600; box-shadow:none; }
/* KOSPI 밸류에이션 = 고/스톱 판정 아닌 참고 지표 → 다른 배경(패널 박스)으로 구분 (2026-07-19 사용자 지시) */
.sncard.snrefcard { background:var(--panel2); border:1px solid var(--line); border-radius:12px; padding:13px 16px; }
.sncard.snrefcard .snqbox { background:transparent; border:0; padding:0; margin-top:8px; }
.sncard.snrefcard .snchart { margin-top:8px; }
/* PER·PBR 2단 (2026-07-23 사용자 지시) — 참고 카드 길이 늘리고, 좌측 상승/하락 카드도 맞춤 */
.snrefcard #snchart-kospiper, .snrefcard #snchart-kospipbr { height:150px; margin-top:6px; }
#snchart-adr { height:322px; }
.snref { flex-shrink:0; font-size:var(--fs-badge); font-weight:700; letter-spacing:.06em; color:var(--dim);
  border:1px solid var(--line); border-radius:6px; padding:1px 7px; }
.sndisc { color:var(--dim); font-size:var(--fs-lab); margin-top:12px; border-top:1px solid var(--line); padding-top:8px; }
/* 신호등 칩 클릭 시 대상 카드 1회 하이라이트 — 150ms 리듬의 페이드 */
.sncard.snhit { animation:snhit 1.1s ease-out; }
@keyframes snhit { 0% { background:color-mix(in srgb, var(--accent) 12%, transparent); }
  100% { background:transparent; } }
@media (prefers-reduced-motion: reduce) { .sncard.snhit { animation:none; } }
/* 좁은 화면: 그리드 1열 (사이드바 축소 900px보다 먼저 접힘) */
@media (max-width: 1150px) { .sngrid { grid-template-columns:1fr; } }

/* ---------- [M7] AI vs AI — 외부 AI 4종 주간 대회 (docs/25 §7, docs/27, 자체 전용 av- 접두) ---------- */
.avwrap { max-width:980px; }
.avwrap h3 { margin:22px 0 8px; }
.avwrap .avh3sub { color:var(--dim); font-size:var(--fs-sub); font-weight:400; margin-left:8px; }
.avup { color:var(--up); } .avdown { color:var(--down); }
.avdot { color:var(--dim); margin:0 8px; }
/* 정보 스트립 — 위아래 헤어라인, 조용한 한 줄 */
.avstrip { color:var(--dim); font-size:12.5px; padding:8px 2px; border-bottom:1px solid var(--line); }
.avstrip b { color:var(--text); font-weight:600; }
/* 모델 업데이트 공지 — 박스 겹침 금지: 헤어라인 행 1줄 */
.avnotice { display:flex; align-items:center; gap:8px; flex-wrap:wrap; padding:8px 2px;
  border-bottom:1px solid var(--line); font-size:12.5px; color:var(--dim); }
.avnotice svg { color:var(--accent); flex-shrink:0; }
.avnotice .avntitle { color:var(--accent); font-weight:600; }
.avnotice .avnrow { display:inline-flex; align-items:baseline; gap:5px; }
.avnotice .avnrow b { color:var(--text); font-weight:600; }
.avnotice .avnto { color:var(--accent) !important; }
.avnotice .avndate { font-size:var(--fs-lab); color:var(--dim); }
#avchart { height:380px; }
/* 이번 주 픽 — 4열 테이블, 헤더 = AI 로고+이름+버전+원문 링크 */
.avpickhead { margin:2px 0 8px; }
.avbadge { display:inline-block; font-size:var(--fs-sub); color:var(--dim); border:1px solid var(--line);
  border-radius:10px; padding:2px 10px; }
.avbadge-on { color:var(--accent); border-color:var(--accent); }
.avpicks { width:100%; border-collapse:collapse; table-layout:fixed; }
.avpicks th { padding:8px 6px; border-bottom:1px solid var(--line); font-weight:500; text-align:center; }
.avpicks th .avainame { display:block; font-size:13px; margin-top:4px; }
.avpicks th .avaiver { display:block; font-size:var(--fs-lab); color:var(--dim); font-weight:400; }
/* 로고 배경: ChatGPT 등 검정 로고가 다크 테마에서 안 보임 → 흰 원 위에 표시 */
.avlogo { width:22px; height:22px; border-radius:50%; vertical-align:middle; background:#fff; }
.avsrc { display:inline-flex; align-items:center; gap:3px; font-size:var(--fs-lab); color:var(--dim);
  text-decoration:none; margin-top:3px; }
.avsrc:hover { color:var(--accent); }
.avpicks td.avstock { padding:7px 6px; border-bottom:1px solid var(--line); text-align:center;
  font-size:13px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
/* 중복 픽 = 밝은 주황 셀 음영 (사용자 지시 2026-07-16): 여러 AI가 같은 종목 = 주목 신호.
   폰트는 기본색 그대로, 셀 배경만 강조. 다크는 반투명 주황(밝은 텍스트 가독 유지), 라이트는 밝은 주황 */
.avpicks td.avstock.avdup-some, .avpicks td.avstock.avdup-all { background:rgba(245,158,11,.20); }
body[data-theme="light"] .avpicks td.avstock.avdup-some,
body[data-theme="light"] .avpicks td.avstock.avdup-all { background:#ffe0b2; }
.avdup { display:inline-block; min-width:15px; font-size:var(--fs-lab); line-height:15px; text-align:center;
  color:var(--dim); font-weight:600; vertical-align:1px; }
/* 리더보드 — 메달 이모지 금지: 타이포 위계 (1위만 accent) */
.avlb { width:100%; border-collapse:collapse; }
.avlb th { padding:6px; border-bottom:1px solid var(--line); color:var(--dim); font-size:var(--fs-th);
  font-weight:500; text-align:left; }
.avlb td { padding:8px 6px; border-bottom:1px solid var(--line); font-size:13px; }
.avlb .avrank { width:44px; font-variant-numeric:tabular-nums; color:var(--dim); }
.avlb .avrank1 { color:var(--accent); font-weight:700; font-size:15px; }
.avlb .avrank3 { color:var(--text); font-weight:600; }
.avlb .avlbmodel { display:flex; align-items:center; gap:8px; }
.avlb th:nth-child(n+5), .avlb td.avnum { text-align:right; font-variant-numeric:tabular-nums; }
.avlb .avaiver { font-size:var(--fs-lab); color:var(--dim); }
.avlb .avbench td { color:var(--dim); }
.avdisc { color:var(--dim); font-size:var(--fs-lab); margin-top:16px; border-top:1px solid var(--line); padding-top:8px; }

/* [공통] AI 대화 드로어 — 전 화면 공용, 좌측(사이드바 옆)에서 넣고 빼기
   (우측→좌측 도킹 전환: 사용자 지시 2026-07-21 M0-2 · 배치는 chatdock.js)
   기존 #chatpanel 내부 스타일(chathead·chatlog·quickq·chatform)은 그대로 재사용 — 배치만 드로어로 */
/* 대화 드로어 (docs/33): 메뉴|챗|본문 순서 — 사이드바 오른쪽에서 나오는 좁은 슬라이드 패널.
   세로 2단 — 위 1/3 포트 목록, 아래 2/3 대화 (사용자 확정 2026-07-15). */
#chatpanel { position:fixed; top:0; left:var(--nav-w); bottom:0; width:var(--chat-w, 440px); max-width:94vw; z-index:80;
  border-radius:0; border:0; border-right:1px solid var(--line); height:auto;
  background:var(--panel);   /* 그림자 제거 (사용자 지시 2026-07-23 "그라데이션 하지 말자 — 메인 잘 보이게") — 경계는 1px 라인만 */
  display:flex; flex-direction:column; overflow:hidden;
  transform:translateX(calc(-102% - var(--nav-w))); transition:transform .2s ease, left .18s ease; }
body.chat-open #chatpanel { transform:none; }
/* 부팅 동결 (index.html head의 bootfreeze — 사용자 지시 2026-08-24 "원래 위치에서 딱").
   저장 상태는 <body> 직후 스크립트가 첫 페인트 전에 걸어 두므로 **움직일 이유가 없지만**,
   부팅 중 늦게 붙는 클래스(landing·pfview 등)가 남아 있는 한 여기서 한 번 더 막는다.
   대상은 가로로 움직이는 것들뿐이고, 해제는 main.js가 화면을 정하고 한 프레임 뒤에 한다 —
   사람이 탭을 눌러 여닫는 슬라이드는 그 뒤로 그대로 산다(그건 부팅이 아니다). */
html.bootfreeze #chatpanel, html.bootfreeze #app, html.bootfreeze #sidebar,
html.bootfreeze #chattab, html.bootfreeze #brandload { transition:none !important; }
/* 가로 드래그 리사이즈 — 우측 엣지 핸들 (기준 440px, 당겨서 넓게. chatdock.js) */
#chatresize { position:absolute; right:-3px; top:0; bottom:0; width:8px; z-index:82; cursor:ew-resize; }
#chatresize::after { content:""; position:absolute; left:3px; top:50%; transform:translateY(-50%);
  width:2px; height:38px; border-radius:2px; background:var(--line); transition:background-color .15s ease; }
#chatresize:hover::after, body.chat-resizing #chatresize::after { background:var(--ai); }
body.chat-resizing { cursor:ew-resize; user-select:none; }
body.chat-resizing #chatpanel, body.chat-resizing #app { transition:none; }   /* 드래그 중엔 즉시 반응 */
@media (max-width:900px) { #chatresize { display:none; } }   /* 좁은 화면(덮기 모드)은 리사이즈 없음 */
/* ===== 상단 네비 (2026-07-29) — 클로드 사이드바 문법: 위 포트 · 아래 대화 =====
   구 #portzone(만들기 마법사 포함)은 제거. 여기는 '어디로 갈까'만 맡는다 —
   유형·종목·지침·자료는 입력창 위 칩 팝오버가 맡는다(한 가지 일은 한 곳에서). */
/* 슬라이드 오버레이 (2026-08-01 클로드식) — 드로어는 위→아래 전부 챗, 목록은 옆에서
   미끄러져 **덮는다**(본문을 밀지 않는다 — 사용자: "마운팅까지 되면 3겹이라 복잡").
   #navbtn(챗 헤더의 패널 아이콘)·scrim·Esc·항목 선택으로 여닫는다. */
#chatnav { position:absolute; top:0; left:0; bottom:0; width:min(320px, 88%); z-index:92;
  background:var(--panel); border-right:1px solid var(--line);
  box-shadow:10px 0 28px rgba(0,0,0,.16);
  overflow-y:auto; padding:8px 8px 12px;
  transform:translateX(-103%); visibility:hidden;
  /* visibility 지연: 슬라이드가 끝난 뒤 내려간다. 닫힌 패널이 transform만으로 숨으면
     Tab이 보이지 않는 버튼 20여 개를 순회하고 스크린리더가 랜드마크를 읽는다 (리뷰 I4) */
  transition:transform .18s ease, visibility 0s linear .18s; }
body.jvnav-open #chatnav { transform:none; visibility:visible;
  transition:transform .18s ease; }
#navscrim { position:absolute; inset:0; z-index:88; background:transparent; }
#navscrim[hidden] { display:none; }
/* 포트 패널 핸들 (2026-08-02) — 구 모듈 펴기 핸들의 **뚜렷한 세로 박스 문법을 이어받는다**
   (사용자: "1번 여는 그 스타일·크기를 2번에 쓰자"). 드로어 왼쪽 경계에 붙은 손잡이,
   누르면 포트·세션 목록이 오른쪽으로 미끄러져 나온다. */
/* 패널 여는 버튼 — **모양·크기는 원래 그대로**(세로로 긴 둥근 손잡이, 사용자 2026-08-02).
   2026-08-24에 정사각으로 키웠다가 "버튼은 원래 이 모양"이라고 반려돼 되돌렸다.
   바뀐 것은 **안의 아이콘뿐**(» → 사이드바 글리프)과 색(기본부터 시그니처 초록빛,
   호버에서 한 단계 진해짐). */
#navbtn { position:absolute; left:9px; top:8px; width:24px; height:48px; z-index:6;
  display:inline-flex; align-items:center; justify-content:center; padding:0;
  background:color-mix(in srgb, var(--accent) 11%, var(--panel));
  border:1px solid color-mix(in srgb, var(--accent) 42%, var(--line));
  border-radius:12px;
  box-shadow:var(--shadow); color:var(--accent); cursor:pointer;
  transition:color .15s ease, background-color .15s ease, border-color .15s ease,
             box-shadow .15s ease; }
#navbtn:hover { color:var(--accent); border-color:var(--accent);
  background:color-mix(in srgb, var(--accent) 24%, var(--panel));
  box-shadow:0 2px 6px rgba(0,0,0,.14), 0 10px 24px rgba(0,0,0,.10); }
/* 좌측 칼럼 면 — 이 한 조각이 '사이드바'를 읽히게 한다(선만 있으면 그냥 네모+막대) */
#navbtn svg .nbfill { fill:currentColor; stroke:none; opacity:.34; }
#navbtn svg { width:15px; height:15px; fill:none; stroke:currentColor; stroke-width:2;
  stroke-linecap:round; stroke-linejoin:round; }
#chatnav .cntop { display:flex; align-items:center; gap:8px; padding:2px 2px 8px; }
#chatnav .cntop b { font-size:var(--fs-th); color:var(--ai); font-weight:700; }
#chatnav .cnclose { background:transparent; border:0; color:var(--dim2); cursor:pointer;
  padding:3px; display:inline-flex; border-radius:7px; }
#chatnav .cnclose:hover { color:var(--accent); background:var(--panel2); }
#chatnav .cnclose svg { width:16px; height:16px; fill:none; stroke:currentColor; stroke-width:1.8;
  stroke-linecap:round; stroke-linejoin:round; }
/* 세션 행 액션 = ⋯ 하나 (머신러너님 지시 2026-08-31) — 종전의 핀·X 두 아이콘을 대신한다.
   데스크톱은 호버로 나타나고(밀도 보존), **폰에서는 늘 보인다** — 호버가 없는 기기에서
   숨은 버튼은 없는 버튼이다. 폰은 꾹 누르기로도 같은 메뉴가 열리지만, 보이는 손잡이가
   하나는 있어야 '여기서 무언가 할 수 있다'가 읽힌다. */
#chatnav .cndots { background:transparent; border:0; color:var(--dim2); cursor:pointer;
  padding:5px 6px; opacity:0; flex-shrink:0; display:inline-flex; border-radius:7px; }
#chatnav .cnrow:hover .cndots, #chatnav .cndots:focus-visible { opacity:1; }
#chatnav .cndots:hover { color:var(--accent); background:var(--panel2); }
#chatnav .cndots svg { width:15px; height:15px; fill:currentColor; stroke:none; }
/* 핀은 아이콘 버튼을 잃었다 — 상태를 읽는 길까지 잃지 않게 **표시**로 남긴다 */
/* 핀은 아이콘 버튼을 잃은 대신 **표시**로 남았다. 11px에 30% 반투명 채움까지 겹쳐 있어
   "뭔가 흐릿하게 붙어 있다"로만 보였다 (머신러너님 지시 2026-08-31 "너무 작아 · 애플 스타일로").
   키우고 **꽉 채운다** — 작은 자리에서 반투명은 흐림이지 절제가 아니다. 형태 하나로 읽히게. */
#chatnav .cnpinned { flex-shrink:0; display:inline-flex; color:var(--accent); padding:0 2px; }
#chatnav .cnpinned svg { width:14px; height:14px; fill:currentColor;
  stroke:currentColor; stroke-width:1.6; stroke-linecap:round; stroke-linejoin:round; }

/* 세션 메뉴 팝오버 — body 직속 fixed다. #chatnav(대화창 안 absolute) 안에 두면 목록의
   `overflow:auto`에 잘리고, 폰에서는 대화창(z:86)의 쌓임 맥락에 갇힌다. */
.cnmenu { position:fixed; z-index:200; background:var(--panel); border:1px solid var(--line);
  border-radius:12px; box-shadow:0 6px 18px rgba(0,0,0,.18), 0 24px 48px rgba(0,0,0,.16);
  padding:5px; display:flex; flex-direction:column; gap:1px;
  max-height:min(62vh, 420px); overflow-y:auto; }
.cnmenu button { display:flex; align-items:center; gap:9px; width:100%; text-align:left;
  background:transparent; border:0; cursor:pointer; color:var(--text);
  font:inherit; font-size:var(--fs-sub); padding:9px 10px; border-radius:8px; }
.cnmenu button:hover, .cnmenu button:focus-visible { background:var(--panel2); }
.cnmenu button.danger { color:var(--alert); }
.cnmenu button.danger:hover { background:color-mix(in srgb, var(--alert) 12%, transparent); }
.cnmenu button > i { flex:none; display:inline-flex; color:var(--dim2); }
.cnmenu button.danger > i { color:inherit; }
.cnmenu button > i svg { width:15px; height:15px; fill:none; stroke:currentColor; stroke-width:1.8;
  stroke-linecap:round; stroke-linejoin:round; }
.cnmenu .cnmname { min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.cnmenu .cnmhead { display:flex; align-items:center; gap:6px; padding:4px 6px 6px; }
.cnmenu .cnmhead b { font-size:var(--fs-lab); color:var(--dim2); font-weight:600; }
.cnmenu .cnmback { width:auto; padding:4px; color:var(--dim2); }
.cnmenu .cnmback svg { width:15px; height:15px; fill:none; stroke:currentColor; stroke-width:2;
  stroke-linecap:round; stroke-linejoin:round; }
.cnmenu .cnmout { border-top:1px solid var(--line); border-radius:0 0 8px 8px; margin-top:3px;
  padding-top:10px; color:var(--dim2); }
.cnmenu .cnmempty { padding:8px 10px 10px; font-size:var(--fs-lab); color:var(--dim2); line-height:1.6; }

#chatnav .cnpin { background:transparent; border:0; color:var(--dim2); cursor:pointer;
  padding:5px 4px; opacity:0; flex-shrink:0; display:inline-flex; }
#chatnav .cnrow:hover .cnpin, #chatnav .cnpin:focus-visible, #chatnav .cnpin.on { opacity:1; }
#chatnav .cnpin.on { color:var(--accent); }
#chatnav .cnpin:hover { color:var(--accent); }
#chatnav .cnpin svg { width:12px; height:12px; fill:none; stroke:currentColor; stroke-width:1.9;
  stroke-linecap:round; stroke-linejoin:round; }
#chatnav .cnpin.on svg { fill:color-mix(in srgb, var(--accent) 30%, transparent); }
/* 상단 액션 = **박스 없는 메뉴 행** (사용자 2026-08-02, 클로드 스타일 첨부 — "상단을 박스로
   하지 말자"): 아이콘+텍스트 좌정렬, 호버에만 배경. 새로 채팅·주식포트 생성이 같은 문법. */
#chatnav .cnnew, #chatnav .cnmk { display:flex; align-items:center; gap:9px; width:100%;
  padding:7px 9px; background:transparent; border:0; border-radius:8px; color:var(--text);
  font-size:var(--fs-body); font-weight:600; cursor:pointer; text-align:left;
  transition:background-color .15s ease, color .15s ease; }
#chatnav .cnnew:hover, #chatnav .cnmk:hover { background:var(--panel2); }
#chatnav .cnnew i, #chatnav .cnmk i { display:inline-flex; color:var(--dim2); }
#chatnav .cnnew:hover i, #chatnav .cnmk:hover i { color:var(--accent); }
#chatnav .cnnew svg, #chatnav .cnmk svg { width:14px; height:14px; fill:none; stroke:currentColor;
  stroke-width:1.9; stroke-linecap:round; stroke-linejoin:round; }
/* 섹션 경계 = 명료한 가로선 (사용자 2026-08-01 "구분선이 명료했으면") — --line만으론
   라이트에서 흐릿해 dim2를 섞어 한 단계 또렷하게. 버튼 무리↔고정됨, 고정됨↔최근 세션 둘 다. */
#chatnav .cnsec { display:flex; align-items:center; margin:14px 0 2px;
  border-top:1px solid color-mix(in srgb, var(--dim2) 28%, var(--line)); padding-top:10px; }
/* 두 번째 이후 섹션(고정됨·최근 세션)은 선 없이 — 선이 많으면 복잡하다 (사용자 2026-08-02) */
#chatnav .cnsec ~ .cnsec { border-top:0; padding-top:2px; margin-top:10px; }
#chatnav .cnh { flex:1; display:flex; align-items:center; gap:5px; background:transparent; border:0;
  padding:3px 2px; font-size:var(--fs-sub); font-weight:700; letter-spacing:.12em; color:var(--dim2);
  cursor:pointer; text-align:left; }
#chatnav .cnh:hover { color:var(--text); }
#chatnav .cnc { display:inline-flex; transition:transform .15s ease; }
#chatnav .cnc.fold { transform:rotate(-90deg); }
#chatnav .cnc svg { width:11px; height:11px; fill:none; stroke:currentColor; stroke-width:2.4;
  stroke-linecap:round; stroke-linejoin:round; }
#chatnav .cnlist { display:flex; flex-direction:column; gap:1px; }
#chatnav .cnlist.fold { display:none; }
/* 행 = 컨테이너 + 버튼 2개(열기·삭제). 여는 동작이 키보드로 닿아야 한다 —
   div+onclick 시절엔 Tab에 삭제만 잡혔다(위험한 쪽만 접근 가능, 실측 2026-07-29). */
#chatnav .cnrow { display:flex; align-items:center; border-radius:8px; position:relative; }
/* 호버 = **눌릴 수 있음**을 느끼게 하는 유일한 신호 (사용자 지시 2026-08-19).
   왜 --panel2인가: #chatnav 자신의 배경이 --panel이라 예전 `background:var(--panel)`은
   같은 색을 같은 색 위에 칠하는 것이어서 호버·선택이 **둘 다 보이지 않았다**. 선택은 액센트
   바 하나로만 버티고 있었고, 호버 피드백은 사실상 0이었다. */
#chatnav .cnrow:hover { background:color-mix(in srgb, var(--text) 5%, transparent); }
/* 선택 = **채움 하나**로만 (머신러너님 지시 2026-08-31 "좌측 세로 줄 촌스러워 · 조잡하다").
   종전에는 청록 틴트 + 좌측 액센트 바 + 굵은 글씨로 **신호가 셋**이었다. 포트와 그 아래
   세션이 동시에 선택되면 초록 덩어리 둘이 세로 줄까지 달고 겹쳐 목록이 소란스러워졌다.
   지금 여기를 알리는 데 셋은 과하다 — 중성 채움 하나면 충분하고, 색은 브랜드가 아니라
   **글자색에서 파생**시켜 라이트·다크 어디서도 뜨지 않는다(클로드 목록 문법). */
#chatnav .cnrow.on { background:color-mix(in srgb, var(--text) 9%, transparent); }
#chatnav .cnmain { flex:1; min-width:0; display:flex; align-items:center; gap:8px; padding:6px 9px;
  background:transparent; border:0; border-radius:8px; font:inherit; font-size:var(--fs-body);
  color:var(--text); cursor:pointer; text-align:left; }
/* 굵기는 한 단만 — 700은 채움과 겹쳐 행이 튀어나와 보였다 */
#chatnav .cnrow.on .cnmain { font-weight:600; color:var(--text); }
#chatnav .cnrow.th .cnmain { padding-left:15px; font-size:var(--fs-body); color:var(--dim2); }
/* 하위 세션 (선택한 포트 아래 전개) — **들여쓰기만** (사용자 2026-08-02 빨간 펜:
   세로선은 상위 포트의 액센트 바만 남기고 하위 가이드선은 복잡해서 제거) */
#chatnav .cnrow.sub { margin-left:20px; }
#chatnav .cnrow.th.on .cnmain { color:var(--text); }
/* 세션 아이콘 — **모양으로 구분**한다(색 아님, 사용자 2026-08-02): 폴더=덮개 접힘선,
   말풍선=꼬리. 둘 다 같은 중립색·16px — 클로드 목록 문법. */
#chatnav .cnico { position:relative; display:inline-flex; flex-shrink:0; color:var(--dim2); }
#chatnav .cnico svg { width:16px; height:16px; fill:none; stroke:currentColor; stroke-width:1.7;
  stroke-linecap:round; stroke-linejoin:round; }
#chatnav .cnrow.th.on .cnico { color:var(--text); }
/* 마커 = 아이콘 **우측 상단 한 자리** (사용자 최종 2026-08-02): 응답 중(회색 명암 껌뻑) ›
   확인 필요(청록) › 포트 소속(작은 회색 고리 — 별은 즐겨찾기 같아 반려). */
#chatnav .cndot { position:absolute; right:-4px; top:-4px; width:8px; height:8px;
  border-radius:50%; border:1.5px solid var(--panel); box-sizing:content-box; }
/* 소속 아이콘의 안쪽 말풍선은 가는 선으로 — 16px에서 뭉개지지 않게 */
#chatnav .cnico svg path:nth-child(2) { stroke-width:1.4; }
/* 진행 중 = 연한 회색 ↔ 진한 회색 **명암 그라데이션 껌뻑임** (사용자 2026-08-02 —
   투명도 페이드가 아니라 색 자체가 옅어졌다 진해졌다). 완료 미확인 = 주비스 청록 마커. */
#chatnav .cndot.busy { background:var(--dim2); animation:cndot-pulse 1.4s ease-in-out infinite; }
#chatnav .cndot.unread { background:var(--accent); }
@keyframes cndot-pulse {
  0%, 100% { background:var(--dim2); }
  50% { background:color-mix(in srgb, var(--dim2) 28%, var(--panel2)); }
}
#chatnav .cnname { flex:0 1 auto; min-width:0; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
#chatnav .cnflex { flex:1; }                      /* 남는 공간 — 개수는 제목 곁에 붙는다 */
/* 개수 = 제목 바로 옆 보조 숫자 (사용자 2026-08-02 "피지컬 AI 2 — 회색, 보조라는 느낌") */
#chatnav .cnn { font-size:var(--fs-lab); color:var(--dim2); font-variant-numeric:tabular-nums;
  flex-shrink:0; margin-left:-4px; } /* .cnmain gap 8px 상쇄 → 실간격 ~4px */
#chatnav .cnx { background:transparent; border:0; color:var(--dim2); cursor:pointer; padding:5px 7px;
  opacity:0; flex-shrink:0; display:inline-flex; }
#chatnav .cnrow:hover .cnx, #chatnav .cnx:focus-visible { opacity:1; }
/* 포트 설정 톱니 — 우측 정렬 끝(삭제 왼쪽), 호버 시 표시 (사용자 2026-08-02) */
#chatnav .cng { background:transparent; border:0; color:var(--dim2); cursor:pointer; padding:5px 4px;
  opacity:0; flex-shrink:0; display:inline-flex; }
#chatnav .cnrow:hover .cng, #chatnav .cng:focus-visible { opacity:1; }
#chatnav .cng:hover { color:var(--accent); }
#chatnav .cng svg { width:12px; height:12px; fill:none; stroke:currentColor; stroke-width:1.9;
  stroke-linecap:round; }
/* 전개된 포트 안 ＋새 대화 — 하위 행 문법, 액센트로 행동임을 알림 */
#chatnav .cnnewsub .cnmain { color:var(--accent); font-size:var(--fs-sub); }
/* 더보기 — 목록의 일부가 아니라 조작이라는 걸 보조색으로 (ChatGPT 추종) */
#chatnav .cnmore .cnmain { color:var(--dim2); font-size:var(--fs-sub); }
#chatnav .cnmore:hover .cnmain { color:var(--fg); }
#chatnav .cnplus2 { display:inline-flex; }
#chatnav .cnplus2 svg { width:12px; height:12px; fill:none; stroke:currentColor; stroke-width:2;
  stroke-linecap:round; }
#chatnav .cnx:hover { color:var(--up); }
#chatnav .cnx svg { width:11px; height:11px; fill:none; stroke:currentColor; stroke-width:2.2;
  stroke-linecap:round; }
#chatnav .cnempty { display:block; width:100%; text-align:left; padding:7px 9px; font-size:var(--fs-sub);
  color:var(--dim2); line-height:1.5; background:transparent; border:0; }
/* 목록을 못 불러왔을 때 — '없음'과 구분해서 말하고, 다시 시도할 손잡이를 준다 */
#chatnav .cnerr { display:block; width:100%; margin-top:6px; padding:6px 9px; text-align:left;
  font-size:var(--fs-lab); color:var(--up); background:color-mix(in srgb, var(--up) 8%, transparent);
  border:1px solid color-mix(in srgb, var(--up) 35%, transparent); border-radius:8px; cursor:pointer; }
#chatnav .cnerr:hover { background:color-mix(in srgb, var(--up) 14%, transparent); }

/* CI = 홈 버튼 (사용자 지시 2026-08-13). 버튼이지만 테두리·배경 없이 로고만 보이게 */
#chathead .chattitle { font-weight:700; color:var(--ai); font-size:14px; display:inline-flex; align-items:center;
  background:transparent; border:0; padding:2px; margin:-2px; cursor:pointer; border-radius:8px;
  transition:opacity .15s ease, background-color .15s ease; }
#chathead .chattitle:hover { opacity:.78; background:var(--panel2); }
/* CI 로고 (사용자 지시 2026-08-11 — '주비스' 글자 대체). 잉크색이 테마마다 반대라 파일을 갈아 끼운다 */
#chathead .chattitle .cimark { height:25px; width:auto; display:block; }   /* 19→25px (사용자 지시 2026-08-13 "조금 더 키우고") */
body[data-theme="dark"] #chathead .chattitle .cimark { content:url(/static/img/brand/joovis_ci_dark.png); }
/* 빈 상태 — 큰 인사 + 투자 제안 카드 (ChatGPT 예시 프롬프트를 투자용으로) */
#chatlog .greet { margin:auto 0; text-align:center; padding:20px 16px; }
#chatlog .greet .gmark { display:flex; justify-content:center; margin-bottom:12px; }
#chatlog .greet .gmark svg { width:26px; height:26px; }
#chatlog .greet .gmark svg path { fill:var(--ai); }
/* 팻(마스코트) — 대화 빈 상태에만. 인사하듯 아주 느리게 떠 있는다 (2026-08-04).
   72px: 104px는 "너무 크다"고 반려됨(사용자 2026-08-04). 인사말(.gh 22px)이 주인공이고
   팻은 그 위에 얹히는 표식이라 제목보다 과하게 크면 안 된다 — 키울 거면 이 관계를 먼저 볼 것. */
#chatlog .greet .gpet { width:72px; height:auto; display:block; object-fit:contain;
  image-rendering:pixelated; }   /* 픽셀아트 — 보간되면 뭉개진다 (2026-08-05 새 팻)
     인사 화면의 팻은 **정지**한다 (사용자 지시 2026-08-05 "홈화면에서 움직이는 게 더 이상하다").
     움직임은 답변을 기다릴 때(.jvthink 스프라이트)만 — 그때만 '일하는 중'이라는 뜻이 된다. */
@keyframes gpetfloat { 0%, 100% { transform:translateY(0) rotate(-1deg); } 50% { transform:translateY(-4px) rotate(1deg); } }
#chatlog .greet .gh { font-size:22px; font-weight:300; letter-spacing:-.01em; }
#chatlog .greet .gs { font-size:13px; color:var(--dim); margin-top:6px; }
#chatlog .suggest { display:grid; grid-template-columns:1fr 1fr; gap:8px; margin-top:20px; text-align:left; }
#chatlog .suggest button { background:var(--panel2); border:1px solid var(--line); border-radius:10px;
  padding:11px 13px; font-size:12.5px; color:var(--text); cursor:pointer; transition:border-color .15s ease, transform .15s ease; }
#chatlog .suggest button:hover { border-color:var(--ai); transform:translateY(-1px); }
#chatlog .suggest button .sk { display:block; font-size:var(--fs-lab); color:var(--dim2); margin-top:3px; }
/* 컴포저 — 클로드식: 함께보기 컨텍스트 칩 + 라운드 박스 안 자동확장 textarea + 전송 (docs/33) */
/* 구분선 없음 (머신러너님 지시 2026-08-31 "프롬프트 창과 위에 출력창을 구분하는 선 제거하라").
   #chatbox가 이미 제 테두리와 바탕을 갖고 있어, 폼의 선은 경계를 두 번 그리는 것이었다. */
#chatform { position:relative; display:flex; flex-direction:column; gap:7px; padding:10px 12px 12px; }

/* 맨 아래로 (2026-08-31, 사용자 지시 "마지막 아래가 아니면 이 화살표 누르면 아래로 쭉")
   컴포저 위에 뜨는 원형 버튼. #chatform이 position:relative라 bottom:100%면 로그 위로 걸린다.
   기본이 display:none이라 처음엔 안 보인다 — 여는 것은 .on 하나뿐. */
#chatdown { position:absolute; left:50%; transform:translateX(-50%); bottom:100%; margin-bottom:8px;
  width:32px; height:32px; border-radius:50%; padding:0; z-index:8; cursor:pointer;
  display:none; align-items:center; justify-content:center;
  background:var(--panel); color:var(--dim); border:1px solid var(--line);
  box-shadow:0 4px 14px rgba(0,0,0,.22); transition:color .15s ease, border-color .15s ease; }
#chatdown.on { display:inline-flex; }
#chatdown:hover { color:var(--accent); border-color:var(--accent); }
#chatdown svg { width:16px; height:16px; fill:none; stroke:currentColor; stroke-width:2;
  stroke-linecap:round; stroke-linejoin:round; }

/* @멘션 자동완성 드롭다운 — 컴포저 위로 뜸 */
.mentionpop { position:absolute; left:12px; right:12px; bottom:100%; margin-bottom:6px; z-index:9;
  background:var(--panel); border:1px solid var(--line); border-radius:10px; box-shadow:0 -8px 26px rgba(0,0,0,.3);
  max-height:210px; overflow-y:auto; padding:4px; }
.mentionpop[hidden] { display:none; }
.mentionpop .mrow { display:flex; align-items:center; gap:8px; padding:7px 9px; border-radius:7px; cursor:pointer; font-size:12.5px; color:var(--text); }
.mentionpop .mrow.on, .mentionpop .mrow:hover { background:var(--panel2); }
.mentionpop .mrow .mcode { margin-left:auto; font-size:var(--fs-lab); color:var(--dim); font-variant-numeric:tabular-nums; }
.mentionpop .mhint { padding:8px 9px; font-size:var(--fs-sub); color:var(--dim); }
/* @멘션 첨부 칩 (기업 종합분석 컨텍스트) */
.chatmentions { display:flex; flex-wrap:wrap; gap:5px; }
.chatmentions:empty { display:none; }
.chatmentions .mchip { display:inline-flex; align-items:center; gap:5px;
  background:color-mix(in srgb, var(--mention) 14%, var(--panel2)); border:1px solid var(--mention); color:var(--mention);
  border-radius:14px; padding:2px 5px 2px 10px; font-size:var(--fs-sub); font-weight:600; }
.chatmentions .mchip button { background:transparent; border:0; color:var(--mention); cursor:pointer;
  display:inline-flex; align-items:center; padding:0; }
.chatmentions .mchip button svg { width:11px; height:11px; fill:none; stroke:currentColor; stroke-width:2.4; stroke-linecap:round; }
.chatctx { display:inline-flex; align-items:center; gap:5px; max-width:100%;
  background:var(--panel); border:1px solid var(--line); border-radius:8px; padding:3px 8px;
  font-size:var(--fs-lab); color:var(--dim2); }   /* 칩은 '지금 어디에 담기나'를 읽는 자리 — 본문 대비 필요 */
.chatctx[hidden] { display:none; }
.chatctx svg { width:12px; height:12px; fill:none; stroke:currentColor; stroke-width:1.8; flex-shrink:0; }
.chatctx .cxlabel { white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
/* ── 컴포저 v3 — 클로드 코워크식 세로 3단 한 박스 (사용자 지시 2026-07-28
   "너무 작고 구성도 별로 — 타깃은 무조건 클로드")
   구 버전은 [+][한 줄 textarea][전송]을 한 행에 눌러 담아 입력면이 39px밖에 안 됐다.
   → 입력면이 박스 폭을 꽉 쓰고(2줄 기본), 버튼은 아래 툴바로 내려 '쓰는 자리'를 넓힌다. */
#chatbox { display:flex; flex-direction:column; background:var(--panel2); border:1px solid var(--line);
  border-radius:16px; padding:10px 12px 8px; transition:border-color .15s ease, box-shadow .15s ease; }
#chatbox:focus-within { border-color:var(--accent);   /* 컴포저 원톤=시그니처 청록 (사용자 지시 2026-07-22) */
  box-shadow:0 0 0 3px color-mix(in srgb, var(--accent) 12%, transparent); }
/* 칩 줄(함께보기 눈·@멘션) = 박스 안 최상단. 둘 다 없으면 자리 자체가 사라진다(:has) */
/* 부팅 무이동 (사용자 지적 2026-08-24 "아래에서 위로 올라오는 느낌") — 화면 칩(#chatctx)은
   showView 뒤에 붙는다. 예전엔 이 줄이 0 → 42px로 자라며 **컴포저를 그만큼 위로 밀어올렸다**.
   칩은 화면이 정해지면 반드시 하나는 뜨므로 자리를 처음부터 비워 둔다(높이 고정 = 이동 없음). */
.cbchips { display:flex; flex-wrap:wrap; gap:6px; align-items:center; min-height:34px; padding-bottom:8px; }
/* ↑ align-items:center (2026-08-05): 첨부 썸네일(56px)이 같은 줄에 서면 기본 stretch가
   화면 칩("삼성전자")을 세로로 늘렸다 — 칩은 제 키를 유지하고 세로 중앙에 선다. */
/* (구) 칩이 있을 때만 주던 아래 여백은 위에서 **상시**가 됐다 — 조건부면 칩이 뜨는 순간 또 8px 움직인다. */
/* 툴바 — 좌 도구(+) · 중앙 키 힌트(포커스 때만) · 우 전송 */
.cbbar { display:flex; align-items:center; gap:8px; margin-top:6px; }
.cbbar .cbhint { flex:1; min-width:0; font-size:var(--fs-lab); color:var(--dim2); opacity:0;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; transition:opacity .15s ease; }
#chatbox:focus-within .cbbar .cbhint { opacity:1; }
@media (max-width:900px) { .cbbar .cbhint { display:none; } }
/* @멘션 하이라이트 v2 (2026-07-22, 사용자 "글자 겹쳐 보임" 픽스): 이전 투명 textarea + 미러 글자
   방식은 한글 IME 조합 글자에 투명이 안 먹어 이중으로 보였다. 뒤집어서 — textarea 글자를 그대로
   보이게 하고, 미러(#chathl)는 글자를 투명으로 두고 @기업 토큰에 배경 하이라이트만 칠한다.
   미러 볼드도 제거(굵기가 다르면 폭이 어긋나 하이라이트가 밀림 — 메트릭 완전 일치). */
.tawrap { position:relative; width:100%; min-width:0; }
/* 미러(#chathl)와 입력(#chatinput)은 메트릭이 1px도 달라선 안 된다(하이라이트 밀림) → 한 규칙으로 묶어 지정 */
/* 14.5 → 16.7 → **15.5px** (2026-08-20 두 번에 걸친 사용자 지시).
   처음엔 "너무 작다"고 해서 +15%로 올렸는데, 그러자 이번엔 "플레이스홀더는 크고 답변은
   작다, 둘 사이 중간으로 맞추자"였다. 그래서 답변(15px)과 **거의 같은 자리**로 모았다 —
   입력이 0.5px 큰 것은 빈 상자의 안내문이 답변 글보다 작아 보이지 않게 하는 정도다.
   **미러(#chathl)와 함께 바꾼다** — 둘의 메트릭이 1px이라도 어긋나면 @기업·/스킬
   하이라이트가 글자에서 밀린다. 그래서 애초에 한 규칙으로 묶여 있다. */
#chathl, #chatinput { font-size:15.5px; line-height:1.55; padding:2px 2px; letter-spacing:0;
  font-family:inherit; font-weight:400; }
#chathl { position:absolute; inset:0; z-index:2; pointer-events:none; overflow:hidden; color:transparent;
  white-space:pre-wrap; overflow-wrap:break-word; word-break:break-word; }   /* z-index 2 = 미러가 위 — .hls가 원문 글자를 덮고 색 글자로 대체 (2026-07-23) */
/* @기업 · /스킬 토큰 = 같은 스타일 — 배경은 박스색(--panel2)으로 원문 글자만 가리고, 글자만 하늘색.
   (사용자 지시 2026-07-25 "@삼성전자도 /스킬처럼 하늘색으로 색만 바뀌고 바탕은 바뀌지 않게"
    — 구 .hlm은 반투명 배경을 칠해 알약처럼 보였다. --panel2 = #chatbox 배경과 동일해 '바탕 불변') */
#chathl .hlm { background:var(--panel2); color:var(--mention); }
/* 슬래시 토큰 = 하늘색 배경 알약 (클로드 문법 — 사용자 확정 2026-07-26 "배경도 하늘색").
   패딩·마진 금지 — 미러와 원문 textarea의 글자 정렬이 픽셀 단위로 같아야 한다 */
#chathl .hls { background:color-mix(in srgb, var(--mention) 22%, transparent);
  color:var(--mention); border-radius:4px; }
/* 입력면 = 박스 폭 전체, 기본 2줄(46px)에서 시작해 autoGrow가 늘린다. CSS max-height는 JS 상한의 백스톱 */
#chatinput { position:relative; z-index:1; display:block; width:100%; border:0; background:transparent; outline:none; resize:none;
  /* 최소 높이도 글자와 같은 비율로 (46 → 53px). 안 올리면 커진 글자가 두 줄이 안 되는
     상자에 갇혀, 처음부터 스크롤이 생긴다. 그 위로는 autoGrow가 늘린다. */
  color:var(--text); caret-color:var(--text); min-height:50px; max-height:min(340px, 42vh); }
#chatinput::placeholder { color:var(--dim); }
#chatsend { background:var(--accent); border:0; color:#fff; border-radius:50%; width:35px; height:35px; flex-shrink:0;
  display:inline-flex; align-items:center; justify-content:center; cursor:pointer; transition:opacity .15s ease; }
#chatsend:disabled { opacity:.35; cursor:default; }

#chatsend svg { width:17px; height:17px; fill:currentColor; }
/* 화살표는 **선**으로 그린다 (머신러너님 지시 2026-08-31, 클로드 문법).
   `:not(.stop)`으로 좁히는 이유: 중단 아이콘은 채운 사각이라 여기에 걸리면 속 빈 네모가 된다. */
#chatsend:not(.stop) svg { fill:none; stroke:currentColor; stroke-width:2.4;
  stroke-linecap:round; stroke-linejoin:round; }
#chathead { position:relative; padding:10px 78px 10px 44px; display:flex; align-items:center; gap:8px; flex-wrap:wrap; border-bottom:1px solid var(--line); }
/* 좌측 44px = 포트·세션 핸들(#navbtn, 좌상단 곡선 필) 자리 */
/* 부제는 **한 줄로 끝나게 쓴다**(chat.js CHAT_SUB_BY_VIEW, 24자 이내 — 잠금은
     tests/js/test_chat_sub_oneline.mjs). 그래도 넘칠 때를 위한 안전망 둘:
     `text-wrap:pretty`가 마지막 줄에 한 글자만 남는 고아를 막고(사용자 지적 2026-08-27
     — 둘째 줄에 "요" 한 글자), `word-break:keep-all`이 어절 중간을 안 자른다. */
  #chathead #chatsub { flex-basis:100%; margin-top:2px; text-wrap:pretty; word-break:keep-all;
    /* <small> 기본은 부모의 0.8배(11.2px)라 읽기 하한을 밑돌았다 → 캐논의 '읽는 글자 최소'로
       올린다(사용자 지시 2026-08-28 "조금 더 커도 될 것 같다"). 24자 × 12.5 = 300px로
       가용 폭 318px 안에 그대로 들어간다 — 한 줄 계약(위 주석)은 유지된다. */
    font-size:var(--fs-sub); }
/* 접기 = 반대편 « 손잡이(#navbtn)와 같은 문법 (사용자 지시 2026-08-13):
   세로로 긴 둥근 직사각형 + 패널 배경 + 소프트 섀도. 좌우 손잡이가 한 벌로 읽힌다. */
#chatclose { position:absolute; top:8px; right:9px; width:24px; height:48px; z-index:6;
  background:var(--panel); border:1px solid var(--line); border-radius:12px;
  box-shadow:var(--shadow); color:var(--dim); cursor:pointer; padding:0;
  display:inline-flex; align-items:center; justify-content:center;
  transition:color .15s ease, background-color .15s ease, border-color .15s ease, box-shadow .15s ease; }
#chatclose:hover { color:var(--accent); background:var(--panel2); border-color:var(--accent);
  box-shadow:0 2px 6px rgba(0,0,0,.14), 0 10px 24px rgba(0,0,0,.10); }
#chatclose svg { width:14px; height:14px; fill:none; stroke:currentColor; stroke-width:2; stroke-linecap:round; stroke-linejoin:round; }
/* [기억] 헤더 버튼 + 패널 (docs/32 — 사용자 통제: 조회·삭제) */
#chathead { padding-right:78px; }
#membtn { position:absolute; top:10px; right:44px; background:transparent; border:1px solid var(--line);
  color:var(--dim); border-radius:8px; width:26px; height:26px; cursor:pointer;
  display:inline-flex; align-items:center; justify-content:center; }
#membtn:hover { color:var(--ai); border-color:var(--ai); }
#membtn svg { width:14px; height:14px; fill:none; stroke:currentColor; stroke-width:1.8; stroke-linecap:round; stroke-linejoin:round; }
#mempanel { border-bottom:1px solid var(--line); background:var(--panel2); max-height:240px; overflow-y:auto; padding:4px 0; }
#mempanel .memhead { font-size:var(--fs-sub); font-weight:700; letter-spacing:.08em; color:var(--dim); padding:8px 14px 4px; }
#mempanel .memhead small { font-weight:400; letter-spacing:0; }
#mempanel .memrow { display:flex; align-items:center; gap:8px; padding:5px 14px; font-size:12.5px; }
#mempanel .memkind { color:var(--ai); font-size:var(--fs-lab); border:1px solid var(--ai); border-radius:8px; padding:0 6px; flex-shrink:0; }
#mempanel .memtext { flex:1; color:var(--text); }
#mempanel .memdel { background:transparent; border:0; color:var(--dim); cursor:pointer; flex-shrink:0; }
#mempanel .memdel:hover { color:var(--up); }
#mempanel .memempty { padding:12px 14px; font-size:var(--fs-sub); color:var(--dim); }
/* 주비스 여는 손잡이 — **좌측 최상단 모서리**(사용자 지시 2026-08-26).
   구: 사이드바 경계 세로 중앙의 엣지 탭. 화면 한복판에 떠 있어 본문을 가로막았다.
   지금은 사이드바 위쪽, **검색행 높이**에 앉는다 — 시선이 처음 닿는 자리다.
   top:44px = 티커(38) 바로 아래 6px. 맨 위(0)에 붙였더니 "너무 위"라고 반려돼
   한 칸 내렸다(2026-08-26). 사이드바 첫 항목(홈)과 나란히 서고, 세로 중앙이
   검색창 중앙과 맞는다. 검색창은 오른쪽으로 밀어 겹치지 않게 한다(아래 `header`). */
#chattab { position:fixed; left:var(--nav-w); top:44px; z-index:79;
  display:flex; flex-direction:column; align-items:center; gap:6px;
  background:var(--panel); border:1px solid var(--line); border-left:0;
  border-radius:0 12px 12px 0;
  /* 크기는 자리를 옮기기 전 그대로 — 세로로 긴 박스 (사용자 지시 2026-08-05, 2026-08-26 재확인) */
  color:var(--dim); padding:22px 8px; cursor:pointer;
  box-shadow:var(--shadow);
  transition:color .15s ease, border-color .15s ease, background-color .15s ease, left .18s ease; }
#chattab:hover { background:color-mix(in srgb, var(--accent) 10%, var(--panel)); }
/* 손잡이가 앉은 만큼 헤더(검색창)를 오른쪽으로 — 열려 있을 땐 손잡이가 없으니 원래대로 */
body:not(.chat-open) header { padding-left:54px; }
/* 팻(작게) 위 · 가로쓰기 'AI' 아래 (사용자 지시 2026-08-05 — 세로쓰기 폐기) */
#chattab .ctpet { width:20px; height:auto; display:block; image-rendering:pixelated; }
#chattab span { font-size:12.5px; font-weight:600; letter-spacing:.04em; line-height:1; }
#chattab:hover { color:var(--ai); border-color:var(--ai); }
body.chat-open #chattab { display:none; }
/* [삭제됨 2026-08-12] 답변 리드 기호(📈📉🔹🔸) 크기 보정 규칙.
   기호 자체가 2026-08-08 사용자 확정으로 **전면 폐지**됐고(answer.md "표시 기호 — 쓰지 않는다"),
   mdlite는 `.lead-mk`도 `img.emoji`도 만들지 않는다 — 아무 데도 안 걸리는 사문화 CSS였다.
   구분은 마크다운(굵은 리드 + `##`), 판단은 위젯(`signal`·`gauge`)이 맡는다. */

/* ---------- 주비스 아이콘 (사용자 확정 2026-08-12) ----------
   "색은 없으나 형태가 상징적인" 단색 라인 아이콘 — 컬러 이모지의 대안(icons.js JV_ICONS).
   **스스로 색을 갖지 않는다**: stroke가 currentColor라 글자 색을 그대로 따라간다.
   크기도 글자를 따라간다(1em) — 어느 문단·어느 크기에 놓아도 본문과 같은 결로 앉는다. */
.jvico { width:1em; height:1em; vertical-align:-.14em; flex-shrink:0;
  fill:none; stroke:currentColor; stroke-width:1.8; stroke-linecap:round; stroke-linejoin:round; }
.msg.ai .msgbody .jvico { margin-right:.18em; opacity:.85; }   /* 답변 본문에선 글자보다 한 톤 뒤로 */
/* 목록에서 아이콘이 앞에 오면 그 아이콘이 곧 마커다 — 점(•)을 지워 마커가 둘이 되지 않게.
   들여쓰기는 그대로 두어 다른 항목과 왼쪽 선이 맞는다 (사용자 지시 2026-08-12). */
.msg.ai .msgbody ul li.mdli-ico { list-style:none; }
.msg.ai .msgbody ul li.mdli-ico > .jvico:first-child { margin-left:-1.35em; margin-right:.42em; }
/* 번호 목록(ol)은 **번호를 지운다** — 순서가 곧 뜻이라, 1번만 사라지고 2번이 남으면 깨져 보인다.
   아이콘은 번호 뒤에 나란히 선다 (실측 2026-08-12). */
.msg.ai .msgbody ol li.mdli-ico > .jvico:first-child { margin-right:.42em; }

/* AI 사용량 게이지 (docs/56 — 사용자는 %만 본다). 계정 메뉴 안, 로그아웃 위. 이모지 금지 */
.acctlimits { padding:8px 12px 4px; display:flex; flex-direction:column; gap:9px; }
/* 배지와 '추천 코드 등록하기'가 한 줄 — 등급 옆이 그 등급을 바꾸는 자리다 */
.acctlimplan { margin-bottom:1px; line-height:1; display:flex; align-items:center;
  justify-content:space-between; gap:8px; }
/* 임시 버튼 (사용자 지시 2026-08-29) — 구독이 열리면 걷는다. 배지보다 조용해야 하므로
   테두리 있는 글자 버튼: 등급 이름표가 주인공이고 이건 그 옆의 할 일이다. */
/* 테두리 = **옅은 무지개** (사용자 지시 2026-08-29 "조금 자연스러운 빛깔로 무지개
   그라데이션풍 테두리", 시안 = 파스텔 무지개).
   두께는 1px 그대로다(CSS 테두리의 하한). 대신 회색 --line을 걷고 채도를 낮춘 무지개를
   깔아 **선의 무게**를 덜었다 — 같은 1px이라도 옅은 색이 얇게 읽힌다.
   기법은 배경 두 겹: padding-box에는 메뉴 바탕(--panel)을, border-box에는 무지개를 깐다.
   `border-color`는 한 색만 받으므로 이 방법 말고는 선 안에서 색이 흐르게 할 수 없다.
   ※ padding-box 색이 메뉴 바탕과 어긋나면 버튼 안쪽에 네모가 뜬다 — --panel 고정. */
.acctinvbtn { flex:none; padding:2px 8px; font:inherit; font-size:var(--fs-lab);
  color:var(--dim); border:2px solid transparent; border-radius:7px;
  background:linear-gradient(var(--panel), var(--panel)) padding-box, var(--rainbow) border-box;
  cursor:pointer; white-space:nowrap;
  transition:color .15s ease, filter .15s ease; }
/* 호버 = 색을 바꾸지 않고 **같은 무지개를 한 단계 또렷하게**. 액센트 청록으로 갈아타면
   무지개가 사라져 다른 버튼이 된 것처럼 보인다. */
.acctinvbtn:hover { color:var(--text); filter:saturate(1.4) brightness(1.04); }
/* 플랜 배지 — 등급을 **같은 자리·같은 크기**에 놓고 채움만 바꾼다 (사용자 지시 2026-08-18).
   11→12px: 사용량 라벨보다 위계가 높은 이름표라 조금 커야 한다. */
/* Basic — 두 번 고쳤다. 회색(`--panel2`)은 메뉴 호버색과 같아 "눌린 버튼"으로 읽혔고,
   그다음 옅은 틴트(16%)는 탁했다(사용자 지적 2026-08-18). 결론: **연하게 깔지 말고
   꽉 채운다.** 두 등급의 차이는 진하기가 아니라 결이다 — Basic은 단색 한 판,
   Pro는 같은 청록 계열이 오로라로 번진다 (사용자 확정 2026-08-18).
   원색 #45c9d8은 흰 글자 대비가 1.9:1이라 12px 글자에 못 쓴다 — 검정을 40% 섞어
   5:1까지 올렸다. 색조는 그대로 청록이고 밝기만 내려간다. */
/* Basic = 그라데이션 없는 한 색 + 얕은 광택. 시안(basic_tag.png)이 그렇다 — 색을 빼서
   Pro와 갈린다. 완전 둥근 필도 시안 그대로. */
.acctplan { display:inline-block; padding:3px 11px; border-radius:999px;
  font-size:13.5px; font-weight:700; letter-spacing:.2px; line-height:1.35;
  color:#fff; border:1px solid transparent; background:var(--tag-basic);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.30), inset 0 -1px 0 rgba(0,0,0,.12); }
/* 구독 준비 중 안내 한 줄 — 배지 바로 아래. 배지 자체는 Basic 그대로 두고
   상태만 덧붙인다(머신러너님 지시 2026-09-01 "Pro 기능을 사용할 수 있다고만 언급"). */
.acctplanopen { margin:5px 0 9px; font-size:var(--fs-lab); color:var(--dim2); line-height:1.5; }
/* Pro = 심해 청록 → 하늘빛 → 샴페인 → 금빛으로 **한 번에 흐르는 대각 램프**
   (시안 pro_tag.png, 사용자 확정 2026-08-29). 금빛이 Basic과 갈리는 표식이다.
   ※ 금빛을 **따로 얹지 않는다** — 방사 그라데이션을 위에 덧대는 방식은 두 번 반려됐다
   ("막 겹쳐있잖아" → 이음매, "뭐가 묻은 느낌" → 얼룩). 층이 둘이면 위층의 가장자리가
   반드시 보인다. 금빛은 램프의 마지막 구간일 뿐이고, 124°라 그 끝이 우측 하단이다.
   ※ 핵심은 **밝은 곳으로 돌아가는 것**(--tag-aqua → --tag-champ): 청록에서 노랑으로
   곧장 건너가면 어느 색공간에서든 중간이 탁한 연두로 가라앉는다. 밝기를 올린 채 건너면
   같은 구간이 '빛이 도는' 것으로 읽힌다. `in oklab`은 그 구간의 채도까지 지켜준다
   (구형 브라우저는 이 줄을 무시하므로 바로 위에 sRGB 폴백을 같이 둔다).
   애니메이션은 넣지 않았다 — 계정 메뉴는 오래 보는 화면이 아니고 움직이는 배지는 싸 보인다. */
.acctplan.pro { color:#fff; border-color:transparent;
  background:linear-gradient(124deg, var(--tag-deep) 0%, var(--tag-mid) 34%, var(--tag-azure) 58%,
             var(--tag-aqua) 76%, var(--tag-champ) 90%, var(--tag-gold) 100%);
  background:linear-gradient(124deg in oklab, var(--tag-deep) 0%, var(--tag-mid) 34%, var(--tag-azure) 58%,
             var(--tag-aqua) 76%, var(--tag-champ) 90%, var(--tag-gold) 100%);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.30), inset 0 -1px 0 rgba(0,0,0,.12), 0 1px 6px color-mix(in srgb, var(--tag-azure) 30%, transparent); }
.acctlimrow { display:flex; flex-direction:column; gap:3px; }
.acctlimtop { display:flex; justify-content:space-between; align-items:baseline;
  gap:8px; font-size:13.5px; color:var(--dim); }
/* 라벨이 "2시간 47분까지 남은 사용량"처럼 길어졌다(2026-08-12) — 좁은 메뉴에서
   숫자를 밀어내지 않게 라벨만 줄이고 오른쪽 값은 항상 온전히 보인다. */
.acctlimtop > span:first-child { min-width:0; overflow:hidden;
  text-overflow:ellipsis; white-space:nowrap; }
.acctlimpct { flex:none; font-variant-numeric:tabular-nums; font-weight:600; color:var(--fg); }
.acctlimbar { height:4px; border-radius:3px; background:var(--line); overflow:hidden; }
.acctlimfill { display:block; height:100%; border-radius:3px; background:var(--accent);
  transition:width .3s ease; }
/* 게이지 3단 (사용자 확정 2026-08-26): 기본 → 거의 다 씀 주황 → 다 씀 빨강.
   `hot`이 `--down`이었던 것이 실장애였다 — 이 프로젝트에서 `--down`은 **하락=파랑**이라
   다 쓴 순간 막대가 파랗게 떴다("파란색 바가 빨간색으로 바뀌어야지"). 데이터 의미색을
   UI 경고로 빌려 쓰면 이런 일이 난다. 경고는 경고 전용 빨강(`--alert`)을 쓴다 —
   상승색(`--up`)과 일부러 다른 색이라 등락과 안 헷갈린다.
   주황은 종전 금빛(#d9a441)이 "주황"으로 안 읽혀 한 단계 붉게 옮겼다. */
.acctlimfill.warn { background:#e8883c; }
.acctlimfill.hot { background:var(--alert); }

/* 챗 첨부 칩 (docs/51 L0 멀티모달 — 2026-08-05): 파일·사진 20MB, 캡처 붙여넣기 */
.attchips { display:flex; flex-wrap:wrap; gap:6px; }
.attchips:empty { display:none; }
.attchip { display:inline-flex; align-items:center; gap:6px; max-width:230px; padding:3px 8px;
  border:1px solid var(--line); border-radius:9px; font-size:var(--fs-sub); color:var(--dim); background:var(--card); }
.attchip svg { width:13px; height:13px; fill:none; stroke:currentColor; stroke-width:1.8;
  stroke-linecap:round; stroke-linejoin:round; flex:none; }
.attchip .attname { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.attchip button { border:0; background:none; color:var(--dim); cursor:pointer; padding:0 1px;
  display:inline-flex; align-items:center; }
.attchip button:hover { color:var(--accent); }
.attchip button svg { width:11px; height:11px; }
.attline { margin-top:6px; padding-top:5px; border-top:1px dashed var(--line);
  font-size:var(--fs-sub); color:var(--dim); }
/* 이미지 첨부 = 둥근 정사각 썸네일 (2026-08-05 사용자 확정: 호버 시 우상단 × · 클릭 = 확대) */
.attthumb { position:relative; display:flex; width:56px; height:56px; border-radius:11px;
  overflow:hidden; border:1px solid var(--line); cursor:zoom-in; flex:none; background:var(--card); }
.attthumb img { width:100%; height:100%; object-fit:cover; display:block; }
.attthumb button { position:absolute; top:3px; right:3px; width:18px; height:18px; border:0;
  border-radius:50%; background:rgba(10,14,13,.62); color:#e8edec; cursor:pointer; padding:0;
  display:flex; align-items:center; justify-content:center; opacity:0; transition:opacity .12s; }
.attthumb:hover button, .attthumb button:focus-visible { opacity:1; }
.attthumb button svg, #attlightbox button svg { fill:none; stroke:currentColor;
  stroke-width:2.2; stroke-linecap:round; }
.attthumb button svg { width:10px; height:10px; }
#attlightbox { position:fixed; inset:0; z-index:300; background:rgba(8,10,10,.82);
  display:flex; align-items:center; justify-content:center; cursor:zoom-out; backdrop-filter:blur(2px); }
#attlightbox[hidden] { display:none; }
#attlightbox img { max-width:90vw; max-height:86vh; border-radius:12px;
  box-shadow:0 18px 60px rgba(0,0,0,.5); cursor:default; }
#attlightbox button { position:absolute; top:18px; right:18px; width:34px; height:34px; border:0;
  border-radius:50%; background:rgba(255,255,255,.1); color:#e8edec; cursor:pointer;
  display:flex; align-items:center; justify-content:center; }
#attlightbox button:hover { background:rgba(255,255,255,.2); }
#attlightbox button svg { width:14px; height:14px; }

/* [M0-2] 도구·스킬 '+' 메뉴 + 도구 데이터 카드 (docs/46 §4, agentmenu.js — 사용자 지시 2026-07-21) */
#chatplus { background:transparent; border:1px solid var(--line); color:var(--dim); border-radius:9px;
  width:30px; height:30px; flex-shrink:0; display:inline-flex; align-items:center; justify-content:center;
  cursor:pointer; transition:color .15s ease, border-color .15s ease; }
#chatplus:hover { color:var(--accent); border-color:var(--accent); }   /* 에이전트 UI 원톤=시그니처 청록 (사용자 지시 2026-07-22) */
#chatplus svg { width:16px; height:16px; fill:none; stroke:currentColor; stroke-width:2; stroke-linecap:round; }

/* 폰 컴포저 압축 (2026-08-31, 사용자 지시 "프롬프트 창이 좀 좁아야 해 높이가 그래야 전체가 잘 보여")
   데스크톱은 그대로 두고 폰에서만 낮춘다 — 한 줄 입력에 필요한 높이는 24px(15.5px x 1.55)뿐이라
   min-height 50px는 폰에서 빈 줄 하나를 늘 깔고 있는 셈이었다. 그 위로는 autoGrow가 늘린다. */
@media (pointer:coarse) and (max-width:900px), (max-width:560px) {
  #chatform { gap:4px; padding:4px 10px 6px; }
  #chatbox { padding:6px 10px 5px; border-radius:14px; }
  #chatinput { min-height:28px; }   /* max-height는 그대로 — JS taMax()와 갈리면 안쪽 스크롤이 생긴다 */
  .cbbar { margin-top:2px; gap:6px; }
  /* 버튼 지름도 폰에서만 줄인다 — 손가락 표적은 44px 권장이지만 이 둘은 컴포저 안쪽에
     넉넉한 여백을 끼고 있어 실제 누르는 면적이 지름보다 크다. 30/35 -> 28/31. */
  #chatplus { width:28px; height:28px; border-radius:8px; }
  #chatsend { width:31px; height:31px; }
  #chatdown { margin-bottom:6px; }
  /* 칩 줄도 함께 줄인다 (머신러너님 지시 2026-08-31 "더 낮아야 해 — 경제적으로 쓰자").
     이 줄은 **늘 자리를 잡고 있다**(부팅 무이동을 위해 비어 있어도 34px을 비워 둔다).
     폰에서 칩 하나의 실제 키는 26px이라 그 8px이 매번 헛돈다. 칩이 두 줄로 넘치면
     flex-wrap이 알아서 늘리므로 하한만 낮추는 것은 안전하다. */
  .cbchips { min-height:24px; padding-bottom:3px; gap:5px; }
  /* 칩 줄의 실제 키를 정하는 것은 min-height가 아니라 **칩 알맹이**였다
     (실측 2026-08-31: min-height 26px인데 줄은 30.6px). 알맹이를 줄여야 줄이 준다. */
  /* ⚠ 실제 주인은 아래쪽 **ID 규칙**(#chatctx·#chatport)이다 — 클래스로 덮으면
     특이도에 져서 조용히 무시된다(실측 2026-08-31: .chatctx로 걸었더니 3px 8px 그대로).
     그래서 여기서는 손대지 않고, 그 규칙 바로 뒤에 같은 미디어로 다시 건다. */
}
/* '+' 메뉴 v2 — 클로드 데스크톱 계층 문법 (사용자 확정 2026-07-26): 레벨1 3행 고정이라
   스크롤 불요, overflow:visible이어야 우측 플라이아웃(.agsub)이 잘리지 않는다 */
/* 두께는 클로드 기준으로 걷어낸다 (사용자 지시 2026-08-03 "너무 두꺼운 느낌 · 클로드가 근본"):
   글자는 볼드 대신 중간 굵기, 아이콘은 액센트 대신 무채색 얇은 선, 행 높이는 낮게. */
/* z-index 150 = 본문·차트보다 확실히 위 (사용자 지시 2026-08-11 "레이어가 뒤에 있지 않고 최상단으로").
   구 9는 드로어 안에서만 유효해 본문 위로 나가면 가려졌다. 모달(200)보다는 아래. */
.plusmenu { position:absolute; left:12px; right:auto; min-width:194px; bottom:100%; margin-bottom:6px;
  z-index:150; background:var(--panel); border:1px solid var(--line); border-radius:12px;
  box-shadow:0 -6px 20px rgba(0,0,0,.18); overflow:visible; padding:5px; }
.plusmenu[hidden] { display:none; }
/* 레벨1 행 — 우측 셰브런, 서브 열림 표시 */
.plusmenu .agnav .agchev { margin-left:auto; display:flex; color:var(--dim); }
.plusmenu .agnav .agchev svg { width:12px; height:12px; fill:none; stroke:currentColor;
  stroke-width:1.6; stroke-linecap:round; stroke-linejoin:round; }
.plusmenu .agnav.on { background:var(--panel2); }
/* 플라이아웃 — 우측 전개, 자체 스크롤 (클로드 데스크톱 문법) */
/* 폭 234→198: 기본 프롬프트 창 크기에서 우측 토글이 잘렸다 (사용자 지시 2026-08-11 "가로로 조금 짧게").
   z-index는 부모(.plusmenu 150) 안에서의 순서라 11이면 충분하다. */
.agsub { position:absolute; left:calc(100% + 6px); bottom:0; width:198px; background:var(--panel);
  border:1px solid var(--line); border-radius:12px; box-shadow:0 6px 20px rgba(0,0,0,.18);
  padding:5px; z-index:11; }
.agsub[hidden] { display:none; }
.agsub .agsublist { max-height:300px; overflow-y:auto; }
.agsub .agsubft { border-top:1px solid var(--line); margin-top:4px; padding-top:4px; }
.agsub .agsubhd { border-bottom:1px solid var(--line); margin-bottom:4px; padding-bottom:4px; }
.plusmenu .agtxt.mono { font-family:ui-monospace,"Cascadia Mono",Consolas,monospace;
  font-size:var(--fs-sub); font-weight:500; }
/* 커넥터 행 — 파비콘 + 미니 토글 스위치 */
.agfav { width:20px; height:20px; border-radius:6px; background:var(--panel2); display:flex;
  align-items:center; justify-content:center; font-size:var(--fs-badge); font-weight:700; color:var(--dim);
  overflow:hidden; flex:none; }
.agfav img { width:14px; height:14px; }
/* 스위치는 **어디에 놓이든 손가락 커서**여야 한다 (사용자 지시 2026-08-19).
   종전엔 `.pfitem .agsw`·`.pfmemhead .agsw`에만 붙어 있어, 설정의 총 평가자산 토글만
   화살표 커서였다 — 같은 모양인데 어떤 건 눌리고 어떤 건 안 눌리는 것처럼 보였다. */
.agsw { position:relative; width:28px; height:16px; border-radius:999px; background:var(--line);
  margin-left:auto; flex:none; cursor:pointer; transition:background .15s ease; }
.agsw:hover { background:color-mix(in srgb, var(--dim) 35%, var(--line)); }
.agsw.on:hover { background:color-mix(in srgb, #000 12%, var(--accent)); }
.agsw::after { content:""; position:absolute; top:2px; left:2px; width:12px; height:12px;
  border-radius:50%; background:#fff; transition:left .15s ease; box-shadow:0 1px 2px rgba(0,0,0,.3); }
.agsw.on { background:var(--accent); }
.agsw.on::after { left:14px; }
.plusmenu .agsec { padding:7px 9px 3px; font-size:var(--fs-lab); font-weight:700; letter-spacing:.12em; color:var(--dim); }
.plusmenu .agsec small { font-weight:400; letter-spacing:0; margin-left:6px; }
.plusmenu .agrow { display:flex; align-items:center; gap:10px; padding:6px 8px; border-radius:7px; cursor:pointer; }
/* '프롬프트 에이전트' 구획 라벨 (사용자 명명 2026-08-22) — 스킬·커넥터·플러그인 삼단의 이름표 */
.plusmenu .aglbl { font-size:11px; color:var(--dim); padding:8px 8px 3px; margin-top:3px;
  border-top:1px solid var(--line); }
.plusmenu .agrow:hover { background:var(--panel2); }
/* 첨부(입력에 붙이는 것) ↔ 스킬·커넥터·플러그인(에이전트 능력)은 성격이 다르다.
   구분선은 **아주 옅게** — 경계를 느끼되 선 자체가 눈에 띄면 안 된다 (사용자 지시 2026-08-03) */
.plusmenu .agrow.agatt { margin-bottom:4px; padding-bottom:9px;
  border-bottom:1px solid color-mix(in srgb, var(--line) 45%, transparent); }
.plusmenu .agrow.skill { cursor:default; }
.plusmenu .agrow.off { opacity:.55; cursor:default; }
/* 아이콘은 무채색 얇은 선 — 액센트 초록은 행마다 시선을 끌어 메뉴를 무겁게 만들었다.
   **굵기·색·크기는 설정 네비(.pfnavi svg)와 같다** (사용자 지시 2026-08-19 "이걸로 통일").
   스킬·커넥터·플러그인은 두 자리에서 같은 도형을 쓰는데, 획이 1.5 대 1.7로 갈리고 색이
   달라서 같은 기호로 안 보였다 — 도형만 맞추고 획을 놔두면 통일이 아니다. */
.plusmenu .agico { flex-shrink:0; display:inline-flex; color:var(--dim); }
.plusmenu .agico svg { width:17px; height:17px; fill:none; stroke:currentColor; stroke-width:1.7; stroke-linecap:round; stroke-linejoin:round; }
.plusmenu .agtxt { flex:1; min-width:0; }
.plusmenu .agtxt b { display:block; font-size:12.5px; font-weight:500; color:var(--text); }
.plusmenu .agtxt small { display:block; font-size:var(--fs-lab); color:var(--dim); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.plusmenu .agrun { flex-shrink:0; font-size:var(--fs-lab); color:var(--accent); border:1px solid var(--accent); border-radius:9px; padding:2px 8px; }
.plusmenu .agrow.off .agrun { color:var(--dim); border-color:var(--line); }
.plusmenu .agauto { flex-shrink:0; font-size:var(--fs-lab); color:var(--dim); border:1px solid var(--line); border-radius:9px; padding:2px 8px; }
.plusmenu .aghint, .agmsg .aghint { padding:8px 9px; font-size:var(--fs-lab); color:var(--dim); }
/* 커넥터 탐색 — 인앱 모달 (클로드 데스크톱 설정창 문법, 사용자 지시 2026-07-23 "새 창 말고 첨부처럼") */
#agdirmodal { position:fixed; inset:0; z-index:120; }
#agdirmodal[hidden] { display:none; }
#agdirmodal .agdirback { position:absolute; inset:0; background:rgba(0,0,0,.55); }
#agdirmodal .agdirwin { position:absolute; top:50%; left:50%; transform:translate(-50%,-50%);
  width:min(920px, 92vw); height:min(720px, 88vh); border-radius:16px; overflow:hidden;
  border:1px solid var(--line); box-shadow:0 24px 80px rgba(0,0,0,.5); background:var(--bg);
  animation:agdirin .16s ease-out; }
@keyframes agdirin { from { opacity:0; transform:translate(-50%,-49%) scale(.985); }
                     to { opacity:1; transform:translate(-50%,-50%) scale(1); } }
#agdirmodal iframe { width:100%; height:100%; border:0; display:block; }

/* '/' 스킬 슬래시 v2 (클로드 데스크톱 문법 — 사용자 확정 2026-07-26 스크린샷):
   좁은 목록(아이콘+/이름) + **우측 설명 패널**(호버·화살표에 따라 이동). 팝업은
   overflow:visible이어야 패널이 안 잘린다 — 목록이 짧아 스크롤 불요. */
#slashpop { right:auto; min-width:230px; max-width:280px; max-height:none; overflow:visible; }
#slashpop .mrow { gap:9px; }
#slashpop .mrow b { color:var(--text); font-weight:700; }
#slashpop .mrow b.mono { font-family:ui-monospace,"Cascadia Mono",Consolas,monospace; font-size:12.5px; }
#slashpop .mrow .agico { display:flex; color:var(--dim); flex:none; }
#slashpop .mrow .agico svg { width:14px; height:14px; fill:none; stroke:currentColor;
  stroke-width:1.8; stroke-linecap:round; stroke-linejoin:round; }
#slashpop .sdesc { position:absolute; left:calc(100% + 8px); width:300px; background:var(--panel);
  border:1px solid var(--line); border-radius:10px; box-shadow:0 8px 26px rgba(0,0,0,.35);
  padding:11px 13px; font-size:var(--fs-sub); line-height:1.65; color:var(--text); z-index:10; }
#slashpop .sdesc[hidden] { display:none; }
#slashpop .sdesc b { font-weight:700; }
#slashpop .sdesc small { display:block; margin-top:6px; color:var(--dim); font-size:var(--fs-lab); }
/* 커넥터 관리 (클로드식 — 사용자 지시 2026-07-22): 행 토글·hover 삭제·추가 폼·OAuth 로그인
   (셀렉터 없는 고아 선언 2줄 제거 2026-08-05 — 07-22 정리 때 남은 죽은 조각, 짝 없는 `}`의 원인) */
.plusmenu .agrow.connadd .agico { color:var(--dim); }
.plusmenu .agrow.connadd:hover .agico, .plusmenu .agrow.connadd:hover .agtxt b { color:var(--accent); }
/* (인라인 커넥터 폼 .agform은 디렉터리 창(/static/connectors.html)으로 이전 — 2026-07-22 삭제) */
.agmsg .msgid .agtag { font-style:normal; font-size:var(--fs-badge); color:var(--accent); border:1px solid var(--accent); border-radius:8px; padding:1px 7px; margin-left:6px; }
.agcard { display:flex; flex-direction:column; gap:7px; border:1px solid var(--line); border-radius:10px; padding:11px 13px; background:var(--panel2); }
.agcard .agbig b { font-size:32px; font-weight:800; letter-spacing:-.01em; }
.agcard .agbig .agvs { font-size:13px; color:var(--dim); margin-left:8px; }
/* 큰 숫자 옆 이름표 — "이 숫자가 무엇인지"를 숫자만큼 또렷하게 (사용자 지시 2026-08-19
   "3.71이 pPER이라는 걸 이해하기 쉽게 크게"). 숫자와 같은 줄, 한 단계 작은 크기. */
.agcard .agbig .aglbl { font-style:normal; font-size:18px; font-weight:700; color:var(--text);
  margin-left:9px; letter-spacing:-.01em; cursor:help; }
.agcard .agbig.pperbig { display:flex; align-items:baseline; flex-wrap:wrap; }
/* pPER 뜻풀이는 **본문색**이다 (사용자 지시 2026-08-19 "회색이 너무 안 보여").
   읽으라고 둔 문장이라 --dim(라이트에서 3.97:1로 본문 기준 미달)을 쓰지 않는다.
   .agvs 기본값보다 뒤에 와야 이긴다 — 챗 위젯의 다른 .agvs는 그대로 회색. */
.agcard .agbig.pperbig .agvs { color:var(--text); }
/* 뜻풀이는 굵게, 괄호 안 원어는 굵기를 빼고 한 톤 물린다 (사용자 지시 2026-08-19) —
   같은 굵기로 붙이면 원어가 문장의 일부처럼 읽힌다. 기울임은 쓰지 않는다(한글과 안 어울린다). */
/* ⚠ font-size를 **반드시** 다시 정한다 — 위의 `.agcard .agbig b { font-size:32px }`가
   .agvs 안의 <b>까지 잡아서, 굵게 하려던 문장이 큰 숫자 크기로 커져 버린다
   (실수 2026-08-19: 사용자가 "볼드로 하랬지 키우랬냐"고 지적한 그 건). */
.agcard .agbig.pperbig .agvs b { font-size:inherit; font-weight:700; }
.agcard .agbig.pperbig .agvs i { font-style:normal; font-weight:400; color:var(--dim2); }
.agcard .agcov { font-size:12.5px; color:var(--text); }
.agcard .agbar { display:flex; height:8px; border-radius:4px; overflow:hidden; background:var(--line); }
.agcard .agbar i { display:block; height:100%; }
.agcard .sA, .agcard .dot.sA { background:var(--accent); }
.agcard .sB, .agcard .dot.sB { background:color-mix(in srgb, var(--accent) 45%, var(--panel2)); }
.agcard .sC, .agcard .dot.sC { background:var(--dim); }
.agcard .sD, .agcard .dot.sD { background:var(--up); }
.agcard .agleg { display:flex; flex-wrap:wrap; gap:5px 14px; font-size:13.5px; color:var(--dim); }
.agcard .agleg .dot { display:inline-block; width:8px; height:8px; border-radius:50%; margin-right:4px; vertical-align:.5px; }
.agcard .agleg b { color:var(--text); font-variant-numeric:tabular-nums; }
.agcard .agwarn { font-size:12.5px; color:var(--up); }
.agcard .agfoot { font-size:var(--fs-sub); color:var(--dim); border-top:1px solid var(--line); padding-top:6px; }
.agcard .agtbl { width:100%; border-collapse:collapse; font-size:var(--fs-tbl); }
.agcard .agtbl th { text-align:left; font-size:var(--fs-th); color:var(--dim); font-weight:600; padding:2px 6px 10px; border-bottom:1px solid var(--line); }
.agcard .agtbl td { padding:4px 6px; }
.agcard .agtbl td.num, .agcard .agtbl th:nth-child(n+2) { text-align:right; font-variant-numeric:tabular-nums; }
.agcard .agtbl td.nm { max-width:130px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.agcard .agtbl tr.ex { opacity:.6; }
.agcard .agtbl .bk { display:inline-block; min-width:16px; text-align:center; font-size:var(--fs-lab); font-weight:700;
  color:#fff; border-radius:5px; padding:1px 4px; }
.agcard .agmorebtn { align-self:flex-start; background:transparent; border:1px solid var(--line); color:var(--dim);
  border-radius:9px; padding:3px 10px; font-size:var(--fs-lab); cursor:pointer; }
.agcard .agmorebtn:hover { color:var(--ai); border-color:var(--ai); }
/* 스킬 4~6호 카드 (2026-07-22): 체크리스트 판정 리스트 · 구간 이중바 · 현금 트리거
   판정색: 양호=--accent · 주의=앰버 · 경고=--up · 측정불가=--dim (의미색 — 원톤 원칙의 예외 허용) */
.agcard .gp { --gd:var(--accent); } .agcard .gw { --gd:#e8a33d; }
.agcard .gf { --gd:var(--up); } .agcard .gn { --gd:var(--dim); }
.agcklist { display:flex; flex-direction:column; gap:6px; }
.agck { display:grid; grid-template-columns:auto auto auto 1fr; align-items:baseline; gap:7px; font-size:var(--fs-sub); }
.agck .ckdot { width:7px; height:7px; border-radius:50%; background:var(--gd); align-self:center; }
.agck .cklb { font-weight:600; color:var(--text); white-space:nowrap; }
.agck .ckgd { color:var(--gd); font-weight:700; font-size:var(--fs-lab); white-space:nowrap; }
.agck .cknote { color:var(--dim); min-width:0; }
.ckbadge { font-size:var(--fs-lab); font-weight:700; color:#fff; background:var(--gd); border-radius:8px;
  padding:1px 8px; margin-left:8px; vertical-align:3px; }
/* 투자 논리 카드 (헌장: 이유의 기억, 2026-07-25) — 종목·이유·되돌릴 조건 */
.agth { display:grid; grid-template-columns:auto auto auto 1fr; align-items:baseline; gap:6px 8px;
  font-size:var(--fs-sub); padding:6px 0; border-bottom:1px solid var(--line); }
.agth:last-child { border-bottom:0; }
.agth .agthq { grid-column:1/-1; color:var(--text); font-size:var(--fs-sub); }
.agth .agthf { grid-column:1/-1; color:var(--dim); font-size:var(--fs-lab); }
.agth .agthd { grid-column:1/-1; color:var(--dim); font-size:var(--fs-lab); }

/* 챗 인라인 연결 카드 (카카오식 원탭 — 사용자 지시 2026-07-25): 필요한 순간 그 자리에서 연결 */
.agconn .msgbody { padding:0; }
/* 높이를 2/3로 (사용자 지시 2026-08-19) — 권유 한 줄이 답변보다 두꺼우면 주객전도다.
   실측 46px → 31px: 카드 패딩 11→6, 버튼 6→3, 글자 12.5→11.5 */
.agconncard { display:flex; align-items:center; gap:8px; background:var(--panel);
  border:1px solid var(--line); border-radius:10px; padding:6px 8px 6px 11px; box-shadow:var(--shadow); }
.agconnico { flex-shrink:0; display:inline-flex; color:var(--accent); }
.agconnico svg { width:14px; height:14px; fill:none; stroke:currentColor; stroke-width:1.8; stroke-linecap:round; stroke-linejoin:round; }
.agconntx { flex:1; min-width:0; font-size:11.5px; color:var(--text);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.agconnbtn { flex-shrink:0; background:var(--accent); color:#fff; border:0; border-radius:8px;
  padding:3px 12px; font:inherit; font-size:11.5px; font-weight:600; cursor:pointer; }
.agconnbtn:hover { opacity:.88; }
/* 끄기 — 거절도 한 번에 되어야 한다. 조용한 회색, 권하는 쪽은 여전히 오른쪽 */
.agconnoff { flex-shrink:0; background:transparent; color:var(--dim); border:0; border-radius:8px;
  padding:3px 9px; font:inherit; font-size:11.5px; cursor:pointer; }
.agconnoff:hover { background:var(--panel2); color:var(--text); }
/* 커넥터 탐색 딥링크 하이라이트 — 어떤 카드를 눌러야 하는지 한눈에 */
.feat.focus { border-color:var(--accent); box-shadow:0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent); }

/* 커넥터 사용 허용 카드 (docs/68) — 클로드 권한 카드 문법 (사용자 레퍼런스 2026-08-22):
   자물쇠+제목 / 회색 상자(요청 대상) / 버튼 3개(프라이머리='한 번만 허용') */
/* 슬림판 (2026-08-23 "너무 두꺼워") → 콤팩트판 (사용자 지시 2026-08-28 "세로 반·가로 30%↓"):
   버튼을 세로 알약 3단에서 가로 한 줄로 — 높이 절반은 배치 전환에서 나온다 */
.jvperm { display:flex; flex-direction:column; gap:5px; margin:8px 0; max-width:300px;
  background:var(--panel); border:1px solid var(--line); border-radius:12px;
  padding:8px 10px; box-shadow:var(--shadow); }
.jvperm .jvpermhd { display:flex; align-items:center; gap:7px; font-size:12px;
  color:var(--text); }
.jvperm .jvpermhd b { font-weight:700; }
.jvperm .jvpermhd svg { width:13px; height:13px; flex-shrink:0; fill:none;
  stroke:currentColor; stroke-width:1.8; stroke-linecap:round; stroke-linejoin:round; }
.jvperm .jvpermhd { line-height:1.25; }
.jvperm .jvpermbox { background:var(--panel2); border-radius:7px; padding:3px 9px;
  font-size:11px; line-height:1.35; color:var(--dim); overflow:hidden;
  text-overflow:ellipsis; white-space:nowrap; }
.jvperm .jvpermrow { display:flex; gap:5px; }
.jvperm button { flex:1 1 auto; border-radius:999px; padding:3px 9px; font:inherit;
  font-size:11.5px; font-weight:650; line-height:1.35; cursor:pointer;
  border:1px solid var(--line); background:var(--panel); color:var(--text);
  white-space:nowrap; }
.jvperm .jvpermrow [data-perm="deny"] { flex:0 0 auto; }
.jvperm button:hover { background:var(--panel2); }
.jvperm button.pri { background:var(--text); color:var(--bg); border-color:transparent; }
.jvperm button.pri:hover { opacity:.85; }
.jvperm button[disabled] { opacity:.5; cursor:default; }

/* PER-ROE 사분면 카드 (스킬 8호, 2026-07-23) — 2×2 그리드 */
.agqgrid { display:grid; grid-template-columns:1fr 1fr; gap:6px; }
.agq { border:1px solid var(--line); border-radius:9px; padding:8px 9px; display:flex;
  flex-direction:column; gap:4px; min-height:64px; }
.agq.good_cheap { border-color:color-mix(in srgb, var(--accent) 40%, var(--line)); }
.agq.risk { border-color:color-mix(in srgb, var(--up) 35%, var(--line)); }
.agqh { font-size:var(--fs-lab); font-weight:700; color:var(--text); display:flex; justify-content:space-between; gap:6px; }
.agqh i { font-style:normal; font-weight:400; color:var(--dim); white-space:nowrap; }
.agqi { font-size:var(--fs-lab); color:var(--dim); }
.agqi b { color:var(--text); font-weight:600; font-variant-numeric:tabular-nums; }
.agqe { font-size:var(--fs-lab); color:var(--dim); opacity:.5; }
.agfrow2 { display:flex; align-items:center; gap:8px; }
.agfrow2 .agflb { flex:0 0 76px; font-size:var(--fs-lab); color:var(--dim); text-align:right; }
.agfrow2 .agbar { flex:1; }

/* [M0-2] 포트폴리오 화면 — 동일비중 바스켓 (docs/46 §7, portfolio.js) — 요약은 agcard 재사용 */
#pfbody { display:flex; flex-direction:column; gap:12px; max-width:860px; }
/* 담기 줄이 화면의 첫 줄이다 (대제목 폐지, 2026-08-29): 왼쪽에 검색, 종목 수·기준일은
   오른쪽 끝으로 민다 — 왼쪽은 "할 일", 오른쪽은 "지금 상태". 위 여백은 대제목이 갖고
   있던 자리를 조금만 물려받는다(26 → 4). */
.pfbar { display:flex; align-items:center; gap:12px; flex-wrap:wrap; margin-top:4px; }
.pfbar .pfcount { margin-left:auto; }
.pfsearchwrap { position:relative; flex:0 1 360px; min-width:240px; }
#pfsearch { width:100%; background:var(--panel2); border:1px solid var(--line); border-radius:10px;
  padding:8px 12px; font-size:13px; color:var(--text); outline:none; transition:border-color .15s ease; }
#pfsearch:focus { border-color:var(--accent); }
#pfsuggest { position:absolute; top:100%; left:0; right:0; margin-top:5px; z-index:12;
  background:var(--panel); border:1px solid var(--line); border-radius:10px; box-shadow:var(--shadow);
  max-height:250px; overflow-y:auto; padding:4px; }
#pfsuggest[hidden] { display:none; }
#pfsuggest .pfsrow { display:flex; align-items:center; gap:8px; padding:7px 9px; border-radius:7px;
  cursor:pointer; font-size:12.5px; color:var(--text); }
#pfsuggest .pfsrow:hover { background:var(--panel2); }
#pfsuggest .pfsrow span { color:var(--dim); font-size:var(--fs-lab); }
#pfsuggest .pfsrow .pfcode { margin-left:auto; font-variant-numeric:tabular-nums; }
#pfsuggest .pfsrow .pfact { color:var(--accent); border:1px solid var(--accent); border-radius:9px; padding:1px 8px; }
#pfsuggest .pfsrow.in { opacity:.55; cursor:default; }
#pfsuggest .pfsrow.in .pfact { color:var(--dim); border-color:var(--line); }
#pfsuggest .pfsrow.none { color:var(--dim); cursor:default; }
/* 씨앗 목록 머리 — stock.js #suggest .sghead와 같은 문법 */
#pfsuggest .pfshead { cursor:default; padding:7px 9px 6px; font-size:11.5px; color:var(--dim);
  border-bottom:1px solid var(--line); letter-spacing:.02em; }
#pfsuggest .pfshead:hover { background:transparent; }
.pfcount { font-size:var(--fs-sub); color:var(--dim); }
.pfsum { max-width:640px; }
.pftblwrap { padding:15px 10px 12px; }
/* 표 **카드 아래**의 빈 자리 (사용자 요청 2026-08-29, 두 번 좁다는 지적 뒤 확정) — 카드
   안쪽 패딩(.pftblwrap)이 아니라 카드가 끝난 뒤 스크롤이 끝나기까지의 여백이다.
   ⚠ **컨테이너 패딩으로 준다**: `.page`가 스크롤 컨테이너(overflow-y:auto)라, 마지막
   자식의 margin-bottom은 스크롤 끝에서 브라우저가 버릴 수 있다(실측: 48px를 줬는데
   화면은 그대로였다). 기본 16 → 160px. */
#view-portfolio { padding-bottom:160px; }
/* 종목명 = 행의 주인공 — 크고 굵게 (사용자 확정 2026-08-03). 업종은 그 아래 조용히. */
.pftbl td .nm a, .pftbl td.nm a { color:var(--text); cursor:pointer; text-decoration:none;
  font-size:13px; font-weight:700; letter-spacing:-.01em; }
.pftbl td.nm a:hover { color:var(--accent); }
.pftbl td.nm small { display:block; font-size:var(--fs-lab); color:var(--dim); margin-top:2px; }
.pftbl td .exwhy { margin-left:6px; font-size:var(--fs-badge); color:var(--dim); }
.pftbl .u { color:var(--up); } .pftbl .d { color:var(--down); }
.pfdel { background:transparent; border:0; color:var(--dim); cursor:pointer; padding:2px;
  display:inline-flex; align-items:center; }
.pfdel:hover { color:var(--up); }
.pfdel svg { width:12px; height:12px; fill:none; stroke:currentColor; stroke-width:2.2; stroke-linecap:round; }
.pfempty { padding:26px 18px; font-size:13px; color:var(--dim); line-height:1.7;
  border:1px dashed var(--line); border-radius:12px; }

/* 산 이유 열 — 기록된 논리 + 서버가 미리 붙인 판정 (docs/46 §4.7, 사용자 지시 "백단에서 해둬라")
   이유가 없는 행이 비어 보이는 것 자체가 기록을 유도하는 장치다. */
.pftbl td.th { max-width:230px; }
/* 시나리오 제목 = 종목명보다 한 단계 작게 (사용자 확정 2026-08-03) — 주인공은 종목명이다 */
.pftbl td.th .thline { display:block; max-width:230px; overflow:hidden; text-overflow:ellipsis;
  white-space:nowrap; font-size:var(--fs-sub); }
.pftbl td.th small { display:block; font-size:var(--fs-lab); color:var(--dim); margin-top:1px; }
.pftbl td.th .vd { display:inline-block; margin-top:3px; font-size:var(--fs-badge); font-weight:700;
  border-radius:7px; padding:1px 7px; border:1px solid var(--vdb, var(--line));
  color:var(--vdc, var(--dim)); background:var(--vdbg, transparent); }
/* 표시 배지 tone 5색 (사용자 확정 2026-08-26) — 어휘·tone은 서버(thesis.display_verdict)가
   정하고 여기는 색만 준다. 테이블 셀·모달 헤더·어디서든 같은 클래스 하나로 통일한다.
   green=논리 유지·긍정 변화 / gray=중립 변화(진회색 — 주황이면 경고처럼 읽힌다는 지적) /
   amber=부정 변화·이상 발생(신호 1건·강한 반증) / red=이상 발생(신호 2건 이상) / na=확인 불가.
   ⚠ 직접 color를 칠하지 않고 **변수(--vdc·--vdb·--vdbg)로 전달**한다 — 소비처 기본 규칙
   (.pftbl td.th .vd 등)의 특이도가 더 높아 직접 칠하면 조용히 진다 (실측 2026-08-26). */
.vd.tgreen { --vdc:var(--accent); --vdb:color-mix(in srgb, var(--accent) 40%, var(--line)); }
.vd.tgray { --vdc:color-mix(in srgb, var(--text) 82%, var(--dim));
  --vdb:color-mix(in srgb, var(--dim) 60%, var(--line));
  --vdbg:color-mix(in srgb, var(--dim) 10%, transparent); }
.vd.tamber { --vdc:#d97706; --vdb:color-mix(in srgb, #d97706 55%, var(--line));
  --vdbg:color-mix(in srgb, #d97706 12%, transparent); }
.vd.tred { --vdc:var(--up); --vdb:color-mix(in srgb, var(--up) 45%, var(--line));
  --vdbg:color-mix(in srgb, var(--up) 10%, transparent); }
.vd.tna { --vdc:var(--dim); }


/* 실계좌형 표 정렬 — **열 번호로 결정론적으로** 고정한다 (사용자 재지시 2026-08-03 "가로 정렬을
   잘하라"). td 클래스에 기대면 셀 하나가 클래스를 빠뜨리는 순간 그 열만 어긋난다.
   12열: 1 종목 · 2 시나리오 = 왼쪽 / 3~9 숫자 = 오른쪽 / 10~12 배지·삭제 = 가운데 */

/* 매매 기록 버튼 — 삭제(×)와 같은 조용한 문법, 색만 액센트 */
.pftbl .pftrd { display:inline-flex; padding:3px; color:var(--dim); background:transparent;
  border:0; border-radius:6px; cursor:pointer; }
.pftbl .pftrd svg { width:13px; height:13px; fill:none; stroke:currentColor; stroke-width:2; stroke-linecap:round; }
.pftbl .pftrd:hover { color:var(--accent); background:var(--panel); }








/* 보유(수량·평단) — **표시가 기본, 편집은 누를 때만** (사용자 재지시 2026-08-03 "너무 복잡해
   보여"). 행마다 입력 박스를 상시로 깔면 표가 양식지가 된다. 애플식 절제: 평소엔 글자 하나,
   손이 닿을 때만 입력이라는 걸 드러낸다. */
.pftbl td.hold { text-align:right; }
.pftbl .pfhold { font:inherit; font-size:var(--fs-tbl); color:var(--text); background:transparent;
  border:0; border-radius:7px; padding:3px 7px; cursor:text; white-space:nowrap;
  transition:background .12s ease, color .12s ease; }
.pftbl .pfhold:hover { background:var(--panel2); }
/* '입력' — **평소엔 조용한 회색, 손이 닿을 때만 청록**이다 (사용자 재지시 2026-08-19).
   늘 청록이면 빈 칸이 표에서 가장 눈에 띄어, 값이 들어 있는 행보다 안 든 행이 더 크게
   읽혔다. 청록은 '지금 누를 수 있다'는 신호로만 남긴다.
   상자·테두리는 없다 — 표에 칸이 두 겹으로 보인다.
   반응하는 것은 **커서가 얹힌 그 칸 하나뿐**: 청록으로 바뀌며 빛이 한 번 훑고 지나간다. */
.pftbl .pfhold.empty { color:color-mix(in srgb, var(--dim) 72%, transparent);
  font-size:var(--fs-tbl); font-weight:400; transition:color .12s, font-weight .12s; }
.pftbl .pfhold.empty:hover { color:var(--accent); font-weight:700;
  animation:pfTwinkle 1.1s ease-in-out infinite; }
@keyframes pfTwinkle {
  0%, 100% { text-shadow:none; filter:none; }
  50%      { text-shadow:0 0 9px color-mix(in srgb, var(--accent) 55%, transparent);
             filter:brightness(1.22); }
}
@media (prefers-reduced-motion: reduce) { .pftbl .pfhold.empty { animation:none !important; } }
/* 편집 — 그 칸에서만 열린다 */
.pfholdin { display:inline-flex; gap:4px; }
.pfholdin input { width:78px; padding:3px 6px; font:inherit; font-size:var(--fs-tbl); text-align:right;
  color:var(--text); background:var(--panel2); border:1px solid var(--accent); border-radius:7px; }
.pfholdin input:focus { outline:none; box-shadow:0 0 0 2px color-mix(in srgb, var(--accent) 22%, transparent); }
.pfholdin input::placeholder { color:color-mix(in srgb, var(--dim) 60%, transparent); font-size:var(--fs-sub); }
/* 매매 기록 팝오버 (plans/008) — 칸은 넷뿐. 복잡하면 안 쓰게 된다(사용자 조건). */
#pftrdov { position:fixed; inset:0; z-index:210; display:flex; align-items:center;
  justify-content:center; padding:24px; background:rgba(0,0,0,.42); }
.pftrdbox { width:min(400px, 100%); padding:16px 18px 14px; background:var(--panel);
  border:1px solid var(--line); border-radius:14px; box-shadow:var(--shadow); }
.pftrdhead { display:flex; align-items:center; margin-bottom:12px; }
.pftrdhead b { font-size:14px; }
.pftrdhead .pfthx { margin-left:auto; }
.pftrdform { display:grid; grid-template-columns:1fr 1fr; gap:8px; }
.pftrdform input { padding:6px 9px; font:inherit; font-size:12.5px; color:var(--text);
  background:var(--panel2); border:1px solid var(--line); border-radius:8px; }
.pftrdform input:focus { outline:none; border-color:var(--accent); }
.pftrdside { display:flex; gap:0; border:1px solid var(--line); border-radius:8px; overflow:hidden; }
.pftrdside button { flex:1; padding:6px 0; font:inherit; font-size:var(--fs-sub); color:var(--dim);
  background:var(--panel2); border:0; cursor:pointer; }
.pftrdside button.on { color:#fff; background:var(--accent); font-weight:700; }
#pftsave { grid-column:1 / -1; padding:7px 0; }
.pftrdmsg { margin-top:8px; font-size:var(--fs-sub); color:var(--up); }
.pftrdlist { margin-top:12px; padding-top:10px; border-top:1px solid var(--line); }
.pftrdrow { display:flex; align-items:center; gap:8px; font-size:var(--fs-sub); padding:3px 0;
  font-variant-numeric:tabular-nums; }
.pftrdrow .d { color:var(--dim); width:38px; }
.pftrdrow .s { width:26px; font-weight:700; }
.pftrdrow .s.b { color:var(--up); } .pftrdrow .s.s2 { color:var(--down); }
.pftrdrow .q { width:56px; text-align:right; }
.pftrdrow .p { width:74px; text-align:right; color:var(--dim2); }
.pftrdrow .w { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
  font-size:var(--fs-lab); color:var(--dim); padding-left:6px; }
.pftrdrow.seed .s { color:var(--dim2); }         /* 시작 보유 줄 — 매매가 아니라 출발점 */
.pftrdform input.wide { grid-column:1 / -1; }
.pftrdrow .x { color:var(--dim); background:transparent; border:0; cursor:pointer; font-size:13px;
  line-height:1; padding:2px 4px; border-radius:5px; }
.pftrdrow .x:hover { color:var(--up); background:var(--panel2); }
.pftrdempty { font-size:var(--fs-sub); color:var(--dim); }
/* 담기 서브창 (2026-08-04) — 매매 기록 서브창과 같은 몸통(.pftrdbox) 재사용.
   답답하지 않게 넉넉히 (사용자 지시 2026-08-04) + 주요 액션 = 주비스 AI(색으로 유도) */
#pfaddov { position:fixed; inset:0; z-index:210; display:flex; align-items:center;
  justify-content:center; padding:24px; background:rgba(0,0,0,.42); }
#pfaddov .pftrdbox { width:min(500px, 100%); padding:24px 26px 20px; }
#pfaddov .pftrdhead b { font-size:16px; }
#pfaddov .pftrdform { gap:10px; }
#pfaddov .pftrdform input { padding:9px 12px; font-size:13px; }
.pfaddcode { margin-left:8px; font-size:var(--fs-sub); color:var(--dim); }
.pfaddguide { margin:0 0 14px; font-size:12.5px; line-height:1.65; color:var(--dim2); }
.pfaddguide span { color:var(--dim); }
.pfaddnote { margin-top:12px; font-size:var(--fs-lab); color:var(--dim); }
.pfthbtn.wide { grid-column:1 / -1; padding:9px 0; font-size:12.5px; }
/* 주요 액션 = 채움 에메랄드 — 시나리오 없는 보유는 반쪽이라는 걸 색이 말한다 */
.pfthbtn.solid { background:var(--accent); border-color:var(--accent); color:#fff; font-weight:700; }
.pfthbtn.solid:hover { background:color-mix(in srgb, var(--accent) 85%, #000); color:#fff; }
.pfthbtn.quiet { border-color:transparent; color:var(--dim2); }
.pfthbtn.quiet:hover { border-color:var(--line); color:var(--text); background:transparent; }
/* 담기 대화의 [추가하기] — 굵게 + 테두리 박스 (사용자 지시 2026-08-14).
   quiet의 투명 테두리를 되돌려 위 버튼과 같은 '눌리는 것'으로 보이게 한다.
   채움색은 주지 않는다 — 권하는 길은 여전히 위쪽(근거 채우기)이다 */
#pfaddgo { font-weight:700; border-color:var(--line); color:var(--text); }
#pfaddgo:hover { border-color:var(--accent); color:var(--accent); }
/* 판정 불가 배지 — 사유는 툴팁에, 표에는 점 하나 (행이 접히지 않게) */
.pftbl .bk.na { color:var(--dim); background:transparent; border:0; cursor:help; font-weight:700;
  width:auto; height:auto; }
/* 장중 현재가 표식 — 값 옆 작은 청록 점 (기술적 분석의 라이브 문법과 동일) */
/* [폐기 2026-08-19] .pftbl .pflive — 가격 옆 장중 표시 초록 점.
   사용자 지시 "가격 옆에 원 없애라". 기준 시점은 표 위 '종가 YYYY-MM-DD'가 말한다. */
/* 입력 유도 한 줄 — 수량이 하나도 없을 때만. 채우면 사라진다 */
.pfhint { display:flex; align-items:center; justify-content:flex-end; gap:10px;
  margin:0 0 6px; font-size:var(--fs-sub); color:var(--dim2); }
.pfhintbtn { margin-left:auto; background:transparent; border:1px solid
  color-mix(in srgb, var(--accent) 50%, var(--line)); color:var(--accent); border-radius:8px;
  padding:3px 10px; font:inherit; font-size:var(--fs-th); cursor:pointer; }
.pfhintbtn:hover { background:color-mix(in srgb, var(--accent) 12%, transparent); }
.pftbl td .num small, .pftbl td.num small { display:block; font-size:var(--fs-sub); }
/* 'AI와 이유 적기' — 한 번 누르면 주비스가 먼저 묻는다(사용자는 명령어를 배울 필요가 없다) */
.pfask { display:inline-flex; align-items:center; gap:5px;
  background:transparent; border:1px dashed var(--line); border-radius:8px; cursor:pointer;
  color:var(--dim); font:inherit; font-size:var(--fs-tbl); padding:4px 11px; }
/* 앞의 반짝 아이콘 = "여기서 주비스가 함께 쓴다"는 표시. 이모지가 아니라 단색 SVG다
   (docs/28 — 이모지 금지). 글자가 회색일 때도 아이콘만은 청록이라 눈이 먼저 걸린다. */
.pfask svg { flex:none; width:16px; height:16px; fill:var(--accent); }
.pfask:hover { color:var(--accent); border-color:var(--accent); border-style:solid; }
/* 한 줄 이유 = 근거 상세로 가는 문 (plans/003) — 클릭 가능함이 보여야 한다 */
.pftbl td.th a.thline { cursor:pointer; text-decoration:none; color:var(--text); }
.pftbl td.th a.thline:hover { color:var(--accent); text-decoration:underline; text-underline-offset:3px; }
/* 챗에서 이유가 저장되면 해당 행이 잠깐 빛난다 — 저장이 화면에 닿았다는 증거 */
@keyframes pfflash { 0% { background:color-mix(in srgb, var(--accent) 22%, transparent); }
  100% { background:transparent; } }
.pftbl tr.pfflash td { animation:pfflash 2.4s ease-out; }

/* ---- 이유 상세 팝오버 (plans/003) — 기록 원문 + 기록 시점 찬반 근거 + 지금 판정 ---- */
/* ⚠ 높이는 100vh가 아니라 **100vh/–-zoom** — body가 transform:scale(1.2)라 body 좌표계의
   가시 높이는 100vh/1.2뿐이다. 100vh로 재면 팝업이 화면 위로 밀려 제목·X가 안 보인다
   (실측 2026-08-26). align-items의 safe는 그래도 넘칠 때 중앙 대신 위부터 붙이는 보험. */
#pfthov { position:fixed; inset:0; z-index:210; display:flex; align-items:safe center;
  justify-content:center; padding:24px; background:rgba(0,0,0,.42); overflow:auto; }
/* 폭 840px (2026-08-26) — 데이터 근거가 기록 vs 현재 비교 테이블 2개로 늘어 720이 좁다 */
.pfthpop { width:min(840px, 100%); max-height:calc(100vh / var(--zoom, 1) - 48px); overflow:auto;
  padding:20px 24px 22px; background:var(--panel); border:1px solid var(--line);
  border-radius:16px; box-shadow:var(--shadow); }
.pfthhead { display:flex; align-items:center; gap:10px; }
.pfthhead > div b { font-size:20px; font-weight:700; letter-spacing:-.01em; }   /* 카드의 주인공 — 크게 (2026-08-26 재지시) */
.pfthhead > div small { display:block; font-size:var(--fs-lab); color:var(--dim); margin-top:1px; }
.pfthhead .vd { flex:none; font-size:var(--fs-lab); font-weight:700; border-radius:7px;
  padding:2px 8px; border:1px solid var(--vdb, var(--line)); color:var(--vdc, var(--dim));
  background:var(--vdbg, transparent); }
/* 색은 공용 tone 클래스(.vd.t*, 산 이유 열 옆 — --vdc 변수 전달)가 준다 */
/* 함께 보기(도킹) 버튼 — X 왼쪽. 도킹 중엔 액센트로 켜져 상태가 보인다 */
.pfthdock { margin-left:auto; display:flex; padding:5px; color:var(--dim); background:transparent;
  border:0; border-radius:7px; cursor:pointer; }
.pfthdock:hover { color:var(--text); background:var(--panel2); }
#pfthov.docked .pfthdock { color:var(--accent); background:color-mix(in srgb, var(--accent) 10%, transparent); }
.pfthdock svg { width:14px; height:14px; fill:none; stroke:currentColor; stroke-width:2; stroke-linecap:round; }
.pfthx { display:flex; padding:5px; color:var(--dim); background:transparent;
  border:0; border-radius:7px; cursor:pointer; }
.pfthx:hover { color:var(--text); background:var(--panel2); }
.pfthx svg { width:14px; height:14px; fill:none; stroke:currentColor; stroke-width:2; stroke-linecap:round; }
/* ① 1행 전폭 — 매수 근거와 핵심 시나리오 (plans/004 사용자 확정 레이아웃)
   첫 줄 = 대표 문장(크게), 아래 = 불릿 추가 설명 (사용자 확정 2026-08-02 "설명과 함께 불릿") */
.pfthr1 { padding-bottom:14px; border-bottom:1px solid var(--line); }
.pfthesis { margin:14px 0 4px; font-size:16px; line-height:1.5; color:var(--text); font-weight:700; }
/* 요약 = 각진 정사각 박스 (사용자 재지시 2026-08-26 "박스 정사각형으로") */
.pfthesis .pfthsumk { display:inline-block; margin-right:10px; padding:5px 7px;
  transform:translateY(-2px); font-size:var(--fs-lab); font-weight:700; line-height:1;
  color:var(--accent); border:1.5px solid color-mix(in srgb, var(--accent) 45%, transparent);
  border-radius:4px; background:color-mix(in srgb, var(--accent) 8%, transparent); }
/* 기록 시점 종가 = 조용한 스트립 — 위의 요약(액센트 박스)과 문법을 겹치지 않는다
   (사용자 재지시 2026-08-26 "요약과 안 어울린다"): 테두리·액센트 없이 panel2 바탕만,
   라벨은 흐리게. 이후 등락(u/d)의 빨강·파랑은 그대로. */
.pfthmeta { display:inline-flex; align-items:baseline; gap:8px; font-size:var(--fs-body);
  color:var(--text); margin-bottom:10px; padding:6px 12px; border-radius:8px;
  border:0; background:var(--panel2); }
.pfthmeta .pfthmk { font-style:normal; font-size:var(--fs-lab); font-weight:600;
  letter-spacing:.02em; color:var(--dim); }
.pfthmeta .pfthmv { font-weight:700; }
.pfthmeta small { font-size:var(--fs-lab); color:var(--dim); }
.pfthmeta .pfthmarr { color:var(--dim); }
.pfthmeta .u { color:var(--up); } .pfthmeta .d { color:var(--down); }
/* 시나리오 불릿 = 핵심 1·2·3 (사용자 지시 2026-08-26) — 점 대신 라벨이 리드.
   본문은 기본 크기(--fs-body)로 — "전반적으로 글자가 너무 작다"가 이 개편의 출발점이다 */
.pfthscnl { list-style:none; margin:0 0 12px; padding:0; }
.pfthscnl li { display:flex; align-items:baseline; gap:9px; padding:3.5px 0;
  font-size:var(--fs-body); line-height:1.65; color:var(--text); }
.pfthscnl .pfthkn { flex:none; font-size:var(--fs-lab); font-weight:700; color:var(--accent);
  letter-spacing:.01em; }
/* 데이터 근거 = 기록 vs 현재 비교 테이블 2개 (사용자 지시 2026-08-26) — 좌 기술적·우 재무적.
   서술형 note는 항목 셀 툴팁(data-tip)으로 접었다 (설명은 툴팁으로, 숫자·판정만 노출). */
.pfthevwrap { margin-top:12px; padding-top:16px; border-top:1px solid var(--line); }
/* 3대 섹션 제목(데이터 근거·매도 신호·투자 근거 추적) = 주비스의 핵심 — 한 급 키우고(16px)
   액센트 바를 그라데이션으로 (사용자 지시 2026-08-26 "부각되도록") */
.pfthevwrap h4 { display:flex; align-items:baseline; gap:8px; font-size:16px; font-weight:700;
  color:var(--text); letter-spacing:-.01em; margin:0 0 10px; }
.pfthevwrap h4::before { content:""; align-self:stretch; width:4px; border-radius:2px;
  background:linear-gradient(180deg, var(--accent), color-mix(in srgb, var(--accent) 35%, transparent)); }
.pfthevhead { display:flex; align-items:center; gap:10px; margin-bottom:8px; }
.pfthevhead h4 { margin:0; }
.pfthevhead .pfthnow { margin-left:auto; padding:3px 10px; font-size:var(--fs-lab); }
.pfthcmpg { display:grid; grid-template-columns:1fr 1.15fr; gap:0 22px; align-items:start; }
.pfthcmpw h5 { margin:0 0 3px; font-size:var(--fs-lab); font-weight:700; color:var(--dim2);
  letter-spacing:.02em; }
.pfthcmp { width:100%; border-collapse:collapse; font-size:var(--fs-body); }
.pfthcmp th { text-align:left; font-size:var(--fs-lab); font-weight:600; color:var(--dim);
  padding:4px 0; border-bottom:1px solid var(--line); white-space:nowrap; }
.pfthcmp th small { font-weight:400; font-size:10.5px; color:var(--dim); }
.pfthcmp td { padding:5.5px 0; color:var(--text);
  border-bottom:1px solid color-mix(in srgb, var(--line) 55%, transparent); }
.pfthcmp tr:last-child td { border-bottom:0; }
.pfthcmp th:nth-child(n+2), .pfthcmp td:nth-child(n+2) { text-align:right; padding-left:10px; }
.pfthcmp td[data-tip] { cursor:help; text-decoration:underline dotted
  color-mix(in srgb, var(--dim) 50%, transparent); text-underline-offset:3px; }
/* 정성 테이블 — 서사 문장이라 좌측 정렬·줄바꿈 허용 (정량은 숫자라 우측 정렬 유지) */
.pfthcmp.qual th:nth-child(n+2), .pfthcmp.qual td:nth-child(n+2) { text-align:left;
  padding-left:12px; }
.pfthcmp.qual td { line-height:1.5; vertical-align:top; }
.pfthcmp.qual td:first-child { font-weight:600; white-space:nowrap; }
/* 기록 대비 화살표 — 등락 빨강·파랑과 혼동 금지: 개선=초록, 악화=주황 */
.pfthcmp .impv, .pfthcmp .wrsn { font-style:normal; font-size:10px; margin-left:4px; }
.pfthcmp .impv { color:var(--accent); }
.pfthcmp .wrsn { color:#d97706; }
.pfthnowskel { display:inline-block; width:44px; height:12px; border-radius:4px; }
/* 2행 반반 — ② 매도 신호 · ③ 점검 */
.pfthgrid { display:grid; grid-template-columns:1fr 1fr; gap:0 18px; }
.pfthsec { margin-top:14px; }
/* 섹션 제목 — 사용자 지시 2026-08-02 "너무 작아 구분 안 됨" → 크게·본문색·좌측 액센트 바 */
.pfthsec h4 { display:flex; align-items:baseline; gap:8px; font-size:16px; font-weight:700;
  color:var(--text); letter-spacing:-.01em; margin:0 0 10px; }
.pfthsec h4::before { content:""; align-self:stretch; width:4px; border-radius:2px;
  background:linear-gradient(180deg, var(--accent), color-mix(in srgb, var(--accent) 35%, transparent)); }
.pfthsec h4 small { font-weight:400; font-size:var(--fs-lab); color:var(--dim); margin-left:2px; }
.pfthsec ul { list-style:none; margin:0; padding:0; }
.pfthsec li { display:flex; align-items:baseline; gap:7px; font-size:var(--fs-body); padding:3.5px 0; }
.pfthsec li small { color:var(--dim); font-size:var(--fs-lab); }
.pfthquiet { font-size:var(--fs-sub); color:var(--dim); padding:3px 0; }
.pfthchk { border-left:1px solid var(--line); padding-left:18px; }
.pfthnext { display:block; margin-top:6px; font-size:var(--fs-lab); color:var(--dim); }
.pfthacts { display:flex; flex-wrap:wrap; gap:6px; margin-top:10px; }
/* ③ 투자 근거 추적 (plans/005) — 우측 상단 업데이트 시각 + 요약/레퍼런스 박스 */
.pfthtrkhead { display:flex; align-items:baseline; gap:8px; }
.pfthtrkhead h4 { flex:1; min-width:0; }
.pfthupat { flex:none; font-size:var(--fs-lab); color:var(--dim); }
.pfthtrkl { margin-bottom:6px; }
.pfthtrkl .edot { background:color-mix(in srgb, var(--accent) 55%, var(--line)); top:4px; }
.pfthupd { margin-top:8px; padding:8px 10px; border:1px solid var(--line); border-radius:10px;
  background:var(--panel2); }
.pfthupd p { margin:0 0 6px; font-size:var(--fs-body); line-height:1.6; color:var(--text); }
.pfthrefs { display:flex; flex-direction:column; gap:3px; padding-top:6px;
  border-top:1px dashed var(--line); }
.pfthrefs a { font-size:var(--fs-lab); color:var(--dim2); text-decoration:none; overflow:hidden;
  text-overflow:ellipsis; white-space:nowrap; }
.pfthrefs a::before { content:"↗ "; color:var(--accent); }
.pfthrefs a:hover { color:var(--accent); text-decoration:underline; text-underline-offset:3px; }
.pfthrefs .refnew { display:inline-block; margin-right:5px; padding:0 4px; font-size:9px;
  font-weight:800; letter-spacing:.04em; color:var(--accent); border:1px solid
  color-mix(in srgb, var(--accent) 50%, var(--line)); border-radius:5px; }
.pfthupd.nochange p { color:var(--dim2); }
.pfthbtn.busy { opacity:.65; cursor:progress; }
/* [AI 업데이트] 진행 단계 — 서버가 기록한 실단계, 마지막 줄만 시머 (ChatGPT식 소스 표기) */
@keyframes pfupshim { 0% { opacity:.45; } 50% { opacity:1; } 100% { opacity:.45; } }
.pfupsteps { margin-top:8px; padding:8px 10px; border:1px solid var(--line); border-radius:10px;
  background:var(--panel2); }
.pfupsteps div { position:relative; padding:2.5px 0 2.5px 16px; font-size:var(--fs-sub);
  line-height:1.5; color:var(--dim2); }
.pfupsteps div::before { content:""; position:absolute; left:2px; top:10px; width:6px; height:6px;
  border-radius:50%; background:var(--accent); }
.pfupsteps div.ok::before { background:color-mix(in srgb, var(--accent) 45%, var(--line)); }
.pfupsteps div.on { color:var(--text); animation:pfupshim 1.2s ease-in-out infinite; }
/* 3개 항 아래 **구분된** 푸터 바 (사용자 확정 "분명히 구분지으란거다") */
.pfthfootbar { display:flex; justify-content:flex-end; gap:8px; margin-top:16px;
  padding-top:14px; border-top:1px solid var(--line); }
.edot, .fdot { flex:none; width:6px; height:6px; border-radius:50%; background:var(--dim);
  position:relative; top:-2px; }
.edot.eok { background:var(--accent); }
.edot.ewarn { background:#d97706; }   /* 주의 = 호박 단일 톤 — .sgwarn과 통일 (C6 델타 리뷰 3) */
.edot.ebad { background:var(--up); }
/* 매도 신호등 (2026-08-02) — 점 크기는 근거 점과 동일, 색으로만 구분 (사용자 지시).
   순항=에메랄드 / 주의=호박 / 발동=빨강 / 직접 확인=점선 회색(기계 판정 아님을 형태로도 구분) */
.pfthfals li.sg { align-items:flex-start; }
.pfthfals li.sg .fdot { top:5px; }
.pfthfals li.sg > div { min-width:0; }
.pfthfals li.sg > div small { display:block; }
/* 신호 판정어 = 둥근 소형 박스 (사용자 지시 2026-08-26 "중요한 거니까") — 색·볼드는 그대로,
   테두리·바탕을 현재 글자색에서 섞어 만들어 상태별 규칙이 따로 필요 없다 */
/* 배지 모양은 **어디서든 같다** — 매도 신호 목록과 '데이터 근거'의 현재 열이 같은 말을
   하므로 같은 모양이어야 한다 (머신러너님 지시 2026-08-31). 그래서 선택자에서 `.pfthfals`를
   뗀다. 목록 안에서만 필요한 것(오른쪽 끝으로 밀기·안 줄어들기)은 아래 한 줄로 남긴다. */
.sgword { display:inline-block; font-size:var(--fs-badge); font-weight:700;
  padding:2px 8px; border-radius:999px; border:1px solid color-mix(in srgb, currentColor 40%, transparent);
  background:color-mix(in srgb, currentColor 9%, transparent); }
.pfthfals .sgword { margin-left:auto; flex:none; }
/* 색은 상태가 정한다. 조상(.sg) 없이 배지에 직접 붙는 경우도 같은 색을 받는다 */
.sgword.sgok { color:var(--accent); }   .sgword.sgwarn { color:#d97706; }
.sgword.sgfired { color:var(--up); }    .sgword.sgman { color:var(--dim); }
.sg.sgok .fdot { background:var(--accent); }        .sg.sgok .sgword { color:var(--accent); }
.sg.sgwarn .fdot { background:#d97706; }            .sg.sgwarn .sgword { color:#d97706; }
.sg.sgfired .fdot { background:var(--up); }         .sg.sgfired .sgword { color:var(--up); }
.sg.sgman .fdot { background:transparent; border:1.5px dashed var(--dim); width:7px; height:7px; }
.sg.sgman .sgword { color:var(--dim); cursor:help; }
.pfthbtn { background:transparent; border:1px solid var(--line); border-radius:8px; cursor:pointer;
  color:var(--text); font:inherit; font-size:var(--fs-sub); padding:5px 12px; }
.pfthbtn:hover { border-color:var(--accent); color:var(--accent); }
.pfthbtn.acc { border-color:color-mix(in srgb, var(--accent) 55%, var(--line)); color:var(--accent); }
.pfthbtn.acc:hover { background:color-mix(in srgb, var(--accent) 12%, transparent); }
/* 함께 보기 도킹 (사용자 지시 2026-08-26) — 카드를 오른쪽에 붙이고 **배경을 잠그지 않는다**:
   왼쪽에서 챗·화면을 그대로 쓰라고 만든 배치다. 오버레이는 pointer-events:none으로 뚫려
   바깥 클릭 닫기(e.target===ov)도 자연히 꺼진다 — 대화 중 실수 클릭에 카드가 안 사라진다. */
#pfthov.docked { pointer-events:none; background:transparent; justify-content:flex-end;
  padding:12px 12px 12px 0; }
#pfthov.docked .pfthpop { pointer-events:auto; width:min(560px, 48vw);
  max-height:calc(100vh / var(--zoom, 1) - 24px);
  border-color:color-mix(in srgb, var(--accent) 30%, var(--line)); }
#pfthov.docked .pfthcmpg { grid-template-columns:1fr; }   /* 좁아진 폭 — 테이블 세로 적층 */
@media (max-width: 560px) {
  .pfthgrid, .pfthcmpg { grid-template-columns:1fr; }
  .pfthchk { border-left:0; padding-left:0; }
}

/* [M0-2] 포트 프로젝트 폴더 — 클로드 코워크(온라인) 벤치마킹 (사용자 확정 2026-07-22, chat.js)
   프로젝트(폴더) 헤더 + 소속 포트 들여쓰기 + 행 호버 액션(이동·삭제) + 이동 팝오버 */
#newproj { display:flex; align-items:center; justify-content:center; background:transparent;
  border:1px solid var(--line); color:var(--text); border-radius:8px; padding:5px 7px; cursor:pointer;
  transition:border-color .15s ease, color .15s ease; }
#newproj:hover { border-color:var(--accent); color:var(--accent); }
#newproj svg { width:13px; height:13px; fill:none; stroke:currentColor; stroke-width:2; stroke-linecap:round; stroke-linejoin:round; }
.projhead { display:flex; align-items:center; gap:6px; padding:7px 10px; border-radius:8px; cursor:pointer; }
.projhead:hover { background:var(--panel); }
.projhead svg { width:13px; height:13px; fill:none; stroke:var(--accent); stroke-width:1.8; stroke-linecap:round; stroke-linejoin:round; flex-shrink:0; }
.projhead .pjcar { width:11px; height:11px; stroke:var(--dim); transition:transform .15s ease; }
.projhead b { font-size:var(--fs-sub); color:var(--text); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.projhead .pjn { font-style:normal; font-size:var(--fs-lab); color:var(--dim); }
.projhead .pjact { margin-left:auto; display:none; gap:2px; }
.projhead:hover .pjact { display:inline-flex; }
.projhead .pjact button { background:transparent; border:0; color:var(--dim); cursor:pointer; padding:2px; display:inline-flex; }
.projhead .pjact button:hover { color:var(--accent); }
.projhead .pjact button svg { width:11px; height:11px; stroke:currentColor; }
.projhead .pjact .pjdel:hover { color:var(--up); }
.proj .port { margin-left:16px; }
#portlist .port { position:relative; }
#portlist .port .pact { margin-left:auto; display:none; gap:2px; flex-shrink:0; }
#portlist .port:hover .pact { display:inline-flex; }
#portlist .port .pact button { background:transparent; border:0; color:var(--dim); cursor:pointer; padding:2px; display:inline-flex; }
#portlist .port .pact button svg { width:11px; height:11px; fill:none; stroke:currentColor; stroke-width:2; stroke-linecap:round; stroke-linejoin:round; }
#portlist .port .pact .pmv:hover { color:var(--accent); }
#portlist .port .pact .pdel:hover { color:var(--up); }
#portmove { position:absolute; right:8px; top:calc(100% - 4px); z-index:9; min-width:160px;
  background:var(--panel); border:1px solid var(--line); border-radius:8px; box-shadow:var(--shadow); padding:4px; }
#portmove .pmvrow { padding:6px 9px; border-radius:6px; font-size:var(--fs-sub); color:var(--text); cursor:pointer; }
#portmove .pmvrow:hover { background:var(--panel2); }
#portmove .pmvrow.new { color:var(--accent); }

/* [M0-2] 처리 과정 — 클로드 Chat/Cowork 인라인 위젯 문법 (사용자 지시 2026-07-23 v2):
   생각 = 이탤릭 시머 한 줄(무테두리) · 도구/스킬 = 테두리 라운드 칩(아이콘+라벨),
   진행 중 = 스피너 + 시머 텍스트 · 완료 = 차분한 고정 행. 초록 체크리스트 폐기. */
.prsteps { display:flex; flex-direction:column; gap:6px; margin-top:10px; }
.prsteps:empty { display:none; }
.prthink { font-size:var(--fs-sub); font-style:italic; color:var(--dim); padding:0 2px; }
/* 도구 카드 — 클로드 웹 표준 (사용자 확정 2026-07-24): 아이콘+라벨+인자 요약, 클릭=결과 미리보기 */
/* 테두리를 벗긴다 (사용자 지시 2026-08-20 "하나하나 박스로 테두리가 있으니까 조금 답답해").
   상자 대여섯 개가 세로로 쌓이면 내용보다 테두리가 먼저 보인다. 상태 신호는 테두리가
   아니어도 이미 다 있다 — 진행은 스피너, 실패는 호박색 아이콘, 펼침은 배경. */
.prcard { border:1px solid transparent; border-radius:10px; background:transparent; overflow:hidden; }
.prcard .prhead { display:flex; align-items:center; gap:9px; font-size:var(--fs-sub); color:var(--dim); padding:7px 11px; }
.prcard.exp .prhead { cursor:pointer; }
.prcard.exp .prhead:hover { background:var(--panel2); }
.prcard .prhead svg { width:13px; height:13px; fill:none; stroke:currentColor; stroke-width:1.8;
  stroke-linecap:round; stroke-linejoin:round; flex-shrink:0; }
.prcard .prhead b { font-weight:600; color:var(--dim); flex-shrink:0; }
.prcard .prdet { min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
  font-size:var(--fs-lab); color:var(--dim); opacity:.75; }
/* 펼치기 = 행의 손잡이라 **맨 왼쪽**. 못 펴는 행도 같은 폭을 비워 두어 아이콘 줄을 맞춘다.
   접힘 상태는 요약 행(.prsum)과 같은 문법으로 오른쪽을 가리킨다(-90°) — 같은 화면 안에서
   같은 모양이 다른 방향을 가리키면 그 자체가 소음이다. */
/* 스패너(도구)는 획이 길게 이어져 같은 1.8이면 다른 아이콘보다 두꺼워 보인다 — 조금 얇게 */
.prcard .prhead svg.pric-wr { stroke-width:1.5; }
.prcard .prcar { width:12px !important; height:12px !important; flex-shrink:0; opacity:.55;
  transform:rotate(-90deg); transition:transform .15s ease; }
.prcard.open .prcar { transform:rotate(0deg); }
.prcard .prcar.ghost { visibility:hidden; }
.prcard.exp .prhead:hover .prcar { opacity:1; }
.prcard .prbody { border-top:1px solid var(--line); padding:8px 11px; font-size:var(--fs-lab); line-height:1.6;
  color:var(--dim); background:var(--panel2); word-break:break-all; max-height:120px; overflow-y:auto; }
/* 사고 과정 접기 — 껍데기는 .prcard를 그대로 쓰되, 본문은 **읽는 글**이라
   진행 카드의 줄바꿈 강제(break-all)와 높이 제한을 푼다. */
.thcard { margin:2px 0 6px; }
.thcard .prbody { word-break:normal; overflow-wrap:anywhere; max-height:none; }
.thcard .prbody p { margin:0 0 6px; }
.thcard .prbody ul { margin:0; padding-left:16px; }
/* 실행 중 스텝의 테두리 박스는 폐지 (사용자 지시 2026-08-23 "박스 없는 게 좋다") —
   진행 표시는 스피너·상태어가 이미 말한다. 박스까지 치면 허용 카드와 위계가 겹친다. */
.prcard.run { border-color:transparent; }
.prshim { background:linear-gradient(100deg, var(--dim) 35%, var(--text) 50%, var(--dim) 65%);
  background-size:200% 100%; -webkit-background-clip:text; background-clip:text; color:transparent;
  animation:prshim 1.7s linear infinite; }
@keyframes prshim { to { background-position:-200% 0; } }
.prspin { width:12px; height:12px; border:1.6px solid var(--line); border-top-color:var(--dim);
  border-radius:50%; flex-shrink:0; animation:prspin .8s linear infinite; }
@keyframes prspin { to { transform:rotate(360deg); } }
.prsteps.done { margin:0 0 10px; gap:5px; }
.prsteps.done .prcard .prhead { padding:5px 10px; font-size:var(--fs-sub); }
/* 실행 타임라인 (2026-08-08, 사용자 지시 "Claude Cowork처럼") — 진행 중엔 세로 연결선,
   끝나면 요약 한 줄로 접힌다. 카드 규격(.prcard/.prspin)은 그대로 재사용. */
.prsteps { position:relative; }
.prsteps > .prcard, .prlist > .prcard { position:relative; }
.prlist { display:flex; flex-direction:column; gap:6px; margin-top:6px; }
/* display를 준 요소는 hidden 속성이 안 먹는다 — UA의 [hidden]{display:none}을 author 규칙이
   이긴다. 이걸 빠뜨려 "접힌 요약 아래에 카드가 그대로 보이는" 버그가 났다 (2026-08-08 실측). */
.prlist[hidden] { display:none; }
/* 세로 연결선 — 카드 왼쪽 **아이콘 중심**을 지난다. 캐럿이 앞에 오면서 아이콘이
   캐럿(12) + 간격(9)만큼 밀렸다: 11(패딩) + 12 + 9 + 6.5 = 38.5 (실측으로 확인) */
.prsteps:not(.done)::before, .prlist::before {
  content:""; position:absolute; left:39px; top:12px; bottom:12px; width:1px;
  background:var(--line); z-index:0; }
.prsteps:not(.done) > .prcard, .prlist > .prcard { z-index:1; }
.prcard .prmeta { margin-left:auto; font-size:var(--fs-lab); color:var(--dim); opacity:.7;
  white-space:nowrap; flex-shrink:0; }
/* 시간·건수는 **행의 오른쪽 끝**에 붙어 세로로 줄이 맞는다 (사용자 지시 2026-08-20).
   캐럿을 피하려고 두었던 오른쪽 여백은 캐럿이 앞으로 가면서 필요 없어졌다. */
.prcard .prmeta { font-variant-numeric:tabular-nums; }
/* 실패 — 숨기지 않는다. 위젯 톤 팔레트의 경고색을 그대로 쓴다(새 토큰 만들지 않음) */
.prcard.bad { border-color:color-mix(in srgb, #f59e0b 45%, var(--line)); }
.prcard.bad .prhead svg { color:#f59e0b; }
/* 완료 요약 한 줄 */
.prsum { display:flex; align-items:center; gap:7px; cursor:pointer; user-select:none;
  font-size:var(--fs-sub); color:var(--dim); padding:5px 4px; border-radius:8px; }
.prsum:hover { background:var(--panel2); }
.prsum:focus-visible { outline:2px solid var(--accent); outline-offset:1px; }
.prsum .prcar { margin:0; width:12px !important; height:12px !important; opacity:.6;
  transition:transform .15s ease; fill:none; stroke:currentColor; stroke-width:1.8;
  stroke-linecap:round; stroke-linejoin:round; transform:rotate(-90deg); }
.prsum.open .prcar { transform:rotate(0deg); }
/* 되묻기 카드 — 조건이 빠진 정량 요청에서만 (사용자 확정 2026-08-08) */
.prask { margin-top:10px; border:1px solid var(--line); border-radius:12px;
  background:var(--panel); padding:11px 12px; }
/* 첫 0.5초에 뜨는 한 줄 계획 — 도구 카드가 아니라 말. 무엇을 할 건지만 조용히 알린다 */
.prplan { font-size:var(--fs-sub); line-height:1.55; color:var(--dim); padding:1px 2px 3px; }
/* 계획 = 머리(계획 2/4) + 단계 목록. 머리만 진하고 목록은 한 단 흐리게 — 읽는 순서가
   '어디까지 왔나 → 무엇을 하나'다. 단계가 길면 접지 말고 흐르게 둔다(펼치기는 도구 카드의
   문법이고, 계획은 카드가 아니다). */
.prplan b { font-weight:600; color:var(--fg); }
.prplan .prplans { display:block; margin-top:1px; color:var(--dim); opacity:.85; }
/* 쓰는 중인 블록의 그릇 — 상자를 만들지 않는다(display:contents). 있으면 문단 간격이 어긋난다 */
.prtail { display:contents; }
.prask .praskq { font-size:12.5px; color:var(--text); line-height:1.5; margin-bottom:9px; }
/* 주제는 칩, 질문은 문장 — 대시로 잇지 않는다 (docs/28 ⑧, 클로드 문답 카드 문법) */
.prask .praskf { display:inline-block; margin-right:7px; padding:1px 7px; border-radius:6px;
  font-size:var(--fs-lab); font-weight:700; letter-spacing:.02em;
  color:var(--dim); background:var(--panel2); vertical-align:1px; }
.prask .praskt { font-weight:600; }
/* 설명이 있는 보기는 알약이 아니라 세로 목록 — 한 줄 설명이 알약에는 안 들어간다 */
.prask .praskopts.rows { flex-direction:column; gap:5px; }
.prask .praskopts.rows .praskopt { display:grid; grid-template-columns:auto 1fr; gap:2px 8px;
  width:100%; text-align:left; border-radius:9px; padding:8px 11px; align-items:baseline; }
.prask .praskopts.rows .prasklb { font-weight:600; }
.prask .praskopts.rows .prasknt { grid-column:2; font-size:var(--fs-lab); line-height:1.45;
  color:var(--dim); font-weight:400; }
.prask .praskk { grid-row:span 2; width:16px; height:16px; border-radius:5px; flex:none;
  display:grid; place-items:center; font-size:var(--fs-badge); font-weight:700;
  color:var(--dim); background:var(--panel2); align-self:center; }
.prask .praskopts.rows .praskopt.on .praskk,
.prask .praskopts.rows .praskopt.on .prasknt { color:inherit; background:transparent; }
/* 확인·직접 입력은 보기와 섞지 않고 아래 줄로 — 고르는 일과 마무리하는 일은 다르다 */
.prask .praskact { display:flex; align-items:center; gap:6px; margin-top:8px; }
.prask .praskact .go { margin-left:auto; }
/* 답한 카드 — 지우지 않고 굳힌다. 무엇을 물었고 내가 뭘 골랐는지가 답 위에 남는다 */
.prask.done { border-style:dashed; background:transparent; padding-bottom:9px; }
.prask.done .praskq { margin-bottom:7px; }
.prask.done .praskopt { opacity:1; cursor:default; }
.prask.done .praskopts.rows .prasknt { display:none; }
.prask.done .praskk { display:none; }
.prask .praskpick { font-size:var(--fs-sub); font-weight:600; color:var(--accent); }
/* 1/N — 진행 표시. 몇 번째인지·몇 개 남았는지 바로 보이게 (사용자 지시 2026-08-08) */
.prask .praskn { display:inline-block; margin-right:7px; padding:1px 7px; border-radius:999px;
  font-size:var(--fs-lab); font-weight:700; color:var(--accent); background:var(--panel2);
  font-variant-numeric:tabular-nums; }
.prask .praskopts { display:flex; flex-wrap:wrap; gap:6px; }
.prask button.on { background:var(--accent); color:var(--panel); border-color:var(--accent); }
.prask button.go { margin-left:auto; }
.prask button:disabled { opacity:.4; cursor:default; }
.prask .praskin { display:flex; align-items:center; gap:7px; }
/* [직접 입력]을 누르면 **카드 안에서** 받는다 (2026-08-29). 보기 줄은 감추되 고른 칩은
   그대로 둔다 — 다중 선택에서 탈출구가 선택을 지우면 처음부터 다시 골라야 한다.
   ⚠ `hidden` 속성만으로는 안 감춰진다: `[hidden]{display:none}`은 UA 규칙이라
   위 `.praskact{display:flex}`에 특이도로 진다(이 저장소의 상습 지뢰). */
.prask .praskact[hidden] { display:none; }
.prask .praskin.praskfree { margin-top:8px; }
.prask .praskin.praskfree .cancel { color:var(--dim); }
.prask .praskin input { flex:1; min-width:0; font:inherit; font-size:12.5px; padding:6px 10px;
  border-radius:9px; border:1px solid var(--line); background:var(--panel2); color:var(--text); }
.prask .praskin input:focus { outline:none; border-color:var(--accent); }
.prask .prasku { font-size:var(--fs-sub); color:var(--dim); }
.prask button { font:inherit; font-size:var(--fs-sub); padding:6px 12px; border-radius:999px;
  border:1px solid var(--accent); background:transparent; color:var(--accent);
  cursor:pointer; transition:background .15s ease; }
.prask button:hover { background:color-mix(in srgb, var(--accent) 12%, transparent); }
/* 숫자키·Tab으로도 고른다 — 키보드로 왔을 때만 테두리를 보인다 */
.prask button:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }
.prask.done button:hover { background:var(--accent); }   /* 굳은 카드는 hover에 반응하지 않는다 */
.prask button.ghost { border-color:var(--line); color:var(--dim); }
.prask button.ghost:hover { background:var(--panel2); }
@keyframes prpulse { 0%, 100% { opacity:.3; } 50% { opacity:1; } }
@media (prefers-reduced-motion: reduce) {
  .prshim { animation:none; background:none; color:var(--dim); -webkit-text-fill-color:var(--dim); }
  /* 회전만 끄고 '진행 중'은 남긴다 — animation:none이면 멈춘 도넛만 남아 고장으로 읽힌다
     (사용자 지적 2026-08-08). 회전 대신 은은한 명멸: 전정기관을 건드리지 않는 움직임. */
  .prspin { animation:prpulse 1.4s ease-in-out infinite; border-top-color:var(--dim); } }
/* 응답 중단 (클로드식 ■ — 2026-07-23): 진행 중 전송 버튼이 정지로, 중단 흔적은 잔잔하게 */
#chatsend.stop { background:var(--panel2); color:var(--accent); border:1px solid var(--accent); }
#chatsend.stop:hover { background:color-mix(in srgb, var(--accent) 14%, var(--panel2)); }
.prstop { margin-top:8px; font-size:var(--fs-sub); color:var(--dim); }
/* 연결이 끊겨 서버에서 답을 이어받는 중 (2026-08-31) — 실패가 아니라 **기다림**이라는 말이다.
   그래서 경고색을 안 쓴다. 침묵보다 한 줄이 낫고, 빨강보다 회색이 맞다. */
.prdrop { margin-top:8px; font-size:var(--fs-sub); color:var(--dim2); }

/* [포트 v2] 컨텍스트 칩 = 포트 선택기 + 팝오버 (2026-07-25 재설계, chat.js)
   설계: docs/superpowers/specs/2026-07-25-port-layer-context-design.md
   상단 목록(#portzone)을 없애고 입력창 바로 위 칩 하나로 — 말하는 순간 맥락이 보이게. */
/* 칩 2종: #chatctx=화면(자동·읽기 전용, 눈 아이콘) · #chatport=포트 선택기(클릭) */
#chatctx, #chatport { display:inline-flex; align-items:center; gap:5px; max-width:100%;
  background:var(--panel); border:1px solid var(--line); border-radius:9px; padding:3px 8px;
  font-size:var(--fs-lab); color:var(--dim2); transition:border-color .15s ease, color .15s ease; }
  /* --dim2: 칩은 '지금 어디를 보고 어디에 담기나'를 읽는 자리 — 다크에서 --dim은 3.86:1 */
#chatctx[hidden], #chatport[hidden] { display:none; }
#chatctx svg { width:12px; height:12px; fill:none; stroke:currentColor; stroke-width:1.8; flex-shrink:0; }
#chatctx .cxlabel, #chatport .cxlabel { white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
/* 폰에서 칩 알맹이를 줄인다 (머신러너님 지시 2026-08-31 "훨씬 낮게. 경제적으로!").
   칩 줄의 키를 정하는 것은 .cbchips의 min-height가 아니라 이 칩이다 — 하한만 낮추면
   줄은 안 준다(실측: min-height 26px인데 줄은 30.6px). */
@media (pointer:coarse) and (max-width:900px), (max-width:560px) {
  #chatctx, #chatport { padding:2px 7px; border-radius:7px; }
  #chatctx svg, #chatport svg { width:11px; height:11px; }
}
#chatport { cursor:pointer; }
#chatport:hover { border-color:var(--accent); color:var(--text); }
#chatport .cxcar { width:11px; height:11px; fill:none; stroke:currentColor; stroke-width:2;
  stroke-linecap:round; stroke-linejoin:round; flex-shrink:0; opacity:.7; }
/* 유형 아이콘 — 시장=지구본(청록) · 개별 종목=별(하늘) · 심리=하트(보라).
   사이드바 아이콘 계열과 맞춰 한눈에 성격이 읽히게 (사용자 지시 2026-07-25 "작게라도 아이콘으로"). */
#chatport .cxdot { display:inline-flex; flex-shrink:0; color:var(--accent); }
#chatport .cxdot svg, .pti svg { width:12px; height:12px; fill:none; stroke:currentColor;
  stroke-width:1.8; stroke-linecap:round; stroke-linejoin:round; }
#chatport[data-t="stock"] .cxdot { color:var(--mention); }
.pti { display:inline-flex; flex-shrink:0; color:var(--dim); }
.pti.t-stock { color:var(--mention); }   /* 주식포트 = 별(하늘) — 단일 개념 (2026-08-01) */
.portpop .ptsetup { border-top:1px solid var(--line); margin-top:4px; padding-top:9px; }
/* ---------- 인앱 확인창 (사용자 지시 2026-08-05 — 브라우저 기본 confirm 대체) ----------
   제목 / 한 줄 설명 / 우측 정렬 버튼 2개(취소 = 중립, 삭제 = 위험 빨강). 화면 정중앙. */
.jvcfm { position:fixed; inset:0; z-index:200; display:flex; align-items:center; justify-content:center;
  background:rgba(0,0,0,.5); animation:jvcfmin .12s ease-out; }
.jvcfm-box { background:var(--panel2); border:1px solid var(--line); border-radius:14px;
  box-shadow:var(--shadow); padding:20px 22px 16px; width:min(420px, calc(100vw - 48px)); }

/* ── 결제 확인 창 (2026-08-23) ────────────────────────────────────────────
   토스 결제창은 카드번호만 받는다. 무엇을 얼마에 사는지 말하는 것은 가맹점 몫이고
   여기가 그 자리다. `.jvcfm` 오버레이를 그대로 쓰고 상자만 따로 세운다.
   색은 전부 토큰이다 — 라이트/다크 어느 쪽에서도 같은 위계로 읽혀야 한다. */
/* **금액이 앵커다.** 표를 세우지 않고 숫자 하나를 크게 두고 조건은 한 줄로 흘린다 —
   행이 늘수록 눈이 훑을 것이 늘고, 결제 직전에 훑을 것이 많으면 손이 멈춘다.
   행 여섯 줄짜리 요약표를 걷어내고 이 형태로 왔다(사용자 반려 2026-08-23 "높이가 너무 크다"). */
.jvpay { position:relative; background:var(--panel2); border:1px solid var(--line);
  border-radius:16px; box-shadow:var(--shadow); padding:18px 20px 14px;
  width:min(360px, calc(100vw - 40px)); }
.jvpay-h { font-size:var(--fs-sub); font-weight:600; color:var(--dim);
  margin-bottom:12px; padding-right:26px; }
.jvpay-prod { font-size:15px; font-weight:600; color:var(--text); }
/* 통화 기호는 위첨자로 올리고 숫자만 키운다 — 통째로 키우면 기호가 값을 비싸 보이게 한다
   (요금제 카드 jvpcprice와 같은 문법) */
.jvpay-amt { display:flex; align-items:baseline; gap:3px; margin:2px 0 6px; }
.jvpay-amt i { font-style:normal; font-size:16px; font-weight:600; color:var(--text);
  transform:translateY(-5px); }
.jvpay-amt b { font-size:30px; font-weight:700; color:var(--text); letter-spacing:-.5px;
  font-variant-numeric:tabular-nums; line-height:1.1; }
.jvpay-amt span { font-size:var(--fs-sub); color:var(--dim); margin-left:2px; }
/* 결제 조건 한 줄 — 정기결제 사전 고지(개정 전자상거래법)를 여기서 이행한다.
   읽어야 하는 문장이라 --fs-sub 아래로 내리지 않는다(docs/28 마이크로카피 하한선). */
.jvpay-cond { font-size:var(--fs-sub); line-height:1.5; color:var(--dim2);
  padding-bottom:14px; border-bottom:1px solid var(--line); margin-bottom:12px; }
/* 결제수단 — 지금은 카드 하나뿐이라 `.one`이 붙는다. 하나일 때는 **고를 것이 없으므로**
   테두리를 지우고 사실만 적는다. 타일 한 장을 선택된 것처럼 세워 두면 "다른 것도 있나"를
   찾게 되고, 찾을 것이 없으면 그게 빈 카테고리다(토스 심사 체크리스트). */
.jvpay-lab { font-size:var(--fs-lab); color:var(--dim); margin-bottom:6px; }
/* ── 구독 관리 (2026-08-23) ────────────────────────────────────────────────
   요금제 카드 **위**에 둔다. 이미 구독 중인 사람에게 먼저 보여야 하는 건 "무엇을 살까"가
   아니라 "지금 내 구독이 어떤 상태인가"다.
   해지 버튼은 **눈에 띄되 유혹하지 않는다** — 테두리만 두르고 채우지 않는다. 숨기면
   다크패턴이고, 강조하면 해지를 권하는 꼴이라 둘 다 틀렸다. */
.jvsub { background:var(--panel); border:1px solid var(--line); border-radius:12px;
  padding:13px 15px 12px; margin-bottom:14px; }
.jvsub-row { display:flex; align-items:baseline; justify-content:space-between; gap:12px;
  padding:3px 0; font-size:var(--fs-sub); }
.jvsub-row span { color:var(--dim); flex:none; }
.jvsub-row b { color:var(--text); font-weight:600; text-align:right; }
.jvsub-note { margin-top:8px; font-size:var(--fs-lab); line-height:1.5; color:var(--dim2); }
.jvsub-cancel { margin-top:11px; padding:7px 14px; border-radius:999px; cursor:pointer;
  border:1px solid var(--line); background:transparent; font:inherit;
  font-size:var(--fs-sub); color:var(--dim); }
.jvsub-cancel:hover { color:var(--text); border-color:var(--text); }

/* 테스트 모드 배지 — **카드번호를 넣기 직전에 보여야 한다.**
   안 보이면 라이브인 줄 알고 진짜 카드를 넣는 사람이 생긴다. 돈은 안 빠지지만
   카드번호는 넣은 셈이라, 그게 가장 나쁜 종류의 침묵이다.
   경고색(--up)을 쓰지 않는다 — 고장이 아니라 상태이고, 빨강은 늑대소년이 된다. */
.jvtestbadge { margin-bottom:12px; padding:7px 11px; border-radius:9px;
  background:var(--panel); border:1px dashed var(--line);
  font-size:var(--fs-lab); color:var(--dim); text-align:center; }

.jvpay-pm { display:flex; gap:8px; margin-bottom:6px; }
.jvpay-pmi { flex:1; display:flex; align-items:center; justify-content:center; gap:6px;
  padding:9px 8px; font:inherit; font-size:var(--fs-sub); color:var(--dim2);
  background:var(--panel); border:1px solid var(--line); border-radius:9px; cursor:pointer; }
.jvpay-pmi .jvico { width:16px; height:16px; flex:none; }
.jvpay-pmi.on { color:var(--text); border-color:var(--dim2); }
/* 못 고르는 수단 — **회색으로 눕히되 고장으로 보이지 않게.** 취소선이나 자물쇠를 붙이면
   서비스가 망가진 것처럼 읽힌다. 흐리게 두고 사유를 바로 아래 한 줄로 붙인다. */
.jvpay-pmi.off { opacity:.45; cursor:default; }
.jvpay-pmwhy { font-size:var(--fs-lab); color:var(--dim); margin-bottom:12px; }
/* 로그인 유도 — 왜 로그인해야 하는지 한 마디. 벽이 아니라 안내로 읽혀야 한다 */
.jvpay-why { font-size:var(--fs-sub); line-height:1.55; color:var(--dim2); margin-bottom:14px; }
.jvpay-mail { font-size:var(--fs-sub); color:var(--dim); margin-bottom:12px;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.jvpay-mail b { color:var(--text); font-weight:500; }
.jvpay-in { width:100%; padding:7px 10px; font:inherit; font-size:var(--fs-sub);
  color:var(--text); background:var(--panel); border:1px solid var(--line);
  border-radius:8px; margin-bottom:12px; }
.jvpay-in:focus { outline:none; border-color:var(--dim2); }
.jvpay-in.bad { border-color:var(--up); }
/* CTA는 Pro 카드 버튼과 **같은 옷**을 입는다 — 누른 버튼과 이어지는 화면이 달라 보이면 멈칫한다 */
.jvpay-go { width:100%; border:0; border-radius:999px; padding:11px; cursor:pointer;
  font:inherit; font-size:14.5px; font-weight:600; color:#fff;
  background:linear-gradient(96deg, var(--pro-1), var(--pro-2) 52%, var(--pro-3)); }
.jvpay-go:hover { filter:brightness(1.07); transform:translateY(-1px); }
.jvpay-sec { margin-top:9px; text-align:center; font-size:var(--fs-lab); color:var(--dim); }
/* 안내창(info) = 버튼 없이 우측 상단 X (사용자 지시 2026-08-19). 제목이 X와 겹치지 않게
   그 폭만큼만 오른쪽을 비운다. 아래 여백은 버튼 줄이 사라진 만큼 줄인다. */
.jvcfm-box.info { padding-bottom:20px; position:relative; }
.jvcfm-box.info .jvcfm-t { padding-right:26px; }
.jvcfm-x { position:absolute; top:12px; right:12px; width:26px; height:26px; padding:0;
  display:flex; align-items:center; justify-content:center;
  background:transparent; border:0; border-radius:7px; color:var(--dim); cursor:pointer;
  transition:color .15s ease, background .15s ease; }
.jvcfm-x:hover { color:var(--text); background:var(--panel); }
.jvcfm-x svg { width:15px; height:15px; fill:none; stroke:currentColor; stroke-width:2; stroke-linecap:round; }
.jvcfm-t { font-size:15px; font-weight:700; color:var(--text); }
.jvcfm-b { font-size:13.5px; color:var(--dim); margin-top:8px; line-height:1.6; white-space:pre-line; }
.jvcfm-a { display:flex; justify-content:flex-end; gap:8px; margin-top:18px; }
.jvcfm-a button { font:inherit; font-size:13px; font-weight:600; border-radius:9px; padding:7px 16px;
  cursor:pointer; border:1px solid transparent; transition:opacity .15s ease, background-color .15s ease; }
.jvcfm-no { background:var(--panel); border-color:var(--line) !important; color:var(--text); }
.jvcfm-no:hover { background:var(--line); }
.jvcfm-yes { background:var(--accent); color:#fff; }
.jvcfm-yes.danger { background:var(--up); color:#fff; }
.jvcfm-a button:hover { opacity:.88; }
@keyframes jvcfmin { from { opacity:0; } to { opacity:1; } }

.projmodal .pmhead .pti { color:var(--accent); }
.projmodal .pmtype { font-size:var(--fs-lab); color:var(--dim); margin-right:6px; }
.projmodal .pmhead b { margin-left:6px; }
/* 검색 후보 — Enter/↑↓ 선택 하이라이트 */
.portpop .ptr.on { background:color-mix(in srgb, var(--accent) 14%, var(--panel2)); }
.portpop .ptr.in { opacity:.5; cursor:default; }
.portpop { position:absolute; left:12px; right:12px; bottom:100%; margin-bottom:6px; z-index:10;
  background:var(--panel); border:1px solid var(--line); border-radius:10px; box-shadow:var(--shadow);
  max-height:min(430px, 56vh); overflow-y:auto; padding:5px; }
.portpop[hidden] { display:none; }
.portpop .ptsec { padding:7px 9px 4px; font-size:var(--fs-lab); font-weight:700; letter-spacing:.12em; color:var(--dim); }
.portpop .ptstock { padding:0 6px 8px; }
.portpop #ptsearch { width:100%; background:var(--panel2); border:1px solid var(--line); border-radius:8px;
  padding:6px 9px; font-size:var(--fs-sub); color:var(--text); outline:none; }
.portpop #ptsearch:focus { border-color:var(--accent); }
.portpop .ptresults { margin-top:4px; border:1px solid var(--line); border-radius:8px; overflow:hidden; }
.portpop .ptresults[hidden] { display:none; }
.portpop .ptr { display:flex; justify-content:space-between; gap:8px; padding:6px 9px;
  font-size:var(--fs-sub); color:var(--text); cursor:pointer; }
.portpop .ptr:hover { background:var(--panel2); }
.portpop .ptr span { color:var(--dim); font-variant-numeric:tabular-nums; }
.portpop .ptr.none { color:var(--dim); cursor:default; }
.portpop .ptchips { display:flex; flex-wrap:wrap; gap:4px; margin-top:6px; }
.portpop .ptchip { display:inline-flex; align-items:center; gap:4px; font-size:var(--fs-lab); font-weight:600;
  background:color-mix(in srgb, var(--mention) 12%, var(--panel2)); border:1px solid var(--mention);
  color:var(--mention); border-radius:12px; padding:2px 4px 2px 9px; }
.portpop .ptchip button { background:transparent; border:0; color:inherit; cursor:pointer; padding:0;
  display:inline-flex; }
.portpop .ptchip svg { width:10px; height:10px; fill:none; stroke:currentColor; stroke-width:2.4; stroke-linecap:round; }
.portpop .ptempty { font-size:var(--fs-lab); color:var(--dim2); padding:4px 3px; }
.portpop .ptrow { display:flex; align-items:center; gap:8px; padding:7px 9px; border-radius:8px;
  cursor:pointer; font-size:var(--fs-sub); color:var(--text); }
.portpop .ptrow:hover { background:var(--panel2); }
.portpop .ptrow.on { background:var(--panel2); }
.portpop .ptname { flex:1; min-width:0; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.portpop .pttype { font-size:var(--fs-badge); color:var(--dim2); flex-shrink:0; }
.portpop .ptdel { background:transparent; border:0; color:var(--dim); cursor:pointer; padding:2px;
  display:none; flex-shrink:0; }
.portpop .ptrow:hover .ptdel { display:inline-flex; }
.portpop .ptdel:hover { color:var(--up); }
.portpop .ptdel svg { width:11px; height:11px; fill:none; stroke:currentColor; stroke-width:2.2; stroke-linecap:round; }
.portpop .ptnew, .portpop .ptnewproj { color:var(--accent); }
/* 현재 포트 헤더 (2026-07-29) — 무엇을 만지는 중인지부터 보인다. 이름은 여기서 바로 고친다. */
.portpop .pthead { display:flex; align-items:center; gap:8px; padding:9px 9px 7px;
  border-bottom:1px solid var(--line); margin-bottom:3px; }
.portpop .pthname { flex:1; min-width:0; font-size:13px; font-weight:700; color:var(--text);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; cursor:text; }
.portpop span.pthname:hover { text-decoration:underline dotted; text-underline-offset:3px; }
.portpop input.pthname { background:var(--panel2); border:1px solid var(--accent); border-radius:7px;
  padding:3px 7px; font:inherit; font-size:13px; font-weight:700; color:var(--text); outline:none; }
.portpop .pthedit { background:transparent; border:0; color:var(--dim); cursor:pointer; padding:2px;
  display:inline-flex; flex-shrink:0; }
.portpop .pthedit:hover { color:var(--accent); }
.portpop .pthedit svg { width:12px; height:12px; fill:none; stroke:currentColor; stroke-width:1.9;
  stroke-linecap:round; stroke-linejoin:round; }
/* 지침·자료 = 상태가 보이는 카드. 비어 있으면 '무엇을 하는 자리'인지 카드가 스스로 말한다
   (사용자 지적 2026-07-29 "이름·지침·자료" 나열은 뭔지 모르겠다 → 상태 + 행동으로). */
.portpop .ptcards { display:flex; gap:5px; padding:0 6px 4px; }
.portpop .ptcard { flex:1; min-width:0; display:grid; grid-template-columns:auto 1fr;
  grid-template-rows:auto auto; column-gap:6px; align-items:center; text-align:left;
  background:var(--panel2); border:1px solid var(--line); border-radius:9px; padding:7px 9px;
  color:var(--text); cursor:pointer; transition:border-color .15s ease; }
.portpop .ptcard:hover { border-color:var(--accent); }
.portpop .ptcard i { grid-row:1 / span 2; display:inline-flex; color:var(--dim); }
.portpop .ptcard svg { width:15px; height:15px; fill:none; stroke:currentColor; stroke-width:1.7;
  stroke-linecap:round; stroke-linejoin:round; }
.portpop .ptcard b { font-size:var(--fs-sub); font-weight:700; }
.portpop .ptcard span { font-size:var(--fs-lab); color:var(--dim2); white-space:nowrap; overflow:hidden;
  text-overflow:ellipsis; }
.portpop .ptcard.set { border-color:color-mix(in srgb, var(--accent) 45%, var(--line)); }
.portpop .ptcard.set i, .portpop .ptcard.set span { color:var(--accent); }
/* 투자 스타일 카드 (2026-08-04) — 생성 서브창·설정 모달 공용. 클릭 선택, 재클릭 해제 */
.pstyle-grid { display:grid; grid-template-columns:1fr 1fr; gap:7px; margin:2px 0 6px; }
.pstyle-card { display:grid; grid-template-columns:auto 1fr; grid-template-rows:auto auto;
  column-gap:7px; align-items:center; text-align:left; padding:8px 10px;
  background:var(--panel2); border:1px solid var(--line); border-radius:10px;
  color:var(--text); cursor:pointer; transition:border-color .15s ease, background .15s ease; }
.pstyle-card:hover { border-color:var(--accent); }
.pstyle-card i { grid-row:1 / span 2; display:inline-flex; color:var(--dim); }
.pstyle-card svg { width:15px; height:15px; fill:none; stroke:currentColor; stroke-width:1.7;
  stroke-linecap:round; stroke-linejoin:round; }
.pstyle-card b { font-size:var(--fs-sub); font-weight:700; }
.pstyle-card span { font-size:var(--fs-badge); color:var(--dim2); white-space:nowrap; overflow:hidden;
  text-overflow:ellipsis; }
.pstyle-card.on { border-color:var(--accent);
  background:color-mix(in srgb, var(--accent) 9%, var(--panel2)); }
.pstyle-card.on i { color:var(--accent); }
.pstyle-note { font-size:var(--fs-badge); color:var(--dim2); margin:0 0 8px; }
/* 2층 (2026-07-29): 포트(프로젝트) 아래 세션(대화). 들여쓰기 + 작은 점으로 하위임을 보인다 —
   유형 아이콘은 상위 단위의 것이라 대화 행에는 붙이지 않는다(성격은 포트가 정한다). */
.portpop .ptses { padding-left:14px; font-size:var(--fs-sub); color:var(--dim); }
.portpop .ptses.on { color:var(--text); }
.portpop .ptbul { width:5px; height:5px; border-radius:50%; background:currentColor;
  opacity:.45; flex-shrink:0; }
.portpop .ptses.on .ptbul { background:var(--accent); opacity:1; }
.portpop .ptnewses { color:var(--accent); padding-left:14px; font-size:var(--fs-sub); }
/* ===== 그냥 대화 ↔ 프로젝트 (2026-07-29) =====
   기본은 자유(그냥 대화), 프로젝트는 **고르는 사람만** 갖는다. 대비가 있어야 만드는 행위가 특별해진다. */
/* 나가기는 **되돌리는 동작**이라 눈에 띄어야 한다 (사용자 지시 2026-08-20).
   회색 작은 글씨일 때는 포트 안에 있는 사람이 나갈 길을 못 찾았다 — 위험해서 빨간 게
   아니라(데이터는 그대로 남는다) 여기가 **경계를 넘는 자리**라서 색을 준다.

   `--up`(상승)을 빌려 쓰지 않는다 — 데이터 의미색은 이 팔레트와 무관하게 불변이고(§상단 주석),
   섞으면 언젠가 "빨강이 상승인가 경고인가"를 묻게 된다. 경고 전용 색을 따로 둔다. */
.portpop .ptleave { color:var(--alert); border-top:1px solid var(--line); margin-top:4px;
  padding-top:9px; font-size:var(--fs-th); }
.portpop .ptleave .pti { color:var(--alert); }
.portpop .ptleave:hover { color:var(--alert);
  background:color-mix(in srgb, var(--alert) 10%, transparent); }

/* 만들어진 사건을 화면에 남긴다 — 대화창의 생성 카드 */
.pcdone { padding:22px 4px 8px; }
.pcdone .pcdh { display:flex; align-items:center; gap:7px; font-size:var(--fs-sub); font-weight:700;
  letter-spacing:.02em; color:var(--accent); }
.pcdone .pcdh .pti { color:inherit; }
.pcdone .pcdname { margin-top:9px; font-size:20px; font-weight:700; letter-spacing:-.01em;
  color:var(--text); }
.pcdone .pcdmeta { margin-top:4px; font-size:var(--fs-sub); color:var(--dim); }
.pcdone .pcdnote { margin-top:12px; padding-top:12px; border-top:1px solid var(--line);
  font-size:var(--fs-sub); color:var(--dim); line-height:1.65; }
.pcdone .suggest { margin-top:14px; }
.portpop .ptplus { font-style:normal; width:7px; text-align:center; }
.portpop .ptsec small { font-weight:400; letter-spacing:0; margin-left:6px; text-transform:none; }
.portpop .ptdot.t-proj { background:#f59e0b; }              /* 프로젝트 = 앰버 */
.portpop .ptgear { background:transparent; border:0; color:var(--dim); cursor:pointer; padding:2px;
  display:none; flex-shrink:0; }
.portpop .ptrow.proj:hover .ptgear, .portpop .ptrow.proj.on .ptgear { display:inline-flex; }
.portpop .ptgear:hover { color:var(--accent); }
.portpop .ptgear svg { width:12px; height:12px; fill:none; stroke:currentColor; stroke-width:1.9;
  stroke-linecap:round; }

/* 프로젝트 설정 모달 — 지침 + 지식 파일 (2026-07-25) */
.projmodal { position:fixed; inset:0; z-index:120; background:rgba(0,0,0,.45);
  display:flex; align-items:center; justify-content:center; padding:24px; }
.projmodal[hidden] { display:none; }
.projmodal .pmbox { width:min(520px, 100%); max-height:82vh; overflow-y:auto; background:var(--panel);
  border:1px solid var(--line); border-radius:14px; box-shadow:var(--shadow); padding:16px 18px 14px; }
.projmodal .pmhead { display:flex; align-items:center; margin-bottom:4px; }
.projmodal .pmhead b { font-size:15px; flex:1; }
.projmodal .pmx { background:transparent; border:0; color:var(--dim); cursor:pointer; padding:3px; display:inline-flex; }
.projmodal .pmx:hover { color:var(--text); }
.projmodal .pmx svg { width:14px; height:14px; fill:none; stroke:currentColor; stroke-width:2.2; stroke-linecap:round; }
.projmodal .pmsec { margin:14px 0 6px; font-size:var(--fs-lab); font-weight:700; letter-spacing:.12em; color:var(--dim); }
.projmodal .pmlead { margin-top:2px; font-size:var(--fs-sub); color:var(--dim); line-height:1.6; }
.projmodal .pmlead b { color:var(--text); font-weight:700; }
.projmodal .pmname { width:100%; background:var(--panel2); border:1px solid var(--line);
  border-radius:10px; padding:9px 11px; font:inherit; font-size:13.5px; color:var(--text); outline:none; }
.projmodal .pmname:focus { border-color:var(--accent); }
.projmodal .pmghost { background:transparent; border:1px solid var(--line); color:var(--dim);
  border-radius:9px; padding:8px 14px; font-size:12.5px; cursor:pointer; }
.projmodal .pmghost:hover { color:var(--text); border-color:var(--dim); }
/* 주요 버튼 = 살짝 옅은 청록 + **흰 글자** (사용자 2026-08-02 "사람이 보는 거잖아" —
   구 #04231a 잉크는 다크 테마 민트용이라 라이트의 딥 에메랄드 위에선 죽은 색이었다).
   다크 테마는 액센트가 밝은 민트라 흰 글자가 안 읽힘 → 진한 잉크 유지. */
.projmodal .pmgo { background:color-mix(in srgb, var(--accent) 93%, #ffffff); border:0;
  color:#fff; font-weight:700; border-radius:9px; padding:8px 16px; font-size:12.5px;
  cursor:pointer; transition:background-color .15s ease; }
.projmodal .pmgo:hover:not(:disabled) { background:var(--accent); }
body[data-theme="dark"] .projmodal .pmgo { background:var(--accent); color:#04231a; }
body[data-theme="dark"] .projmodal .pmgo:hover:not(:disabled) {
  background:color-mix(in srgb, var(--accent) 86%, #ffffff); }
.projmodal .pmgo:disabled { opacity:.35; cursor:default; }

/* 프로젝트 만들기 (2026-07-29) — "그냥 대화"와 다른 **의도적인 행위**로 보이게:
   이름이 첫 칸이고, 유형은 설명이 붙은 큰 카드 3택이며, 만들기를 누르기 전엔 아무것도 안 생긴다. */
.projmodal .pcname { width:100%; background:var(--panel2); border:1px solid var(--line);
  border-radius:10px; padding:9px 11px; font:inherit; font-size:13.5px; color:var(--text); outline:none; }
.projmodal .pcname:focus { border-color:var(--accent); }
.projmodal .pmcreate .pmhead .pti { color:var(--accent); }
.projmodal .pmcreate .pmhead .pti svg { width:16px; height:16px; }
.projmodal .pctypes { display:flex; gap:6px; }
.projmodal .pctype { flex:1; min-width:0; background:var(--panel2); border:1px solid var(--line);
  border-radius:10px; padding:10px 9px; text-align:left; cursor:pointer; color:var(--text);
  transition:border-color .15s ease, background .15s ease; }
.projmodal .pctype:hover { border-color:var(--accent); }
.projmodal .pctype.on { border-color:var(--accent);
  background:color-mix(in srgb, var(--accent) 10%, var(--panel2)); }
.projmodal .pctype .pti { display:block; margin-bottom:5px; }
.projmodal .pctype .pti svg { width:16px; height:16px; }
.projmodal .pctype b { display:block; font-size:12.5px; font-weight:700; }
.projmodal .pctype span { display:block; margin-top:2px; font-size:var(--fs-lab); color:var(--dim);
  line-height:1.45; }
.projmodal .pcstock[hidden] { display:none; }
.projmodal #pcsearch, .projmodal #pmsearch { width:100%; background:var(--panel2); border:1px solid var(--line);
  border-radius:9px; padding:8px 11px; font:inherit; font-size:12.5px; color:var(--text); outline:none; }
.projmodal #pcsearch:focus, .projmodal #pmsearch:focus { border-color:var(--accent); }
.projmodal .ptresults { margin-top:5px; border:1px solid var(--line); border-radius:9px;
  overflow:hidden; }
.projmodal .ptresults[hidden] { display:none; }
.projmodal .ptr { display:flex; justify-content:space-between; gap:8px; padding:7px 10px;
  font-size:var(--fs-sub); color:var(--text); cursor:pointer; }
.projmodal .ptr:hover, .projmodal .ptr.on { background:var(--panel2); }
.projmodal .ptr span { color:var(--dim); }
.projmodal .ptr.in { opacity:.5; cursor:default; }
.projmodal .ptchips { display:flex; flex-wrap:wrap; gap:5px; margin-top:7px; }
.projmodal .ptchip { display:inline-flex; align-items:center; gap:4px; font-size:var(--fs-sub);
  font-weight:600; background:color-mix(in srgb, var(--mention) 12%, var(--panel2));
  border:1px solid var(--mention); color:var(--mention); border-radius:12px; padding:2px 5px 2px 10px; }
.projmodal .ptchip button { background:transparent; border:0; color:inherit; cursor:pointer;
  padding:0; display:inline-flex; }
.projmodal .ptchip svg { width:10px; height:10px; fill:none; stroke:currentColor; stroke-width:2.4; }
.projmodal .ptempty { font-size:var(--fs-lab); color:var(--dim); }
.projmodal .pmcreate textarea { min-height:64px; }
.projmodal .pmsec small { font-weight:400; letter-spacing:0; margin-left:6px; }
.projmodal textarea { width:100%; min-height:104px; resize:vertical; background:var(--panel2);
  border:1px solid var(--line); border-radius:10px; padding:9px 11px; font:inherit; font-size:12.5px;
  line-height:1.6; color:var(--text); outline:none; }
.projmodal textarea:focus { border-color:var(--accent); }
.projmodal .pmfiles { display:flex; flex-direction:column; gap:4px; }
.projmodal .pmfile { display:flex; align-items:center; gap:8px; padding:6px 10px; font-size:var(--fs-sub);
  background:var(--panel2); border:1px solid var(--line); border-radius:9px; }
.projmodal .pmfn { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.projmodal .pmfm { font-size:var(--fs-lab); color:var(--dim); flex-shrink:0; }
.projmodal .pmfx { background:transparent; border:0; color:var(--dim); cursor:pointer; padding:2px; display:inline-flex; }
.projmodal .pmfx:hover { color:var(--up); }
.projmodal .pmfx svg { width:11px; height:11px; fill:none; stroke:currentColor; stroke-width:2.2; stroke-linecap:round; }
.projmodal .pmup { display:inline-block; margin-top:8px; padding:6px 12px; font-size:var(--fs-sub);
  color:var(--accent); border:1px dashed var(--accent); border-radius:9px; cursor:pointer; }
.projmodal .pmup:hover { background:color-mix(in srgb, var(--accent) 8%, transparent); }
.projmodal .pmbar { display:flex; align-items:center; gap:10px; margin-top:16px; }
.projmodal .pmmsg { flex:1; font-size:var(--fs-sub); color:var(--dim); }
.projmodal .pmsave { background:color-mix(in srgb, var(--accent) 93%, #ffffff); color:#fff;
  border:0; border-radius:9px; padding:7px 16px; font-size:12.5px; cursor:pointer;
  transition:background-color .15s ease; }
.projmodal .pmsave:hover { background:var(--accent); }
body[data-theme="dark"] .projmodal .pmsave { background:var(--accent); color:#04231a; }

/* 좁은 화면: 사이드바=상단 스트립 → 드로어·탭은 좌측 끝에서 전체 덮기 */
@media (max-width: 900px) { #chatpanel { left:0; width:100vw; max-width:100vw; height:auto; } #chattab { left:0; } }
/* ===== M3 종목 분석 · 폰 마감 (머신러너님 지적 2026-08-29, 캡처 5장) =====
   레퍼런스는 클로드 모바일 — 명료하고, 한 화면에 한 가지가 또렷하게.

   ① **머리줄이 짜부라져 제목이 세로로 쪼개졌다** (캡처 2·4 "개행이 엉망").
      실측: `.tctl`(폭 321px) 안에서 버튼들이 51+132+165=348px을 먼저 차지하자 제목
      `.tlabel`이 **15px**로 눌려 "기 술 적 분 석"이 한 글자씩 내려갔다. `.rgseg`는 44px 넘쳤다.
      수급도 같다 — `.pk-wrap`이 17px로 눌려 "수 급 동 향(외 국 인..."이 세로로 흘렀다.
      데스크톱에서는 폭이 남아 한 줄에 들어가므로 이 문법이 옳다. 좁은 화면에서만 **접는다** —
      제목이 제 줄을 갖고, 컨트롤이 다음 줄로 내려간다.
   ② **온도계가 과했다** (캡처 2 "너무 크고 폰트도 이상하고"). 지지·저항 29px, 현재가 35px은
      375px 화면에서 세 칸(102·125·102px)에 밀어 넣기엔 크다. 숫자가 칸을 꽉 채우면
      셋의 관계(지지 ← 현재 → 저항)가 안 읽힌다. 한 단 낮춰 관계가 먼저 보이게 한다.
   ③ **카드에 빈 구멍** (캡처 1 "박스 완성도가 떨어진다"). 그리드가 행 높이를 맞추느라
      종가 카드(190px, KRX+NXT 2단)에 시가총액 카드가 끌려가 아래가 통째로 비었다.
      좁은 화면에서는 내용만큼만 — 줄을 맞추는 것보다 **구멍이 없는 것**이 낫다.
   ④ **햄버거가 본문 위를 떠다녔다** (캡처 2~5, 섹션 제목 위에 ☰가 얹혔다). 헤더는 스크롤에
      밀려 사라지는데 버튼만 `position:fixed`로 남아서다. 헤더를 상단에 붙여 버튼이 늘
      제 집(헤더) 안에 있게 한다 — 클로드·ChatGPT의 모바일 문법이고, 검색도 늘 손에 잡힌다. */
@media (pointer:coarse) and (max-width:900px), (max-width:560px) {
  /* ① 머리줄은 접는다 — 제목 한 줄, 컨트롤 다음 줄 */
  .tctl { flex-wrap:wrap; row-gap:8px; column-gap:6px; }
  .tctl .tlabel { flex:1 0 100%; margin-right:0; }
  .tctl .tfseg { margin-left:0; }
  .tctl .rgseg { margin-left:0; padding-left:0; border-left:0; }   /* 줄이 바뀌면 세로 구분선은 뜻이 없다 */

  /* ①-b **두 줄 = 두 그룹** (머신러너님 지시 2026-08-30 "그룹핑 잘해서 정렬하라").
     접기만 하면 줄은 바뀌어도 폭이 제각각이라 무엇과 무엇이 한 묶음인지 안 읽힌다.
     뜻으로 가르면 둘이다 — **봉의 모양**(캔들·일/주/월/연봉)과 **보는 기간**(연중~5년).
     각 줄 안에서 칸을 균등하게 나눠(`flex:1 1 0`) 세그먼티드 컨트롤처럼 보이게 한다.
     좌우 패딩을 0으로 두는 이유: 균등 분할이 폭을 정하므로 패딩이 남으면 글자가 눌린다. */
  .tctl #candlebtn { flex:0 0 auto; }
  .tctl .tfseg { flex:1 1 0; display:flex; gap:4px; min-width:0; }
  .tctl .rgseg { flex:1 0 100%; display:flex; gap:4px; }
  .tctl .tfseg .ct, .tctl .rgseg .ct { flex:1 1 0; min-width:0; padding-left:0; padding-right:0; text-align:center; }
  .tpanel .ph { flex-wrap:wrap; row-gap:6px; }
  .tpanel .pk-wrap { flex:1 0 100%; }

  /* ② 온도계 — 관계가 먼저, 숫자는 그 다음
     2차 지지·저항 줄(`.trsecond`)은 폰에서 **감춘다** (머신러너님 지시 2026-08-30
     "지지와 저항은 남기고 그 사이 숫자들은 보기 안 좋다. 매물대 등").
     375px에서 네 개의 값과 근거 이름(매물대·피보 50.0%·이평 60일선…)이 두 줄로 흘러
     히어로의 1차 지지↔현재가↔저항 관계를 덮었다. 폰에서 필요한 것은 **한 쌍**이다.
     데스크톱은 폭이 남아 한 줄에 들어가므로 그대로 둔다. */
  .trsecond { display:none; }

  .trhero .num { font-size:21px; }
  .trhero .col.cur .num { font-size:26px; }
  .trhero .lab { letter-spacing:.06em; }

  /* ③ 카드 정렬 — **종가는 2칸, 나머지는 1칸** (머신러너님 지시 2026-08-29 "정렬 깔끔하게").
     종가 카드(.pxwide)만 KRX·NXT 2단이라 홀로 190px이고 나머지는 106px이다. 그대로 두면
     같은 행의 시가총액 아래가 84px 비고(구멍), 높이를 맞추면 카드 안이 빈다. 둘 다 지저분하다.
     격자에서 **두 줄을 차지하게** 하면 답이 하나로 모인다 — 종가는 정확히 다른 카드의 2배가 되고,
     오른쪽 칸은 시가총액·PER이 차례로 채워 빈 곳이 없다. 나머지는 전부 같은 한 칸 높이다. */
  #cards { align-items:stretch; grid-auto-rows:1fr; }   /* 1fr = 모든 행이 가장 큰 행과 같은 높이 */
  /* **두 가격을 가로로** (머신러너님 지시 2026-08-30) — 종가만 KRX·NXT를 세로로 쌓아 홀로 두 배였다.
     나란히 놓으면 한 칸에 들어가고, `grid-auto-rows:1fr`이 **여섯 장을 모두 같은 높이**로 맞춘다.
     ("필요하면 높이를 조금 키워도 좋다, 대신 모두 동일해야 한다")
     칸 안쪽 148px을 둘로 나누면 한쪽 69px이라 숫자를 한 단 줄인다 — 18→15px. 그래도
     "257,000원"이 한 줄에 들어간다. 배지·시각은 보조라 한 단 더 내린다. */
  #cards .card.pxwide .pxwrap { flex-direction:row; gap:10px; align-items:flex-start; }
  #cards .card.pxwide .pxblk { flex:1 1 0; min-width:0; }
  #cards .card.pxwide .pxv { font-size:15px; white-space:nowrap; letter-spacing:-.4px; }
  #cards .card.pxwide .pxd, #cards .card.pxwide .pxt { font-size:11px; white-space:nowrap; }

  /* ③-b 밸류에이션 밴드 머리줄이 겹쳤다 (캡처 2026-08-29 — '선행 Forward PER'와 '현재 실적'
     알약이 제목 "밸류에이션 밴드" 위로 올라탔다). `.fglab`은 제목·부제·토글을 한 줄에 nowrap으로
     두는데, 폰 폭에서는 셋이 들어갈 자리가 없어 서로 겹친다.
     `.tctl`과 같은 처방 — **제목이 제 줄을 갖고 컨트롤은 다음 줄로**. */
  .fglab { flex-wrap:wrap; row-gap:8px; }
  .fglab .fgtit { flex:1 0 100%; }
  .fglab.bandlab .fgtit { text-align:left; }
  .fglab small { flex:0 1 auto; min-width:0; }

  /* ⑥ **대화창이 열리면 앱 햄버거를 감춘다** (머신러너님 지적 2026-08-29 "프롬프트 상단이 깨져").
     폰의 대화 드로어는 화면을 통째로 덮는데(375x812), 햄버거는 `z-index:84`로 그보다 위(80)라
     **헤더 위에 얹혀** 세션 손잡이(#navbtn, 9,8)와 부제(#chatsub, 44,45)를 가렸다.
     드로어가 화면 전부일 때 뒤쪽 앱의 메뉴 버튼은 뜻이 없다 — 드로어에는 제 손잡이가 있다.
     열려 있는 동안만 감춘다. 닫으면 다시 나온다.

     ⚠ [정정 2026-08-30] "뜻이 없다"는 틀렸다 — 머신러너님 지적: 대화창에서 JooVIS를 눌러
     들어온 사람은 **모듈로 갈 길이 하나도 없다**(그 화면의 내비 진입점 0개). 감출 이유였던
     것은 위치(헤더를 덮음)였지 존재가 아니다. 그래서 감추지 않고 **헤더 아래로 내려** 띄운다
     — 아래쪽 별도 블록(파일 끝, '대화창 안의 햄버거')이 자리와 층을 정한다. */

  /* ⑥-b 헤더에 숨 쉴 자리를 준다 — CI·배지가 한 줄, 부제가 다음 줄인데 75px에 눌려 있었다. */
  #chathead { padding-top:12px; padding-bottom:12px; row-gap:2px; }

  /* ⑤ "Enter 전송 · Shift+Enter 줄바꿈" 문구는 폰에서 **거짓말이 된다** — 엔터가 줄바꿈이고
     전송은 버튼이다(chat.js·landing.js의 jvIsPhone 가드). 안내를 지운다.
     `.cbhint`는 이미 900px에서 숨지만 조건이 폭뿐이라, 동작과 같은 조건으로 한 번 더 못 박는다. */
  .lndhint, .cbbar .cbhint { display:none; }
  /* ⑤-b 힌트를 지우면 **전송 버튼이 왼쪽으로 딸려 온다** (머신러너님 지적 2026-08-29 "우측으로
     버튼 이동"). 그 문구가 `margin-left:auto`(랜딩)·`flex:1`(대화창)로 버튼을 오른쪽 끝까지
     밀고 있었기 때문이다 — 문구는 안내이면서 동시에 **여백 역할**을 겸하고 있었다.
     문구를 지웠으니 미는 일을 버튼 자신에게 옮긴다. '+'는 왼쪽, 전송은 오른쪽 끝. */
  #lndsend, #chatsend { margin-left:auto; }

  /* ④ 헤더를 상단에 붙인다 — 햄버거(fixed, top:38)가 늘 이 안에 있게 된다.
     ⚠ `body{overflow-y:auto}`를 함께 걷어야 한다 (실측 2026-08-29: sticky를 걸었는데 안 먹었다).
        `position:sticky`는 **가장 가까운 스크롤 조상** 안에서만 붙는데, body가 `overflow-y:auto`라
        그 조상이 돼 버린다. 그런데 body는 높이가 내용과 같아 **스스로는 절대 스크롤되지 않으므로**
        붙을 일이 영영 없다. 실제로 구르는 것은 루트(html)다(위 `:root{overflow-y:auto}`).
        그러니 body의 overflow는 되돌린다 — 스크롤 주체를 하나로 모아야 sticky가 산다.
        `overflow-x`도 함께 visible로 둔다: 한 축만 visible이면 규격상 다른 축이 auto로 승격돼
        body가 다시 스크롤 컨테이너가 된다. 마퀴의 가로 넘침은 루트의 `overflow-x:hidden`이 막는다. */
  body { overflow:visible; }
  header { position:sticky; top:0; z-index:81; }
}

/* 폰에서 대화창을 **여는 손잡이** — 엄지 자리로 (2026-08-29).
   폰은 드로어가 기본 닫힘이 됐으므로(index.html·chatdock.js) 이 손잡이가 유일한 입구다.
   좌상단(top:44px)은 데스크톱에서 시선이 처음 닿는 자리라 옳지만, 폰에서는 **한 손으로 쥐면
   엄지가 안 닿는 구석**이다. 그래서 우하단 떠 있는 알약으로 바꾼다 — 폰의 공용 문법이고,
   본문 위를 지나가도 가리는 면적이 가장 작다.
   ⚠ 반드시 위 `@media (max-width:900px) { #chattab { left:0 } }` **뒤에** 온다 — 같은 특이도라
   앞에 두면 left가 다시 0으로 덮인다. `left:auto`를 명시하는 것도 그래서다.
   `env(safe-area-inset-*)`: 아이폰 홈 인디케이터·둥근 모서리 아래로 깔리지 않게 (P0-4 선반영).
   세로(column) 배치를 가로로 바꾼다 — 떠 있는 알약은 납작해야 본문을 덜 가린다.
   최소 44x44는 애플·구글 권장 터치 최소치다. */
/* 터치 히트 영역 — **보이는 크기는 하나도 안 바꾼다** (머신러너님 확정 2026-08-29).
   실측: 산업 트렌드 66개 중 50개(76%), 포트폴리오 35개 중 20개(57%)가 44px 미만이었다.
   실제로 키우면 한 화면에 담기는 정보가 줄어드는데, 이 화면들은 밀도가 곧 값어치다.
   그래서 투명한 `::after`를 얹어 **눌리는 범위만** 세로 44px로 넓힌다 — 픽셀은 그대로,
   오탭만 줄어든다. 가로는 글자 폭이 이미 충분해 건드리지 않는다.
   `position:relative`는 기준점을 만들려는 것뿐이고, 이 요소들은 전부 static이라 배치에 영향이 없다.
   `.rgseg`처럼 서로 붙어 있는 버튼은 히트 영역이 겹칠 수 있어 `left/right:0`으로 자기 폭 안에 가둔다. */
@media (pointer:coarse) and (max-width:900px), (max-width:560px) {
  .tctl .ct, .gsel .ct, .rgseg .rgbtn, .lndtry a, .vstabs a, .preset { position:relative; }
  /* 산업 트렌드의 순위 칩 — 이 화면 터치 미달의 **79%가 이것 하나**였다(45/57, 실측 2026-08-30).
     칩 높이 34px·세로 간격 50px이라 히트만 44px로 넓혀도 위아래가 안 겹친다(여유 6px).
     칩은 이미 `position:absolute`라 기준점이 있다 — relative를 새로 걸지 않는다. */
  .tctl .ct::after, .gsel .ct::after, .rgseg .rgbtn::after,
  .lndtry a::after, .vstabs a::after, .preset::after, .inb-chip::after {
    content:""; position:absolute; left:0; right:0; top:50%;
    transform:translateY(-50%); height:44px; }
}

@media (pointer:coarse) and (max-width:900px), (max-width:560px) {
  /* **원**이다 (머신러너님 지시 2026-08-31 "조금만 더 크게 원 모양으로").
     알약이던 것을 정원으로 바꾸고 'AI' 글자를 뺀다 — 글자를 둔 채 원으로 만들면 마스코트와
     글자가 서로를 눌러 둘 다 작아진다. 폰의 떠 있는 버튼은 **한 가지만** 말해야 한다.
     그 한 가지는 마스코트다: 이 제품의 얼굴이고, 글자보다 멀리서 읽힌다(뜻은 aria-label이 진다).
     56px = 애플 권장 44보다 넉넉 — 본문 위를 지나가는 버튼이라 빗나가면 화면이 움직여 버린다. */
  #chattab {
    left:auto; right:calc(14px + env(safe-area-inset-right, 0px));
    top:auto;  bottom:calc(16px + env(safe-area-inset-bottom, 0px));
    flex-direction:row; gap:0; padding:0;
    width:56px; height:56px; min-width:56px; min-height:56px;
    align-items:center; justify-content:center;
    border:1px solid var(--line); border-radius:50%;
    box-shadow:0 2px 8px rgba(0,0,0,.16), 0 8px 22px rgba(0,0,0,.10);
    z-index:81;   /* 본문 위 — 드로어(80)보다 위여야 닫은 뒤 다시 보인다 */
    transition:color .15s ease, border-color .15s ease, background-color .15s ease; }
  /* 'AI' 글자를 되살린다 (머신러너님 지시 2026-08-31 "여기에 AI 문구가 있어야 사람들이
     이걸 눌러서 질문할 것 같아"). 앞서 원으로 바꾸며 뺐던 판단을 뒤집는다 — 마스코트는
     **예쁘지만 무엇을 하는 버튼인지 말해 주지 않는다.** 화면에서 유일하게 떠 있는 버튼이라
     여기서 막히면 대화 자체가 안 열린다. `aria-label`은 스크린리더에만 들린다.
     원은 그대로 두고 **세로로 쌓는다**(마스코트 위, 글자 아래) — 가로로 놓으면 둘이 서로를
     눌러 지름을 키워야 하고, 그러면 본문을 더 가린다. 24 + 1 + 12 = 37px이 56px 원 안에
     위아래 9.5px씩 남기고 앉는다.
     색은 시그니처 청록 — 회색이면 '꺼진 버튼'으로 읽힌다. 마스코트와 함께 눈을 끄는 게 목적이다. */
  #chattab { flex-direction:column; gap:1px; }
  #chattab span { display:block; font-size:var(--fs-lab); font-weight:700;
    letter-spacing:.08em; line-height:1; color:var(--accent); }
  #chattab .ctpet { width:24px; }        /* 글자와 나란히 서도록 30 → 24px */
}

/* 데이터 자동 갱신 토스트 — 스냅샷 재발행 시 1회 알림 (2026-07-29, docs/28 최소주의) */
#jvtoast {
  position:fixed; left:50%; bottom:28px; transform:translate(-50%, 12px);
  background:var(--panel); color:var(--text);
  border:1px solid var(--line); border-left:3px solid var(--accent);
  border-radius:10px; padding:10px 16px; font-size:13px; font-weight:500; line-height:1.4;
  box-shadow:var(--shadow); z-index:9000; opacity:0; pointer-events:none;
  max-width:min(90vw, 460px);
  transition:opacity .28s ease, transform .28s ease;
}
#jvtoast.on { opacity:1; transform:translate(-50%, 0); }
@media (prefers-reduced-motion: reduce) { #jvtoast { transition:opacity .01s; } }

/* ---------- [M5] 시장은 지금 — 밸류 히어로 + 코스피/코스닥 세그먼트 + 2모드 (docs/25 §5, docs/26 M5)
   M2 화면 문법 재사용(.trow2/.tpanel/.tnarr/.tag/.cmphase는 기존 정의 호출만) — 여기는 mn 전용만. */
#mnwrap { display:flex; flex-direction:column; gap:14px; }
#mnhead { display:flex; align-items:center; gap:12px; }
#mnstamp { margin-left:auto; font-size:var(--fs-sub); color:var(--dim); }
.mnbox { background:var(--panel); border:1px solid var(--line); border-radius:10px; }
/* 히어로 = 대형 타이포 앵커 4열: 지수 | 시장 PER | Forward-PER | PBR (M2 .trhero 리듬) */
/* 히어로 = **두 줄짜리 흰 패널** (사용자 지시 2026-08-28 "미국 등 지수를 위에 흰색
   레이어로 두고 폰트를 키우자"). 윗줄은 지수·배수 넷, 아랫줄은 참고 지수(원/달러·나스닥·VIX).
   그전엔 참고 지수가 패널 **밖** 회색 바닥에 12.5px로 깔려 있어, 매일 보는 숫자가
   각주처럼 읽혔다. 격자는 안쪽 `.mnherotop`이 맡는다 — 바깥은 세로로만 쌓는다. */
.mnhero { display:block; padding:18px 20px 15px; }
.mnherotop { display:grid; grid-template-columns:1.25fr 1fr 1fr 1fr; gap:10px; align-items:end; }
.mnh { min-width:0; }
.mnh .mnlab { font-size:var(--fs-sub); font-weight:600; color:var(--dim); letter-spacing:.02em;
  display:flex; align-items:center; gap:6px; }
.mnh .mnnum { font-size:30px; font-weight:700; letter-spacing:-.01em; line-height:1.25;
  font-variant-numeric:tabular-nums; }
.mnh.mnidx .mnnum { font-size:35px; }
.mnh .mnnum.na { font-size:21px; color:var(--dim); font-weight:600; line-height:1.8; }
.mnh .mnsub { font-size:var(--fs-lab); color:var(--dim); margin-top:2px; overflow:hidden;
  text-overflow:ellipsis; white-space:nowrap; }
/* 배수 셀은 부제를 비웠다(설명은 툴팁으로). 빈 줄 높이는 유지해야 지수 셀과 숫자 밑선이 맞는다 */
.mnh .mnsub:empty::before { content:"\00a0"; }
.mnh[title] { cursor:help; }
.mnzone { font-size:var(--fs-badge); font-weight:700; padding:1px 7px; border-radius:8px; line-height:1.5; }
.mnzone.zhi  { color:var(--up);     background:color-mix(in srgb, var(--up) 10%, transparent); }
/* 저평가권 = 초록 (사용자 확정 2026-08-13). 파랑(--down)은 '하락'이라는 뜻이 먼저 읽혀서,
   '싸다'는 판정에는 브랜드 초록이 맞다. 고평가권과 같은 규격이고 색만 다르다. */
.mnzone.zlo  { color:var(--accent); background:color-mix(in srgb, var(--accent) 12%, transparent); }
.mnzone.zmid { color:var(--dim);  background:var(--panel2); }
/* (.mnbasis 제거 2026-08-28 — "KRX 공식 … 일별 재구성"은 히어로 패널 툴팁으로 갔다) */
/* 외부 팩트 미니 스트립 — 티커(흐름)와 역할 구분: 구조·맥락의 한 줄 */
.mnctxrow { display:flex; gap:28px; flex-wrap:wrap; font-size:17px; color:var(--dim); padding:0; }
/* 히어로 안에 들어온 참고 지수 줄 — 위 배수 줄과 옅은 선 하나로만 가른다 */
.mnhero .mnctxrow { margin-top:22px; }
.mnctxrow .mnc b { color:var(--text); font-weight:600; font-variant-numeric:tabular-nums; }
.mnctxrow .mnc i { font-style:normal; font-size:14.5px; }
.mnctxrow .mnc em { font-style:normal; font-size:var(--fs-badge); color:var(--dim); margin-left:4px;
  border:1px solid var(--line); border-radius:6px; padding:0 4px; }
/* 모드 전환 — M5도 2026-08-28에 **그림 있는 탭 문법**으로 옮겼다(사용자 지시, M2와 같은 모양).
   모양은 파일 끝 "모듈 선택 탭" 선택자가 #stockmode와 **함께** 정한다 — 여기엔 배치만 둔다.
   여기서 모양을 다시 쓰면 두 화면이 또 갈린다(2026-08-19에 한 번 갈렸던 자리). */
#mnmode { display:grid; grid-template-columns:1fr 1fr; gap:8px; margin-top:12px; }
#mnmode button { display:flex; align-items:center; justify-content:center; gap:12px;
  text-align:left; padding:13px 15px; }
@media (max-width:900px) { #mnmode { grid-template-columns:1fr; } }
.mnpane { padding:16px 18px 14px; }
#mnchart { height:460px; margin-top:10px; }
#mnrsi { height:210px; }
#mndd { height:250px; }                 /* 위 44px = 보조 지수 스트립 + 아래 낙폭 곡선 (M2 문법) */
#mncandle svg { flex-shrink:0; }
/* 메인 차트 커서 — M2 #techchart 규약 미러: 팬=손바닥 · 박스줌=십자 */
#mnchart:not(.boxzoom) > div { cursor:grab !important; }
#mnchart.grabbing:not(.boxzoom) > div { cursor:grabbing !important; }
#mnchart.boxzoom > div { cursor:crosshair !important; }
/* 딥러닝 차트 분석 — M2 #predrow/#predloading/#deeppanel 자리. 버튼·카드·1×2 패널의
   클래스(predbtn, pl-, dpanel, dp-)는 전역 정의를 그대로 쓴다 — 여기는 컨테이너만.
   ⚠ 이 주석에 별표+슬래시를 쓰지 말 것: 종전 표기 `.pl-*` + `/`가 주석을 조기 종료시켜
   바로 아래 #mnpredrow 규칙이 통째로 무효화됐다(실측 2026-08-14 — CSSOM에서 규칙 소실,
   그래서 M5 딥러닝 버튼만 중앙 정렬이 안 됐다). */
#mnpredrow { display:flex; justify-content:center; margin:18px 0 16px; }
#mnchartwrap { position:relative; }
#mnpredloading { position:absolute; inset:0 0 4px 0; display:flex; align-items:center;
  justify-content:flex-end; padding-right:6%; z-index:5; border-radius:10px;
  background:linear-gradient(90deg, transparent 55%, color-mix(in srgb, var(--radar) 12%, transparent) 100%); }
#mnpredloading[hidden] { display:none; }
#mndeep[hidden] { display:none; }
#mndeep { margin-top:2px; }
/* 재무 그리드 — M2 #fingrid/.fgcell/.fhmeta 문법의 M5 미러 (ID 스코프라 재선언 필요).
   정렬 하드값(2026-08-05 M2 확정): 차트 grid top34/bottom24 + 높이 248 + 셀 바닥정렬 + gap 18 */
#mnfingrid { display:grid; grid-template-columns:1fr 1fr; gap:20px; }
#mnfingrid > .jsect { grid-column:1/-1; }
#mnfingrid > .jsect:first-of-type { margin-top:14px; }
#mnfingrid .fgcell { background:var(--panel); border:1px solid var(--line); border-radius:10px;
  padding:16px 18px 8px; min-width:0; overflow:hidden; display:flex; flex-direction:column; }
#mnfingrid .mnfull { grid-column:1 / -1; padding-bottom:14px; }
#mnfingrid #mneps, #mnfingrid #mnper, #mnfingrid #mnroe, #mnfingrid #mnband {
  height:248px; margin-top:auto; }      /* 바닥선 일치 — 플롯 영역까지 같은 y (M2 규약) */
#mnfingrid .pempty { margin-top:auto; min-height:248px; display:flex; align-items:center; justify-content:center; }
#mnfingrid .fhmeta { display:block; font-size:var(--fs-lab); color:var(--dim); font-variant-numeric:tabular-nums;
  margin-bottom:10px; }
#mnfingrid .fhmeta .dot { margin:0 8px; color:var(--line); }
#mnfingrid .fhmeta .soon { color:var(--accent); font-weight:600; cursor:help; }
#mnfingrid .cgrid { border-bottom:0; padding-top:0; align-content:start; }
#mnfingrid .ci .na { color:var(--dim); font-size:13px; font-weight:600; }
/* 히어로 셀 3열 = 배수 카드 | 재무 점수 바 | 총평 (M2 #finherobox .radarwrap 리듬) */
#mnfinhero .fhrow { display:grid; grid-template-columns:minmax(0,1.05fr) minmax(180px,.62fr) minmax(0,1.15fr);
  gap:22px; align-items:center; }
#mnfinhero .radarlist { align-self:center; }
#mnfinhero #mnsum { min-width:0; }
@media (max-width:1100px) { #mnfinhero .fhrow { grid-template-columns:1fr; gap:14px; } }
/* 밸류에이션 참고 카드 (M5) — 회색 배경 제거 + PER·PBR 좌우 2열 (사용자 지시 2026-08-16).
   심리(M9)에서는 세로로 쌓았지만 여기선 한눈에 견주는 게 낫다. 차트 높이는 M9 규칙을 잇는다. */
#mnvalref { margin-top:0; }   /* 경계 여백은 .jsect가 담당 */
/* 배경·모서리·여백을 위 재무 셀(#mnfingrid .fgcell)과 같게 — 참고가 아니라 본문 카드다
   (사용자 확정 2026-08-19). transparent면 페이지 회색이 비쳐 '회색 카드'로 보인다. */
#mnvalref .snrefcard { background:var(--panel); border-radius:10px; padding:16px 18px; }
/* 좌=PER · 우=PBR (사용자 지시 2026-08-19 "분명하게 구분하자") — 사이에 세로 구분선.
   #disc의 2열 문법과 같은 방식이라 화면 안에서 "이건 두 덩어리다"가 같은 신호로 읽힌다. */
#mnvalref .mnvalgrid { display:grid; grid-template-columns:1fr 1fr; gap:0; align-items:start; margin-top:12px; }
#mnvalref .mnvalcol { min-width:0; }
#mnvalref .mnvalcol + .mnvalcol { border-left:1px solid var(--line); margin-left:22px; padding-left:22px; }
#mnvalref .mnvalh { font-size:15.5px; font-weight:700; color:var(--text);
  letter-spacing:-.01em; margin-bottom:2px; }                      /* 중제목 캐논 */
/* PER·PBR 전광판 (사용자 지시 2026-08-19 "전광판처럼 표기") — 히어로(.mnh)와 같은 문법:
   큰 숫자가 앵커, 판정은 그 옆 한 마디, 기준·선행은 아래 한 줄. 배지는 쓰지 않는다
   (같은 말을 배지와 문장이 두 번 하던 것이 "표현이 별로"의 원인이었다). */
#mnvalref .mnvalboard { display:flex; align-items:baseline; gap:10px; }
/* 숫자는 **검정**이다 (사용자 지시 2026-08-19). 색을 입히면 "18.64"라는 사실까지
   해석처럼 읽힌다 — 사실은 검정, 해석은 배지가 맡는다(docs/28 사실·해석 분리). */
#mnvalref .mnvalnum { font-size:30px; font-weight:700; color:var(--text); letter-spacing:-.01em;
  line-height:1.25; font-variant-numeric:tabular-nums; }
#mnvalref .mnvalnum.na { font-size:21px; color:var(--dim); font-weight:600; }
/* 판정 배지 3단 — 저평가 / 중립 / 고평가. 채우지 않고 **테두리 + 옅은 바탕**으로:
   꽉 찬 색 알약은 숫자보다 먼저 눈에 들어와 주객이 바뀐다. */
#mnvalref .mnvaltag { font-size:var(--fs-sub); font-weight:700; border-radius:999px;
  padding:2.5px 11px; border:1px solid currentColor; white-space:nowrap; cursor:help; }
#mnvalref .mnvaltag.hi { color:var(--up); background:color-mix(in srgb, var(--up) 9%, transparent); }
#mnvalref .mnvaltag.lo { color:var(--down); background:color-mix(in srgb, var(--down) 9%, transparent); }
#mnvalref .mnvaltag.mid { color:var(--dim); background:color-mix(in srgb, var(--dim) 8%, transparent); }
#mnvalref .mnvalsub { font-size:var(--fs-sub); color:var(--dim); margin-top:3px;
  font-variant-numeric:tabular-nums; }
#mnvalref .mnvalsub .fwd { color:var(--ai); font-weight:700; }
#mnvalref .snq { font-size:14px; font-weight:600; cursor:help; }   /* 카드가 던지는 질문 — 근거는 툴팁 (심리 .snq와 같은 크기) */
#mnvalref .mnvalgrid .snchart { height:255px; margin-top:10px; min-width:0; }   /* 6년치를 225px에 눌러 담아 답답했다 */
  /* 심리(M9)의 150px보다 키웠다 (사용자 지시 2026-08-18 "20% 이상") — 2열이라 가로가 절반이라
     세로가 짧으면 선이 눌려 보인다. 특이성(id+class 2)이 M9 규칙을 이긴다. */
@media (max-width:900px) { #mnvalref .mnvalgrid { grid-template-columns:1fr; }
  #mnvalref .mnvalcol + .mnvalcol { border-left:0; margin-left:0; padding-left:0; margin-top:18px;
    border-top:1px solid var(--line); padding-top:18px; } }
@media (max-width:1000px) { #mnfingrid { grid-template-columns:1fr; } }
@media (max-width:1100px) { .mnherotop { grid-template-columns:1fr 1fr; row-gap:16px; } }

/* ============================================================================
   읽는 문장의 하한선 — docs/28 핵심 선언 ⑨ (사용자 확정 2026-08-06)
   "너무 작고 흐릿해서 없는 게 나을 정도야. 보라는 건지 말라는 건지 그런 느낌의 글은
    아예 없는 게 낫다."

   근본 원인: `small`에 전역 크기 규칙이 없어 브라우저 기본값 `smaller`(×0.83)가 먹는다 —
   10.5px 컨테이너 안의 <small> 설명이 **8.8px**로 렌더되고 있었다(전수 조사 2026-08-06).
   여기서 **읽어야 하는 문장만** 12px로 끌어올린다. 라벨·칩·배지·범례·축 눈금은 대상이 아니다
   (그건 '읽는 글'이 아니라 '보는 표식'이라 작아도 된다).
   실효 대비를 떨어뜨리던 opacity 곱도 함께 걷는다 — 흐림은 위계가 아니라 손실이다.
   ⚠ 새 안내 문구를 12px 미만으로 쓰고 싶어지면, 그 문구가 정말 필요한지 먼저 물을 것.
   ============================================================================ */
.projmodal .pmsec small, .portpop .ptsec small,     /* 포트 생성·편집 모달의 섹션 부제 */
.fglab small,                                       /* 차트 라벨 뒤에 붙는 풀이절 */
.pempty small, .sect small,                         /* 빈 상태의 사유·해결책 · 섹션 부제 */
#mempanel .memhead small { font-size:var(--fs-sub); }
.pstyle-note,                                       /* 투자 스타일 카드 아래 안내 */
.portpop .ptempty, .projmodal .ptempty, #chatnav .cnempty,   /* 빈 상태 유도 문장 */
.sndisc, .avdisc,                                   /* 심리·AI vs AI 하단 안내 */
.pl-sub, .scrmore, .pfhint, .slashtip { font-size:var(--fs-body); }
.cmpanel-h .hint, .cmfoot, .hcard-sub { font-size:var(--fs-sub); opacity:1; }

/* ---------- [M4] 산업 트렌드 — WI26 순위·상세 (docs/59 Phase 3, 내부 검증 전용)
   재사용: .cmphase/.skel/.hcard/.soon/.pempty/.emptywatch는 기존 정의 호출만 — 여기는 in 전용. */
#inwrap { max-width: 1060px; }
.inhead { display:flex; align-items:center; gap:10px; margin-bottom:6px; }
.instamp { margin-left:auto; font-size:var(--fs-sub); color:var(--dim); }
.innote { font-size:var(--fs-sub); color:var(--dim); margin-bottom:12px; }
.inqwarn { font-size:var(--fs-sub); color:var(--warn, #b45309); margin-bottom:10px; }
.inrank { border:1px solid var(--line); border-radius:10px; overflow:hidden; }
.inrow { display:grid; grid-template-columns:30px 128px 1fr 84px 210px; align-items:center;
  gap:10px; padding:7px 12px; cursor:pointer; border-bottom:1px solid var(--line);
  transition:background .15s ease-out; }
.inrow:last-child { border-bottom:0; }
.inrow:hover, .inrow.sel { background:var(--hover, rgba(52,211,153,.06)); }
.inrk { font-size:var(--fs-lab); color:var(--dim); text-align:right; font-variant-numeric:tabular-nums; }
.innm { font-size:13px; font-weight:600; word-break:keep-all; }
.inbar { display:flex; height:10px; }
.inbar-l, .inbar-r { flex:1; position:relative; }
.inbar-l i { position:absolute; right:0; top:0; bottom:0; background:var(--down); opacity:.75;
  border-radius:3px 0 0 3px; display:block; }
.inbar-r i { position:absolute; left:0; top:0; bottom:0; background:var(--up); opacity:.75;
  border-radius:0 3px 3px 0; display:block; }
.inbar-l::after { content:""; position:absolute; right:-.5px; top:-2px; bottom:-2px;
  border-right:1px solid var(--line); }
.inval { text-align:right; font-size:12.5px; font-variant-numeric:tabular-nums; }
.inmeta { text-align:right; font-size:var(--fs-sub); color:var(--dim); font-variant-numeric:tabular-nums; }
.inmeta em { font-style:normal; font-size:var(--fs-lab); }
.inup { color:var(--up); } .indn { color:var(--down); }
.inna { color:var(--dim); }
.indet { margin-top:14px; }
.indet-sub { font-size:var(--fs-sub); color:var(--dim); font-weight:400; margin-left:8px; }
.inew { margin-left:8px; font-size:var(--fs-lab); color:var(--dim); }
.intbl { width:100%; border-collapse:collapse; margin-top:10px; font-size:12.5px; }
.intbl th { text-align:right; font-weight:600; color:var(--dim); font-size:var(--fs-th);
  padding:4px 8px; border-bottom:1px solid var(--line); }
.intbl th:first-child { text-align:left; }
.intbl td { padding:5px 8px; border-bottom:1px solid var(--line); }
.intbl .tr-num { text-align:right; font-variant-numeric:tabular-nums; }
.intbl tbody tr { cursor:pointer; transition:background .15s ease-out; }
.intbl tbody tr:hover { background:var(--hover, rgba(52,211,153,.06)); }
.inexc { margin-top:10px; font-size:var(--fs-sub); color:var(--dim); }
@media (max-width:1000px) { .inrow { grid-template-columns:26px 110px 1fr 78px; }
  .inmeta { display:none; } }
/* [M4-P4] 수출 트렌드 블록 */
.intrade { margin-top:12px; padding:10px 12px; border:1px solid var(--line); border-radius:8px; }
.intr-head { font-size:12.5px; font-weight:600; display:flex; align-items:baseline; gap:6px; }
.intr-head small { color:var(--dim); font-weight:400; }
.intr-main { margin-left:auto; font-size:14px; }
.intr-main small { font-size:var(--fs-lab); color:var(--dim); font-weight:400; }
.intr-row { display:flex; align-items:center; gap:12px; margin-top:8px; }
.intr-bars { display:flex; align-items:flex-end; gap:3px; height:38px; }
.intr-bar { display:flex; align-items:flex-end; width:9px; height:100%; }
.intr-bar i { display:block; width:100%; border-radius:2px 2px 0 0; }
.intr-bar i.u { background:var(--up); opacity:.75; }
.intr-bar i.d { background:var(--down); opacity:.75; }
.intr-sub { font-size:var(--fs-sub); color:var(--dim); font-variant-numeric:tabular-nums; }
.intr-cap { margin-top:7px; font-size:var(--fs-lab); color:var(--dim); }
.inexp { font-style:normal; }
/* [M4-R] 순위 역추적 (기술적 산업 트렌드 — 분기→월간→주간, docs/59 §11) */
.inb-cap { font-size:var(--fs-sub); color:var(--dim); margin:2px 0 10px; }
#inbump { position:relative; overflow:hidden; }
.inb-svg { position:absolute; left:0; top:0; }
.inb-ln { fill:none; stroke:var(--line); stroke-width:1.6; opacity:.85; transition:opacity .15s ease-out; }
.inb-stub { stroke-dasharray:3 4; opacity:.45; }
#inbump.focusing .inb-ln:not(.hl) { opacity:.12; }
.inb-ln.hl { stroke:var(--accent); stroke-width:2.4; opacity:1; marker-end:url(#inbArw); }
.inb-arw { fill:var(--accent); }
.inb-rklb { font-size:var(--fs-badge); fill:var(--dim); }
.inb-colh { position:absolute; top:2px; font-size:12.5px; font-weight:700; }
.inb-colh small { color:var(--dim); font-weight:400; margin-left:6px; }
.inb-chip { position:absolute; height:32px; display:flex; align-items:center; gap:7px;
  padding:0 10px; background:var(--panel2, var(--panel)); border:1px solid var(--line);
  border-radius:8px; color:var(--text); font-size:12.5px; cursor:pointer;
  transition:opacity .15s ease-out, border-color .15s ease-out, box-shadow .15s ease-out; }
.inb-chip:hover { box-shadow:var(--shadow); }
#inbump.focusing .inb-chip:not(.hl):not(.sel) { opacity:.35; }
.inb-chip.hl, .inb-chip.sel { border-color:var(--accent); }
.inb-rk { min-width:15px; text-align:right; font-size:var(--fs-lab); color:var(--dim);
  font-variant-numeric:tabular-nums; }
.inb-nm { flex:1; font-weight:600; word-break:keep-all; white-space:nowrap;
  overflow:hidden; text-overflow:ellipsis; text-align:left; }
.inb-rt { font-size:var(--fs-sub); font-variant-numeric:tabular-nums; }
.inb-fade { position:absolute; left:0; right:0; pointer-events:none;
  background:linear-gradient(180deg, transparent, var(--bg)); }
.inb-more { position:absolute; left:50%; transform:translateX(-50%); padding:6px 16px;
  background:var(--panel2, var(--panel)); border:1px solid var(--line); border-radius:999px;
  color:var(--text); font-size:12.5px; cursor:pointer; transition:border-color .15s ease-out; }
.inb-more:hover { border-color:var(--accent); }
#infinhost { display:flex; flex-direction:column; min-height:600px; }
/* [M4-F] 피드백 반영 (2026-08-12): 탭=모드 버튼 문법 · 헤더 슬림 · 흐름 연출 · 상세 카드화 */
/* 탭 = M9 심리 탭(.sntab)과 같은 카드 판형 (사용자 지시 2026-08-19 "두 번째 캡처처럼").
   왼쪽에 일러스트, 곁에 이름. 세그먼트 버튼이 아니라 **고르는 카드**다. */
/* ⚠ 껍데기는 파일 끝 "모듈 선택 탭" 블록이 한 곳에서 쥔다 — 여기는 배치만 */
#intab { display:grid; grid-template-columns:repeat(3, 1fr); gap:6px; margin-bottom:14px; }
/* 부제가 없는 탭이라 **가운데로 모은다** — 왼쪽에 붙이면 이름 오른쪽이 통째로 비어
   버튼이 아니라 빈 칸처럼 보였다 (사용자 지적 2026-08-26 "감각이 없다"). */
#intab button { display:flex; align-items:center; justify-content:center; gap:12px;
  text-align:left; padding:13px 15px; }
.intab-tx { font-size:15.5px; font-weight:800; letter-spacing:-.3px; word-break:keep-all; text-wrap:balance; }
/* 일러스트 — 아이콘 타일이 아니라 그림이다. 배경 없이 선과 면으로만 (docs/28 라인 문법) */
/* 규격은 M2 모드 탭(.smill)과 **공유한다** — 같은 자리에 쓰는 그림이 크기부터 다르면
   두 화면이 남남으로 보인다 (2026-08-21) */
.inill, .smill { width:46px; height:46px; flex:0 0 46px; display:block; }
.inill svg, .smill svg { width:100%; height:100%; }
.inill svg *, .smill svg * { fill:none; stroke-width:2.4; stroke-linejoin:round; stroke-linecap:round; }
/* 안 고른 쪽은 조용히 물러난다 — 셋이 동시에 소리치면 어느 것도 안 읽힌다 */
#intab button:not(.on) .inill { opacity:.55; filter:saturate(.5); }
/* ① 시상대 — 금·은·동은 기존 메달 팔레트를 그대로 쓴다(.inb-medal). 화면에 새 색을 들이지 않는다 */
.inill.tech svg .pod { stroke:none; }
.inill.tech svg .p1 { fill:#d4a015; } .inill.tech svg .p2 { fill:#a4abb7; } .inill.tech svg .p3 { fill:#b1783c; }
.inill.tech svg .pn { fill:#fff; stroke:none; font-size:11px; font-weight:800; text-anchor:middle;
  font-variant-numeric:tabular-nums; }
.inill.tech svg .pbase { stroke:var(--text); stroke-width:2.2; opacity:.45; }
/* ② 궤적 — 꼬리는 옅게, 머리로 갈수록 진하게. 지도의 혜성과 같은 읽기 */
.inill.fin svg .trail { stroke:var(--accent); stroke-width:1.8; opacity:.28; stroke-dasharray:3 4; }
.inill.fin svg .td { fill:var(--accent); stroke:none; }
.inill.fin svg .t1 { opacity:.22; } .inill.fin svg .t2 { opacity:.38; }
.inill.fin svg .t3 { opacity:.56; } .inill.fin svg .t4 { opacity:.74; }
.inill.fin svg .thead { fill:var(--accent); stroke:var(--panel); stroke-width:2; }
/* ③ 컨테이너선 — 선체는 잉크, 짐과 물결만 색을 쓴다 */
.inill.trade svg .hull { fill:var(--text); stroke:none; }
.inill.trade svg .cab { fill:none; stroke:var(--text); stroke-width:2.2; }
.inill.trade svg .box { stroke:none; }
.inill.trade svg .box.a { fill:var(--accent); }
.inill.trade svg .box.b { fill:color-mix(in srgb, var(--accent) 42%, var(--panel)); }
.inill.trade svg .wave { stroke:var(--accent); stroke-width:2.2; opacity:.7; }
.inill.trade svg .wave.w2 { opacity:.35; }
@media (max-width:1000px) { #intab { grid-template-columns:1fr; }
  .inill, .smill { width:40px; height:40px; flex:0 0 40px; } }

/* ── M2 모드 탭 그림 (2026-08-21) ────────────────────────────────────────────
   ① 기술적 = 캔들과 추세. 추세선은 뒤에 옅게 깔고 봉이 앞에 선다 — 값이 주인공이다.
   ② 재무적 = 건물. 창 몇 개만 청록으로 켜 둔다 — 다 켜면 격자가 되고, 안 켜면 빈 상자다. */
.smill.tech svg .axis, .smill.fin svg .axis { stroke:var(--text); stroke-width:2.2; opacity:.4; }
.smill.tech svg .wick { stroke:var(--text); stroke-width:2; opacity:.5; }
.smill.tech svg .cd { stroke:none; }
.smill.tech svg .cd.up { fill:var(--accent); }
.smill.tech svg .cd.dn { fill:color-mix(in srgb, var(--accent) 34%, var(--panel)); }
.smill.tech svg .tline { stroke:var(--accent); stroke-width:1.8; opacity:.3; stroke-dasharray:3 4; }
.smill.fin svg .blk { stroke:var(--text); stroke-width:2.2; }
.smill.fin svg .win { stroke:none; fill:color-mix(in srgb, var(--accent) 34%, var(--panel)); }
.smill.fin svg .win.on { fill:var(--accent); }
#stockmode button:not(.on) .smill, #mnmode button:not(.on) .smill,
#pfmode button:not(.on) .smill { opacity:.55; filter:saturate(.5); }

/* ── M1 포트폴리오 대표 모듈 탭 (사용자 지시 2026-08-29 "우리 스타일로") ──────────
   껍데기·상호작용은 파일 끝 "모듈 선택 탭" 블록이 쥔다(#pfmode 합류) — 여기는 배치와 그림.
   그림 2장, AI 느낌 대신 (사용자 지시):
     ① AI 포트폴리오 = **파이(비중) + 보유 막대**. 포트란 결국 무엇을 얼마씩 들고 있느냐다.
     ② AI 포트폴리오 평가 = **빨간펜 채점** (사용자 확정 2026-08-29 "α·β 말고 채점 느낌
        직관적이게") — 답안지 위 채점 동그라미와 체크. 빨강은 팔레트의 상승색(--up)만 쓴다. */
#pfmode { display:grid; grid-template-columns:1fr 1fr; gap:8px; margin:4px 0 2px; }
#pfmode button { display:flex; align-items:center; justify-content:center; gap:12px;
  text-align:left; padding:13px 15px; }
@media (max-width:900px) { #pfmode { grid-template-columns:1fr; } }
.smill.pfport svg .ring { stroke:var(--text); stroke-width:2.2; }
.smill.pfport svg .slice { stroke:none; fill:var(--accent); }
.smill.pfport svg .hold { stroke:none; fill:color-mix(in srgb, var(--accent) 34%, var(--panel)); }
.smill.pfport svg .hold.on { fill:var(--accent); }
.smill.pfport svg .axis, .smill.pfabil svg .axis { stroke:var(--text); stroke-width:2.2; opacity:.4; }
.smill.pfabil svg .sheet { stroke:var(--text); stroke-width:2.2; }
.smill.pfabil svg .ln { stroke:var(--text); stroke-width:2; opacity:.35; }
/* 색연필 채점 (사용자 확정 2026-08-29): 정원·직선 대신 손이 지나간 획 — 비뚤한 타원이
   시작점을 덮으며 끝나고(진짜 채점 동그라미의 겹침), 체크는 살짝 휜다. 옆에 어긋난
   옅은 획(.mark2)을 한 벌 깔아 색연필이 두 번 지나간 결을 낸다. */
.smill.pfabil svg .mark { stroke:var(--up); stroke-width:2.6; opacity:.92; }
.smill.pfabil svg .mark2 { stroke:var(--up); stroke-width:1.7; opacity:.32; }
.inb-lead { font-size:15.5px; color:var(--text); font-weight:700; letter-spacing:-.01em; margin:2px 0 12px; display:flex; align-items:baseline; }
.inb-lead .instamp { margin-left:auto; font-weight:400; font-size:var(--fs-sub); letter-spacing:0; }
/* 흐름 연출: 짚은 산업의 경로가 분기→주간으로 그라데이션과 함께 흐른다 (화살표 마커 폐기) */
.inb-ln.hl { stroke:url(#inbGrad); stroke-width:2.6; stroke-linecap:round; opacity:1;
  stroke-dasharray:7 9; animation:inbflow .95s linear infinite; marker-end:none; }
@keyframes inbflow { to { stroke-dashoffset:-16; } }
@media (prefers-reduced-motion: reduce) { .inb-ln.hl { animation:none; stroke-dasharray:none; } }
/* 산업 화면에선 상단 종목 검색·최근 칩 숨김 (F4 — 산업 단위 화면에 종목 검색은 소음) */
body[data-view="industry"] header,
body[data-view="compare"] header, body[data-view="screen"] header { display:none; }
/* 상세: 대표 ETF 스트립 + 얇은 가로선 + 종목 카드형 행 */
.inetf-row { display:flex; align-items:center; gap:8px; margin:10px 0 0; flex-wrap:wrap; }
.inetf-lb { font-size:var(--fs-lab); color:var(--dim); letter-spacing:.4px; }
.inetf { display:inline-flex; align-items:baseline; gap:6px; padding:5px 12px;
  background:var(--panel2, var(--panel)); border:1px solid var(--line); border-radius:999px;
  font-size:12.5px; font-weight:600; }
.inetf small { font-size:var(--fs-lab); color:var(--dim); font-weight:400; font-variant-numeric:tabular-nums; }
.indiv { border:0; border-top:1px solid var(--line); margin:12px 0 4px; }
.inlist { display:flex; flex-direction:column; }
.inrow2 { display:grid; grid-template-columns:26px 1fr 90px 86px 86px 86px; gap:10px;
  align-items:center; padding:9px 10px; border-radius:10px; cursor:pointer;
  transition:background .15s ease-out; }
.inrow2:hover { background:var(--hover, rgba(52,211,153,.06)); }
.inrow2 + .inrow2 { border-top:1px solid color-mix(in srgb, var(--line) 55%, transparent); }
.inr-rk { font-size:var(--fs-lab); color:var(--dim); text-align:right; font-variant-numeric:tabular-nums; }
.inr-nm { font-size:13px; font-weight:600; position:relative; padding-bottom:6px; min-width:0; }
.inr-nm small { color:var(--dim); font-weight:400; font-size:var(--fs-lab); margin-left:8px; }
.inr-wbar { position:absolute; left:0; bottom:0; width:120px; height:3px; border-radius:2px;
  background:color-mix(in srgb, var(--line) 60%, transparent); display:block; }
.inr-wbar b { display:block; height:100%; border-radius:2px; background:var(--accent); opacity:.7; }
.inr-px { text-align:right; font-size:12.5px; font-variant-numeric:tabular-nums; }
.inpill { display:flex; flex-direction:column; align-items:flex-end; gap:1px;
  font-size:12.5px; font-variant-numeric:tabular-nums; }
.inpill small { font-size:var(--fs-badge); color:var(--dim); }
.inr-more { position:static; transform:none; margin:10px auto 2px; display:block; }
@media (max-width:1000px) { .inrow2 { grid-template-columns:22px 1fr 80px 80px; }
  .inpill:nth-of-type(5), .inpill:nth-of-type(6) { display:none; } }
/* [M4-G] 여백·흐름 화살촉·상세 v2 (사용자 지시 2026-08-12) */
#intab { margin-bottom:16px; }
.inb-lead { display:block; margin:4px 0 18px; }            /* flex가 공백을 삼키던 버그 동시 해결 */
.inb-lead:has(+ .inb-note) { margin-bottom:6px; }          /* 풀이가 붙는 탭만 붙여 놓는다 */
.inb-note { font-size:var(--fs-body); line-height:1.8; color:var(--text); margin:0 0 18px; max-width:78ch; }
.inb-note b { font-weight:700; }
.inb-lead .instamp { float:right; }
.inb-lead::after { content:""; display:block; clear:both; }
.inb-chip { height:34px; }
.inb-arwm path { fill:color-mix(in srgb, var(--dim) 55%, transparent); }
.inb-arwm.stub path { fill:color-mix(in srgb, var(--dim) 40%, transparent); }
.inb-arwm.hl path { fill:var(--accent); }
#inbump.focusing .inb-arwm:not(.hl) { opacity:.15; }
.inb-stub { stroke-dasharray:2 4; opacity:.4; }
.inb-rklb { font-size:var(--fs-lab); }
.inb-rklb-r { text-anchor:end; }
/* 상세 v2 — 컬럼 헤더 + ETF 데이터행 + 스파크 */
.indet-sub { font-size:13px; }
.indet .hcard-meta { font-size:13.5px; }
.inlhead, .inrow2 { display:grid;
  grid-template-columns:34px minmax(0,1fr) 108px 92px 74px 74px 74px 74px; gap:10px; align-items:center; }
.inlhead { padding:14px 12px 8px; font-size:var(--fs-sub); color:var(--dim); }
.inlhead span { text-align:right; }
.inlhead span:nth-child(1), .inlhead span:nth-child(2), .inlhead span:nth-child(3) { text-align:left; }
.inrow2 { padding:11px 12px; }
.inr-num { text-align:right; font-size:12.5px; font-variant-numeric:tabular-nums; }
.inr-flow { display:flex; align-items:center; }
.inspark { width:96px; height:26px; color:var(--dim); }
.inspark polyline { fill:none; stroke:currentColor; stroke-width:1.6; opacity:.85; }
.inr-etf { font-size:var(--fs-badge); font-weight:700; color:#fff; background:#3b82f6;
  border-radius:6px; padding:3px 6px; text-align:center; }  /* 파란 박스 배지 (사용자 2026-08-12) */
.inrow2.etf { cursor:default; }
.inrow2.etf:hover { background:transparent; }
.indiv { margin:6px 0; }
@media (max-width:1100px) { .inlhead, .inrow2 { grid-template-columns:30px minmax(0,1fr) 92px 74px 74px 74px; }
  .inlhead span:nth-child(3), .inr-flow { display:none; }
  .inlhead span:nth-child(8), .inrow2 .inr-num:nth-of-type(4) { display:none; } }
/* [M4-H] 진정: 기본은 조용한 연결선만 — 화살촉·접힘 가늠(N위)·스텁은 짚은 산업에만
   (사용자 2026-08-12 "너무 복잡해" — 상시 장식 전면 철회, 호버·선택 시에만 흐름 연출) */
.inb-ln { opacity:.55; }
.inb-arwm, .inb-stub, .inb-rklb { opacity:0; transition:opacity .15s ease-out; }
.inb-arwm.hl { opacity:1; }
.inb-stub.hl { opacity:.8; }
.inb-rklb.hl { opacity:1; }
#inbump.focusing .inb-arwm:not(.hl) { opacity:0; }
/* [M4-I] 종목 행 v3 (사용자 지시 2026-08-12): 시총·비중 최우측 · 분기 다이버징 바(좌청우적) ·
   분기 스파크 부호색+fill 그라데이션 · 세부업종(WICS 소분류) 라벨 */
.inlhead, .inrow2 { grid-template-columns:30px minmax(0,1fr) 102px 84px 66px 66px 66px 66px 104px; gap:8px; }
.inlhead span:last-child { text-align:right; }
.inr-cap { text-align:right; font-size:12.5px; font-variant-numeric:tabular-nums; }
.inr-cap small { display:block; font-size:var(--fs-lab); color:var(--dim); }
.inr-sub { color:var(--dim); font-weight:400; font-size:var(--fs-lab); margin-left:7px; }
.inr-nm small.inr-sub { margin-left:7px; }
.inr-nm { padding-bottom:8px; }
.inr-dbar { position:absolute; left:0; bottom:0; width:150px; height:3px; border-radius:2px;
  background:color-mix(in srgb, var(--line) 55%, transparent); display:block; }
.inr-dbar::after { content:""; position:absolute; left:50%; top:-2px; bottom:-2px; width:1px;
  background:var(--line); }
.inr-dbar b { position:absolute; top:0; height:100%; border-radius:2px; display:block; opacity:.85; }
.inr-dbar b.u { left:50%; background:var(--up); }
.inr-dbar b.d { right:50%; background:var(--down); }
.inspark.u { color:var(--up); }
.inspark.d { color:var(--down); }
.inspark polyline { opacity:1; stroke-width:1.5; }
@media (max-width:1100px) { .inlhead, .inrow2 { grid-template-columns:28px minmax(0,1fr) 84px 66px 66px 66px 96px; }
  .inlhead span:nth-child(3), .inr-flow { display:none; }
  .inlhead span:nth-child(7), .inrow2 .inr-num:nth-of-type(3) { display:none; } }
/* [M4-J] 역추적 열 머리 — 중앙 정렬 + 폰트 확대 (사용자 지시 2026-08-12) */
.inb-colh { text-align:center; font-size:17px; }   /* 주간·월간·분기 확대 (사용자 2026-08-12 최종) */
.inb-colh small { display:block; font-size:var(--fs-lab); margin-left:0; margin-top:3px; }
/* [M4-K] 수출입 산업 트렌드 탭 (docs/59 §12) — hero 2열(.rsum 재사용) + 산업 카드 5 */
#intrhero { display:grid; grid-template-columns:minmax(0,1.9fr) minmax(280px,1fr); gap:14px;
  margin-bottom:16px; align-items:stretch; }
.intr-chartcard { padding:12px 14px; }
#intrchart { height:340px; }
#intrstory .rsum-text { font-size:13.5px; line-height:1.8; }
#intrcards { display:grid; grid-template-columns:repeat(auto-fit, minmax(230px, 1fr)); gap:12px;
  margin-bottom:10px; }
.intr-card { padding:12px 14px; cursor:pointer; transition:border-color .15s ease-out; }
.intr-card:hover { border-color:var(--accent); }
.intr-ch { font-size:13.5px; font-weight:700; display:flex; align-items:baseline; gap:6px; }
.intr-ch small { color:var(--dim); font-weight:400; font-size:var(--fs-lab); }
.intr-cy { margin-left:auto; font-size:14px; font-variant-numeric:tabular-nums; }
.intr-mini { height:120px; margin:8px 0 4px; }
.intr-cf { font-size:var(--fs-sub); color:var(--dim); display:flex; gap:4px; align-items:baseline;
  font-variant-numeric:tabular-nums; }
.intr-cm { margin-left:auto; font-size:var(--fs-lab); }
@media (max-width:1100px) { #intrhero { grid-template-columns:1fr; } }

/* ---- 설정 › 기억 (2026-08-12) — 목록·삭제·끄기. 토글은 커넥터의 .agsw 재사용 ---- */
.pfmemhead { display:flex; align-items:flex-start; gap:14px; margin:0 0 12px; }
.pfmemhead .agsw { margin-top:3px; cursor:pointer; }
.pfmemsub { font-size:var(--fs-body); line-height:1.6; color:var(--dim); word-break:keep-all; }
.pfmemlist { display:flex; flex-direction:column; gap:6px; }
.pfmemi { position:relative; padding:9px 30px 9px 11px; border:1px solid var(--line);
  border-radius:9px; background:var(--panel2); }
.pfmemb { display:flex; align-items:center; gap:7px; margin:0 0 3px; }
.pfmemk { font-size:var(--fs-lab); font-weight:700; letter-spacing:.02em; color:var(--accent); }
.pfmemd { font-size:var(--fs-lab); color:var(--dim); }
.pfmemt { font-size:12.5px; line-height:1.55; word-break:keep-all; }
.pfmemx { position:absolute; top:7px; right:7px; width:20px; height:20px; display:flex;
  align-items:center; justify-content:center; border:0; border-radius:6px; padding:0;
  background:transparent; color:var(--dim); cursor:pointer; opacity:0; transition:opacity .12s ease; }
.pfmemi:hover .pfmemx, .pfmemx:focus-visible { opacity:1; }
.pfmemx:hover { background:var(--panel); color:var(--down); }
.pfmemempty { padding:16px 12px; text-align:center; font-size:var(--fs-sub); color:var(--dim);
  border:1px dashed var(--line); border-radius:9px; }
.pfmemfoot { display:flex; align-items:center; justify-content:space-between; gap:10px;
  margin-top:12px; }
.pfmemclr { background:transparent; border:1px solid var(--line); border-radius:7px;
  padding:5px 11px; font-size:var(--fs-sub); color:var(--dim); cursor:pointer; }
.pfmemclr:hover { border-color:var(--down); color:var(--down); }
.pfmemoff { padding:8px 11px; margin:0 0 2px; border-radius:8px; font-size:var(--fs-sub);
  color:var(--dim); background:var(--panel2); border:1px dashed var(--line); }

/* ---------- [M4-L] 궤적 밸류 컬러바 — 초록(저평가)↔파랑(고평가) 연속 눈금 (2026-08-12) */
#cmvbar { position:absolute; right:10px; top:50%; transform:translateY(-50%);
  display:flex; flex-direction:column; align-items:center; gap:4px;
  pointer-events:none; z-index:3; }
#cmvbar i { width:8px; height:110px; border-radius:4px; opacity:.8;
  border:1px solid var(--line); }
#cmvbar span { font-size:var(--fs-badge); color:var(--dim); }
#cmvbar { position:absolute; }
#cmvbar .cmvb-mid { position:absolute; right:18px; top:58%; transform:translateY(-50%); }
#cmvbar .cmvb-mid { white-space:nowrap; right:16px; }
#cmvbar .cmvb-t { position:absolute; right:20px; font-size:var(--fs-badge); color:var(--dim);
  transform:translateY(-50%); font-variant-numeric:tabular-nums; }

/* ---------- [M4-M] 궤적 컨트롤 정돈 (사용자 2026-08-12: 셀렉터 글자 확대·설명 줄 삭제·우측 범례) */
#cometctrl .jvsel { font-size:14.5px; padding:8px 13px; }
#cometctrl .jvsel-wrap > .jvsel-lb { font-size:13px; }
#cometctrl .cmstat { font-size:13px; color:var(--dim); align-self:center; margin-left:auto; }
#cmvbar .cmvb-size { display:flex; flex-direction:column; align-items:center; gap:2px;
  margin-top:12px; font-size:var(--fs-sub); color:var(--dim); white-space:nowrap; }
#cometsel .cmpanel-h .hint, #cometcand .cmpanel-h .hint { font-size:12.5px; }

/* ---------- [M4-N] 주간 메달(V리본·이중 링) + 상장 배지 (사용자 2026-08-12 2차, SVG) */
.inb-medal, .aw-ic { width:20px; height:23px; flex-shrink:0; display:inline-flex; }
.inb-medal svg, .aw-ic svg { width:100%; height:100%; }
.inb-medal .ring, .aw-ic .ring { fill:none; stroke:rgba(255,255,255,.6); stroke-width:.9; }
.inb-medal text { font-size:6.8px; font-weight:800; fill:#fff; text-anchor:middle;
  font-variant-numeric:tabular-nums; }
.inb-medal.m1 .core, .aw-ic.m1 .core { fill:#d4a015; }
.inb-medal.m1 .rb.l, .aw-ic.m1 .rb.l { fill:#a97f08; }
.inb-medal.m1 .rb.r, .aw-ic.m1 .rb.r { fill:#e6c25e; }
.inb-medal.m2 .core { fill:#a4abb7; }  .inb-medal.m2 .rb.l { fill:#7f8794; }
.inb-medal.m2 .rb.r { fill:#c9cfd8; }
.inb-medal.m3 .core { fill:#b1783c; }  .inb-medal.m3 .rb.l { fill:#8f5f2c; }
.inb-medal.m3 .rb.r { fill:#d2a26c; }
.inb-crown { position:absolute; pointer-events:none; z-index:2;
  border:1.5px solid rgba(190,145,10,.55); border-radius:13px;
  box-shadow:0 0 0 3px rgba(217,164,6,.07); }
.inb-crown-lb { position:absolute; top:-12px; left:50%; transform:translateX(-50%);
  display:inline-flex; align-items:center; gap:6px; padding:0 10px; white-space:nowrap;
  font-size:12.5px; font-weight:700; color:#a4780a; background:var(--bg); border-radius:6px; }
.inb-crown .aw-ic { width:15px; height:17px; }
#cometctrl { margin:18px 0 14px; }             /* 컨트롤 줄 상하 여유 (사용자 2026-08-12) */
#cometctrl .cmstat b { color:var(--text); font-weight:600; }
.cmsize { display:inline-flex; align-items:center; gap:5px; }
.cmsize .c { display:inline-block; border-radius:50%; background:var(--dim); opacity:.5; }
.cmsize .c.s { width:7px; height:7px; }
.cmsize .c.b { width:16px; height:16px; margin-left:10px; }

/* ---------- [M4-O] 수출입 카드 여유 + TOP10 더보기 (사용자 2026-08-12 "다닥다닥 붙은 느낌") */
#intrcards { grid-template-columns:repeat(auto-fit, minmax(250px, 1fr)); gap:18px; margin-top:18px; }
.intr-card { padding:16px 18px 14px; }
.intr-ch { font-size:14px; margin-bottom:8px; }
.intr-ch small { font-size:var(--fs-sub); }
.intr-cf { font-size:var(--fs-sub); line-height:1.6; margin-top:8px;
  word-break:keep-all; flex-wrap:wrap; }
.intr-cm { font-size:var(--fs-lab); }
.intr-more { grid-column:1 / -1; }
#intrunlinked .inexc { margin-top:14px; }
#intrhero { margin-top:16px; }

/* 기억 주제 (2026-08-12) — 목록은 주제 한 줄, 세부는 눌러야 나온다 */
/* 카드 한 장은 **얇을수록 목록으로 읽힌다** (사용자 지시 2026-08-19 '지금은 너무 두껍다').
   제목·요약·개수 세 조각의 시작선을 왼쪽 한 줄에 맞추고, 위아래 여백만 덜어냈다. */
.pfmemtopic { display:grid; grid-template-columns:1fr auto; gap:1px 10px; width:100%;
  text-align:left; padding:7px 11px; border:1px solid var(--line); border-radius:8px;
  background:var(--panel2); cursor:pointer; }
.pfmemtopic:hover { border-color:color-mix(in srgb, var(--accent) 45%, var(--line)); }
.pfmemtt { grid-column:1; grid-row:1; font-size:13px; font-weight:700; line-height:1.35; }
.pfmemts { grid-column:1; grid-row:2; font-size:var(--fs-sub); color:var(--dim); line-height:1.4;
  word-break:keep-all; overflow:hidden; text-overflow:ellipsis;
  display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; }
.pfmemtc { grid-column:2; grid-row:1 / span 2; align-self:center; font-size:var(--fs-lab);
  color:var(--dim); min-width:18px; text-align:right; font-variant-numeric:tabular-nums; }
.pfmemsec { margin:14px 0 6px; font-size:var(--fs-lab); font-weight:700; color:var(--dim); }
.pfmemdhead { display:flex; align-items:center; justify-content:space-between; margin:0 0 10px; }
.pfmemback { background:transparent; border:0; padding:0; font-size:var(--fs-sub); color:var(--dim);
  cursor:pointer; }
.pfmemback:hover { color:var(--fg); }
.pfmemdel { background:transparent; border:1px solid var(--line); border-radius:7px;
  padding:4px 11px; font-size:var(--fs-sub); color:var(--dim); cursor:pointer; }
.pfmemdel:hover { border-color:var(--down); color:var(--down); }
.pfmemdt { font-size:15px; font-weight:700; margin:0 0 2px; }
.pfmemdsum { font-size:12.5px; line-height:1.6; word-break:keep-all; }
.pfmemul { margin:0; padding-left:18px; display:flex; flex-direction:column; gap:6px; }
.pfmemul li { font-size:12.5px; line-height:1.6; word-break:keep-all; }
/* 프로필 › 호칭 입력 (2026-08-12) */
.pfrow2i { display:flex; align-items:center; gap:12px; margin:10px 0 4px; }
.pfrow2i label { font-size:12.5px; flex:none; }
.pfrow2i input { flex:1; min-width:0; background:var(--panel2); border:1px solid var(--line);
  border-radius:8px; padding:7px 10px; font-size:12.5px; color:var(--fg); font-family:inherit; }
.pfrow2i input:focus { outline:none; border-color:var(--accent); }
.intr-ch { flex-wrap:wrap; word-break:keep-all; row-gap:2px; }
.intr-ch small { word-break:keep-all; }

/* ---------- [M4-P] 크기 범례 = 실제 머리처럼 띠 있는 원 + 검정 라벨 (사용자 2026-08-12) */
.cmsize { color:var(--text); font-weight:600; font-size:13.5px; gap:7px; }
.cmsize .c { background:var(--dim); opacity:1; border-radius:50%;
  box-shadow:0 0 0 2px var(--bg), 0 0 0 3px var(--dim),
             0 0 0 5px var(--bg), 0 0 0 6px var(--line); }
.cmsize .c.s { width:9px; height:9px; margin:0 4px 0 6px; }
.cmsize .c.b { width:26px; height:26px; margin:0 5px 0 22px; }
#cmvbar span { font-size:12.5px; color:var(--text); font-weight:600; }
#cmvbar .cmvb-mid { font-size:var(--fs-sub); }

/* ---------- [M4-Q] 상세 정렬 = 열 머리 클릭 (사용자 2026-08-12 "튀지 않게") */
/* 공용 도움말 '?' — 제목 옆 한 글자로 설명을 툴팁(#jvtip)에 내린다.
   화면에는 판단에 바로 쓰는 문장만 남기기 위한 장치다 (docs/28 간결성). */
.jhelp { margin-left:6px; font-size:var(--fs-badge); font-weight:600; color:var(--dim); cursor:help;
  border:1px solid var(--line); border-radius:50%; padding:0 5px; vertical-align:2px; letter-spacing:0; }
.jhelp:hover { color:var(--ai); border-color:var(--ai); }
.inl-sort { cursor:pointer; user-select:none; }
.inl-sort:hover { color:var(--text); text-decoration:underline; text-underline-offset:3px; }
.inl-sort.on { color:var(--accent); font-weight:700; }
/* 정렬 방향 셰브런 — 기본(내림차순)은 아래를 본다. 오름차순이면 뒤집는다. */
.inl-dir { width:11px; height:11px; margin-left:3px; vertical-align:-1px;
  fill:none; stroke:currentColor; stroke-width:2.6; stroke-linecap:round; stroke-linejoin:round;
  transition:transform .15s ease; }
.inl-sort.asc .inl-dir { transform:rotate(180deg); }
/* 세부업종 라벨 우측 정렬 (사용자 2026-08-12) — dbar는 절대배치라 무영향 */
.inr-nm { display:flex; align-items:baseline; }
.inr-nm small { margin-left:auto; padding-left:10px; text-align:right; word-break:keep-all; }
.inr-nm small.inr-sub { margin-left:auto; }   /* 특이도 매칭 — 3918행 7px 규칙을 덮는다 */
/* 세부업종 = 이름 아래 '막대'의 오른쪽 끝에 정렬 (사용자 재지시 2026-08-12) —
   이름 블록 폭을 막대(150px)에 맞춰 그 안에서 우측 정렬. 셀 우측 끝 정렬은 반려 */
.inr-nm { width:158px; flex-shrink:0; }
.inr-nm { white-space:nowrap; }   /* 긴 이름 줄바꿈 금지 — 막대 폭보다 길면 라벨만 옆으로 밀림 */

/* ---------- [M4-R2] 궤적 주도 기준 버튼 + 순위 칩 (사용자 2026-08-13) */
.cmptop { margin-left:14px; }
.cmind-rk { font-size:var(--fs-lab); font-weight:700; color:var(--dim); min-width:14px; text-align:right; }
.cmind.on .cmind-rk { color:var(--accent); }

/* ---------- [M4-S] 범프 끝점 원 + 등수 변화 라벨 (사용자 2026-08-13) */
.inb-dot { fill:var(--accent); opacity:0; transition:opacity .15s ease; }  /* 선택·호버만 (사용자 2026-08-13) */
.inb-svg .inb-dot.hl { opacity:.95; }
.inb-mvlb { font-size:var(--fs-sub); font-weight:700; fill:var(--text); text-anchor:middle;
  opacity:0; paint-order:stroke; stroke:var(--bg); stroke-width:4px; transition:opacity .15s ease; }
.inb-svg .inb-mvlb.hl { opacity:1; }

/* ---------- [M4-T] 수출 트렌드 블록 확대 (사용자 2026-08-13 "참고 수준이라 아쉽다") */
/* 두 블록(수출 트렌드·수급 동향) 공통 타이포 계층 — 항목이 같으면 스타일도 같다
   (사용자 2026-08-13): 제목 15.5px/700 · 부제 12.5px/dim · 대표 수치 19px/700 ·
   본문 수치 13px · 캡션 12px/dim. 행 높이·간격도 함께 여유 */
.intrade { padding:24px 24px 20px; margin-top:22px; }
.intr-head { font-size:15.5px; font-weight:700; gap:8px; margin-bottom:14px; }
.intr-head small { font-size:12.5px; }
.intr-main { font-size:19px; font-weight:700; }
.intr-main small { font-size:12.5px; }
.intr-row { gap:20px; align-items:center; }
.intr-bars { height:148px; align-items:flex-end; gap:6px; }   /* 수급 차트와 동일 높이 (1.25배) */
.intr-bar { width:11px; }
.intr-sub { font-size:13px; }
.intr-cap { font-size:var(--fs-sub); margin-top:14px; }

/* ---------- [M4-U] 산업 수급 블록 — 종목 기술적 수급의 단순형 (사용자 2026-08-13) */
.inflow { margin-top:26px; padding:24px 24px 32px; }
.inflow .if-h { display:flex; align-items:baseline; gap:10px; margin-bottom:20px; }
.inflow .if-t { font-size:var(--fs-sect); font-weight:700; }   /* 중제목 — 산업 상세 안의 큰 단락 */
.inflow .if-sub { font-size:13.5px; color:var(--text); }        /* 기준 메타 = 읽는 문장(본문색) */
.inflow .if-sum { margin-left:auto; font-size:13px; color:var(--dim); }   /* = .intr-sub */
.inflow .if-grid { display:grid; grid-template-columns:minmax(0,1.4fr) minmax(300px,1fr);
  gap:24px; align-items:center; }
.inflow svg.ifchart { width:100%; height:222px; display:block; }  /* 148 x1.5 (viewBox CH도 110→165 동반) */
.inflow .ifchart polyline { fill:none; stroke-width:2; }
.inflow .ifchart .zero { stroke:var(--line); stroke-width:1; }
.inflow table { border-collapse:collapse; width:100%; font-size:13px; }
.inflow th, .inflow td { padding:14px 10px; text-align:right; border-bottom:1px solid var(--split); }
.inflow th:first-child { text-align:left; font-weight:600; }
.inflow thead th { color:var(--dim); font-weight:600; }
/* 레전드 = 차트 **위** 한 줄 (사용자 지시 2026-08-19 "상단에 선의 레전드, 같은 스타일").
   M2 수급 차트의 범례 문법 그대로: 선 한 줄 + 가운데 빈 원. 채움 면은 두지 않는다. */
.inflow .if-lg { display:flex; align-items:center; gap:16px; font-size:var(--fs-sub); color:var(--dim); }
.inflow .if-lg.top { margin:0 0 8px; }
.inflow .if-lg span { display:inline-flex; align-items:center; gap:5px; }
/* 범례 = 누르는 것 (사용자 지시 2026-08-19). 끈 항목은 회색으로 물러나되 사라지지는 않는다 —
   무엇을 껐는지 보여야 다시 켤 수 있다. */
.inflow .if-lgb { display:inline-flex; align-items:center; gap:5px; background:none; border:0;
  padding:2px 0; font:inherit; color:var(--dim); cursor:pointer; user-select:none; }
.inflow .if-lgb:hover { color:var(--text); }
.inflow .if-lgb.off { opacity:.4; }
.inflow .if-lgb.off .if-lgi { stroke:var(--dim) !important; }
.inflow .if-lgb.off .if-lgi line, .inflow .if-lgb.off .if-lgi circle { stroke:var(--dim); }
.inflow .ifchart polyline.off { display:none; }
.inflow .if-lg .if-lgr { margin-left:auto; }
.inflow .if-lgi { width:26px; height:12px; flex:none; fill:none; stroke-width:2; }
.inflow .if-lgi circle { fill:var(--panel); }
/* 호버 오버레이 — SVG는 preserveAspectRatio="none"이라 그 안의 원이 타원으로 눌린다.
   안내선·점·상자를 HTML로 얹어 비율 왜곡에서 떼어 놓는다. */
.inflow .ifplot { position:relative; }
.inflow .ifguide { position:absolute; top:0; bottom:0; width:1px; margin-left:-.5px;
  background:var(--dim); opacity:.45; pointer-events:none; }
.inflow .ifdot { position:absolute; width:7px; height:7px; border-radius:50%;
  margin:-3.5px 0 0 -3.5px; box-shadow:0 0 0 1.5px var(--panel); pointer-events:none; }
.inflow .iftip { position:absolute; top:6px; z-index:5; pointer-events:none;
  display:flex; flex-direction:column; gap:2px; white-space:nowrap;
  background:var(--panel2); border:1px solid var(--line); border-radius:8px;
  padding:7px 10px; font-size:var(--fs-sub); color:var(--text);
  box-shadow:0 6px 18px rgba(0,0,0,.14); font-variant-numeric:tabular-nums; }
.inflow .iftip b { font-weight:700; }
@media (max-width:1100px) { .inflow .if-grid { grid-template-columns:1fr; } }

/* 상세 하단 여백 — 집계 제외 종목 나열은 제거하되 여백은 유지 (사용자 2026-08-13) */
.inexc-sp { height:26px; }

/* ── 유사 국면 요약 (2026-08-16) ─────────────────────────────────────────────
   "AI가 가격을 예측한다"가 아니라 "비슷했던 과거 이후 실제로 이랬다"를 보여주는 블록.
   기존 .dp-row 문법(항목 왼쪽·숫자 오른쪽·본문색)을 그대로 따라 이질감이 없게 한다. */
.dp-props { padding:2px 0 8px; border-bottom:1px solid var(--line); }
.dp-pr { display:flex; align-items:center; gap:9px; padding:3px 0; font-size:12.5px; }
.dp-prl { flex:none; width:30px; color:var(--text); }
/* 막대 뒤에 옅은 바닥을 깔아야 '전체 중 얼마'인지 눈으로 잡힌다 */
.dp-prb { position:relative; flex:1; height:9px; border-radius:5px; background:var(--line); }
.dp-prf { position:absolute; left:0; top:0; bottom:0; border-radius:5px; }
.dp-prf.up { background:var(--up); } .dp-prf.down { background:var(--down); }
.dp-prf.flat { background:var(--dim); opacity:.55; }
/* 전체 평균 눈금 — 이게 없으면 '38%'가 높은 건지 낮은 건지 알 수 없다 */
.dp-prm { position:absolute; top:-3px; bottom:-3px; width:1.5px; background:var(--text);
  opacity:.45; }
.dp-prv { flex:none; width:34px; text-align:right; font-variant-numeric:tabular-nums;
  font-weight:700; }
.dp-cases { padding:8px 0 2px; }
.dp-csh { font-size:12.5px; color:var(--text); margin-bottom:5px; }
.dp-cs { display:flex; align-items:baseline; gap:8px; padding:2.5px 0; font-size:var(--fs-sub); }
.dp-csn { flex:1; color:var(--text); overflow:hidden; text-overflow:ellipsis;
  white-space:nowrap; }
.dp-csd { flex:none; color:var(--dim); font-variant-numeric:tabular-nums; }
.dp-csr { flex:none; width:52px; text-align:right; font-weight:700;
  font-variant-numeric:tabular-nums; }
.dp-csr.up { color:var(--up); } .dp-csr.down { color:var(--down); }
.dp-csr.flat { color:var(--dim); }

/* 데려가기 — 답변 문구를 눌러 그 화면으로 (2026-08-16 사용자 확정 "말 + 데려가기").
   버튼이지만 **문장 안에 사는 글자**다: 문단 흐름을 끊지 않게 버튼 기본 상자를 전부 지우고
   밑줄만 남긴다. 외부 링크(실선)와 구분되게 점선을 쓴다. 화살표 같은 기호는 붙이지 않는다. */
.jvgo { border:0; background:none; padding:0; margin:0; font:inherit; color:var(--ai);
  cursor:pointer; text-decoration:underline dotted; text-underline-offset:3px;
  text-decoration-thickness:1px; }
.jvgo:hover { text-decoration-style:solid; }
.jvgo:focus-visible { outline:2px solid var(--accent); outline-offset:2px; border-radius:3px; }

/* 깊게 추론 스위치 — 첨부와 같은 층(입력에 붙이는 것이 아니라 **이번 대화의 방식**)이라
   구분선은 이 행 아래로 옮긴다. 첨부 행의 선은 그대로 두면 선이 둘이 되어 무거워진다. */
.plusmenu .agrow.agthink { margin-bottom:4px; padding-bottom:9px;
  border-bottom:1px solid color-mix(in srgb, var(--line) 45%, transparent); }
.plusmenu .agrow.agatt { margin-bottom:0; padding-bottom:6px; border-bottom:0; }
.plusmenu .agrow.agthink .agsw { margin-left:auto; }
/* 무료에서는 **꺼진 스위치 그 자체**가 잠금이다 (사용자 지시 2026-08-19 "좌물쇠는 없애").
   스위치 옆에 자물쇠를 또 붙이면 같은 말을 두 번 하는 데다, 자물쇠가 스위치와 겹쳐
   무엇을 눌러야 하는지 흐려진다. 흐린 농도(.planlocked opacity)는 그대로 둔다. */
.plusmenu .agrow.agthink.planlocked::after { content:none; }
.plusmenu .agrow.agthink.planlocked .agsw { cursor:default; }

/* ---- 플랜 잠금 (docs/63) — 무료에서 잠긴 기능 ----
   숨기지 않고 **자물쇠를 채워 남겨둔다**: 무엇이 있는지 보여야 구독할 이유가 생긴다.
   커서는 pointer 그대로 — 눌러야 안내가 뜬다(disabled로 만들면 클릭조차 안 먹는다). */
.planlocked { position:relative; opacity:.55; }
.planlocked::after { content:""; position:absolute; right:6px; top:50%; width:11px; height:11px;
  transform:translateY(-50%); background:currentColor; opacity:.75;
  -webkit-mask:var(--jv-lock) center/contain no-repeat; mask:var(--jv-lock) center/contain no-repeat; }
:root { --jv-lock:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'><rect x='4' y='10.5' width='16' height='10.5' rx='2'/><path d='M8 10.5V7a4 4 0 0 1 8 0v3.5'/></svg>"); }
.planlocked.predbtn { padding-right:22px; }
/* 켜져 있는 동안은 자물쇠를 그리지 않는다 — 그때 이 버튼의 일은 '끄기'이고,
   끄기는 무료에서도 된다 (2026-08-21, plan.js jvPlanOn과 한 쌍) */
.planlocked.on::after { content:none; }
.planlocked.on { opacity:1; }

/* 4대 AI 주간 추천 — 서버가 종목명을 이미 ●●●●로 가려 보낸다. 여기서는 그 자리를
   흐리게 해 "가려져 있다"를 눈으로 알린다. blur만으로는 잠금이 아니므로 서버가 정본이다. */
.pickmasked { filter:blur(3px); user-select:none; pointer-events:none; }

/* 오늘 질문을 다 썼을 때 — **마스코트가 다음 약속을 말한다** (사용자 지시 2026-08-19).
   경고색을 쓰지 않는다: 막혔다고 겁줄 일이 아니라 내일 다시 만나자는 인사다.
   남았을 때의 카운트다운 예고는 없앴다 — 아끼는 마음으로는 묻지 않는다. */
/* 테두리·바탕 없음 (사용자 지시 2026-08-19) — 카드로 감싸면 '또 하나의 답변'처럼 읽힌다.
   이건 답이 아니라 인사라 대화 흐름에 그냥 놓인다. */
.quotaend { display:flex; align-items:center; gap:12px; justify-content:center;
  margin:18px 4px 6px; padding:6px 16px; }
.quotaend .gpet { width:46px; height:auto; flex:none; image-rendering:pixelated; }
.quotaendtx { font-size:12.5px; line-height:1.7; color:var(--dim); }
.quotaendtx b { color:var(--text); font-weight:700; }

/* ---- 보유(포트폴리오) 표시 — 관심종목 ★과 **모양으로** 구별한다 ----
   색만 다른 두 별은 작은 화면·색각 이상·범례 없는 첫 방문에서 구별되지 않는다.
   관심 = ★ 윤곽 / 보유 = ● 꽉 찬 원 + 체크(시그니처 청록).
   청록인 이유: 부고 통지가 지키는 색과 같아, 감시 배지를 붙일 때 의미가 이어진다. */
.heldmark { display:inline-flex; align-items:center; color:var(--accent); line-height:0; }
.toport { background:transparent; border:0; padding:0 2px; line-height:0; cursor:pointer;
  color:var(--line); transition:color .12s ease; }
.toport:hover { color:var(--accent); }
/* 보유 행은 왼쪽 청록 선으로 훑기만 해도 "내 것"이 보이게 한다 */
.wtbl tbody tr:has(.heldmark) > td:first-child { box-shadow:inset 2px 0 0 var(--accent); }

/* ---- 포트폴리오 손익 카드 (사용자 확정 2026-08-18) ----
   지표는 하나만: "내가 넣은 돈이 얼마가 됐나". 금액이 주인공이고 %는 보조다 —
   사람은 퍼센트보다 금액으로 자기 상태를 안다.
   총 평가자산은 기본 감춤(앵커링). 한 번 각인된 기준점은 토글로 못 지운다. */
.pfpnl { padding:12px 14px; margin-bottom:20px; background:var(--panel);
  border:1px solid var(--line); border-radius:12px; }
.pfpnlmain { display:flex; align-items:baseline; gap:10px; }
.pfpnlamt { font-size:24px; font-weight:800; letter-spacing:-.4px; color:var(--text);
  font-variant-numeric:tabular-nums; }
.pfpnlpct { font-size:14px; font-weight:700; color:var(--dim); font-variant-numeric:tabular-nums; }
.pfpnlamt.up, .pfpnlpct.up { color:var(--up); }
.pfpnlamt.down, .pfpnlpct.down { color:var(--down); }
.pfpnlsub { margin-top:4px; font-size:var(--fs-sub); color:var(--dim); }
.pfpnlskip { margin-left:6px; padding:1px 6px; border:1px solid var(--line); border-radius:7px;
  font-size:var(--fs-lab); }
.pfpnlnote { font-size:var(--fs-sub); color:var(--dim); }
.pfpnlrow { display:flex; flex-wrap:wrap; gap:10px 18px; justify-content:space-between;
  margin-top:9px; padding-top:9px; border-top:1px solid var(--line);
  font-size:var(--fs-sub); color:var(--dim); }
.pftotalwrap { display:inline-flex; align-items:center; gap:6px; }
.pftotalwrap b { color:var(--text); font-variant-numeric:tabular-nums; letter-spacing:.5px; }
.pfeye, .pfcashedit { background:transparent; border:0; padding:0 2px; cursor:pointer;
  color:var(--dim); line-height:0; }
.pfcashedit { font-size:var(--fs-lab); line-height:1.4; text-decoration:underline; text-underline-offset:2px; }
.pfeye:hover, .pfcashedit:hover { color:var(--accent); }

/* 체험이 남은 기능 — 자물쇠 대신 **한 번 무료** 표시.
   잠긴 모습을 먼저 보여주면 눌러볼 생각조차 안 한다. */
/* 체험이 남은 기능에는 **아무 표시도 하지 않는다** (사용자 지시 2026-08-19).
   버튼에 "1회 무료" 배지를 달았더니 촌스러웠다 — 광고처럼 읽힌다. 그냥 눌리게 두고,
   쓰고 난 뒤에 조용히 알린다(plan.js의 응답 헤더 감지 → 토스트 한 줄). */

/* 관심 ↔ 포트폴리오 전환 — 같은 표, 다른 목록.
   표 모양을 바꾸면 두 화면을 따로 배워야 한다. 담긴 것만 갈아 끼운다. */
.wtabs { display:flex; gap:2px; margin:0 0 8px; padding:2px; width:fit-content;
  background:var(--bg); border-radius:8px; }
.wtab { display:inline-flex; align-items:center; gap:6px; padding:5px 12px; font-size:var(--fs-sub);
  color:var(--dim); background:transparent; border:0; border-radius:6px; cursor:pointer; }
.wtab:hover { color:var(--text); }
.wtab.on { background:var(--panel2); color:var(--text); font-weight:700; }
.wtabn { font-size:var(--fs-lab); color:var(--dim); font-variant-numeric:tabular-nums; }
.wtab.on .wtabn { color:var(--accent); }

/* 포트폴리오 관리 탭 — 현금 입력 줄 (설정 창 전용, 사용자 지시 2026-08-19) */
.pfrow2i .pfpdunit { font-size:var(--fs-sub); color:var(--dim); }
#pfpdcashamt { width:150px; text-align:right; font-variant-numeric:tabular-nums; }

/* 확인 창의 한 줄 입력 (jvConfirm input 옵션) — '판 이유' 같은 짧은 메모용 */
.jvcfm-i { width:100%; margin:10px 0 2px; padding:7px 9px; font-size:12.5px;
  color:var(--text); background:var(--panel2); border:1px solid var(--line); border-radius:7px; }
.jvcfm-i:focus { outline:none; border-color:var(--accent); }

/* 부고 배지 — 사이드바 포트폴리오 항목의 점 (사용자 확정 2026-08-19).
   숫자를 쓰지 않는다: 3건이든 5건이든 할 일은 "가서 본다" 하나이고, 점이 더 조용하다.
   접힌 레일에서도 보이도록 아이콘 옆이 아니라 항목 오른쪽 위에 붙인다. */
#sidebar nav a .pfwdot { position:absolute; right:9px; top:50%; transform:translateY(-50%);
  width:6px; height:6px; border-radius:50%; background:var(--down); flex:none; }
#sidebar nav a { position:relative; }
body.nav-collapsed #sidebar nav a .pfwdot { right:6px; top:9px; transform:none; }

/* ---- 설정 한 줄의 표준 문법 (사용자 지시 2026-08-19) ----
   **좌측 이름·짧은 설명, 우측 컨트롤.** 설정 창은 읽는 곳이 아니라 고르는 곳이다.
   컨트롤이 화면 폭을 다 먹으면 무엇을 고르는 자리인지가 흐려진다 — 우측에 붙여 고정폭으로. */
/* 구분선은 **줄과 줄 사이에만** 긋는다 (사용자 지시 2026-08-29 "구분선이 너무 많아").
   예전에는 모든 줄이 아래 선을 갖고 `:last-child`만 예외였다. `:last-child`는 pane 전체의
   마지막 한 줄이라, 구획 제목(.pfsec) 바로 앞줄에는 선이 그대로 남았다 —
   [선] + [여백] + [제목]이 겹쳐 서면서 화면이 줄자처럼 보였다.

   인접 형제(`+`)로 바꾸면 규칙이 하나로 정리된다: **연속한 두 줄 사이에만 선.**
   제목 앞·목록 앞·구획 끝에는 저절로 선이 사라지고, 묶음을 가르는 일은 여백이 맡는다
   (.pfsec3의 margin-top 20px). 선을 빼는 게 아니라 **선이 할 일을 여백에 넘기는** 것이다. */
/* 줄 사이에 선을 **긋지 않는다** (사용자 지시 2026-08-29, 2차 — "가로 선이 너무 많아").
   1차에서는 `:last-child` 방식을 인접 형제로 바꿔 선을 5개에서 3개로 줄였다. 그래도 많았다.
   묶음이 이미 셋으로 보이기 때문이다 — **굵은 구획 제목 + 26px 여백**이 경계를 다 말하고
   있는데, 그 안에서 선이 또 한 번 가르니 층이 두 겹이 됐다.

   그래서 선을 걷고 경계는 여백에 맡긴다. 행간은 11 → 9px로 조금 좁힌다: 선이 없으면
   같은 여백도 더 벌어져 보여서, 좁혀야 묶음이 한 덩어리로 읽힌다. */
.pfset { display:flex; align-items:center; gap:16px; padding:9px 0; }
/* 크기는 타이포 캐논(app.css 상단 :root)을 따른다 — 설정 창만 따로 정하지 않는다
   (사용자 지시 2026-08-19 "설정 화면 전체적으로 폰트 키워라"). */
.pfsetl { flex:1; min-width:0; }
.pfsetn { font-size:14.5px; color:var(--text); }
.pfsets { margin-top:3px; font-size:var(--fs-sub); color:var(--dim); }
/* 컨트롤은 **오른쪽 끝에 붙는다** (사용자 지시 2026-08-29 "내용은 좌측, 선택 버튼 등은 우측 정렬").
   칸의 폭(220px)은 그대로 둔다 — 2026-08-19의 '줄 맞춤'은 **입력칸끼리 폭과 왼쪽 끝을
   맞추라**는 것이었고, 아래 `.pfin { width:100% }`가 칸을 꽉 채우므로 그 요구는 그대로 산다.
   바뀌는 것은 **짧은 것들**(값 텍스트·버튼)뿐이다: 종전엔 flex-start라 220px 칸 왼쪽에
   붙어 화면 한가운데 떠 있었다. 이름은 왼쪽 끝, 조작은 오른쪽 끝 — 눈이 양 끝만 훑으면 된다. */
.pfsetc { flex:none; width:220px; max-width:46vw; display:flex; align-items:center;
  justify-content:flex-end; gap:8px; }
.pfsetc .pfin { width:100%; max-width:none; }
.pfsetv { font-size:var(--fs-th); color:var(--text); font-variant-numeric:tabular-nums; }
/* ---- 접히는 안내 (사용자 지시 2026-08-29 "뭔가 선택이나 관리 버튼이 있어야지") ----
   종전에는 오른쪽에 값 텍스트('이용 안 함')만 있었다. 읽을 것은 있는데 **할 것이 없어**
   조작부 자리가 비어 보였다 — 설정 창의 오른쪽은 '고르는 자리'라는 약속이 깨진 셈이다.
   화살표(펼치기)를 놓으면 그 약속이 지켜지고, 긴 설명은 접어 둘 수 있어 목록도 짧아진다.

   헤더는 줄 문법(.pfset)을 그대로 입은 <button>이다 — 새 모양을 만들지 않는다.
   버튼의 UA 기본값(배경·테두리·폰트·정렬)만 걷어낸다. */
.pfacch { width:100%; text-align:left; background:none; border:0; font:inherit;
  color:inherit; cursor:pointer; }
/* 머리글은 **소제목처럼 굵게** — 클로드 계정 화면 문법 (사용자 지시 2026-08-29
   "클로드의 모양과 같이해"). 상자(배경·테두리)는 두르지 않는다: 배경을 깔면 두 줄이
   한 덩어리로 뭉쳐, 읽히기 전에 '누르는 것'으로만 보인다. 구분은 굵기와 꺾쇠로 충분하다. */
.pfacch .pfsetn { font-weight:600; }
.pfchev { flex:none; color:var(--dim); transition:transform .18s ease; }
.pfacch.on .pfchev { transform:rotate(180deg); color:var(--text); }
.pfacch:hover .pfchev { color:var(--text); }
/* 펼친 내용 — 이름 열과 같은 왼쪽 끝에서 시작한다(오른쪽 칸을 침범하지 않는다) */
.pfaccb { padding:2px 0 14px; }
.pfacclist { margin:0; padding-left:18px; font-size:var(--fs-body); line-height:1.75;
  color:var(--dim); }
.pfacclist li + li { margin-top:6px; }
/* 접힌 그룹 사이에도 선을 두지 않는다 — 위 `.pfset` 주석과 같은 판단(2026-08-29 2차).
   화살표가 이미 "여기가 하나의 묶음"이라고 말하고 있어 선이 겹친다. */
/* ---- 계정 탭 · 아바타 (사용자 지시 2026-08-29, 클로드 계정 화면 문법) ---- */
.pfqsub { margin-top:3px; font-size:var(--fs-sub); color:var(--dim); }
/* 조용한 실행 버튼 — 위험(탈퇴)은 자기 색을 갖고, 그 밖의 조치는 중립이어야 한다 */
.pfghost { padding:5px 12px; font:inherit; font-size:var(--fs-lab); color:var(--dim);
  background:transparent; border:1px solid var(--line); border-radius:8px; cursor:pointer;
  white-space:nowrap; transition:color .15s ease, border-color .15s ease; }
.pfghost:hover { color:var(--accent); border-color:var(--accent); }
.pfghost:disabled { opacity:.55; cursor:progress; }
/* 기기·세션 목록 — 표가 아니라 줄이다. 칸이 둘뿐이라 표 머리가 배보다 배꼽이 된다. */
.pfdevs { display:flex; flex-direction:column; }
.pfdevrow { display:flex; align-items:center; gap:10px; padding:9px 0;
  border-bottom:1px solid var(--line); }
.pfdevrow:last-child { border-bottom:0; }
.pfdevname { flex:1; min-width:0; font-size:var(--fs-th); color:var(--text);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.pfdevmeta { flex:none; font-size:var(--fs-sub); color:var(--dim);
  font-variant-numeric:tabular-nums; }
/* '이 창' — 자기 세션을 모르고 끊는 사고를 막는 유일한 표식이라 눈에 띄어야 한다 */
.pfdevnow { margin-left:6px; padding:1px 7px; border-radius:999px; font-size:var(--fs-lab);
  color:var(--accent); border:1px solid color-mix(in srgb, var(--accent) 40%, var(--line));
  background:color-mix(in srgb, var(--accent) 8%, transparent); }
/* 쪽 넘김 — 목록이 스무 줄을 넘을 때만 뜬다(profile.js pfPagerHtml).
   조용해야 한다: 이건 목록의 부속이지 그 자체로 볼 것이 아니다. */
.pfpager { display:flex; align-items:center; justify-content:flex-end; gap:8px;
  padding:9px 0 2px; }
.pfpagenum { font-size:var(--fs-sub); color:var(--dim); font-variant-numeric:tabular-nums; }
/* 아바타 — 설정 줄의 미리보기 버튼 */
.pfavbtn { padding:0; background:none; border:0; cursor:pointer; line-height:0;
  border-radius:50%; transition:transform .12s ease; }
.pfavbtn:hover { transform:scale(1.06); }
.pfavbtn svg, .pfavimg, .pfavini { width:34px; height:34px; border-radius:50%; display:block; }
.pfavimg { object-fit:cover; }
.pfavini { display:flex; align-items:center; justify-content:center; font-size:14px;
  font-weight:600; color:var(--accent);
  background:color-mix(in srgb, var(--accent) 16%, transparent); }
/* 되돌리기 × — **아바타를 한 번이라도 누른 사람에게만** 뜬다(profile.js).
   기본 이미지인 사람에게는 되돌릴 것이 없어서 없는 게 맞다. */
.pfavwrap { position:relative; display:inline-block; line-height:0; }
.pfavclear { position:absolute; top:-5px; right:-7px; width:17px; height:17px; padding:0;
  display:flex; align-items:center; justify-content:center; font:inherit; font-size:12px;
  line-height:1; color:var(--dim); background:var(--panel); border:1px solid var(--line);
  border-radius:50%; cursor:pointer; transition:color .15s ease, border-color .15s ease; }
.pfavclear:hover { color:var(--text); border-color:var(--dim); }
#pfpdcashamt { width:132px; text-align:right; font-variant-numeric:tabular-nums; }
/* 작은 3택 — 폭을 내용에 맞춘다(꽉 찬 버튼은 설정이 아니라 탭처럼 보인다) */
.pfseg.pfseg-sm { display:inline-flex; width:auto; margin:0; }
.pfseg.pfseg-sm button { padding:6px 16px; font-size:var(--fs-th); }

/* ---- 프로필 카드 (사용자 지시 2026-08-19 — 클로드 프로필 화면처럼) ----
   여러 항목을 **한 카드에 묶고 줄로만 나눈다.** 항목마다 상자를 두면 화면이 계단처럼
   보이고, 무엇이 한 묶음인지가 흐려진다. 좌측 이름 · 우측 값은 설정 전체의 문법과 같다. */
.pfcard2 { background:var(--panel2); border:1px solid var(--line); border-radius:12px;
  padding:2px 14px; }
.pfc2row { display:flex; align-items:center; gap:16px; padding:12px 0;
  border-bottom:1px solid var(--line); }
.pfc2row:last-child { border-bottom:0; }
.pfc2k { flex:none; width:64px; font-size:var(--fs-th); color:var(--dim); }
.pfc2v { flex:1; min-width:0; font-size:15px; color:var(--text); }
/* 읽기 전용 값 — 입력칸처럼 보이지 않게 테두리·배경을 주지 않는다 */
.pfc2ro { padding:0; }
input.pfc2v { background:transparent; border:0; padding:0; outline:none; }
input.pfc2v::placeholder { color:var(--line); }

/* ---- 설정 네비 아이콘 (사용자 지시 2026-08-19 — 클로드 설정 화면처럼) ----
   색을 쓰지 않는다: 고르는 자리라 어느 아이콘이 화려한지가 아니라 무엇이 선택됐는지가
   먼저 보여야 한다. 선택 표시는 배경 하나로 충분하다(docs/28 — 이모지 금지). */
.pfnavi { display:flex; align-items:center; gap:10px; }
.pfnavi svg { flex:none; color:var(--dim); }
.pfnavi.on svg { color:var(--text); }

/* 설정 입력칸 — 클로드처럼 **우측에 테두리 있는 상자**. 값이 아니라 고칠 자리임을 보여준다 */
.pfin { width:220px; max-width:46vw; padding:8px 11px; font-size:15px; color:var(--text);
  background:var(--panel); border:1px solid var(--line); border-radius:9px; outline:none; }
.pfin:focus { border-color:var(--accent); }

  /* ── 구독 비교 창 (Basic 좌 · Pro 우) ───────────────────────────────────
     참고 화면은 ChatGPT·Claude의 업그레이드 카드다. 두 곳이 공통으로 지키는 것만 가져왔다 —
     통화 기호는 위첨자, 숫자만 크게, CTA는 목록보다 **위에**(가격 바로 아래), 기능은 한 줄씩.

     Pro만 파랗게 칠한다. 두 장이 똑같이 생기면 비교표는 자료일 뿐이고 자료는 사람을
     움직이지 않는다(사용자 지시 2026-08-20 "구독하고 싶게끔, 조금 화려해도 좋다").
     다만 파랑을 쓰는 자리는 **넷으로 못박는다** — 배지·카드 바탕·아이콘·버튼.
     이름까지 그라데이션으로 칠하면 그때부터는 광고지가 된다("과도하면 안 되고"). */
  .jvpcwrap { background:var(--panel); border:1px solid var(--line); border-radius:16px;
              width:min(760px, 95vw); max-height:86vh; overflow:auto; padding:18px 20px 20px;
              box-shadow:var(--shadow); }
  .jvpcgrid { display:grid; grid-template-columns:1fr 1fr; gap:14px; margin-top:6px;
              align-items:stretch; }
  .jvpccard { position:relative; display:flex; flex-direction:column;
              border:1px solid var(--line); border-radius:14px; padding:17px 16px 16px; }
  /* Pro 카드 = 파란 테두리 + 위에서 아래로 사라지는 옅은 바탕 + 파란 글로우.
     바탕을 꽉 채우면 글자 대비가 무너진다 — 58%에서 투명으로 빠지게 둔다 */
  .jvpccard.pro {
    border-color:color-mix(in srgb, var(--pro-2) 45%, var(--line));
    background:linear-gradient(168deg,
      color-mix(in srgb, var(--pro-2) 10%, transparent) 0%, transparent 58%);
    box-shadow:0 8px 26px color-mix(in srgb, var(--pro-2) 13%, transparent);
  }
  /* 배지는 **한 장에만.** 두 장 다 달면 어느 쪽을 권하는지 도로 사라진다 */
  /* 카드 윗줄 — 배지와 주기 선택이 여기 산다. **두 카드 모두** 이 줄을 갖는다(Basic은 빈
     칸). 한쪽에만 두면 그 카드만 높아져 가격·버튼·목록이 통째로 밀린다.
     예전에는 배지가 position:absolute였는데, 옆에 세그먼트가 붙으면서 겹침 계산을
     손으로 하게 되므로 흐름 안으로 들여왔다 — 겹침 계산은 폰트가 바뀌면 틀린다. */
  .jvpctop { display:flex; justify-content:flex-end; align-items:center; gap:8px;
             min-height:26px; }
  /* 월간·연간. .acctseg와 같은 문법이되 카드 안이라 알약형이다 */
  .jvpcseg { display:inline-flex; gap:1px; padding:2px; background:var(--bg);
             border-radius:999px; }
  .jvpcseg button { padding:4px 10px; font:inherit; font-size:var(--fs-lab); line-height:1.35;
                    font-weight:600; color:var(--dim); background:transparent; border:0;
                    border-radius:999px; cursor:pointer; white-space:nowrap; }
  .jvpcseg button:hover { color:var(--text); }
  .jvpcseg button.on { background:var(--panel); color:var(--text); }
  .jvpccard.pro .jvpcseg button.on { color:var(--pro-2); }
  .jvpcbadge { padding:3px 10px; border-radius:999px;
               font-size:var(--fs-lab); font-weight:700; letter-spacing:.02em; color:#fff;
               background:linear-gradient(96deg, var(--pro-1), var(--pro-2) 60%, var(--pro-3)); }
  .jvpcname { font-size:22px; font-weight:700; letter-spacing:-.015em; }
  .jvpctag { font-size:var(--fs-th); color:var(--dim); margin-top:4px; }
  .jvpcprice { display:flex; align-items:baseline; gap:6px; margin:15px 0 13px; }
  /* 통화 기호는 위첨자 — 숫자와 같은 크기로 두면 값이 실제보다 커 보인다 */
  .jvpcprice i { font-style:normal; font-size:18px; font-weight:600; align-self:flex-start;
                 margin-top:5px; }
  .jvpcprice b { font-size:38px; font-weight:700; letter-spacing:-.025em; line-height:1; }
  /* min-height 2줄이 **두 카드의 버튼을 같은 높이에 세운다.**
     Basic은 곁말이 한 줄("무료로 계속"), Pro는 두 줄("KRW / 월" + "부가세 포함")이다.
     baseline 정렬이라 둘째 줄이 통째로 기준선 **아래로** 붙어 Pro 카드만 15px 내려앉고,
     그 어긋남이 버튼·안내·목록까지 그대로 밀려 내려간다(2026-08-23 사용자 지적).
     px로 박으면 글자 캐논이 바뀔 때 다시 어긋나므로 em(2줄 = 1.4×2)으로 맨다. */
  .jvpcprice span { font-size:var(--fs-sub); color:var(--dim); line-height:1.4; margin-left:3px;
                    min-height:2.8em; }
  .jvpccta { width:100%; border-radius:999px; padding:11px 12px; font-size:14.5px;
             font-weight:600; font-family:inherit; cursor:default;
             border:1px solid var(--line); background:transparent; color:var(--dim);
             transition:transform .12s ease, filter .12s ease; }
  /* 결제가 아직 안 열렸어도 파랑은 유지하고 **투명도로만** 준비 중을 말한다 —
     여기서 회색으로 죽이면 카드 전체가 "아직 없는 상품"으로 읽힌다 */
  .jvpccta.pro { background:linear-gradient(96deg, var(--pro-1), var(--pro-2) 52%, var(--pro-3));
                 color:#fff; border-color:transparent;
                 box-shadow:0 4px 14px color-mix(in srgb, var(--pro-2) 34%, transparent); }
  .jvpccta.pro:not([disabled]) { cursor:pointer; }
  .jvpccta.pro:not([disabled]):hover { filter:brightness(1.07); transform:translateY(-1px); }
  .jvpccta.pro[disabled] { opacity:.55; box-shadow:none; }
  /* min-height는 **빈 안내문 칸을 살려 두기 위한 것**이다. Pro 쪽은 글자가 없는데
     (2026-08-23 삭제) 높이까지 0이 되면 그 카드의 목록만 위로 올라붙어 두 장이 어긋난다. */
  .jvpcnote { font-size:var(--fs-th); color:var(--dim); margin:14px 0 10px;
              min-height:1.4em; }
  .jvpcnote.strong { color:var(--text); font-weight:600; }
  .jvpclist { list-style:none; margin:0; padding:0; display:flex; flex-direction:column;
              gap:9px; }
  .jvpclist li { display:flex; align-items:flex-start; gap:9px; font-size:14px;
                 line-height:1.45; }
  /* 한도 줄 — 값은 오른쪽 끝에 세운다. 같은 열에 서야 두 카드가 눈으로 비교된다.
     긴 값("하루 3번(매일 9시 리셋)")은 한 줄에 못 들어가므로 **줄바꿈을 허용**한다 —
     nowrap으로 버티면 카드 밖으로 넘치고, 줄여 쓰면 글자가 다시 작아진다 */
  .jvpclist li.lim { flex-wrap:wrap; }
  .jvpclist li.lim em { margin-left:auto; padding-left:10px; font-style:normal;
                        text-align:right; color:var(--dim); }
  .jvpccard.pro .jvpclist li.lim em { color:var(--text); font-weight:600; }
  .jvpcic { flex:none; width:1.4em; height:1.4em; margin-top:0; opacity:.8; }
  /* Pro 목록만 아이콘에 색을 준다 — 글자는 그대로 두고 그림만 파랗게 해야 시끄럽지 않다 */
  .jvpccard.pro .jvpcic { color:var(--pro-2); opacity:1; }
  .jvpcfoot { margin-top:18px; font-size:var(--fs-sub); color:var(--dim); line-height:1.65; }
  @media (max-width:560px) { .jvpcgrid { grid-template-columns:1fr; } }

  /* 구독 준비 중 안내 (머신러너님 지시 2026-09-01 "잠시 내리자 · 준비중이라고만 언급").
     가격표가 있던 자리라 허전하지 않게 여백을 넉넉히 주되, 장식은 얹지 않는다 —
     팔지 않는 화면에 카드·배지를 두면 팔 준비가 된 것처럼 읽힌다. */
  .jvprep { padding:26px 4px 8px; text-align:center; color:var(--dim); line-height:1.7;
    font-size:var(--fs-sub); }
  .jvprep p { margin:0 0 6px; }
  .jvprep .jvprep-lead { color:var(--text); font-size:var(--fs-body); font-weight:600;
    margin-bottom:10px; }
  .jvprep .jvprep-open { margin-top:16px; padding-top:14px; border-top:1px solid var(--line); }
  .jvprep .jvprep-open strong { color:var(--text); font-weight:600; }

/* ---------- [M9] 심리 = 큰 버튼 둘로 갈리는 한 화면 (사용자 확정 2026-08-22) ----------
   ① 시장 목소리 ② 주식 고스톱. 반쪽씩 나란히 두던 것을 갈음했다 — 어느 쪽도 제 크기를 못 썼다.
   고른 쪽이 화면 전체를 쓰고, 기본은 시장 말말말이다 (사용자 확정 2026-08-23).
   색 문법은 ADR과 한 몸: 공포=--sn-adr-down(파랑) · 탐욕=--sn-adr-up(빨강) · 중립=--dim. */
/* 최상단 숨통 (사용자 지시 2026-08-23 "답답함을 없애자").
   대제목의 여백은 **전 모듈 공유 캐논**(portfolio.css `#view-* > h2` — margin:26px 0 18px)이라
   여기서 건드리면 다른 모듈까지 흔든다. 그래서 제목이 아니라 **이 화면에** 숨통을 준다. */
#view-sentiment { padding-top:18px; }
/* 헤더의 전역 종목 검색·최근 칩을 심리 화면에서는 감춘다 (사용자 지시 2026-08-29
   "심리 모듈에서 상단에 종목 검색 두지 말자"). 이 화면은 **시장 전체**의 심리를 읽는 자리라
   한 종목을 찾는 입력이 화면의 질문과 어긋난다 — 포트폴리오(body.pfview)와 같은 문법. */
body.snview header .searchwrap, body.snview header #recent { display:none; }
/* 스크롤해도 두 버튼은 남는다 (사용자 지시 2026-08-23): 대제목은 올려 보내고 **어느 쪽을 보고
   있는지**는 손에 쥐고 있게. `.page`가 제 스크롤 통이라 top:0이 이 화면의 위쪽이 된다.
   붙었을 때 아래 카드가 비쳐 보이지 않도록 바탕색과 위아래 숨통을 함께 준다. */
/* 위 여백 12 → 30 (사용자 지적 2026-08-26 "대제목 아래가 짤려 보임").
   아래 ::before 띠(30px)가 설 자리를 여기서 만든다 — 인접 형제의 세로 여백은 **더해지지 않고
   합쳐진다**(margin collapsing). h2 아래 18 + 여기 위 12 = 30이 아니라 max(18,12)=18이었고,
   모자란 12px만큼 띠가 제목의 아랫단을 덮어 글자가 잘려 보였다.
   대제목 여백은 전 모듈 공유 캐논(portfolio.css)이라 건드리지 않고 이쪽을 띠 높이에 맞춘다. */
.sntabs { position:sticky; top:0; z-index:12; background:var(--bg);
  display:grid; grid-template-columns:1fr 1fr; gap:6px; max-width:1080px; margin:30px 0 12px;
  padding:10px 0 9px; }
/* 붙었을 때 버튼 **위쪽 18px**으로 구름이 비쳐 보였다 (실측 2026-08-23) — 화면 자체의 여백이라
   띠가 거기까지 못 덮는다. 바탕색을 위로 30px 늘려 그 틈을 메운다. 안 붙었을 때는 제목과 탭
   사이의 빈 30px 위에 얹히므로 보이지 않는다(위 규칙의 margin-top:30px과 같은 값 — 함께 고친다). */
.sntabs::before { content:""; position:absolute; left:0; right:0; bottom:100%; height:30px;
  background:var(--bg); }
/* 일러스트가 왼쪽에 크게, 글이 그 곁에 (사용자 지시 2026-08-23 · 드로잉 기준).
   좌우를 뒤집고 싶으면 flex-direction:row-reverse 한 줄이면 된다.
   overflow:hidden이 핵심이다: 상단 액센트 띠(3px)는 제 힘으로 16px 라운드를 못 그려
   모서리 밖으로 삐져나왔다(실측 2026-08-23). 버튼이 제 라운드로 잘라 준다. */
/* 121 → 약 95px (사용자 지시 2026-08-23 "너무 커서 아래가 안 보인다") — 일러스트와 안팎 여백을
   같이 줄인다. 글자 크기는 건드리지 않는다: 설명 15px는 사장님이 직접 정한 눈금이다. */
/* ⚠ 껍데기는 파일 끝 "모듈 선택 탭" 블록이 한 곳에서 쥔다 — 여기는 배치만 */
.sntab { display:flex; align-items:center; gap:16px; text-align:left; padding:14px 18px; }
.sntab-txt { display:flex; flex-direction:column; gap:3px; min-width:0; }
/* 일러스트 — 아이콘 타일이 아니라 그림이다. 배경 없이 선과 면으로만 (docs/28 라인 문법) */
.snill { width:54px; height:54px; flex:0 0 54px; display:block; }
.snill svg { width:100%; height:100%; }
.snill svg * { fill:none; stroke-width:2.6; stroke-linejoin:round; stroke-linecap:round; }
/* 말말말 = **퍼 나르는 망** (사용자 정의 2026-08-23): 하나의 목소리가 아니라, 인터넷에서
   서로 퍼 나르고 다시 퍼 나르는 말풍선들의 그물. 화면 아래 키워드 클라우드와 같은 문법이다
   (점과 실). 허브 하나가 크고 나머지가 작아 '퍼져 나간다'는 방향이 읽힌다. */
/* 색은 **출처의 색**을 쓴다 (사용자 지시 2026-08-26 "유튜브·구글·네이버를 센스있게").
   종전의 잉크 그물은 '퍼져 나간다'는 뜻은 맞았지만 **어디서 온 말인지**를 말하지 못했다.
   석 장을 부채처럼 겹치고 앞장에만 말꼬리를 단다 — 세 출처가 모여 한마디가 되는 그림이다.
   앞장 둘레는 바탕색으로 한 겹 둘러 뒤 카드와 붙어 보이지 않게 한다(테두리가 아니라 여백). */
.snill.voice svg .yt { fill:#ff0000; stroke:none; }
.snill.voice svg .ytp { fill:#fff; stroke:none; }
.snill.voice svg .gt { fill:#fff; stroke:#dadce0; stroke-width:1.4; }
.snill.voice svg .gg { fill:#4285f4; stroke:none; font-size:15px; font-weight:800;
  text-anchor:middle; letter-spacing:-.3px; }
.snill.voice svg .nv, .snill.voice svg .nvtail { fill:#03c75a; stroke:var(--panel); stroke-width:2.4;
  stroke-linejoin:round; }
.snill.voice svg .nn { fill:#fff; stroke:none; font-size:17px; font-weight:800;
  text-anchor:middle; font-style:italic; letter-spacing:-.5px; }
/* 고스톱 = **3-8광땡** — 화투의 얼굴. 3광(벚꽃에 붉은 만막) 뒤, 8광(공산명월) 앞.
   원색 대신 이 화면의 고/스톱 팔레트(--sn-go)를 붉은색으로 써서 혼자 튀지 않게 한다. */
/* 비광 — **우산 든 붉은 도포의 사람과 금두꺼비**가 이 패의 얼굴이다 (사용자 지시 2026-08-23).
   처음엔 우산과 물결만 그렸는데, 그건 비광이 아니라 그냥 비 그림이었다.
   광(光) 표시는 두 장 모두 뺐다 — 흰 테두리 붉은 원이 국기처럼 보인다는 지적. */
.snill.gostop svg .card11 { stroke:none; fill:var(--panel); }
.snill.gostop svg .card11ln { stroke:var(--sn-go); fill:none; }   /* 테두리는 그림 위에 다시 긋는다 */
.snill.gostop svg .eave { fill:#23232c; stroke:none; }
.snill.gostop svg .umb { fill:#3f9b6d; stroke:none; }             /* 초록 우산살 — 원본의 표식 */
.snill.gostop svg .umbstem { stroke:#23232c; stroke-width:2.1; }
.snill.gostop svg .wave { stroke:var(--sn-stop); stroke-width:2.2; }
.snill.gostop svg .robe { fill:var(--sn-go); stroke:none; }
.snill.gostop svg .face { fill:#fdf3e6; stroke:none; }
.snill.gostop svg .hat { fill:#23232c; stroke:none; }
.snill.gostop svg .frog { fill:#e0a53c; stroke:none; }
.snill.gostop svg .frogleg { stroke:#e0a53c; stroke-width:2; }
.snill.gostop svg .frogeye { fill:#23232c; stroke:none; }
.snill.gostop svg .card8 { stroke:var(--sn-go); fill:var(--sn-go); }
.snill.gostop svg .moon { fill:#fff; stroke:none; }
.snill.gostop svg .hill { fill:#23232c; stroke:none; }
/* 안 고른 쪽은 조용히 물러난다 — 두 그림이 동시에 소리치면 어느 쪽도 안 읽힌다 */
/* 색을 너무 빼면 그림이 회색 덩어리가 된다 — 물러나되 무엇인지는 남게 (2026-08-23) */
.sntab:not(.on) .snill { opacity:.55; filter:saturate(.5); }
.sntab b, .sntab i { word-break:keep-all; text-wrap:balance; }   /* "키/워드"로 끊기던 것 (2026-08-23) */
.sntab b { font-size:18px; font-weight:800; letter-spacing:-.5px; color:var(--text); }
/* 설명은 버튼의 절반이다 — 회색 12.5px은 읽히지 않았다 (사용자 지시 2026-08-23: 검정 +20%) */
.sntab i { font-style:normal; font-size:15px; color:var(--text); letter-spacing:-.2px; line-height:1.38; }
@media (max-width: 1150px) { .snill { width:48px; height:48px; flex:0 0 48px; } }
/* 탭 아래 무대 — 탭 밑줄과 본문 사이에 숨통을 준다 (사용자 지적 2026-08-26 "답답하다").
   탭 그룹의 아래 여백(12px)에 이만큼을 더해 한 호흡 띄운다. */
.snstage { max-width:1080px; padding-top:14px; }

/* ══════ 모듈 선택 탭 — 세 곳이 쓰는 **한 문법** (사용자 확정 2026-08-26, 시안 D "바닥선 탭바") ══════

   대상: 산업 트렌드(#intab button) · 심리(.sntab) · 종목 vs 종목(.vscard).
   셋은 하는 일이 같다 — **한 모듈 안에서 무엇을 볼지 고르는 탭**이다. 그런데 각자
   자기 자리에서 따로 자라 테두리 두께(.5/1px)·라운드(14/16)·여백이 조금씩 달랐다.
   같은 일을 하는 것이 조금씩 다르게 생기면, 화면은 "누가 대충 만들었다"고 말한다.

   ── 왜 이 모양인가 (시안 4종 중 D 선택) ──────────────────────────────────
   카드로 두면 이 줄이 **아래 본문과 경쟁**한다. 화면에는 이미 카드가 가득한데 탭까지
   카드면 무엇이 목차이고 무엇이 내용인지 형태로 구분되지 않는다. 그렇다고 상자를 통째로
   지우면(시안 B) 누를 수 있는 것임이 덜 보인다. D는 그 사이를 간다.
     · 탭마다 **거의 안 보이는 판**(잉크 3%)만 깔아 누를 자리를 알려 주고,
     · 그룹 아래로 1px 레일이 지나가며,
     · 고른 탭만 그 레일 위에 액센트 3px으로 굵게 얹힌다 — "이 탭이 아래 화면의 주인".
   테두리가 한 줄도 없어 화면의 선이 크게 줄고, 판의 농도만으로 위계가 선다.

   ── 누르고 싶게 만드는 장치 ─────────────────────────────────────────────
     ① hover에서 판이 3%→6%로 짙어진다 — 커서가 닿는 곳이 바로 반응한다.
     ② :active에서 1px 내려앉는다 — 마우스로도 손끝의 반응이 생긴다.
     ③ 안 고른 탭은 이름을 한 톤 물리고 그림을 흐린다(.55). hover·선택에서 되살아난다.
   키보드 초점(:focus-visible)은 링으로 보인다 — 눈으로 볼 수 없는 컨트롤은 없는 컨트롤이다.

   ⚠ 두 가지를 건드리지 말 것.
     · 탭에 overflow:hidden 금지 — 밑줄은 버튼 **밖**(bottom:-9px)의 레일 자리에 그린다.
     · 그룹의 padding-bottom(9px)과 밑줄의 bottom(-9px)은 **한 쌍**이다. 한쪽만 고치면
       밑줄이 레일에서 떨어져 공중에 뜬다.
   여기 없는 것: 각 화면의 배치(패딩·간격·글자 크기)와 그림. 그건 각자의 자리에 남는다. */
#intab, .sntabs, .vstabs-cards, #stockmode, #mnmode, #pfmode { position:relative; padding-bottom:9px; }
/* ⚠ .sntabs만은 **sticky를 되돌린다** (사용자 지적 2026-08-29 "두 버튼은 상단에 두도록.
   이 기능은 이전에 있었는데 어떤 이유에서인지 모르게 바뀌었다").
   위 공용 규칙의 `position:relative`가 같은 특이도(0,1,0)이면서 **뒤에 오기 때문에**
   심리 탭의 `position:sticky`(위 .sntabs 규칙)를 조용히 덮었다 — 밑줄 레일을 얻는 대신
   붙어 있기를 잃은 것이다. 레일(::after)은 absolute라 sticky 위에서도 그대로 그려진다.
   ⚠ 이 한 줄을 지우면 스크롤에서 두 버튼이 다시 떠내려간다 (잠금: tests/test_css_sanity). */
.sntabs { position:sticky; }
#intab::after, .sntabs::after, .vstabs-cards::after, #stockmode::after, #mnmode::after,
#pfmode::after {
  content:""; position:absolute; left:0; right:0; bottom:0; height:1px; background:var(--line); }
#intab button, .sntab, .vscard, #stockmode button, #mnmode button, #pfmode button {
  position:relative; cursor:pointer; font:inherit; color:var(--text);
  background:color-mix(in srgb, var(--text) 3%, transparent); border:0; border-radius:11px;
  -webkit-tap-highlight-color:transparent;
  transition:background-color .16s ease, transform .08s ease; }
#intab button:not(.on) .intab-tx, .sntab:not(.on) b, .vscard:not(.on) .vscard-txt b,
#stockmode button:not(.on) .intab-tx, #mnmode button:not(.on) .intab-tx,
#pfmode button:not(.on) .intab-tx {
  color:color-mix(in srgb, var(--text) 74%, var(--dim)); }
#intab button:hover, .sntab:hover, .vscard:hover, #stockmode button:hover, #mnmode button:hover,
#pfmode button:hover {
  background:color-mix(in srgb, var(--text) 6%, transparent); }
/* 그림도 hover에서 함께 깨어난다 — 안 고른 상태의 흐림(.55/.62)을 되돌린다 */
#intab button:hover .inill, .sntab:hover .snill, .vscard:hover .vsill img,
#stockmode button:hover .smill, #mnmode button:hover .smill, #pfmode button:hover .smill {
  opacity:1; filter:none; }
#intab button:active, .sntab:active, .vscard:active, #stockmode button:active,
#mnmode button:active, #pfmode button:active { transform:translateY(1px); }
#intab button:focus-visible, .sntab:focus-visible, .vscard:focus-visible,
#stockmode button:focus-visible, #mnmode button:focus-visible, #pfmode button:focus-visible {
  outline:2px solid var(--accent); outline-offset:2px; }
/* 고른 것 = 판이 우리 색으로 물들고, 레일 위에 굵은 밑줄이 얹힌다 */
#intab button.on, .sntab.on, .vscard.on, #stockmode button.on, #mnmode button.on,
#pfmode button.on {
  background:color-mix(in srgb, var(--accent) 8%, transparent); }
#intab button.on::after, .sntab.on::after, .vscard.on::after, #stockmode button.on::after,
#mnmode button.on::after, #pfmode button.on::after {
  content:""; position:absolute; left:0; right:0; bottom:-9px; height:3px; z-index:1;
  border-radius:3px; background:var(--accent); }
@media (prefers-reduced-motion:reduce) {
  #intab button, .sntab, .vscard, #stockmode button, #mnmode button, #pfmode button { transition:none; }
  #intab button:active, .sntab:active, .vscard:active, #stockmode button:active,
  #mnmode button:active, #pfmode button:active { transform:none; } }
.snstage-pane[hidden] { display:none; }

/* 시장 목소리 카드 — 패널·라운드. **상단 에메랄드 띠는 뺐다** (사용자 지적 2026-08-26):
   탭이 바닥선 문법으로 바뀌면서 탭의 밑줄과 카드의 윗줄이 9px 사이로 나란히 놓였다.
   같은 색 굵은 선 둘이 붙으면 어느 쪽이 무엇을 가리키는지 흐려진다 — 선택을 말하는 선은
   탭의 밑줄 하나면 족하다. 카드는 조용히 받기만 한다. */
.snvoice { position:relative; display:flex; flex-direction:column; background:var(--panel);
  border:.5px solid var(--line); border-radius:18px; overflow:hidden; box-shadow:var(--shadow);
  padding:24px 24px 20px; text-align:center; }
.snvoice .snsum-regime { margin-top:9px; }
.snv-lead { font-family:Georgia,"Nanum Myeongjo",Batang,serif; font-size:13.5px; line-height:1.6;
  color:var(--text); margin-top:12px; }
.snv-lead .two { color:var(--dim); }
.snv-empty { margin:40px 0; font-size:var(--fs-body); color:var(--dim); }

/* 키워드 아트 장 — 카드 안 남는 세로를 다 쓴다 */
.snv-field { position:relative; flex:1; min-height:150px; margin:14px 0 10px; text-align:left; }
.snv-w { position:absolute; white-space:nowrap; transition:transform .35s ease-out; cursor:default; }
.snv-w.f { color:var(--sn-adr-down); } .snv-w.g { color:var(--sn-adr-up); } .snv-w.n { color:var(--dim); }
.snv-w:nth-child(n+5) { opacity:.8; } .snv-w:nth-child(n+9) { opacity:.66; }

/* 시장 체온계 — 구(球)에서 수은이 차오른다. 눈금 하나(50%)만, 숫자는 없다 */
.snv-therm { display:flex; align-items:center; margin:2px 4px 0; }
.snv-therm-bulb { width:26px; height:26px; border-radius:50%; flex:0 0 26px; z-index:1;
  box-shadow:inset 0 0 0 2px var(--panel); }
.snv-therm-tube { flex:1; height:12px; margin-left:-7px; background:var(--panel2);
  border:1px solid var(--line); border-radius:0 8px 8px 0; position:relative; overflow:hidden; }
.snv-therm-fill { position:absolute; left:0; top:0; bottom:0; border-radius:0 6px 6px 0;
  transition:width .6s ease; }
.snv-therm-tick { position:absolute; top:0; bottom:0; width:1px; background:var(--dim); opacity:.55; }
.snv-therm-axis { display:flex; justify-content:space-between; margin:7px 4px 0;
  font-size:var(--fs-badge); letter-spacing:.08em; }
.snv-therm-axis .f { color:var(--sn-adr-down); } .snv-therm-axis .g { color:var(--sn-adr-up); }
.snv-meta { margin-top:14px; font-size:var(--fs-lab); color:var(--dim); opacity:.9; }

@media (max-width: 1150px) { .sntabs { grid-template-columns:1fr; } }

/* 선택형 상세 (2026-08-20 5차): 기본은 힌트 한 줄, 누르면 열린다 */
.sn-hint { max-width:1080px; text-align:center; padding:26px 0 10px; font-size:var(--fs-lab);
  color:var(--dim); opacity:.85; }
/* 전폭이 된 뒤로 카드 전체가 들리는 건 과하다 (반쪽 카드 시절의 문법) — 테두리만 답한다 */
.snvoice.clickable { cursor:pointer; transition:border-color .18s ease, box-shadow .18s ease; }
.snvoice.clickable:hover { border-color:color-mix(in srgb, var(--accent) 55%, var(--line)); }
.snvoice.sel { border-color:var(--accent); }
#sngostop .snchip { cursor:pointer; }
#sngostop .snchip.sel { box-shadow:0 0 0 3px color-mix(in srgb, var(--accent) 45%, transparent); }
.snsect { margin-top:26px; }
.snvdetail { margin-top:2px; }
.snvd-article { font-size:var(--fs-body); line-height:1.8; color:var(--text); margin:2px 0 14px; }
.snvd-quote { font-family:Georgia,"Nanum Myeongjo",Batang,serif; font-size:13px; color:var(--text);
  border-left:2px solid var(--accent); padding-left:12px; margin-bottom:12px; }
.snvd-quote .c { font-family:inherit; font-size:var(--fs-badge); color:var(--dim); }
.snvd-src { font-size:var(--fs-badge); color:var(--dim); }
/* 체온계 눈금·수치 */
.snv-therm-tube { overflow:visible; }
.snv-therm-fill { border-radius:0 6px 6px 0; }
.snv-therm-tick.mid { opacity:.8; }
.snv-therm-val { position:absolute; top:-19px; transform:translateX(-50%);
  font-size:11.5px; font-weight:800; font-variant-numeric:tabular-nums; }
.snv-therm { margin-top:14px; }

/* ---------- 심리 6차 (2026-08-20): 대제목 아이콘·헤어라인, 유튜브 소제목, 헤드라인, 키워드 아트 ---------- */
.snpt-ic { width:30px; height:30px; border-radius:9px; flex:0 0 30px;
  background:color-mix(in srgb, var(--accent) 12%, transparent); color:var(--accent);
  display:inline-flex; align-items:center; justify-content:center; }
.snpt-ic svg { width:17px; height:17px; fill:none; stroke:currentColor; stroke-width:1.9; stroke-linecap:round; }
.snpt-ic.gostop svg .cgo { stroke:var(--up); } .snpt-ic.gostop svg .cstop { stroke:var(--down); }

.snv-sub2 { display:flex; align-items:center; justify-content:center; gap:8px;
  font-size:13px; color:var(--text); letter-spacing:.02em; }
.snv-sub2 b { font-weight:700; }
.snv-sub2 .ytmark { width:23px; height:16px; flex:0 0 23px; }
.snv-head2 { font-weight:800; letter-spacing:-0.8px; line-height:1.22; margin-top:10px; color:var(--text); }

/* 키워드 아트 — 단어는 버튼(클릭=근거), 논조 점, 히어로만 세리프, 배경에 큰 따옴표 워터마크 */
.snv-field .snv-w { background:none; border:0; padding:2px 3px; font-family:inherit; cursor:pointer;
  font-weight:600; }
.snv-w::before { content:""; display:inline-block; width:5px; height:5px; border-radius:50%;
  margin:0 6px 2px 0; background:currentColor; opacity:.5; }
.snv-w.hero { font-family:Georgia,"Nanum Myeongjo",Batang,serif; font-weight:700; }
.snv-w:hover, .snv-w.sel { text-decoration:underline; text-underline-offset:6px;
  text-decoration-thickness:1.5px; }
.snv-field::before { content:"\201C"; position:absolute; left:50%; top:52%;
  transform:translate(-50%,-50%); font-family:Georgia,serif; font-size:170px; line-height:0;
  color:var(--text); opacity:.05; pointer-events:none; }

.snv-head2, .snv-lead { word-break:keep-all; }   /* "엇갈리/다"처럼 단어 중간이 꺾이지 않게 */

/* 보조 렌즈(POCF) — 딥러닝 기업 가치 분석 칩, 1년·2년 **각 카드 안** 자기 지평 아래 한 줄
   (사용자 확정 2026-08-21). 크고 분명하게, 부속 수치 없이. */
#valpredchip .vp-alt2{margin-top:7px;padding-top:7px;border-top:1px solid var(--line);
  font-size:var(--fs-body);color:var(--dim);font-weight:600}
#valpredchip .vp-alt2 small{font-size:var(--fs-lab);font-weight:600}
#valpredchip .vp-alt2 b{font-weight:800;font-size:15px;font-variant-numeric:tabular-nums;margin-left:3px}

/* ---------- 심리 7차 (2026-08-21): 빅데이터 자연어 분석 얼굴 ---------- */
.snv-nlp { position:absolute; top:13px; right:14px; font-size:var(--fs-lab); font-weight:700;
  color:var(--accent); background:color-mix(in srgb, var(--accent) 10%, transparent);
  padding:3px 10px; border-radius:20px; letter-spacing:.03em; }
.snv-srcs { display:flex; justify-content:center; gap:8px; margin:10px 0 2px; flex-wrap:wrap; }
.snv-chip { display:inline-flex; align-items:center; gap:6px; padding:3.5px 11px;
  border:1px solid var(--line); border-radius:20px; font-size:var(--fs-lab); color:var(--dim);
  font-variant-numeric:tabular-nums; }
.snv-chip b { color:var(--text); font-weight:700; }
.snv-chip.off { opacity:.55; border-style:dashed; }
.snv-chip .ytmark.s { width:20px; height:14px; }
.snv-chip .gmark, .snv-chip .nmark { display:inline-flex; align-items:center; justify-content:center;
  width:15px; height:15px; border-radius:50%; color:#fff; font-size:10px; font-weight:800; font-style:normal; }
.snv-chip .gmark { background:#4285F4; }
.snv-chip .nmark { background:#03C75A; border-radius:4px; }
.snv-tonebar { display:flex; height:6px; border-radius:3px; overflow:hidden; margin:14px 6px 5px; }
.snv-tonebar i { display:block; }
.snv-tonebar .f { background:var(--sn-adr-down); }
.snv-tonebar .m { background:var(--line); }
.snv-tonebar .g { background:var(--sn-adr-up); }
.snv-tonecap { display:flex; justify-content:center; gap:14px; font-size:var(--fs-badge);
  font-variant-numeric:tabular-nums; }
.snv-tonecap .f { color:var(--sn-adr-down); } .snv-tonecap .g { color:var(--sn-adr-up); }
.snv-tonecap .m { color:var(--dim); } .snv-tonecap .d { color:var(--dim); opacity:.8; }
.snvoice .snv-sub2 { margin-top:16px; }   /* NLP 배지(우상단)와 소제목이 겹치지 않게 한 줄 내림 */

/* ---------- 심리 8차 (2026-08-21): 키워드 아트 → 심리 지도 (옵시디언 그래프 문법) ---------- */
.snv-graph { height:330px; margin:4px 0 0; cursor:default; }

/* ---------- 키워드 심층 패널 (2026-08-26 재작업) ----------
   2026-08-21엔 '분석 엔진의 내부'라며 일부러 검게 칠했다. 그러나 이 화면의 나머지는 전부 밝고,
   여기만 어두우니 **딴 세계에서 온 조각**처럼 보였다(사용자 지적 2026-08-26).
   이제 다른 카드와 같은 판형(패널·헤어라인·본문색)을 쓰고 테마를 따른다 — 다크 모드면 함께 어두워진다.
   논조색도 화면 나머지와 같은 ADR 팔레트로 통일. 글자는 캐논대로 올렸다(읽는 글자는 12.5px 아래로 금지). */
.snkwgrid { row-gap:22px; }
.snkw { position:relative; background:var(--panel); border:2px solid var(--line); border-radius:16px;
  padding:15px 17px 7px; cursor:default; overflow:hidden; min-width:0; box-shadow:var(--shadow); }
/* 테두리가 제 논조의 색을 입는다 (사용자 지시 2026-08-26) — 카드 하나가 곧 하나의 말이므로
   그 말의 색이 테두리까지 이어져야 한 덩어리로 읽힌다. 면은 그대로 두고 선만 물들인다:
   면까지 칠하면 열두 장이 나란히 놓였을 때 화면이 시끄러워진다. */
.snkw.f { border-color:color-mix(in srgb, var(--sn-adr-down) 52%, var(--line)); }
.snkw.g { border-color:color-mix(in srgb, var(--sn-adr-up) 52%, var(--line)); }
.snkw.n { border-color:color-mix(in srgb, var(--dim) 34%, var(--line)); }
.snkw.wide { padding-bottom:16px; }
.snkw .f { color:var(--sn-adr-down); } .snkw .g { color:var(--sn-adr-up); } .snkw .n { color:var(--dim); }
.snkw-top { display:flex; align-items:baseline; gap:10px; }
.snkw-word { font-size:20px; font-weight:800; letter-spacing:-.3px; }
.snkw-tone { font-size:var(--fs-lab); font-weight:700; padding:2.5px 10px; border-radius:6px; }
.snkw-tone.f { background:color-mix(in srgb, var(--sn-adr-down) 14%, transparent); }
.snkw-tone.g { background:color-mix(in srgb, var(--sn-adr-up) 14%, transparent); }
.snkw-tone.n { background:var(--panel2); }
.snkw-stats { margin-left:auto; font-size:var(--fs-sub); color:var(--dim);
  font-variant-numeric:tabular-nums; white-space:nowrap; }
.snkw-links { display:flex; align-items:center; gap:6px; flex-wrap:wrap; margin:10px 0 2px; }
.snkw-links .lk { font-size:var(--fs-lab); color:var(--dim); letter-spacing:.08em; margin-right:2px; }
.snkw-link { display:inline-flex; align-items:center; gap:5px; background:none; cursor:pointer;
  border:1px solid var(--line); border-radius:14px; padding:3px 11px; font-size:var(--fs-sub);
  font-weight:600; transition:border-color .15s; }
.snkw-link:hover { border-color:var(--accent); }
.snkw-link i { font-style:normal; font-size:var(--fs-lab); color:var(--dim); }
.snkw-rows { margin-top:8px; }
.snkw-row { display:flex; align-items:center; gap:11px; width:100%; text-align:left;
  background:none; border:0; border-top:1px solid var(--line); padding:11px 2px; cursor:pointer;
  font-family:inherit; transition:background .15s; border-radius:6px; }
.snkw-row:hover { background:color-mix(in srgb, var(--accent) 7%, transparent); }
.snkw-row .rank { flex:0 0 16px; font-size:var(--fs-sub); color:var(--dim);
  font-variant-numeric:tabular-nums; }
/* 영상 제목은 **읽는 글자**다 — 이 모듈의 본문 눈금(14.5px)에 맞춘다 (2026-08-26) */
.snkw-row .tt { flex:1; min-width:0; font-size:14.5px; line-height:1.5; color:var(--text);
  letter-spacing:-.2px; }
.snkw-row .tt .ch { display:block; font-size:var(--fs-sub); color:var(--dim); margin-top:3px; }
.snkw-row .vv { flex:0 0 84px; text-align:right; }
/* 근거 소스 (2026-08-26) — 순번 자리를 **브랜드 마크**로 바꿨다. 몇 번째인가보다 어디서 온
   말인가가 값이고, 마크는 글자를 안 읽어도 읽힌다. 머리글(Youtube·Google·Naver)과 같은 마크라
   화면 안에서 한 문법이 된다. 높이를 맞춰 세 마크가 한 줄에 정렬되게 한다. */
.snkw-row .rank { flex:0 0 32px; display:flex; align-items:center; }
.ssrc { display:inline-flex; align-items:center; font-style:normal; opacity:.92; }
.ssrc .slogo { width:auto; height:15px; display:block; }
.ssrc .slogo.nb { height:14px; }        /* blog 마크는 가로가 길어 한 급 낮춰야 무게가 같다 */
/* 구글 G는 **바탕이 없는 글자**다. 유튜브·네이버는 색을 꽉 채운 사각이라 같은 높이면
   G만 작고 옅어 보인다 (사용자 지적 2026-08-26). 높이를 올려 눈에 실리는 무게를 맞춘다. */
.ssrc .slogo.gg { height:20px; }
.sshort { font-style:normal; font-size:10.5px; padding:1px 4px; border-radius:3px;
          background:color-mix(in srgb, var(--dim) 14%, transparent); color:var(--dim); }
.snkw-row .vv.src { font-size:var(--fs-sub); color:var(--dim); overflow:hidden;
                    text-overflow:ellipsis; white-space:nowrap; }
.snkw-row .vv i { display:block; height:3px; border-radius:2px; margin-bottom:4px; margin-left:auto; }
.snkw-row .vv i.f { background:var(--sn-adr-down); } .snkw-row .vv i.g { background:var(--sn-adr-up); }
.snkw-row .vv i.n { background:var(--dim); }
.snkw-row .vv b { font-size:var(--fs-sub); color:var(--dim); font-variant-numeric:tabular-nums; }
.snkw-none { border-top:1px solid var(--line); padding:13px 2px; font-size:var(--fs-body); color:var(--dim); }
.snkw.snhit { animation:snkwhit 1.2s ease-out; }
@keyframes snkwhit { 0% { box-shadow:0 0 0 3px color-mix(in srgb, var(--accent) 60%, transparent); }
  100% { box-shadow:0 0 0 3px transparent; } }
@media (prefers-reduced-motion: reduce) { .snkw.snhit { animation:none; } }
/* 목소리 분석(아티클) — 같은 다크 가족 */
.snvd-article2 { font-size:14.5px; line-height:1.8; color:var(--text); letter-spacing:-.2px;
  margin:4px 0 14px; }
/* 다이얼 아래에서 내려온 12주 서사 — 이 주 이야기보다 먼저 전체 흐름을 말한다 */
.snvd-flow2 { font-size:14px; line-height:1.8; color:var(--dim); margin:0 0 14px;
  padding-bottom:12px; border-bottom:1px solid var(--line); }
.snvd-flow2 b { color:var(--accent); font-weight:700; margin-right:5px; }
.snvd-quote2 { font-family:Georgia,"Nanum Myeongjo",Batang,serif; font-size:14px; color:var(--text);
  border-left:2px solid var(--accent); padding-left:12px; margin-bottom:12px; }
.snvd-quote2 .c { font-size:var(--fs-sub); color:var(--dim); }
.snvd-src2 { font-size:var(--fs-sub); color:var(--dim); line-height:1.7; }

/* ---------- 심리 10차 (2026-08-21): 소제목 3사 로고 · 지도 = 다크 옵시디언 판 ---------- */
/* 마크만 남았으니 글자 자리(gap)는 필요 없고, 마크끼리의 숨만 남긴다 (2026-08-26) */
.snv-sub2 .src { display:inline-flex; align-items:center; gap:0; }
/* 숫자는 걷어내고 마크 셋만 남긴다 (사용자 지시 2026-08-26) — 크기는 20% 올려 세운다 */
.snv-sub2 .src[data-tip] { cursor:help; }
.snv-sub2 .src.stale { opacity:.55; }        /* 오늘 값이 아니면 한 톤 물린다 */
.snv-sub2 .src b { font-weight:800; letter-spacing:-.2px; }
.snv-sub2 .slogo { width:19.2px; height:19.2px; }
.snv-sub2 .src:first-child .slogo { width:25.2px; height:18px; }
.snv-sub2 .dot { font-style:normal; color:var(--dim); margin:0 2px; }
.snv-sub2 .rest { margin-left:3px; }
/* 470 → 400 (사용자 지시 2026-08-23 "한 화면에 아래까지 안 보인다"). 전폭이라 가로가 넉넉해
   세로를 줄여도 말이 겹치지 않는다 — 배치는 가로·세로를 따로 펴기 때문이다. */
.snv-graph { height:400px; margin:8px 0 2px; overflow:hidden; }

.snv-sub2 { flex-wrap:wrap; row-gap:2px; }
.snv-sub2 .rest { flex-basis:100%; text-align:center; margin:1px 0 0; }   /* 브랜드 줄 / 문장 줄 2단 */

/* 심리 지도 줌 버튼 (2026-08-21) */
.snv-graph-wrap { position:relative; }
.snv-gz { position:absolute; right:8px; top:8px; display:flex; flex-direction:column; gap:6px; }
/* 끌어보라는 한마디 — 한 번 끌어보면 사라진다(계속 껌뻑이면 잔소리가 된다) */
.snv-pan { position:absolute; right:10px; bottom:8px; font-size:var(--fs-lab); color:var(--accent);
  opacity:.8; pointer-events:none; animation:snvfhint 2.1s ease-in-out infinite; }
.snv-gz button { width:28px; height:28px; border-radius:50%; border:1px solid var(--line);
  background:var(--panel); color:var(--dim); font-size:15px; line-height:1; cursor:pointer;
  box-shadow:var(--shadow); }
.snv-gz button:hover { color:var(--accent); border-color:var(--accent); }

/* 심리 지도 전용 엔진 툴팁 (17차) */
.snv-graph { position:relative; }
.snv-tip { display:none; position:absolute; z-index:5; max-width:236px; pointer-events:none;
  background:var(--panel); border:1px solid var(--line); border-radius:10px;
  box-shadow:var(--shadow); padding:8px 11px; text-align:left; }
.snv-tip b { display:block; font-size:var(--fs-sub); line-height:1.45; color:var(--text);
  font-weight:600; margin-bottom:3px; }
.snv-tip span { font-size:var(--fs-badge); color:var(--dim); }

/* ---------- 흐름 띠 — 변화하는 시장의 목소리 (2026-08-21) ---------- */
#snvflow { margin-top:10px; }
.snvf-head { display:flex; align-items:center; gap:9px; margin-bottom:6px; }
.snvf-head .t { font-size:var(--fs-sub); font-weight:700; color:var(--text); }
.snvf-head .sub { font-size:var(--fs-badge); color:var(--dim); }
.snvf-play, .snvf-now { margin-left:auto; border:1px solid var(--line); background:var(--panel);
  color:var(--dim); border-radius:20px; font-size:var(--fs-badge); padding:2px 10px; cursor:pointer; }
.snvf-play { margin-left:auto; width:26px; padding:2px 0; text-align:center; }
.snvf-now { margin-left:0; }
.snvf-play:hover, .snvf-now:hover, .snvf-play.on { color:var(--accent); border-color:var(--accent); }
.snvf-canvas { position:relative; }

/* 라디오 다이얼 (카드 안, 온도계 자리) */
.snvf-wrap { text-align:left; }
.snvf-canvas { position:relative; margin:2px 0 0; }
.snvf-canvas canvas { border-radius:8px; }
.snvf-head .t { font-size:var(--fs-lab); }
.snvf-head .sub { font-size:var(--fs-badge); color:var(--accent); font-weight:700; }
/* 다이얼 아래 = 그 주의 분위기 **한 줄** (사용자 지시 2026-08-22 — 긴 글은 우측 메모지에만).
   문단이 아니라 한마디다: 가운데 정렬 + 리드 크기(16.5px — 고스톱 코멘터리 lead와 같은 눈금). */
.snvf-nar { font-size:16.5px; line-height:1.5; margin:16px 2px 0; color:var(--text);
  font-weight:700; letter-spacing:-.3px; text-align:center; }
.snvf-nar:empty { display:none; }

/* 두 부분의 이름 + 다이얼 유도 신호 (2026-08-21) */
.snv-secname { font-size:var(--fs-badge); color:var(--dim); letter-spacing:.1em; text-align:left;
  margin:12px 0 -6px 2px; }
.snvf-arw { position:absolute; width:16px; height:16px; color:var(--accent); pointer-events:none;
  animation:snvfarw 1.9s ease-in-out infinite; }
.snvf-arw svg { width:16px; height:16px; fill:none; stroke:currentColor; stroke-width:2.4;
  stroke-linecap:round; stroke-linejoin:round; }
.snvf-arw.r { animation-delay:.12s; }
@keyframes snvfarw {
  0%, 62%, 100% { opacity:.28; transform:translateX(0); }
  74% { opacity:1; }
  82% { opacity:.95; transform:translateX(var(--dx, -3px)); }
}
.snvf-arw.r { --dx:3px; }
.snvf-hint { position:absolute; left:50%; bottom:-3px; transform:translateX(-50%);
  font-size:var(--fs-badge); color:var(--accent); opacity:.85; pointer-events:none;
  animation:snvfhint 1.9s ease-in-out infinite; white-space:nowrap; }
@keyframes snvfhint { 0%,100% { opacity:.45; } 70% { opacity:.95; } }
/* 한 번 잡아본 뒤엔 조용해진다 — 계속 껌뻑이면 잔소리가 된다 */
.snvf-canvas.touched .snvf-hint { display:none; }
.snvf-canvas.touched .snvf-arw { animation:none; opacity:.3; }
@media (prefers-reduced-motion: reduce) {
  .snvf-arw, .snvf-hint { animation:none; opacity:.6; }
}

/* ---------- 아래 두 칸: 좌 아날로그 다이얼 / 우 주비스 메모지 (2026-08-22) ---------- */
.snv-bottom { display:grid; grid-template-columns:1.15fr 1fr; gap:28px; align-items:start;
  margin-top:16px; text-align:left; }
.snv-bcol { min-width:0; }
.snv-bottom #snvflow { margin-top:0; }

/* 주비스 메모지 — AI 문법(.snmemo)과 한 몸: 보라 왼줄 + 스파크. 글 크기는 우측 코멘터리와 같은 14.5px */
.snv-memo { border-left:3px solid var(--ai); padding:1px 0 1px 15px; }
.snv-memo-h { display:flex; align-items:center; gap:7px; font-size:14.5px; font-weight:700;
  color:var(--ai); letter-spacing:-.2px; }
.snv-memo-h svg { width:14px; height:14px; fill:none; stroke:var(--ai); stroke-width:1.6;
  stroke-linejoin:round; flex-shrink:0; }
.snv-memo-h .wk { margin-left:auto; font-size:var(--fs-lab); font-weight:600; color:var(--dim); }
.snv-memo-b { margin:12px 0 0; font-size:14.5px; line-height:1.8; color:var(--text); letter-spacing:-.2px; }
/* 인용은 **읽으라고 넣은 문장**이다 — dim 세리프 13px은 화면에서 사라진다(실측 2026-08-22).
   본문색으로 올리고 왼줄을 액센트로 세워 "누가 한 말"임을 표시한다. */
/* 내 종목의 목소리 — 인용 한 줄이 있던 자리 (2026-08-22).
   추천이 아니라 **내 종목에 관한 말**이라 조용한 판형: 테두리 없는 행, 누르면 유튜브가 열린다. */
.snv-picks { margin-top:16px; padding-top:13px; border-top:1px solid var(--line); }
.snv-picks:empty { display:none; }
.snp-t { font-size:var(--fs-lab); font-weight:700; letter-spacing:.06em; color:var(--dim);
  margin-bottom:9px; }
.snp { display:block; width:100%; text-align:left; border:0; background:none; font:inherit;
  padding:7px 0; cursor:pointer; border-radius:7px; transition:background .15s ease; }
.snp + .snp { border-top:1px solid var(--line); }
.snp:hover { background:color-mix(in srgb, var(--accent) 7%, transparent); }
.snp-tt { display:block; font-size:13.5px; line-height:1.5; color:var(--text); font-weight:600;
  letter-spacing:-.2px; overflow:hidden; display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; }
.snp-m { display:block; margin-top:5px; font-size:var(--fs-sub); color:var(--dim); }
.snp-m i { font-style:normal; margin-right:6px; padding:1.5px 7px; border-radius:5px;
  background:var(--panel2); color:var(--dim); }
/* 내 보유 종목이 이유일 때만 색을 준다 — 왜 이 영상이 나에게 왔는지가 한눈에 */
.snp-m i.mine { background:color-mix(in srgb, var(--accent) 14%, transparent); color:var(--accent);
  font-weight:700; }
@media (max-width: 1150px) { .snv-bottom { grid-template-columns:1fr; } }

/* 다이얼 헤더 줄바꿈 방지 + 안내 문구 자리 (2026-08-21 실측 교정) */
.snvf-head .t { white-space:nowrap; }
.snvf-head .sub { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
  font-size:var(--fs-sub); }
.snvf-canvas { padding-bottom:15px; }          /* 안내 문구가 눈금 위에 겹치지 않게 자리를 준다 */
.snvf-hint { bottom:-1px; }

/* ---------- 좌우 카드 글자 통일 (2026-08-21 사용자 지적: 좌측이 너무 작다) ----------
   기준은 우측 '주식 고스톱'의 코멘터리 14.5px / 리드 16.5px. 좌측도 같은 눈금을 쓴다. */
.snv-sub2 { font-size:14.5px; }
.snv-secname { font-size:12.5px; margin:14px 0 -4px 2px; }
/* 큰 제목의 기준일 — 제목이 이번 주로 고정되므로 **언제의 말인지**를 반드시 밝힌다 (2026-08-23) */
.snv-head-as { margin-top:8px; font-size:var(--fs-sub); color:var(--dim); letter-spacing:.02em; }
.snv-head-as:empty { display:none; }
.snvf-head .t { font-size:14.5px; font-weight:700; }
.snvf-head .sub { font-size:13px; }
.snv-meta { font-size:12.5px; margin-top:14px; }
.snvf-hint { font-size:12px; }
.snv-lead { font-size:15px; }
/* 다이얼: 손잡이가 위 버튼줄과 겹치지 않게 캔버스에 숨 쉴 자리를 준다 */
.snvf-canvas { margin-top:10px; padding-bottom:16px; }

/* ============================================================================
   비로그인 게이트 (사용자 지시 2026-08-22) — 규칙은 web/static/js/anongate.js가 정본.
   여기는 **잠금의 결 셋**만 그린다: 감춤 / 잠금 / 모자이크.
   전부 `body.anon` 아래에 둔다 — 로그인하면 클래스 하나가 빠지며 통째로 사라진다.
   ============================================================================ */
body.anon .jvhide { display:none !important; }

/* 잠김 = 있다는 건 알리되 못 누른다. 회색으로 죽이지 않고 **자물쇠 하나**만 붙인다 —
   흐려 놓으면 고장으로 읽히고, 자물쇠는 "로그인하면 열린다"로 읽힌다.

   자물쇠 그림은 **플랜 잠금(.planlocked)과 같은 것을 쓴다** — `--jv-lock` 마스크 하나가
   정본이다. 잠깐 두 조각(고리+몸통)으로 직접 그렸다가 걷어냈다: 같은 뜻의 아이콘이 둘이면
   화면에서 미묘하게 다르게 보이고, 실제로 그렇게 보였다(사용자 지적 2026-08-22).
   ⚠ 반드시 position:absolute여야 한다. #menu a가 flex라 흐름에 두면 아이콘 앞에 끼어든다. */
body.anon .jvlock { position:relative; opacity:.55; cursor:not-allowed; padding-right:24px; }
body.anon .jvlock::after {
  content:""; position:absolute; right:8px; top:50%; width:12px; height:12px;
  transform:translateY(-50%); pointer-events:none;
  background:currentColor; opacity:.8;
  -webkit-mask:var(--jv-lock) center/contain no-repeat;
  mask:var(--jv-lock) center/contain no-repeat; }

/* 모자이크 = 무엇이 있는지 형태만 남기고 내용은 가린다 (AI vs AI).
   메뉴에서는 자물쇠, 화면에서는 흐림 — 같은 잠금의 두 얼굴이다. */
body.anon #view-aivsai > *:not(h2) { filter:blur(7px) saturate(.75); opacity:.6;
  pointer-events:none; user-select:none; }
body.anon #view-aivsai { position:relative; }
body.anon #view-aivsai::after {
  content:"로그인하면 볼 수 있어요"; position:absolute; left:50%; top:38%;
  transform:translateX(-50%); padding:9px 20px; border-radius:10px;
  font-size:13.5px; font-weight:700; color:var(--text);
  background:var(--panel); border:1px solid var(--line); box-shadow:var(--shadow);
}

/* 잠긴 것을 눌렀을 때 뜨는 한 줄 — 화면 아래 가운데, 2.6초 */
/* 답을 못 받고 끝난 질문의 재시도 줄 (2026-08-26 유령 세션 사고) — 경고가 아니라 안내다.
   빨강을 쓰지 않는다: 사용자가 잘못한 일이 아니고, 할 일은 버튼 하나뿐이다 (docs/28). */
.msg.jvresume { background:none; border:0; padding:2px 0 0; }
.jvresume .rsmbody { display:flex; align-items:center; gap:10px; flex-wrap:wrap;
  padding:9px 12px; border:1px dashed var(--line); border-radius:10px; background:var(--panel2); }
.jvresume .rsmtext { font-size:var(--fs-sub); color:var(--dim); }
.jvresume .rsmgo { margin-left:auto; flex:none; font:inherit; font-size:var(--fs-sub);
  padding:5px 12px; border-radius:999px; cursor:pointer;
  color:var(--accent); background:transparent;
  border:1px solid color-mix(in srgb, var(--accent) 45%, var(--line)); }
.jvresume .rsmgo:hover { background:color-mix(in srgb, var(--accent) 12%, transparent); }

.jvlockmsg { position:fixed; left:50%; bottom:34px; transform:translateX(-50%);
  z-index:9000; padding:9px 18px; border-radius:10px; font-size:13px; font-weight:600;
  color:var(--text); background:var(--panel); border:1px solid var(--line);
  box-shadow:var(--shadow); animation:jvLockIn .18s ease; }
@keyframes jvLockIn { from { opacity:0; transform:translate(-50%, 6px); } }
@media (prefers-reduced-motion: reduce) { .jvlockmsg { animation:none; } }

/* ---- 위임 작업 카드 (에이전틱 M1, docs/77 · 2026-08-28) — .prcard 문법 위 최소 가산 ---- */
.jvjob { border-color:var(--line); }
.jvjob .prhead b { color:var(--text); font-weight:600; }
.jvjob .jvjobst { margin-left:auto; font-size:var(--fs-sub); }
.jvjob .jvjobx { border:1px solid var(--line); background:transparent; color:var(--dim);
  border-radius:7px; padding:2px 9px; font-size:var(--fs-sub); cursor:pointer; }
.jvjob .jvjobx:hover { color:var(--text); border-color:var(--dim); }
.jvjob .prbody { padding:0 11px 9px 32px; font-size:var(--fs-sub); }

/* ---- 이어서 묻기 칩 (머신러너님 지적 2026-08-30 "이동과 이어서 질문은 전혀 다른 형태여야") ----
   데려가기(.jvgo)는 **문장 안**에 살고 화살표가 붙는다 — 누르면 화면이 바뀐다.
   이어서 묻기는 **답변 아래**에 칩으로 내려온다 — 누르면 질문이 나간다.
   두 일이 다르니 모양도 다르다. 칩 규격은 빈 화면의 추천 질문(.suggest)을 그대로 따른다 —
   사용자가 이미 아는 모양을 새로 배우게 하지 않는다. */
/* 얇게 (머신러너님 반려 2026-08-30 "촌스러워... 얇아야지"). 종전에는 바깥 라벨 한 줄 +
   제목·부제 2줄짜리 꽉 찬 상자 두세 개였다 — **답변보다 제안이 커 보였다.**
   지금은 라벨 없이, 한 줄짜리 알약이 최대 두 개. 배경도 채우지 않는다(테두리만).
   호버에 `translateY`를 두지 않는다 — 튀어오르는 상자가 그 촌스러움의 절반이었다. */
.jvw-fup { margin:12px 0 2px; display:flex; flex-wrap:wrap; gap:6px; }
.jvw-fup .wfup { display:inline-flex; align-items:center; max-width:100%; text-align:left;
  background:transparent; border:1px solid var(--line); border-radius:999px;
  padding:5px 12px; font:inherit; font-size:12px; line-height:1.35; color:var(--dim);
  cursor:pointer; transition:color .15s ease, border-color .15s ease, background .15s ease; }
.jvw-fup .wfup:hover { color:var(--text); border-color:var(--ai);
  background:color-mix(in srgb, var(--ai) 7%, transparent); }
.jvw-fup .wfup:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }
/* 데려가기의 '간다' 표식 — 링크 글자 뒤 작은 화살표. 이게 있어야 "여긴 이동"이 한눈에 읽힌다 */
.jvgo .jvgoic { width:10px; height:10px; margin-left:2px; vertical-align:baseline;
  fill:none; stroke:currentColor; stroke-width:2.2; stroke-linecap:round; stroke-linejoin:round; }

/* ---- 웹 검색 출처 칩 (2026-08-28 "웹사이트 N개 검색함") — 진행 타임라인 검색 행 아래 ---- */
.prsites { display:flex; flex-wrap:wrap; gap:6px; padding:1px 11px 8px 32px; }
/* 배경은 투명이 아니라 카드면(라이트=흰색) — 머신러너님 지시 2026-08-29. 진행 타임라인의
   회색 위에 투명 알약을 얹으면 테두리 선만 떠 있어 '누를 것'으로 안 읽힌다. */
.prsites .prsite { display:inline-flex; align-items:center; gap:5px; font-size:var(--fs-sub);
  color:var(--dim); background:var(--panel); border:1px solid var(--line); border-radius:999px;
  padding:2px 10px 2px 6px; text-decoration:none; }
/* **밑줄 금지** (머신러너님 지시 2026-08-31 "밑줄에 링크 느낌 주지말자. 박스에 있는
   것으로 충분해"). 위 `.prsites .prsite`에 이미 none이 있었는데도 밑줄이 그려졌다 —
   진행 블록이 `.msgbody` **안**에 들어가서 `.msg.ai .msgbody a`(0,3,1)가
   `.prsites .prsite`(0,2,0)를 특이도로 이겼기 때문이다. 같은 문맥에서 되받는다. */
.msg.ai .msgbody a.prsite, .msg.ai .msgbody .prsites a {
  text-decoration:none; color:var(--dim); word-break:normal; }
.msg.ai .msgbody a.prsite:hover { color:var(--text); text-decoration:none; }
.prsites .prsite img { width:14px; height:14px; border-radius:3px; object-fit:contain; }
.prsites .prsite:not(:has(img)) { padding-left:10px; }
/* a.prsite만 손잡이 — URL을 모르는 옛 대화의 글자 칩(span)은 누를 데가 없다 */
a.prsite:hover { color:var(--text); border-color:var(--dim); }
a.prsite:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }

/* ==== 폰 내비 = 드로어 (머신러너님 확정 2026-08-29 "ChatGPT처럼") =====================
   종전 폰 문법은 사이드바를 **상단 가로 스트립**으로 눕히는 것이었다(위 @media 900px 블록).
   메뉴 9개가 좌우 스크롤로 놓이니 한 화면에 두세 개만 보였고, 나머지는 밀어야 찾을 수
   있었다 — **무엇이 있는지가 안 보이는 메뉴**다. 세로로 세워 한 번에 다 보이게 하고,
   평소에는 치워 둔다.

   챗 손잡이(#chattab)가 우하단 알약이 된 것과 **한 쌍**이다: 내비는 좌상단, 대화는 우하단.
   좌상단은 원래 데스크톱에서 #chattab이 쓰던 자리이고(header padding-left:54px, app.css:3545),
   폰에서는 그 알약이 아래로 내려가 **비어 있다** — 새 자리를 만드는 게 아니라 빈자리를 쓴다.

   z-index 층: 챗 드로어 80 < 챗탭 81 < 스크림 82 < 내비 드로어 83 < 햄버거 84.
   내비를 열면 그 위를 덮고, 햄버거는 스크림 위에 남아 다시 눌러 닫을 수 있다.

   ⚠ **파일 끝에 둔다.** 위 스트립 규칙과 특이도가 같으므로 순서로 이긴다(같으면 뒤엣것이
   이긴다) — 메인 세션이 #chattab에서 쓴 것과 같은 방법이다.
   ⚠ 조건은 `jvIsPhone()`과 **같은 문장**이다(index.html 프리페인트). 갈라지면 "CSS는 폰으로
   보는데 JS는 아니다"가 생긴다. 좁은 데스크톱 창(pointer:fine)은 스트립 그대로다. */
/* 폰 드로어 문패용 CI — 데스크톱 레일은 글자 로크업이라 그리지 않는다 */
.navci { display:none; }
#navburger { display:none; }
@media (pointer:coarse) and (max-width:900px), (max-width:560px) {
  #navburger {
    display:inline-flex; align-items:center; justify-content:center;
    position:fixed; z-index:84;
    top:calc(38px + env(safe-area-inset-top, 0px));
    left:calc(9px + env(safe-area-inset-left, 0px));
    width:44px; height:44px;              /* 애플·구글 터치 최소치 */
    background:transparent; border:0; padding:0;
    color:var(--dim); cursor:pointer; }
  #navburger svg { width:22px; height:22px; fill:none; stroke:currentColor;
    stroke-width:1.9; stroke-linecap:round; }
  #navburger:active { color:var(--text); }
  /* 랜딩은 **비로그인일 때만** 메뉴를 안 그린다 — 그에게는 둘러보기 화면이고 상단은
     로그인/회원가입이 맡는다. **로그인 사용자에게는 그린다** (머신러너님 지시 2026-08-29):
     그에게 랜딩은 둘러보기가 아니라 매일 여는 **메인 프롬프트 창**인데, 상단이 통째로 비어
     있어 어디로도 갈 수 없었다(실측: 그 화면의 내비 진입점 0개).
     랜딩은 티커가 없으므로 위로 올려 `.lndtop`(y=10)과 눈높이를 맞춘다 — 38px은 티커 높이다. */
  body.landing.anon #navburger { display:none; }
  body.landing #navburger { top:calc(10px + env(safe-area-inset-top, 0px)); }
  /* 검색 입력이 햄버거 밑으로 깔리지 않게. 데스크톱의 :not(.chat-open) 조건 없이 항상 —
     폰에서 대화를 열면 드로어가 화면을 통째로 덮어 헤더가 안 보이므로 손해가 없다. */
  header { padding-left:54px; }

  /* ---- 사이드바를 드로어로 ---- */
  #sidebar {
    position:fixed; top:0; left:0; bottom:0; width:min(78vw, 300px);
    flex-direction:column; align-items:stretch; gap:2px;
    overflow-x:hidden; overflow-y:auto;
    border-right:1px solid var(--line); border-bottom:0;
    padding:calc(14px + env(safe-area-inset-top, 0px)) 10px
            calc(12px + env(safe-area-inset-bottom, 0px)) 10px;
    transform:translateX(-100%); transition:transform .22s ease;
    z-index:83; }
  body.nav-open #sidebar { transform:none; }
  /* 스크림 — 드로어 밖을 눌러 닫는 자리(닫기는 core.js). 열렸을 때만 존재한다. */
  body.nav-open::after { content:""; position:fixed; inset:0; z-index:82;
    background:rgba(0,0,0,.34); }

  /* 접힘(레일) 상태가 드로어를 이기지 않게 — 폰에서 '접힘'은 뜻이 없는 상태다.
     `body.nav-collapsed #sidebar`(특이도 0,2,1)가 위 `#sidebar`(0,1,0)보다 세므로
     같은 선택자를 여기 다시 써서 되돌린다. 위 900px 블록이 폭에 대해 쓴 것과 같은 사유. */
  body.nav-collapsed #sidebar { width:min(78vw, 300px); padding-left:10px; padding-right:10px; }
  body.nav-collapsed #sidebar .logo { justify-content:flex-start; padding:2px 10px 14px; gap:9px; }
  body.nav-collapsed #sidebar .logo .logotext { display:block; }
  body.nav-collapsed #sidebar nav a { justify-content:flex-start; gap:9px; padding:11px 12px;
    font-size:12.5px; }                  /* 레일은 font-size:0으로 라벨을 지운다 — 되살린다 */
  body.nav-collapsed #sidebar nav a .ico { width:20px; }
  body.nav-collapsed #sidebar nav a .ico svg { width:16.5px; height:16.5px; }
  body.nav-collapsed #sidebar .ver { display:block; }

  #sidebar .logo { padding:2px 10px 14px; font-size:18px; }
  #sidebar .logo small { display:block; }
  #sidebar nav { flex-direction:column; flex:1; }
  #sidebar nav a { padding:11px 12px; white-space:nowrap; font-size:12.5px; }
  #sidebar .foot { flex-direction:column; margin-left:0; border-top:1px solid var(--line);
    padding:8px 4px 0; }
  #sidebar .ver { display:block; }

  /* ---- 폰 드로어 마감 (머신러너님 지시 2026-08-29, 레퍼런스 = 클로드 모바일) ---- */

  /* ① 열린 드로어의 **좌상단 토글** (레퍼런스 = 클로드 모바일, 머신러너님 지시 2026-08-29
     "클로드와 chatgpt는 우리의 선조"). 처음엔 겹침을 피하려고 열렸을 때 감췄는데, 클로드는
     감추지 않고 **드로어 안 좌상단의 둥근 사각 버튼**으로 살려 둔다 — 연 손가락이 그대로
     같은 자리에서 닫을 수 있어서다. 그래서 감추는 대신 **그 자리로 들어간다**:
     배경을 주어 버튼으로 읽히게 하고, 문패는 오른쪽으로 비켜 겹침을 없앤다.
     ⚠ 위 `body.landing #navburger{top:...}`과 특이도가 같아 **뒤에 와야** 이긴다. */
  body.nav-open #navburger {
    display:inline-flex; z-index:84;      /* 드로어(83)보다 위 */
    top:calc(14px + env(safe-area-inset-top, 0px));
    left:calc(14px + env(safe-area-inset-left, 0px));
    width:40px; height:40px; border-radius:10px;
    background:var(--panel2); color:var(--text); }
  body.nav-open #sidebar .logo { padding-left:58px; }   /* 문패가 버튼을 비켜 앉는다 */

  /* ①-b 메뉴 글자 — **12.5px는 데스크톱 레일 크기**다(라벨을 지웠다 되살리는 과정에서 따라왔다).
     폰에서 12.5px는 클로드(~17px)의 3분의 2라 눈에 띄게 작고 빈약하게 읽혔다.
     드로어는 폭이 293px로 넉넉하니 읽는 글자 크기로 올린다 — 행 높이도 43→48px이 되어
     터치 최소치(44)를 자연히 넘는다. 아이콘도 글자에 맞춰 함께 키운다. */
  body.nav-collapsed #sidebar nav a { font-size:15.5px; padding:12px 12px; gap:12px; }
  body.nav-collapsed #sidebar nav a .ico { width:24px; }
  body.nav-collapsed #sidebar nav a .ico svg { width:21px; height:21px; }

  /* ② 문패 = CI 이미지 (글자 "주비스" 대신). 웹 서비스의 얼굴과 같은 것을 쓴다.
     위 `body.nav-collapsed ... .logotext{display:block}`보다 세야 해서 특이도를 맞춘다. */
  #sidebar .logo { padding:2px 10px 16px; }
  #sidebar .logo .navci,
  body.nav-collapsed #sidebar .logo .navci { display:block; height:26px; width:auto; }
  #sidebar .logo .logotext,
  body.nav-collapsed #sidebar .logo .logotext { display:none; }
  body[data-theme="dark"] .navci { content:url(/static/img/brand/joovis_ci_dark.png); }

  /* ③ 하단 계정 행 — **이름이 사라지고 아바타만 가운데** 떠 있었다.
     범인은 데스크톱 레일용 규칙(`body.nav-collapsed .acctmeta{display:none}`)이 폰 드로어에도
     그대로 걸린 것이다. 폰 드로어는 300px 폭이라 이름을 감출 이유가 없다.
     이름은 이미 지침의 호칭을 따른다 — `users.display_name()` → `me.name` → `.acctname`.
     클로드 모바일처럼 **좌측 정렬 · 아바타 + 이름 + 등급** 한 줄로 세운다. */
  body.nav-collapsed .acctmeta { display:flex; }
  body.nav-collapsed .acctchev { display:block; }
  body.nav-collapsed .acctbtn { justify-content:flex-start; padding:9px 10px; }
  #sidebar .ver { text-align:left; padding:0 10px 6px; }
  #sidebar .foot { padding:10px 4px calc(4px + env(safe-area-inset-bottom, 0px)); }
}

/* ⚠ 이 블록은 **파일 끝**에 있어야 한다 (2026-08-30에 한 번 밟았다).
   `.pfset`·`.pfsetl`·`.pfsetc`는 위(약 5800행대)에 원본이 있고 특이도가 같다 — 같으면
   **뒤엣것이 이긴다.** 처음엔 앞쪽 폰 구역에 뒀는데, 규칙은 남고 효과만 죽었다.
   `tests/js/test_settings_row_grammar.mjs`가 먼저 알려줬다: 그 시험은 `.pfset {`의 **첫 등장**을
   읽어 줄 문법을 검사하는데, 앞에 둔 내 규칙이 원본을 가려 "행간이 다시 벌어졌다"고 빨개졌다.
   시험의 오탐이 아니라 **순서가 틀렸다는 신호**였다. */
/* ===== 설정 창 · 폰 — 레퍼런스 = 클로드 모바일 설정 (머신러너님 지시 2026-08-30) =====
   **기능은 그대로다. 배치만 클로드 문법으로 바꾼다.**

   왜 손댔나: 데스크톱 2단(좌 네비 158px + 본문)을 폰에 그대로 얹으니 산수가 깨졌다 —
     창 350px − 네비 158px = 본문 192px, 그 줄에서 `.pfsetc`가 220px을 flex:none으로 먼저
     가져가 라벨에 남는 폭이 **음수**가 됐다. "계정·아바타·이름"이 한 글자씩 세로로 흘렀다.

   클로드에서 가져온 것 셋 (첨부 캡처 2026-08-30):
     ① **탭은 한 줄로 평평하게.** 클로드는 일반·계정·개인정보보호·결제·사용량·기능을 상단
        한 줄에 놓고 넘치면 밀어서 본다. 그래서 좌 네비를 상단 가로 탭으로 펴고, 그룹 제목
        (설정·에이전트)은 접는다 — 항목 여덟은 한 줄에서 밀어 닿는다.
     ② **줄은 이름 왼쪽 · 조작 오른쪽, 한 줄에.** 이게 핵심이다. 처음엔 라벨과 컨트롤을
        위아래로 접었는데, 클로드는 접지 않는다 — 이름이 길면 **이름이 여러 줄로 접히고**
        조작은 오른쪽 제자리를 지킨다("Claude가 / 어떻게 불러 / 드릴까요?"가 그 예다).
        눈이 왼쪽 끝에서 이름을, 오른쪽 끝에서 값을 읽는 리듬이 유지된다.
     ③ **조작 칸은 비율로.** 220px 고정은 폰에서 라벨을 죽인다. 58%면 375px에서 ~187px —
        입력칸이 쓸 만하고 이름에도 130px이 남는다.

   줄 사이 선·양 끝 정렬은 `tests/js/test_settings_row_grammar.mjs`가 지키는 문법이라 건드리지 않는다.

   ⚠ 이 블록은 **파일 끝**에 있어야 한다 (2026-08-30에 한 번 밟았다). `.pfset`·`.pfsetl`·
   `.pfsetc`는 위(5800행대)에 원본이 있고 특이도가 같다 — 같으면 뒤엣것이 이긴다. 앞에 뒀더니
   규칙은 남고 효과만 죽었고, 그 시험이 "행간이 다시 벌어졌다"로 먼저 알려줬다(첫 등장을 읽는다). */
@media (pointer:coarse) and (max-width:900px), (max-width:560px) {
  /* ① 좌 네비 → 상단 가로 탭 한 줄 */
  .pfbody { flex-direction:column; }
  .pfnav { width:100%; border-right:0; border-bottom:1px solid var(--line);
    /* `flex-direction:row`를 **명시**한다 — 원본 `.pfnav`가 column이라(좌측 세로 목록)
       display만 덮으면 항목이 그대로 세로로 쌓인다(실측 2026-08-30: 8줄, 항목마다 폭 326px). */
    display:flex; flex-direction:row; flex-wrap:nowrap; gap:2px; padding:7px 12px;
    overflow-x:auto; overflow-y:hidden; scrollbar-width:none; }
  .pfnav::-webkit-scrollbar { display:none; }
  .pfnavg { display:none; }                      /* 그룹 제목은 접는다 — 평평한 한 줄이 클로드 문법 */
  .pfnavi { flex:none; white-space:nowrap; padding:8px 13px; border-radius:999px; }

  /* ② 줄 = 이름 왼쪽(길면 접힌다) · 조작 오른쪽 */
  .pfset { flex-wrap:nowrap; gap:12px; align-items:center; }
  .pfsetl { flex:1 1 auto; min-width:0; }
  .pfsetn { white-space:normal; word-break:keep-all; }   /* 어절 중간에서 안 자른다 */
  /* ③ 조작 칸은 **내용만큼만** 가져간다 (머신러너님 지적 2026-08-30 2차 — 계정 탭의
     "설명들이 너무 보기 불편하다"). 종전 58% 고정은 고르는 칸(선택·입력)을 살리려던 값인데,
     계정 탭의 조작은 [로그아웃]·[보기] 같은 **작은 버튼 하나**다. 버튼에 58%를 떼 주면
     설명이 40%(약 130px)에 갇혀 "지금 보고 있는 이 / 창은 남기고, 다른 / 기기의 로 / 그인만"
     처럼 잘게 쪼개진다 — 화면 안에서 가장 읽어야 할 문장이 가장 안 읽힌다.
     그래서 칸을 자동으로 두고, **폭이 필요한 것(입력·선택)에만** 폭을 준다. 접기 머리줄
     (.pfacch)의 꺾쇠도 같은 규칙을 타 부제가 한 줄로 선다. */
  .pfsetc { flex:0 1 auto; width:auto; max-width:64%; }
  .pfsetc .pfin { width:min(56vw, 220px); max-width:100%; }
  .pfsets { line-height:1.55; }
}

/* ===== 폰: 투자자 페르소나 3종을 한 화면에 (머신러너님 지시 2026-08-30) =====
   "워런 버핏 / 제시 리버모어 / 밸런스가 한 화면에 보여야 한다. 가로로 1 | 2 | 3."
   지금은 `@media (max-width:620px)`가 1열로 펴서 카드 하나가 화면을 통째로 먹었다 —
   **고르는 화면인데 선택지를 한 번에 못 본다.** 비교가 안 되면 고르기가 아니라 스크롤이다.
   3열로 되돌리되 칸이 109px이므로 글자·여백을 그 폭에 맞춘다(항목은 하나도 안 뺀다).
   ⚠ 이 블록은 620px 규칙보다 **뒤에** 있어야 이긴다(특이도가 같다). */
@media (pointer:coarse) and (max-width:900px), (max-width:560px) {
  .pfcards { grid-template-columns:repeat(3, minmax(0,1fr)); gap:7px; }
  .pfcard { padding:9px 7px 10px; border-radius:10px; }
  .pfartwrap { margin-bottom:8px; border-radius:7px; }
  .pfname { font-size:11.5px; line-height:1.3; word-break:keep-all; }
  .pfrole { margin-top:2px; font-size:10.5px; }
  .pfdesc { margin-top:5px; font-size:10.5px; line-height:1.45; word-break:keep-all; }
}

/* ===== 투자 시나리오 상세 창 · 폰 (머신러너님 지적 2026-08-30 "좌우로 움직이지 않게") =====
   `.pfthpop`이 `overflow:auto`라 **양쪽 축이 다 굴러간다.** 데스크톱(840px)에서는 안쪽이
   다 들어가 가로 스크롤이 안 생기지만, 폰에서는 2열 격자 둘이 폭을 넘겨 좌우로 밀리고
   오른쪽이 잘렸다 — '이상 없음' 배지, '업데이트 2026-08-04', 뉴스 제목이 잘려 나갔다.
   창을 옆으로 미는 것은 읽는 흐름을 끊는다. **세로로만 구르게** 한다:
     · 가로 스크롤을 막고(`overflow-x:hidden`)
     · 넘칠 이유였던 2열 격자를 1열로 편다 — 좁은 화면에서 두 칸은 어차피 각 150px이라 못 읽는다
   기능·항목은 그대로다. 순서도 그대로 — 위에서 아래로 읽으면 같은 이야기다. */
@media (pointer:coarse) and (max-width:900px), (max-width:560px) {
  .pfthpop { overflow-x:hidden; overflow-y:auto; padding:16px 16px 18px; }
  .pfthgrid { grid-template-columns:1fr; }      /* 매도 신호 / 점검 */
  .pfthcmpg { grid-template-columns:1fr; }      /* 정성적 · 정량적 정보 */
  /* 안쪽에 표가 있으면 그것만 제 상자에서 밀리게 — 창 전체가 밀리지 않는다 */
  .pfthpop table { display:block; overflow-x:auto; max-width:100%; }
  /* 매도 신호 한 줄 = 점 | 조건문 | 판정 배지. flex + `min-width:0`만으로는 좁은 폭에서
     배지가 오른쪽으로 밀려 나갔고, 위 `overflow-x:hidden`이 그걸 **잘라** '이상 없음'이
     '이상'으로 보였다(머신러너님 지적 2026-08-30). 스크롤을 막았으니 넘칠 이유 자체를 없앤다.
     격자의 `minmax(0,1fr)`은 가운데 칸이 내용보다 작아지는 것을 **문법으로 보장**한다 —
     배지 칸은 auto라 늘 제 폭을 먼저 챙기고, 넘치는 쪽은 언제나 글이다. */
  .pfthfals li.sg { display:grid; grid-template-columns:auto minmax(0,1fr) auto;
    align-items:start; }
  .pfthfals li.sg > div span { overflow-wrap:anywhere; }   /* 끊을 곳 없는 긴 토큰 보험 */

  /* ===== 창 자체가 화면보다 넓어지던 진짜 원인 (실측 2026-08-31, joovis.ai 폰 캡처) =====
     `.pfthpop`은 `#pfthov`(flex)의 아이템이고 `width:min(840px,100%)`이다. 그런데 flex
     아이템의 `min-width`는 기본이 `auto` — **내용의 min-content보다 작아지지 않는다.**
     그 min-content를 끌어올린 범인이 뉴스 링크다: `.pfthrefs a`가 `white-space:nowrap`이라
     min-content = 제목 전체 길이(ellipsis는 상자가 작아져야 나오는데, 상자가 안 작아졌다).
     그 폭이 `.pfthsec`(격자 아이템, 역시 min-width:auto) → `.pfthgrid` → `.pfthpop`으로
     그대로 전파돼 카드가 화면 밖으로 자랐고, 위 `overflow-x:hidden`이 그 오른쪽을 잘랐다.
     '이상 없음'이 '이상'으로, '업데이트 2026-08-26 21:..'이 중간에서, 뉴스 제목이 통째로.
     → 줄어들 수 있게 사슬의 마디마다 `min-width:0`을 박는다. 그러면 ellipsis가 비로소 일한다. */
  .pfthpop { min-width:0; }
  .pfthgrid, .pfthr1, .pfthevwrap, .pfthcmpg { min-width:0; }
  .pfthsec, .pfthcmpw, #pfupzone, .pfthupd, .pfthrefs { min-width:0; }
  .pfthrefs a { min-width:0; max-width:100%; }        /* 이제 '…'로 줄어든다 */
  /* 추적 머리줄 = 제목 | 업데이트 시각. 폰에서는 한 줄에 둘이 안 들어간다 — 자르지도,
     제목을 두 줄로 접지도 않고 **시각을 통째로 아랫줄로** 내린다(`flex-basis:100%`).
     `flex-wrap`만 걸면 시각이 제목 옆에 남아 '투자 근거 / 추적'으로 제목이 접혔다(실측). */
  .pfthtrkhead { flex-wrap:wrap; }
  .pfthtrkhead .pfthupat { flex:1 0 100%; margin-top:2px; }

  /* '함께 보기'(도킹) 버튼은 폰에서 걷는다 (머신러너님 지시 2026-08-31 "좁히는 기능 없애자").
     이 기능은 **데스크톱의 배치**다 — 카드를 오른쪽에 붙이고 왼쪽에서 대화를 쓰라는 것.
     폰은 대화창이 화면을 통째로 덮는 다른 화면이라 옆에 나란히 설 자리가 없고, 눌리면
     카드가 48vw(≈180px)로 쪼그라들어 읽을 수 없게 된다. 데스크톱에서는 그대로 산다.
     혹시 남아 있는 `.docked` 상태도 폰에서는 가운데 오버레이 기하로 되돌린다. */
  .pfthdock { display:none; }
  .pfthx { margin-left:auto; }   /* 오른쪽으로 미는 일을 도킹 버튼이 했었다 — X가 이어받는다 */
  #pfthov.docked { pointer-events:auto; justify-content:center; padding:24px;
    background:rgba(0,0,0,.42); }
  #pfthov.docked .pfthpop { width:min(840px, 100%);
    max-height:calc(100vh / var(--zoom, 1) - 48px); }
}

/* ===== 폰 대화창 = 맨 위 한 겹 (머신러너님 지적 2026-08-30 "레이어가 매우 부자연스러워") =====
   증상: 대화창을 열면 앱 헤더의 종목 칩·검색창이 **대화창을 뚫고** 위에 떠 있었다.
   원인은 내가 만든 것이다 — M3 마감에서 헤더를 상단 고정하며 `z-index:81`을 줬는데
   대화창은 `z-index:80`이다. 한 칸 차이로 앱 껍데기가 대화 위에 얹혔다.

   폰의 층 순서를 여기서 한 번에 못 박는다. 데스크톱은 드로어가 **사이드바 옆에 나란히** 서지만
   (겹치지 않으니 층이 문제되지 않는다), 폰은 대화창이 화면을 통째로 덮는 **다른 화면**이다.
   덮는 것이 목적이라면 그 위에 아무것도 없어야 한다 — 반쯤 겹친 껍데기는 "여기가 어디인지"를
   흐린다. 머신러너님 말대로 작은 화면일수록 한 번에 한 겹만 보여야 경제적이다.

     86  #chatpanel        대화창 (덮는다)
     84  #navburger        앱 햄버거 — 대화창이 열리면 감춘다(위 규칙)
     82  body.nav-open::after  메뉴 스크림
     81  header            앱 상단 고정 헤더 · #chattab(여는 알약)
   ⚠ 파일 끝에 두는 이유: `#chatpanel`(0,1,0) 원본이 3203행에 있어 특이도가 같다 — 뒤엣것이 이긴다. */
@media (pointer:coarse) and (max-width:900px), (max-width:560px) {
  #chatpanel { z-index:86; }
}

/* ===== 폰: 대화창의 '돌아가기' 버튼 (머신러너님 지시 2026-08-30) =====
   "이 버튼이 매우 중요한 버튼이야 — 메인창으로 가는 거니까."
   데스크톱에서 이 «는 드로어를 **옆으로 접는 손잡이**다. 옆에 본문이 보이니 아이콘만으로 족하다.
   폰에서는 대화창이 화면을 통째로 덮으므로 뜻이 달라진다 — **나가는 문**이다. 그런데 조용한
   회색 «는 나가는 문으로 안 읽힌다. 그래서 셋을 바꾼다:
     · 돌아갈 **화면 이름**을 적는다("« 시장은 지금") — 어디로 가는지가 그 자리에서 읽힌다
     · 알약 배경 + 시그니처 청록 테두리로 **헤더의 주된 행동**임을 표시한다
     · 44px 이상으로 키운다 — 질문을 이어가다 누르는 자리라 손가락이 빗나가면 안 된다
   기능은 그대로다(같은 버튼, 같은 동작). 읽히는 방식만 바꾼다. */
.ccbacklbl { display:none; }
@media (pointer:coarse) and (max-width:900px), (max-width:560px) {
  #chatclose {
    position:static; width:auto; height:auto; min-height:36px;
    gap:3px; padding:7px 12px 7px 8px; border-radius:999px;
    background:color-mix(in srgb, var(--accent) 9%, var(--panel));
    border:1px solid color-mix(in srgb, var(--accent) 42%, transparent);
    color:var(--accent); box-shadow:none;
    max-width:46vw; flex:none; }
  #chatclose svg { width:15px; height:15px; flex:none; }
  .ccbacklbl { display:block; font-size:12.5px; font-weight:700; letter-spacing:-.2px;
    white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
  #chatclose:active { background:color-mix(in srgb, var(--accent) 18%, var(--panel)); }
  /* 헤더의 오른쪽 여백은 이 알약이 쓰므로 고정 78px을 걷는다 — 이름이 길어도 안 겹친다 */
  #chathead { padding-right:14px; }
  #chatclose { margin-left:auto; }

  /* 두 줄에 담는다 — 알약을 넣었더니 세 줄(111px)로 불었다(실측 2026-08-30, 종전 73px).
     작은 화면에서 머리가 13%를 먹으면 정작 대화가 줄어든다. 순서를 정해 두 줄로 접는다:
       1줄  CI 로고 ················ 돌아가기 알약
       2줄  요금 배지 · 한 줄 설명
     배지·설명은 **보조 정보**라 아래로 내려도 읽는 순서가 안 바뀐다. 설명은 길면 말줄임. */
  /* 순서는 머신러너님 지시(2026-08-30 2차)다 — "돌아가는 버튼은 가장 우측에, Pro 배지는
     JooVIS 아이콘 옆에". 브랜드와 요금 배지는 **내가 누구로 쓰고 있나**라 한 덩어리로 붙고,
     나가는 문은 반대편 끝에 선다. 손가락이 오가는 거리가 아니라 **뜻**으로 가른 배치다. */
  /* **격자로 놓는다** — flex로는 이 줄을 못 지킨다(실측 2026-08-30 2차). flex의 줄바꿈은
     축소보다 **먼저** 일어나서, `flex:0 1 auto`를 줘도 배지가 줄어드는 대신 알약이 아랫줄로
     밀렸다(머리 109px = 세 줄). 격자는 칸을 미리 나누므로 줄이 바뀔 일이 없다:
         [CI] [배지 — 남는 폭 전부, 넘치면 말줄임] [돌아가기]
         [                 부제                    ]  */
  #chathead { display:grid; grid-template-columns:auto minmax(0,1fr) auto;
    align-items:center; column-gap:8px; row-gap:2px; }
  #cihome { order:1; flex:none; grid-area:1 / 1; }
  /* 배지는 줄여도 되는 유일한 항목이라 **양보를 여기서 받는다**(실측 2026-08-30: 비로그인
     배지가 124px이라 CI+배지+알약 321px > 가용 300px → 세 줄로 불었다). 로그인한 화면의
     'Pro'는 40px이라 온전히 선다. 비로그인의 긴 권유 문구는 잘리지만 같은 말이 바로
     아랫줄 부제에 통째로 있다 — 잃는 정보가 없다. */
  #aibk { order:2; margin-left:2px; grid-area:1 / 2; justify-self:start; max-width:100%;
    overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  #chatclose { order:3; grid-area:1 / 3; }
  /* 부제는 **폰에서 지운다** (머신러너님 지시 2026-08-31 "상단 문구가 복잡해 보인다").
     "이 종목의 실적과 밸류를 같이 읽어요" 같은 안내는 데스크톱의 넓은 머리에서는 친절이지만,
     폰에서는 이미 같은 줄에 CI·요금 배지·돌아가기 알약이 서 있어 **넷째 정보**가 된다.
     게다가 그 내용은 바로 아래 입력칸의 화면 칩(`◉ SK텔레콤`)이 이미 말하고 있다 —
     같은 말을 두 번 하느라 머리가 한 줄 더 길어졌던 셈이다. 지우면 머리가 한 줄이 된다.
     규칙은 남긴다(자리·말줄임) — 되살릴 때 다시 짜지 않도록. */
  #chathead #chatsub { order:4; grid-area:2 / 1 / 3 / 4; min-width:0;
    white-space:nowrap; overflow:hidden; text-overflow:ellipsis; margin-top:0;
    display:none; }

  /* 왼쪽 손잡이(#navbtn)를 누르기 편하게 넓힌다 (머신러너님 지시 2026-08-30 2차).
     데스크톱은 마우스라 24px 폭으로 충분하지만, 폰에서는 화면 맨 왼쪽 끝에 붙은 24px을
     엄지로 정확히 짚어야 한다. 세로(48px)는 이미 넉넉하니 **가로만** 키운다 —
     모양(세로로 긴 둥근 손잡이)은 그대로 남는다. 본문 시작선도 같이 밀어 안 겹치게 한다. */
  #navbtn { width:40px; }
  #chathead { padding-left:56px; }
}

/* ===== 폰: 차트가 세로 스크롤을 삼키지 않게 (실측 2026-08-30) =====
   증상: 종목 분석에서 차트 위에 손가락을 얹고 밀면 **페이지가 안 굴러간다.** 처음 스크롤을
   시험할 때 "안 된다"고 오판했던 것도 손가락이 캔버스 위였기 때문이다.
   규모: 종목 분석 한 화면에서 캔버스가 문서 3,822px 중 **1,860px(49%)**를 차지한다 —
   **절반이 스크롤 죽은 구역**이었다. 긴 화면을 내려가다 차트에 닿으면 멈춘다.
   원인: ECharts 캔버스는 `touch-action:auto`라 브라우저가 제스처 판정을 캔버스에 넘긴다.
   처방: 세로 팬은 브라우저(페이지)에게 돌려주고, 캔버스에는 나머지(탭·가로 제스처)만 남긴다.
   `pan-y`면 위아래로 미는 동작은 캔버스가 못 가져간다 — 탭(툴팁·선택)은 그대로 산다.
   데스크톱은 마우스휠이라 애초에 이 문제가 없고, 이 블록도 안 걸린다. */
@media (pointer:coarse) and (max-width:900px), (max-width:560px) {
  canvas { touch-action:pan-y; }
}

/* ===== 폰: 툴팁이 화면을 넘지 않게 (실측 2026-08-30) =====
   `#jvtip.sz-l`은 **고정 380px**이다 — 375px 화면보다 넓다. 방금 탭으로 툴팁을 열게 만들었으니
   (core.js, 같은 날) 큰 설명일수록 오른쪽이 잘려 나간다. 설명을 열어 줘 놓고 읽을 수 없으면
   안 연 것만 못하다. 세 규격 모두 화면 안으로 가둔다 — 양옆 12px씩 숨을 남긴다.
   `width`가 고정이라 `max-width`로 눌러야 이긴다(고정폭 + max-width = 둘 중 작은 쪽). */
@media (pointer:coarse) and (max-width:900px), (max-width:560px) {
  #jvtip { max-width:calc(100vw - 24px); }
}


/* ===== 폰: '나의 투자 스타일' 입력줄이 주변보다 커 보이던 것 (머신러너님 지적 2026-08-30) =====
   "폰트가 너무 크다. 위에랑 너무 안 맞아서 보기 불편하다."
   범인은 내가 건 iOS 규칙이다 — `input,textarea,select { font-size:16px !important }`.
   16px 미만인 입력칸을 누르면 iOS 사파리가 **페이지를 확대하고 되돌리지 않는다**. 그래서
   이 자리의 12.5px이 16px로 올라갔고, 옆의 라벨(12.5)·위의 제목(15.5)보다 커져 버렸다.
   **16px을 내리는 것은 답이 아니다** — 내리는 순간 확대 버그가 돌아온다(내릴 수 있는 길은
   `maximum-scale=1`로 손가락 확대를 통째로 막는 것뿐인데, 그건 더 큰 손해다).
   그래서 **주변을 입력칸에 맞춘다** — 라벨과 값이 같은 눈높이에 서면 커 보이지 않는다:
     · 라벨 12.5 → 14px (읽어야 하는 글자라 커져서 손해 볼 것도 없다)
     · 입력칸 안쪽 여백을 줄여 상자가 글자를 따라 부풀지 않게
     · 라벨 칸 80 → 68px — 값이 길어 잘리던 자리를 12px 돌려준다
   위쪽 '투자자 페르소나' 카드는 3열이라 작은 글자가 맞고, 여기는 한 줄에 하나라 큰 글자가
   맞다 — 둘은 다른 밀도의 구역이다. 어색했던 건 크기 자체가 아니라 **한 줄 안의 불일치**다. */
@media (pointer:coarse) and (max-width:900px), (max-width:560px) {
  .pftrait { gap:8px; margin-bottom:7px; }
  .pftrait label { width:68px; font-size:14px; }
  .pftrait input { padding:6px 10px; border-radius:8px; }
  /* 구역 제목도 값(16px)보다 작아 위계가 뒤집혔다 — 한 단계 올려 되돌린다 */
  .pfq { font-size:16.5px; }
}


/* ===== 폰: 산업 트렌드 3종 (머신러너님 지적 2026-08-30) =====
   ① 순위 흐름표에 산업 이름이 **한 글자도 없었다** — 실측 `.inb-nm` 폭 = 0px.
      칩 폭은 `colW/3 − 36`이라 343px 화면에서 78px이고, 순위(15)+수익률(46)+여백이
      그걸 다 먹는다. 이름이 0이 되면 이 화면은 "몇 위가 몇 % 올랐다"만 남아 **무슨 산업인지
      모르는 표**가 된다 — 이 화면의 전부를 잃는 셈이다.
      선(흐름)이 가로로 흐르는 그림이라 세로로 접을 수가 없다. 그래서 **가로 폭을 700px로
      주고 옆으로 밀어 보게** 한다(JS `inDrawBump`의 W 하한과 짝). 이름·선·수익률이 전부 산다.
      아래 페이드는 375px만 덮어 반쪽으로 보이므로 폰에서는 걷는다.
   ② 구성종목 표가 뭉갰다 — 7칸 격자에 항목이 8개라 시가총액이 다음 줄 첫 칸으로 떨어지고
      (실측 28×57 세로글씨), 이름 칸은 트랙이 0px인데 `width:158px`이라 현재가 위로 겹쳤다.
      머리줄은 `nth-of-type`이 빗나가 숨김이 어긋나 **머리와 값이 다른 칸을 가리켰다**.
      → 폰에서는 **두 줄 격자**로 다시 짠다: 1줄 = 순위·이름·현재가 / 2줄 = 등락·주간·월간·분기·시총.
        머리줄도 같은 자리에 놓아 값과 짝이 맞는다(월간·분기 머리도 되살린다).
   ③ 수급 범례·표가 개행됐다 — "외국인 누/적", "+1,925/억".
      범례는 3버튼이 자연폭 327px인데 자리가 291px이라 눌려 접혔다. 칸을 넓히고(패딩 24→14)
      글자·아이콘을 줄여 **한 줄**에 세운다. 표는 숫자와 단위가 갈라지지 않게 nowrap. */
@media (pointer:coarse) and (max-width:900px), (max-width:560px) {

  /* ① 순위 흐름표 — 칩을 두 줄로 접고(이름 / 수익률) 남는 만큼 옆으로 밀어 본다.
        수익률이 이름 옆자리를 비켜 주면 같은 이름이 훨씬 좁은 칩에 들어간다 —
        최소 폭 700 → 540px (머신러너님 2026-08-30 "가로 스크롤이 줄었으면").
        대신 칩이 6px 높아지므로 행 간격을 50→46으로 좁혀 세로 압박은 오히려 줄인다. */
  #inbump { overflow-x:auto; overflow-y:hidden; scrollbar-width:none;
            -webkit-overflow-scrolling:touch; }
  #inbump::-webkit-scrollbar { display:none; }
  .inb-fade { display:none; }
  .inb-chip { height:40px; flex-wrap:wrap; align-content:center; row-gap:0; gap:6px;
              padding-left:8px; padding-right:8px; }
  .inb-chip .inb-nm { font-size:12.5px; line-height:1.15; }
  .inb-chip .inb-rk { min-width:13px; line-height:1.15; }
  .inb-chip .inb-rt { flex:1 0 100%; text-align:right; line-height:1.15; font-size:12px; }
  .inb-chip .inb-medal { align-self:center; }
  .inb-colh { font-size:15px; }

  /* 이동 라벨("5위 ← 6위")은 칸 사이 36px에 55px짜리 글자라 폰에서는 늘 칩에 물린다
     (실측: "위 ← 6위"로 잘려 보였다). 밝힌 두 칩이 이미 양쪽 순위를 다 보여 주므로 걷는다. */
  .inb-mvlb { display:none; }

  /* 첫 탭 = 흐름선만 밝히기 · 두 번째 탭 = 종목 열기 (industry.js와 짝) */
  .inb-peek { position:fixed; left:50%; bottom:88px; transform:translateX(-50%) translateY(6px);
    z-index:70; pointer-events:none; padding:8px 15px; border-radius:999px;
    font-size:12.5px; font-weight:600; letter-spacing:-.2px; white-space:nowrap;
    color:var(--panel); background:color-mix(in srgb, var(--text) 88%, transparent);
    opacity:0; transition:opacity .18s ease, transform .18s ease; }
  .inb-peek.on { opacity:1; transform:translateX(-50%) translateY(0); }

  /* ② 구성종목 표 — **값은 한 가로줄에, 폰에서는 당일 등락을 뺀다**
        (머신러너님 2026-08-30: "모바일에서는 당일의 등락을 빼자 그러면 문제가 없을 것 같다")

     경위. 처음엔 일곱(현재가·등락·주간·월간·분기·시총·비중)을 두 줄로 접었더니 아랫줄에
     다섯이 서서 숫자밭이 됐고, 셋으로 갈랐더니 이번엔 주간·월간·분기가 **자기 행보다
     다음 행 이름에 더 가까이** 붙어 행의 경계가 무너졌다(제 행 현재가와 40px / 다음 행
     이름과 83px). 다섯을 한 줄에 세워 그건 풀었지만 글자를 12px까지 눌러야 했다.
     **하나를 빼니 눌림이 사라진다.** 당일 등락은 이 화면의 축(주간·월간·분기)이 아니고
     종목 화면에 그대로 있다 — 폰에서만 뺀다(데스크톱은 아홉 칸 그대로).
         1  두산에너빌리티 기계              55.0조 23.1%   ← 정체 + 크기
            88,200   +20.33%   +45.07%   -16.71%          ← 값 넷, 한 줄
     칸이 55→70px로 넓어져 글자를 12→12.5px로 되돌리고, 현재가만 1.1fr(최댓값 `3,153,000`). */
  .inlhead, .inrow2 { grid-template-columns:22px 1.1fr .96fr .96fr .96fr;
                      column-gap:6px; row-gap:4px; padding-left:2px; padding-right:2px; }
  .inlhead { font-size:11px; }
  .inlhead > span:nth-child(1) { display:none; }                    /* 순위 머리(빈칸) */
  .inlhead > span:nth-child(2) { grid-area:1 / 1 / auto / span 3; text-align:left; }
  .inlhead > span:nth-child(3) { display:none; }                    /* 분기 주가 흐름 */
  .inlhead > span:nth-child(9) { grid-area:1 / 4 / auto / span 2; } /* 시가총액 */
  .inlhead > span:nth-child(4) { grid-area:2 / 2; }                 /* 현재가 */
  .inlhead > span:nth-child(5) { display:none; }                    /* 등락 — 폰에서 뺀다 */
  .inlhead > span:nth-child(6) { grid-area:2 / 3; display:block; }  /* 주간 */
  .inlhead > span:nth-child(7) { grid-area:2 / 4; display:block; }  /* 월간 — 되살림 */
  .inlhead > span:nth-child(8) { grid-area:2 / 5; display:block; }  /* 분기 — 되살림 */
  .inrow2 > :nth-child(1) { grid-area:1 / 1; }                      /* 순위 · ETF 배지 */
  .inrow2 > :nth-child(2) { grid-area:1 / 2 / auto / span 2; }      /* 이름 · 세부업종 */
  .inrow2 > :nth-child(9) { grid-area:1 / 4 / auto / span 2; }      /* 시총 · 비중 */
  .inrow2 > :nth-child(4) { grid-area:2 / 2; }                      /* 현재가 */
  .inrow2 > :nth-child(5) { display:none; }                         /* 등락 — 폰에서 뺀다 */
  .inrow2 > :nth-child(6) { grid-area:2 / 3; }                      /* 주간 */
  .inrow2 > :nth-child(7) { grid-area:2 / 4; }                      /* 월간 */
  .inrow2 > :nth-child(8) { grid-area:2 / 5; }                      /* 분기 */
  .inrow2 { padding-top:11px; padding-bottom:12px; align-items:baseline; }

  /* 이름과 세부업종은 **한 줄에 붙어 있는다.** `margin-left:auto`(데스크톱 문법)로 두면
     폰에서는 옆칸 값 쪽으로 밀려가 `102960`(코드)이 `14,300`(현재가) 옆에 서서 둘 다
     값처럼 읽혔다 — 이름 옆에 붙여 정체의 일부로 만든다.
     이름 밑 파란 막대(분기 다이버징)는 같은 줄에 분기 %가 숫자로 있어 같은 말을 두 번
     한다 — 폰에서는 걷는다. */
  .inrow2 .inr-nm { width:auto; min-width:0; overflow:hidden; display:flex;
                    align-items:baseline; font-size:13.5px; padding-bottom:0;
                    line-height:1.25; white-space:nowrap; }
  .inrow2 .inr-nm small.inr-sub { margin-left:6px; padding-left:0; font-size:11px;
                    font-weight:400; overflow:hidden; text-overflow:ellipsis; }
  .inr-dbar { display:none; }
  .inrow2 .inr-num { font-size:12.5px; letter-spacing:-.2px; }
  .inrow2 .inr-px { font-size:12.5px; font-weight:700; letter-spacing:-.2px; }
  .inr-cap { font-size:12px; line-height:1.25; }
  .inr-cap small { display:inline; font-size:10.5px; margin-left:5px; }
  /* ETF 배지가 20px 칸에 눌려 "ET"로 잘렸다 — 칸을 22px로 넓히고 글자를 9px로 */
  .inr-etf { font-size:9px; padding:3px 0; letter-spacing:-.5px; align-self:center; }

  /* ③ 수급 — 범례·표를 한 줄로 */
  .inflow { padding:16px 14px 22px; }
  .inflow .if-lg { gap:8px; flex-wrap:nowrap; font-size:11.5px; }
  .inflow .if-lgb { flex:none; white-space:nowrap; gap:4px; font-size:11.5px; }
  .inflow .if-lgi { width:18px; height:10px; }
  .inflow .if-lg .if-lgr { flex:none; white-space:nowrap; font-size:11px; }
  .inflow table { font-size:11.5px; letter-spacing:-.2px; }
  .inflow th, .inflow td { padding:12px 2px; white-space:nowrap; }
  /* 머리줄 3토막(제목·기준·요약)이 한 줄을 다투다 제목이 세로로 눌렸다(실측 33x112) — 아래로 편다 */
  .inflow .if-h { flex-wrap:wrap; row-gap:4px; margin-bottom:14px; }
  .inflow .if-t { flex:1 0 100%; }
  .inflow .if-sub, .inflow .if-sum { flex:1 0 100%; margin-left:0; font-size:12px; }
}


/* ===== 폰: 대화창 안의 햄버거 (머신러너님 지시 2026-08-30) =====
   "주비스 버튼을 누르면 여기로 진입한다. 이때 햄버거 버튼을 살려두는 건 어떨까 —
    첫 번째 캡처의 위치쯤에, 상위 레이어에 있는 스타일로."

   맞는 지적이다. 폰의 대화창은 화면을 통째로 덮는 **다른 화면**이라, 들어오고 나면
   모듈로 가는 길이 [« 돌아가기] 하나뿐이다 — 그것도 **직전 화면**으로만 간다.
   종전에 감췄던 이유는 자리였다: `top:38px`이라 대화창 헤더 위에 얹혀 세션 손잡이와
   부제를 가렸다. 자리를 옮기면 그 이유가 사라진다.

   그래서 헤더 **아래**로 내려 띄운다. 대화 로그 위를 지나가므로 떠 있는 것으로 읽히게
   판 배경 + 테두리 + 그림자를 준다(투명한 채로 글자 위에 있으면 둘 다 안 읽힌다).
   맨 위에서 첫 줄을 덮지 않도록 로그에 그만큼의 머리 여백을 준다 — 굴리면 글이 밑으로
   지나가지만, 그건 떠 있는 버튼의 정상 동작이다.

   층이 핵심이다 — 이걸 놓치면 **누르면 회색만 도는** 예전 랜딩 버그가 그대로 재현된다
   (드로어가 대화창 뒤에 열려 스크림만 보였다). 대화창이 86이므로 여기서 다시 못 박는다:
       90  #sidebar               대화창 위에서 열리는 드로어
       89  body.nav-open::after   그 스크림
       88  #navburger             떠 있는 햄버거
       86  #chatpanel             대화창
   ⚠ 파일 끝에 두는 이유는 늘 같다 — 원본과 특이도가 같으면 뒤엣것이 이긴다. */
@media (pointer:coarse) and (max-width:900px), (max-width:560px) {
  body.chat-open #navburger {
    display:inline-flex; z-index:88;
    /* 머리 아래 12px — 부제를 지워 머리가 82→61px이 됐으므로 함께 올린다(2026-08-31).
       안 올리면 33px이 떠 아무 데도 안 붙은 것처럼 보인다. */
    top:calc(73px + env(safe-area-inset-top, 0px));
    left:calc(10px + env(safe-area-inset-left, 0px));
    /* 원형 — 클로드 문법 (머신러너님 지시 2026-08-31). 둥근 사각(12px)은 아래 카드들과
       같은 모양이라 '떠 있는 손잡이'로 안 읽혔다. 원은 이 층에 하나뿐이라 눈에 먼저 잡힌다. */
    width:40px; height:40px; border-radius:50%;
    background:var(--panel); color:var(--dim);
    border:1px solid var(--line); box-shadow:var(--shadow); }
  body.chat-open #navburger:active { color:var(--text); background:var(--panel2); }
  body.chat-open #navburger svg { width:20px; height:20px; }
  /* 맨 위에서 첫 메시지를 덮지 않게 — 버튼 아래끝(73+40=113)이 로그 첫 줄(61+56=117)보다 위 */
  body.chat-open #chatlog { padding-top:56px; }

  /* **딱 한 경우만 감춘다** (머신러너님 지시 2026-08-30): 좌상단 손잡이(#navbtn)로 포트·세션
     목록을 펼쳤을 때. 그 목록은 대화창 **안에서** 미끄러져 들어오는데(`#chatnav`는 z:92지만
     대화창(86) 안의 절대배치라 밖의 고정 요소를 못 이긴다), 떠 있는 햄버거가 그 위에 남아
     목록의 첫 항목을 가린다. 게다가 그 순간 왼쪽에는 이미 '어디로 갈까' 목록이 펼쳐져 있어
     같은 자리에 메뉴 버튼이 하나 더 있을 이유가 없다 — 겹침이 아니라 **중복**이다. */
  body.chat-open.jvnav-open #navburger { display:none; }

  /* 드로어를 열면 대화창 위로 올라온다 — 안 그러면 대화창 뒤에서 열려 스크림만 보인다 */
  body.chat-open.nav-open #sidebar { z-index:90; }
  body.chat-open.nav-open::after { z-index:89; }
  /* 드로어가 열린 동안에는 그 안 좌상단 토글이 되므로(위 `body.nav-open #navburger`)
     떠 있는 자리·모양을 되돌린다 — 두 규칙이 겹치는 유일한 순간이다. */
  body.chat-open.nav-open #navburger {
    z-index:91; top:calc(14px + env(safe-area-inset-top, 0px));
    left:calc(14px + env(safe-area-inset-left, 0px));
    border:0; box-shadow:none; background:var(--panel2); color:var(--text); }
}

/* 심리 탭의 초록 밑줄은 **폰에서 걷는다** (사용자 지시 2026-08-30 "복잡해보인다").
   이 3px 레일은 탭이 **가로로 나란할 때** 어느 쪽을 골랐는지 알려 주는 표식이다. 폰에서는
   탭이 위아래로 쌓이므로 카드 밑에 화면을 가로지르는 초록 막대가 되어 버린다 — 게다가 고른
   카드는 이미 배경이 우리 색으로 물들어 있어(`.sntab.on`) 같은 말을 두 번 하는 셈이다.
   물듦은 남기고 막대만 걷는다. 데스크톱은 그대로 — 거기선 나란해서 이 표식이 일한다. */
@media (pointer:coarse) and (max-width:900px), (max-width:560px) {
  .sntab.on::after { display:none; }
}

/* '클라우드로' 돌아가기 알약 — 폰에서 카드로 내려온 뒤에만 뜬다 (사용자 요청 2026-08-30).
   대화 알약(#chattab)과 **같은 문법·같은 높이**로 맞춘다: 우하단이 대화면 좌하단이 되돌아가기다.
   z-index 81 = #chattab과 같은 층(본문 위 · 드로어 80 위). 기본은 안 보이고 `.on`에서만 뜬다. */
#snback {
  display:none; position:fixed; z-index:81;
  left:calc(14px + env(safe-area-inset-left, 0px));
  bottom:calc(16px + env(safe-area-inset-bottom, 0px));
  align-items:center; gap:6px; padding:10px 15px 10px 12px;
  min-height:44px; font:inherit; font-size:13.5px; font-weight:700; letter-spacing:-.2px;
  cursor:pointer; -webkit-tap-highlight-color:transparent;
  color:var(--accent); background:var(--panel);
  border:1px solid color-mix(in srgb, var(--accent) 42%, var(--line)); border-radius:999px;
  box-shadow:0 2px 8px rgba(0,0,0,.16), 0 8px 22px rgba(0,0,0,.10); }
/* 화살표가 **계속 위로 떠오른다** (머신러너님 요청 2026-08-30 "화살표가 위쪽으로 움직이면
   좋겠는데 동적으로"). 이 알약은 화면 밖으로 사라진 클라우드를 다시 부르는 버튼이라,
   가만히 있으면 그냥 이름표로 보인다 — 위로 오르는 움직임이 곧 "여기 누르면 위로 간다"다.
   상자가 아니라 **화살표만** 움직인다: 알약 전체가 들썩이면 그게 곧 촌스러움이다. */
#snback svg { width:15px; height:15px; flex:none; animation:snbackrise 1.7s ease-in-out infinite; }
@keyframes snbackrise {
  0%, 62%, 100% { transform:translateY(0);      opacity:1; }
  30%           { transform:translateY(-3.5px); opacity:.5; }
}
@media (prefers-reduced-motion: reduce) { #snback svg { animation:none; } }
#snback:active { transform:translateY(1px); }
@media (pointer:coarse) and (max-width:900px), (max-width:560px) {
  #snback.on { display:inline-flex; }
}

/* ===== 폰: 내용이 없는 헤더 띠를 걷는다 (머신러너님 지적 2026-08-30) =====
   "가장 최상단 밴드와 그 아래 내용 사이에 의미 없는 빈 공간이 있다."

   실측: 포트폴리오 화면에서 `<header>`의 자식 **둘 다** display:none이다
   (`body.pfview header .searchwrap, ... #recent` — portfolio.css 71행, 심리는 app.css 6127행).
   그런데 헤더 자신은 남아 `padding:10px 0` + 아래 1px 선 = **21px짜리 빈 띠 + 줄**을 그린다.
   내용이 0인데 자리와 경계선만 남은 것이라, 화면에는 "뭔가 있어야 하는데 비었다"로 읽힌다.

   이 두 화면은 각자 제 검색을 갖고 있어서 전역 검색을 감춘 것이다 — 즉 **비는 게 정상**이고,
   비었으면 띠도 없어야 맞다. 폰에서만 걷는다: 작은 화면에서 21px은 지수 띠 하나만큼이다.
   두 화면 말고는 헤더에 검색이 살아 있으므로 이 규칙에 안 걸린다. */
@media (pointer:coarse) and (max-width:900px), (max-width:560px) {
  body.pfview header, body.snview header { display:none; }
}


/* ===== 폰: 세션 행을 꾹 눌러 메뉴 (머신러너님 지시 2026-08-31) =====
   "모바일: 누르고 있으면 옵션 3개 보이기."
   손가락에는 호버가 없으므로 ⋯를 **늘 보이게** 두고, 꾹 누르기로도 같은 메뉴를 연다.
   꾹 누르는 동안 iOS가 글자를 선택하거나 '복사/공유' 말풍선을 띄우면 우리 메뉴와 겹치므로
   그 둘을 끈다 — 세션 이름은 읽는 글자지 복사하는 글자가 아니다.
   메뉴 항목은 44px 이상으로 — 세 개 중에 **삭제**가 있어서 빗나가면 손해가 크다. */
@media (pointer:coarse) and (max-width:900px), (max-width:560px) {
  /* 실측 30x38 → 44 미만이었다. 보이는 점 셋은 그대로 두고 **누르는 범위만** 키운다 */
  #chatnav .cndots { opacity:1; padding:8px; min-width:40px; min-height:44px;
    align-items:center; justify-content:center; }
  #chatnav .cnrow.th { -webkit-touch-callout:none; -webkit-user-select:none; user-select:none; }
  .cnmenu button { padding:12px 11px; font-size:var(--fs-body); min-height:44px; }
}

/* ── 홈 전광판: 폰에서는 KOSPI·KOSDAQ을 **가로 두 칸**으로 (머신러너님 지시 2026-08-31) ──
   세로로 쌓였던 건 규칙이 아니라 **폭** 때문이다: `.hwrap`이 flex-wrap:wrap인데 52px 숫자와
   폭 100% 스파크라인이 들어 있어 한 줄에 둘이 못 섰다. 그래서 지수 하나가 화면 한 판을
   차지하고, 그 아래 주비스 인사·제안 줄이 접혀 안 보였다.

   숫자를 줄이는 건 '작게'가 목적이 아니라 **두 칸이 한 줄에 서게** 하려는 수단이다.
   "지수 숫자가 대문의 앵커"라는 규칙은 데스크톱에서 그대로 지켜진다 — 이 블록은 폰에만 든다. */
@media (pointer:coarse) and (max-width:900px), (max-width:560px) {
  #homehero .hwrap { flex-wrap:nowrap; gap:12px; align-items:flex-start; }
  /* min-width:0이 없으면 flex 항목이 내용 폭 아래로 안 줄어 두 칸이 다시 밀려난다 */
  #homehero .hcell { flex:1 1 0; min-width:0; }
  #homehero .big .hv { font-size:30px; letter-spacing:-.02em; }
  #homehero .hk { font-size:var(--fs-lab); letter-spacing:.1em; margin-bottom:3px; }
  #homehero .hc { font-size:11.5px; margin-top:3px; }
  #homehero .hspwrap { margin-top:8px; min-height:42px; }
  #homehero .hspark { height:42px; }
}


/* ===== 폰: 세션 목록 글자 (머신러너님 지시 2026-08-31 "세션 목록의 폰트를 키우자") =====
   13px·12.5px은 **데스크톱 레일 크기**다. 좁은 레일에서 아이콘 옆에 붙는 라벨이라 작아도 됐지만,
   폰에서 이 목록은 화면을 거의 다 쓰는 **주 화면**이다 — 여기서 13px은 클로드(~17px)의 3분의 2다.
   사이드바 드로어를 15.5px로 올렸던 것과 같은 판단이고(app.css 폰 드로어 블록), 그때와 같은
   덤이 따라온다: 줄 높이가 자연히 44px을 넘어 손가락이 빗나가지 않는다.
   섹션 머리(주식포트·고정됨·최근 세션)는 자간이 넓은 라벨이라 한 단만 올린다. */
@media (pointer:coarse) and (max-width:900px), (max-width:560px) {
  #chatnav .cnmain { font-size:15.5px; padding:9px 10px; gap:10px; }
  /* ⚠ 세션 행에는 `#chatnav .cnrow.th .cnmain`(0,3,1)이 따로 있다 — 위 (0,1,1)로는 못 이긴다.
     @media는 특이도를 한 톨도 더해 주지 않으므로 **같은 무게로 다시 쓴다.** 실측 2026-08-31:
     '새로 채팅'만 커지고 정작 세션 이름은 13px 그대로였다(고치려던 바로 그 줄이 안 바뀌었다). */
  #chatnav .cnrow.th .cnmain { font-size:15.5px; }
  #chatnav .cnmore .cnmain { font-size:13.5px; }
  #chatnav .cnnew, #chatnav .cnmk { font-size:15.5px; padding:10px 10px; gap:11px; }
  #chatnav .cnnew svg, #chatnav .cnmk svg { width:16px; height:16px; }
  #chatnav .cnh { font-size:13px; padding:5px 2px; }
  #chatnav .cnempty { font-size:13.5px; }
  #chatnav .cnnewsub .cnmain { font-size:14.5px; }
  #chatnav .cntop b { font-size:16.5px; }
}

/* ===== 폰: '나의 투자 스타일' 입력 글자 (머신러너님 지시 2026-08-31 2차) =====
   "너무 커서 부자연스러워." 맞다 — 16px은 읽는 글자가 아니라 **iOS를 달래려고** 준 값이다
   (16px 미만 입력칸을 탭하면 사파리가 페이지를 확대하고 되돌리지 않는다).
   그래서 평소에는 14.5px로 두고, **포커스되는 순간에만** 16px로 올린다. iOS는 확대 여부를
   포커스 시점의 글자 크기로 판정하므로 이 한 줄이면 확대는 안 일어나면서 평소 화면은 자연스럽다.
   ⚠ 이 트릭은 사파리의 판정 시점에 기대고 있다 — 실기에서 탭했을 때 화면이 확대되면
   되돌려야 한다(그때는 16px 고정이 맞고, 대신 주변을 그 크기에 맞춘다). */
@media (pointer:coarse) and (max-width:900px), (max-width:560px) {
  .pftrait input, .pfnote { font-size:14.5px !important; }
  .pftrait input:focus, .pfnote:focus { font-size:16px !important; }
  .pftrait label { font-size:13px; }
}


/* ===== 「지금 답하는 중」 — 세션 목록 맨 위 (머신러너님 확정 2026-08-31) =====
   고정된 세션은 「고정됨」에, 포트 소속이면 그 아래에도 이미 있다. 최근에까지 넣으면 같은
   줄이 세 번 나온다 — 그래서 중복 대신 **지금인 동안만 서는 자리**를 하나 뒀다.
   끝나면 사라지는 것이 이 줄의 계약이라(`endTurn`이 다시 그린다) 눈에 띄되 무겁지 않게 한다:
   라벨은 액센트, 행은 옅은 액센트 바탕 + 왼쪽 바. 「고정됨」·「최근 세션」과 같은 문법이되
   색으로만 갈린다 — 새 모양을 만들지 않는다. */
#chatnav .cnrunlbl { display:inline-flex; align-items:center; gap:6px; padding:3px 2px;
  font-size:var(--fs-sub); font-weight:700; letter-spacing:.12em; color:var(--accent); }
#chatnav .cnrunlbl .cndot { position:static; flex:none; }
#chatnav .cnrow.cnrun { background:color-mix(in srgb, var(--accent) 9%, transparent); }
#chatnav .cnrow.cnrun::before { content:""; position:absolute; left:0; top:6px; bottom:6px;
  width:2px; border-radius:2px; background:var(--accent); }
#chatnav .cnrow.cnrun .cnname { color:var(--text); font-weight:600; }

@media (pointer:coarse) and (max-width:900px), (max-width:560px) {
  #chatnav .cnrunlbl { font-size:13px; padding:5px 2px; }
}

/* ===== 폰: 대화창 머리의 Pro 배지를 걷는다 (머신러너님 지시 2026-08-31 "이거 pro 빼자") =====
   어제 이 자리로 옮긴 배지다(브랜드 옆). 실물에서 보니 **작은 화면의 머리줄에서 할 일이 없다** —
   요금제는 계정 메뉴에서 언제든 확인하고, 대화 중에 "나는 Pro다"를 되뇌어 줄 이유가 없다.
   `#aibk` 자체는 남긴다 — 비로그인의 "로그인하고 AI와 대화" 권유와 오너의 백엔드 표시가
   같은 자리를 쓰기 때문이다. 걷는 것은 **Pro 상태일 때뿐**이다.
   데스크톱은 머리줄이 넓어 이 블록에 안 걸린다(종전 그대로). */
@media (pointer:coarse) and (max-width:900px), (max-width:560px) {
  #aibk.pro { display:none; }
}
