/* ─────────────────────────────────────────────────────────────────────────
   StockMonitoring 색 시스템
   토큰 정의는 여기 한 곳. 규칙과 대비비는 docs/DESIGN.md 에 있다.
   컴포넌트 CSS 에 HEX 를 직접 쓰지 않는다 (등록된 파생 색 제외).
   ───────────────────────────────────────────────────────────────────────── */

:root {
  /* 2.1 글자 */
  --fg: #172b24;
  --fg-soft: #334c41;
  --muted: #607568;
  --on-accent: #ffffff;

  /* 2.2 면 */
  --bg: #ffffff;
  --bg-2: #ffffff;
  --surface: #ffffff;
  --surface-2: #f3f8f4;

  /* 2.3 선 */
  --border: #dce9df;
  --border-strong: #b9d0bf;

  /* 2.4 accent */
  --accent: #167a55;
  --accent-2: #2c9a70;
  --accent-hover: #105c40;
  --accent-soft: #e9f5ee;
  --accent-ring: rgba(22, 122, 85, 0.22);

  /* 2.5 의미색 — 국내 관례: 상승 빨강 / 하락 파랑 */
  --danger: #b3402c;
  --success: #4a7a38;
  --up: #b3402c;
  --down: #1c5a8a;

  /* 2.5-1 창 뒤를 덮는 막 */
  --scrim: rgba(23, 43, 36, 0.55);
  --page-transition-scrim: rgba(255, 255, 255, 0.68);

  /* 2.6 그림자 잉크 (초록 기운을 섞은 어두운 색) */
  --shadow-xs: 0 1px 2px rgba(23, 72, 49, 0.06);
  --shadow-sm: 0 1px 3px rgba(23, 72, 49, 0.08), 0 1px 2px rgba(23, 72, 49, 0.04);
  --shadow: 0 6px 16px rgba(23, 72, 49, 0.1), 0 2px 6px rgba(23, 72, 49, 0.06);
  --shadow-lg: 0 18px 44px rgba(23, 72, 49, 0.16), 0 4px 12px rgba(23, 72, 49, 0.08);
  --shadow-accent: 0 6px 18px var(--accent-ring);

  /* 3.1 차트 계열 색 */
  --series-price: #167a55;
  --series-revenue: #3f5a75;
  --series-operating: #4c6b47;
  --series-net: #a15139;
  --series-assets: #7a5443;
  --series-liabilities: #85661f;
  --series-equity: #8a4a63;
  --series-cashflow: #2f6b66;

  /* 3.1-1 기술 지표 계열 색 (docs/DESIGN.md 3.1 확장) */
  --series-ma5: #c97a2e;
  --series-ma20: #2f6b66;
  --series-ma30: #7a5443;
  --series-ma60: #3f5a75;
  --series-ma120: #8a4a63;
  --series-ma180: #4c6b47;
  --series-ma224: #85661f;
  --series-rsi: #6b4c91;
  --series-cci: #2f6b66;
  --series-macd: #3f5a75;
  --series-macd-signal: #a15139;
  --series-macd-hist-up: rgba(74, 122, 56, .5);
  --series-macd-hist-dn: rgba(179, 64, 44, .5);
  /* 거래량 막대 — 새 색을 만들지 않고 위 막대 색 쌍을 그대로 쓴다 */
  --series-volume-up: var(--series-macd-hist-up);
  --series-volume-dn: var(--series-macd-hist-dn);
  /* 서브 플롯의 선 색 — 이미 등록된 MA 팔레트를 가리킨다(새 HEX 를 만들지 않는다).
     별칭은 여기 한 번만 적는다: `var()` 는 쓰는 자리에서 풀리므로 어두운 테마의
     `--series-ma*` 재정의를 그대로 따라간다. */
  --series-obv: var(--series-ma120);
  --series-pdi: var(--series-ma5);
  --series-mdi: var(--series-ma30);
  --series-adx: var(--series-ma180);
  --div-bull: #1b7f45;
  --div-bear: #c8372b;

  /* 4페이지 클러스터링 (docs/DESIGN.md 3.3). 계열 색이 아니라 **역할 색**이다 —
     한 축에 백 개 넘는 선이 깔리므로 종목마다 색을 주면 무지개가 된다.
     평균/중앙값/구성원/강조 넷만 구분한다. */
  --cluster-mean: #3f5a75;
  --cluster-median: #8a4a63;
  --cluster-member: rgba(122, 84, 67, .22);

  /* 3.2 데이터 상태 톤 */
  --tone-cfs: #115e59;
  --tone-ofs: #5c5044;
  --tone-delayed: #92400e;

  /* 지식그래프 — 우주 배경과 그 위의 노드(DESIGN.md 3.4). 밝기 모드와 상관없이 늘 밤하늘이다. */
  --kg-space: #04050b;
  --kg-space-2: #121634;
  --kg-space-edge: rgba(140, 150, 210, 0.28);
  --kg-star: rgba(255, 255, 255, 0.9);
  --kg-star-dim: rgba(190, 200, 255, 0.55);
  --kg-ink: #e9ecff;
  --kg-ink-dim: rgba(200, 208, 240, 0.7);
  --kg-label-bg: rgba(10, 12, 30, 0.72);
  --kg-hot: #fff6d6;
  --kg-trail: #ffd166;
  --kg-dim: rgba(120, 130, 170, 0.3);
  --kg-edge: rgba(150, 170, 255, 0.5);
  --kg-edge-dim: rgba(120, 135, 200, 0.2);
  --kg-cluster: #8ea6d8;
  --kg-stock: #c9d2ea;
  --kg-buy: #22c55e;
  --kg-sell: #ff3b3b;
  --kg-picked: #f04452;
  /* 3D 노드 전용: 흑은빛 바탕과 기간별 금속빛 장식. 선·신호 색과 분리한다. */
  --kg-metal-silver: #d8e0ed;
  --kg-metal-steel: #8291ad;
  --kg-metal-glint: #fffdf5;
  --kg-metal-gold: #e6ca91;
  --kg-metal-rose: #ca9eae;
  --kg-metal-ice: #97cedb;
  --kg-metal-jade: #a6c9b7;
  --kg-metal-amethyst: #ad9ed2;
  --kg-r3m: #ff9f68;
  --kg-r6m: #6fdcff;
  --kg-rytd: #8dff9e;
  --kg-r1y: #ffd36b;
  --kg-r2y: #ff8ad8;
  --kg-r3y: #b79bff;
  --tone-na: #9b3049;
  --tone-adjusted: #1c5a8a;

  /* 6. 색이 아닌 토큰 */
  --radius-xl: 20px;
  --radius-lg: 16px;
  --radius-md: 11px;
  --radius-sm: 7px;
  --radius-pill: 999px;
  --ease: cubic-bezier(0.4, 0, 0.2, 1);
}


/* ───────────────────────────────────────────────────────────────── 기본 */

* { box-sizing: border-box; }

html {
  /* 기준 글자 크기. 나머지가 rem 이라 여기만 바꾸면 화면 전체가 비례한다. */
  font-size: 20px;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  min-height: 100vh;
  color: var(--fg-soft);
  font-family: "Pretendard", -apple-system, BlinkMacSystemFont, "Segoe UI",
    "Malgun Gothic", "Apple SD Gothic Neo", system-ui, sans-serif;
  font-size: 0.95rem;
  line-height: 1.65;
  /* 한글은 낱말 단위로만 줄을 바꾼다 — 좁은 화면에서 '종목' 이 '종 / 목' 으로
     갈라지지 않게. 그래도 넘치는 긴 영문만 끊는다. */
  word-break: keep-all;
  overflow-wrap: break-word;
  background-color: var(--bg);
  background: var(--bg);
}

.page-loader {
  position: fixed;
  z-index: 9999;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.7rem;
  background: var(--page-transition-scrim);
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
  color: var(--fg);
  opacity: 1;
  visibility: visible;
  transition: opacity 0.22s var(--ease), visibility 0.22s var(--ease);
}
.page-loader.is-done { opacity: 0; visibility: hidden; pointer-events: none; }
.page-loader img { display: block; width: 4.4rem; height: 4.4rem; animation: brand-breathe 1.35s ease-in-out infinite; }
.page-loader-name { font-size: 1.05rem; font-weight: 800; letter-spacing: -0.03em; }
.page-loader-bar {
  position: relative;
  width: 4rem;
  height: 0.16rem;
  margin-top: 0.15rem;
  overflow: hidden;
  border-radius: var(--radius-pill);
  background: var(--accent-soft);
}
.page-loader-bar::after {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: 35%;
  border-radius: inherit;
  background: var(--accent);
  animation: brand-progress 1.15s ease-in-out infinite alternate;
}
@keyframes brand-breathe { 50% { transform: scale(1.055); opacity: 0.82; } }
@keyframes brand-progress { to { transform: translateX(190%); } }

h1, h2, h3 { color: var(--fg); margin: 0; font-weight: 700; letter-spacing: -0.01em; }
h1 { font-size: 1.5rem; }
h2 { font-size: 1.1rem; }
h3 { font-size: 0.98rem; }

a { color: var(--accent); text-decoration: none; }
a:hover { color: var(--accent-hover); text-decoration: underline; }

::selection { background: var(--accent-soft); color: var(--accent-hover); }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

::-webkit-scrollbar { width: 12px; height: 12px; }
::-webkit-scrollbar-thumb {
  background: var(--border-strong);
  border-radius: var(--radius-pill);
  border: 3px solid transparent;
  background-clip: content-box;
}

.num { font-variant-numeric: tabular-nums; }
[hidden] { display: none !important; }

/* ───────────────────────────────────────────────────────────── 레이아웃 */

.wrap {
  max-width: 66rem;
  margin: 0 auto;
  padding: 1.2rem 1.1rem 4rem;
}
/* 띠가 이미 위쪽을 채우므로 본문은 띠에서 조금만 떨어진다. */
.topbar-band + .wrap { padding-top: 1.4rem; }

/* 분석·비교·타임라인은 사이드바만큼, 관리자는 3열 카드·섹터 편집 그리드가
   66rem 안에서는 한 열당 너무 좁아져서 같이 넓힌다. 클러스터링은 왼쪽 설정 칸
   을 떼고 남은 폭에 묶음 카드(그림 + 구성 종목 표)를 두 열로 세우는데,
   66rem 에서는 표의 종목명과 단추 글자가 줄바꿈되거나 잘려서 같이 넓힌다. */
.page-analysis .wrap, .page-compare .wrap, .page-timeline .wrap, .page-admin .wrap,
.page-clusters .wrap, .page-divergence .wrap { max-width: 100rem; }

/* 설정 칸의 폭은 화면 폭에 따라 세 단계다. 예전에는 34rem 하나로 못 박혀 있어서
   12.9" 아이패드(1366px)에서 설정이 화면의 40% 를 먹고, 정작 보러 온 그림이
   그만큼 눌렸다. 넓어질수록만 넓어진다 — 좁은 쪽을 기준으로 잡는다. */
.page-layout {
  --settings-w: 21rem;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, var(--settings-w));
  gap: 1.4rem;
  align-items: start;
}
@media (min-width: 1440px) { .page-layout { --settings-w: 24rem; } }
@media (min-width: 1700px) { .page-layout { --settings-w: 27rem; } }

.page-main { min-width: 0; }
.page-aside { min-width: 0; position: sticky; top: 1rem; }
.page-aside:empty { display: none; }
/* 사이드바가 비어 있으면(관리자) grid-template-columns 가 여전히 오른쪽 열
   너비를 예약해 본문이 그만큼 좁아 보인다 — 아예 1열로 접는다. */
.page-layout:has(.page-aside:empty) { grid-template-columns: 1fr; }

/* 분석·비교·타임라인: 검색·옵션 폼 + 섹터 패널(왼쪽 열)이 결과(오른쪽 열)보다
   먼저 온다. 아직 조회한 종목이 없으면(#result 도 #loading 도 안 보이면)
   오른쪽 열을 비워 두지 않고 왼쪽 열 하나만 화면 가운데로 모은다 — 검색 전엔
   빈 결과 자리를 보여줄 이유가 없다. 세 페이지가 같은 규칙을 쓴다.

   **두 열 규칙 전체를 min-width 로 감싼다.** `:has(#result…)` 는 아래쪽 좁은
   화면 미디어 쿼리(`.page-timeline .page-layout`, 0-2-0)보다 특정도가 높아서
   (0-4-0), 감싸지 않으면 좁은 화면에서도 두 열이 그대로 남는다 — 실제로 폭
   473px 에서 본문 열이 0px 로 찌부러졌다. 미디어 쿼리는 특정도를 올려 주지
   않으므로, 순서로 이기려 하지 말고 **애초에 적용 범위를 나눈다.** */
@media (min-width: 1181px) {
  .page-analysis .page-layout, .page-compare .page-layout, .page-timeline .page-layout {
    grid-template-columns: minmax(0, var(--settings-w));
    justify-content: center;
  }
  .page-analysis .page-layout:has(#result:not([hidden])),
  .page-analysis .page-layout:has(#loading:not([hidden])),
  .page-compare .page-layout:has(#result:not([hidden])),
  .page-compare .page-layout:has(#loading:not([hidden])),
  .page-timeline .page-layout:has(#result:not([hidden])),
  .page-timeline .page-layout:has(#loading:not([hidden])) {
    grid-template-columns: minmax(0, var(--settings-w)) minmax(0, 1fr);
    justify-content: stretch;
  }
  .page-analysis .page-aside, .page-compare .page-aside, .page-timeline .page-aside { order: 1; }
  .page-analysis .page-main, .page-compare .page-main, .page-timeline .page-main { order: 2; }

  /* 검색 폼 + 섹터 패널(사이드바)이 결과 목록(본문)과 휠 스크롤을 따로 받도록,
     사이드바 자체를 뷰포트 높이로 제한된 스크롤 컨테이너로 만든다. sticky 로
     붙어 있기만 하면 본문을 스크롤할 때 같이 끌려다녀 독립적으로 못 움직인다.

     **결과가 있을 때만** 그렇게 한다. 검색 전에는 사이드바가 유일한 열이라
     가운데 혼자 서 있는데, 그때까지 높이를 100vh 로 묶으면 검색 폼과 섹터 패널이
     화면 안에서 따로 스크롤돼 페이지가 안 움직이는 것처럼 보인다. */
  .page-analysis .page-layout:has(#result:not([hidden])) .page-aside,
  .page-analysis .page-layout:has(#loading:not([hidden])) .page-aside,
  .page-compare .page-layout:has(#result:not([hidden])) .page-aside,
  .page-compare .page-layout:has(#loading:not([hidden])) .page-aside,
  .page-timeline .page-layout:has(#result:not([hidden])) .page-aside,
  .page-timeline .page-layout:has(#loading:not([hidden])) .page-aside {
    max-height: calc(100vh - 2rem);
    overflow-y: auto;
  }

  /* 한 열만 있는(= 검색 전) 상태에서는 붙잡아 둘 본문이 없다. */
  .page-analysis .page-layout:not(:has(#result:not([hidden]))):not(:has(#loading:not([hidden]))) .page-aside,
  .page-compare .page-layout:not(:has(#result:not([hidden]))):not(:has(#loading:not([hidden]))) .page-aside,
  .page-timeline .page-layout:not(:has(#result:not([hidden]))):not(:has(#loading:not([hidden]))) .page-aside {
    position: static;
  }

  /* 클러스터링: 왼쪽(요약·설정·안내)은 좁고, 오른쪽(묶음 카드)은 넓다.
     묶음 카드가 여러 개면 오른쪽 열이 훨씬 길어지므로, 왼쪽 열 위에서 휠을
     굴릴 때 오른쪽까지 같이 끌려 스크롤되지 않도록 오른쪽 열을 뷰포트
     높이로 제한된 자체 스크롤 컨테이너로 만든다. */
  .page-clusters .page-layout { grid-template-columns: minmax(0, var(--settings-w)) minmax(0, 1fr); }
  .page-clusters .page-aside {
    max-height: calc(100vh - 2rem);
    overflow-y: auto;
  }

  /* 다이버전스: 왼쪽(시장·필터·안내)은 좁고, 오른쪽(신호 목록)은 넓다.
     목록이 수백 줄이라 왼쪽 열 위에서 휠을 굴릴 때 목록까지 끌려가지 않도록
     오른쪽 열을 자체 스크롤 컨테이너로 만든다(클러스터링과 같은 규칙). */
  .page-divergence .page-layout { grid-template-columns: minmax(0, var(--settings-w)) minmax(0, 1fr); }
  .page-divergence .page-aside {
    max-height: calc(100vh - 2rem);
    overflow-y: auto;
  }
}

/* 좁은 화면은 한 열. 검색·설정(사이드바)이 위, 결과가 아래다 — 위쪽 규칙이
   min-width 로 갇혀 있어서 여기서 되돌릴 것은 순서뿐이다. */
@media (max-width: 1180px) {
  .page-layout { grid-template-columns: 1fr; gap: 1rem; }
  .page-aside { position: static; order: 2; }
  .page-analysis .page-aside, .page-compare .page-aside, .page-timeline .page-aside { order: 1; }
  .page-analysis .page-main, .page-compare .page-main, .page-timeline .page-main { order: 2; }
}

/* ── 설정 칸 접기 ────────────────────────────────────────────────────
   **모든 폭에서** 접힌다. 좁은 화면에서는 설정이 결과 위에 얹혀 결과를 아래로
   밀어내고, 넓은 화면에서는 옆에서 한 뼘을 가져간다 — 어느 쪽이든 "지금은
   결과만 보고 싶다" 가 있다. 손잡이는 설정이 놓인 칸(`[data-settings-pane]`)
   안에 있고, 그 칸이 어디인지는 서버가 정한다(app.py 의 `SETTINGS_SLOT`). */
.aside-toggle {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  width: 100%;
  font: inherit;
  font-weight: 700;
  cursor: pointer;
  text-align: left;
  color: var(--fg);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  padding: 0.7rem 1.1rem;
  margin-bottom: 1rem;
  transition: border-color 0.15s var(--ease);
}
.aside-toggle:hover { border-color: var(--border-strong); }
.aside-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.aside-toggle[aria-expanded="false"] .caret { transform: rotate(-90deg); }
.aside-toggle-label { flex: 1; min-width: 0; }
.aside-toggle-state { flex: none; color: var(--muted); font-size: 0.82rem; font-weight: 600; }

/* 접으면 카드 전부가 사라지고 손잡이만 남는다. 남은 손잡이 아래는
   `.page-layout` 의 gap 이 이미 벌려 주므로 카드용 margin 을 뺀다.
   접힌 손잡이는 **얇은 띠**다 — 결과를 보려고 접은 것이니 손잡이가 자리를
   먹으면 안 된다(폰·아이패드 세로에서 3rem 넘게 차지하던 것을 줄였다). */
[data-settings-pane][data-collapsed] > .aside-body { display: none; }
[data-settings-pane][data-collapsed] > .aside-toggle {
  margin-bottom: 0;
  padding: 0.38rem 0.9rem;
  font-size: 0.86rem;
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-xs);
  color: var(--fg-soft);
}
[data-settings-pane][data-collapsed] > .aside-toggle .aside-toggle-state { font-size: 0.78rem; }

/* 넓은 화면에서 접으면 설정 열이 **얇은 세로 띠 하나**(2rem)로 줄고, 남는 폭을
   전부 결과가 가져간다. 통째로 숨기지 않는 것은 되돌릴 자리를 남겨 두기 위해서다.

   `writing-mode` 를 **버튼에 걸지 않는다.** 아이패드 사파리는 폼 컨트롤(button)
   의 세로쓰기를 제대로 그리지 못해 손잡이가 가로 글자 그대로 좁은 열에 끼어
   절반이 잘려 보였다. 버튼은 세로로 쌓는 flex 상자로 두고, 글자 칸(span)만
   세로로 세운다 — 일반 요소의 세로쓰기는 사파리도 오래전부터 그린다.

   열 너비를 다시 적어 이기려 들지 않는다 — 위쪽 열 규칙들이 `#result` 를 물어
   특정도가 (1-3-0) 이라 `.page-layout.is-collapsed` 로는 못 이긴다. 대신 그
   규칙들이 **공통으로 읽는 변수 하나**를 바꾼다. `minmax(0, auto)` 는 칸이
   내용(= 손잡이)만큼만 차지한다는 뜻이라, 다섯 화면의 열 규칙을 한 줄도
   건드리지 않고 같은 결과를 얻는다. */
@media (min-width: 1181px) {
  .page-layout.is-collapsed { --settings-w: 2rem; column-gap: 0.9rem; }
  .page-layout.is-collapsed [data-settings-pane] {
    position: sticky;
    top: 1rem;
    width: 2rem;
    max-height: none;
    overflow: visible;
  }
  .page-layout.is-collapsed [data-settings-pane] > .aside-toggle {
    flex-direction: column;
    align-items: center;
    justify-content: flex-start;
    gap: 0.55rem;
    width: 2rem;
    min-height: 7.5rem;
    padding: 0.7rem 0;
    overflow: hidden;
    border-radius: var(--radius-pill);
  }
  .page-layout.is-collapsed .aside-toggle-label {
    flex: none;
    -webkit-writing-mode: vertical-rl;
    writing-mode: vertical-rl;
    white-space: nowrap;
    font-size: 0.8rem;
    letter-spacing: 0.08em;
    line-height: 1;
  }
  .page-layout.is-collapsed .aside-toggle-state { display: none; }
  /* 설정 칸은 늘 왼쪽 열이라 "펴기" 는 오른쪽으로 연다 — 삼각형이 오른쪽을 본다. */
  .page-layout.is-collapsed .aside-toggle .caret { transform: rotate(-90deg); }
  .page-layout.is-collapsed [data-settings-pane] > .aside-toggle:hover {
    color: var(--accent);
    border-color: var(--accent-ring);
  }
}

/* 머리말 — 마크·이름표는 가운데, 계정은 오른쪽 끝, 메뉴는 그 아래 한가운데.
   계정 칩은 절대 배치로 흐름에서 빼낸다. 흐름에 두면 그 폭만큼 이름표가
   왼쪽으로 밀려 "가운데"가 눈에 보이는 가운데와 어긋난다. */
/* 머리말 띠는 흰 면에 얇은 선을 두른다. `.wrap` 이 본문과 좌우 눈금을 맞춘다. */
.topbar-band {
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  box-shadow: var(--shadow-xs);
}
.topbar-band .wrap { padding-top: 0.85rem; padding-bottom: 0.85rem; }

.topbar {
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
}

.topbar-row {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 2.4rem;
}

.brand { display: inline-flex; align-items: center; gap: 0.55rem; text-decoration: none; }
.brand:hover { text-decoration: none; }

.brand-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  border-radius: 0.65rem;
  transition: transform 0.15s var(--ease);
}
.brand-mark img { width: 2rem; height: 2rem; display: block; }
.brand:hover .brand-mark { transform: translateY(-1px); }

/* 계정 — 이름 다음에 설정·관리자(권한이 있을 때)·로그아웃을 한 줄로 둔다. */
.account {
  position: absolute;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  gap: 0.9rem;
}
.account-name {
  color: var(--fg-soft);
  font-weight: 700;
  font-size: 0.9rem;
  text-decoration: none;
  max-width: 12rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  transition: color 0.15s var(--ease);
}
.account-out {
  appearance: none;
  border: 0;
  background: none;
  padding: 0;
  cursor: pointer;
  font: inherit;
  font-size: 0.86rem;
  font-weight: 600;
  color: var(--muted);
  transition: color 0.15s var(--ease);
}
.account-out:hover { color: var(--fg); }
.account-out[aria-current="page"] { color: var(--accent); }

.nav {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 0.15rem;
  flex-wrap: wrap;
}

.nav a {
  color: var(--muted);
  font-size: 0.92rem;
  font-weight: 700;
  padding: 0.4rem 0.95rem;
  border-radius: var(--radius-pill);
  text-decoration: none;
  transition: background 0.15s var(--ease), color 0.15s var(--ease);
}
.nav a:hover { color: var(--fg); background: var(--surface-2); text-decoration: none; }
.nav a[aria-current="page"] {
  color: var(--accent);
  background: var(--accent-soft);
  box-shadow: var(--shadow-xs);
}
/* 페이지 제목 — 머리말에서 내려왔다. 이름표와 제목이 한 줄에 붙어 있으면
   어느 쪽이 이 화면의 이름인지 흐려진다. */
.page-head { margin-bottom: 1rem; }
.page-head h1 { font-size: 1.35rem; }
.page-head .sub { display: block; margin-top: 0.3rem; color: var(--muted); font-size: 0.88rem; }
.page-head .sub:empty { display: none; }

/* 좁은 화면에서는 계정을 흐름으로 되돌린다. 절대 배치로 두면 마크와 겹친다. */
@media (max-width: 720px) {
  .topbar-row { flex-wrap: wrap; gap: 0.6rem; }
  .account { position: static; transform: none; margin-left: auto; }
  .brand { margin-right: auto; }
  /* 메뉴 여섯은 3칸 × 2줄 격자로 세운다. flex-wrap 으로 흘리면 줄마다 개수가
     달라져(4 + 2) 둘째 줄이 한쪽으로 쏠린다 — 칸을 고정해야 가운데가 맞는다. */
  .nav {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 0.25rem;
    width: 100%;
    max-width: 26rem;
    margin: 0 auto;
  }
  .nav a { text-align: center; white-space: nowrap; padding: 0.4rem 0.3rem; font-size: 0.86rem; }
}

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-sm);
  padding: 1.1rem 1.2rem;
  margin-bottom: 1rem;
}

.card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.8rem;
  flex-wrap: wrap;
  margin-bottom: 0.85rem;
}

.hint { color: var(--muted); font-size: 0.85rem; }
.nowrap { white-space: nowrap; }
/* 카드 제목은 한 줄이다. 옆의 힌트가 자리를 먹으면 제목을 접는 대신 힌트가
   다음 줄로 내려간다(`.card-head` 가 wrap 하는 flex). 그래도 모자라면 말줄임. */
.card-head > h2, .section-toggle h2 {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}
.section-title { color: var(--muted); font-size: 0.82rem; font-weight: 700; letter-spacing: 0.02em; }

/* ─────────────────────────────────────────────────────────────── 검색 */

.search-row { display: flex; gap: 0.6rem; align-items: stretch; }
.search-box { position: relative; flex: 1; }

input[type="text"], input[type="date"], input[type="number"],
input[type="email"], input[type="password"], select, textarea {
  width: 100%;
  font: inherit;
  color: var(--fg);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 0.6rem 0.8rem;
  transition: border-color 0.15s var(--ease), box-shadow 0.15s var(--ease);
}

textarea { resize: vertical; min-height: 3.4rem; line-height: 1.5; }
input::placeholder, textarea::placeholder { color: var(--muted); }

input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-ring);
}

.btn {
  font: inherit;
  font-weight: 700;
  cursor: pointer;
  white-space: nowrap;
  color: var(--on-accent);
  background: linear-gradient(180deg, var(--accent-2), var(--accent));
  border: 1px solid var(--accent);
  border-radius: var(--radius-md);
  padding: 0.6rem 1.2rem;
  box-shadow: var(--shadow-accent);
  transition: transform 0.12s var(--ease), box-shadow 0.15s var(--ease);
}
.btn:hover { transform: translateY(-1px); box-shadow: var(--shadow); }
.btn:active { transform: translateY(0); box-shadow: var(--shadow-xs); }
.btn[disabled] { opacity: 0.55; cursor: progress; transform: none; }

.btn-ghost {
  color: var(--fg-soft);
  background: var(--surface-2);
  border: 1px solid var(--border);
  box-shadow: none;
  font-weight: 600;
}
.btn-ghost:hover { color: var(--fg); border-color: var(--border-strong); box-shadow: var(--shadow-xs); }

/* 자동완성 */

.suggest {
  position: absolute;
  z-index: 30;
  top: calc(100% + 0.35rem);
  left: 0;
  right: 0;
  max-height: 20rem;
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: 0.3rem;
}
.suggest:empty, .suggest[hidden] { display: none; }

.suggest-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.7rem;
  padding: 0.5rem 0.65rem;
  border-radius: var(--radius-md);
  cursor: pointer;
}
.suggest-item:hover, .suggest-item.active { background: var(--surface-2); }
.suggest-item .name { color: var(--fg); font-weight: 600; }
.suggest-item .code { color: var(--muted); font-size: 0.85rem; }

/* 거래소 — 국내와 미국이 한 목록에 섞이므로 어느 시장인지 적는다.
   회사명과 종목코드 사이에 두되 색은 죽여 둔다: 고를 때 읽는 것은 이름이고,
   거래소는 "왜 이게 여기 있지" 를 물을 때만 눈에 들어오면 된다.
   `margin-left: auto` 로 코드와 함께 오른쪽에 붙어, 이름이 길어져도
   두 칩의 세로줄이 흔들리지 않는다. */
.suggest-item .exchange {
  margin-left: auto;
  flex: none;
  color: var(--muted);
  font-size: 0.72rem;
  letter-spacing: 0.02em;
  padding: 0.1rem 0.4rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}
.suggest-item .code { flex: none; }

/* ─────────────────────────────────────────────────────────────── 옵션 */

.options {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem 1.6rem;
  margin-top: 0.9rem;
  padding-top: 0.9rem;
  border-top: 1px solid var(--border);
}

.opt { display: flex; flex-direction: column; gap: 0.4rem; }
.opt > label { color: var(--muted); font-size: 0.82rem; font-weight: 700; letter-spacing: 0.02em; white-space: nowrap; }
.opt select, .opt input { width: auto; }
/* 옵션 제목 옆에 붙는 "전체 선택 · 전체 해제" — 그 묶음 하나만 건드린다. */
.opt-head { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; flex-wrap: wrap; }
.opt-head > label { color: var(--muted); font-size: 0.82rem; font-weight: 700; letter-spacing: 0.02em; white-space: nowrap; }

/* 세부 설정 접기 — `<details data-fold>`. 처음에는 닫혀 있다(common.js). 제목 줄이
   곧 손잡이고, 삼각형은 카드 접기(`.caret`)와 같은 모양이다. */
.opt-fold { margin-top: 0.9rem; border-top: 1px solid var(--border); }
.opt-fold > summary {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding-top: 0.8rem;
  list-style: none;
  cursor: pointer;
  color: var(--muted);
  font-size: 0.82rem;
  font-weight: 700;
  white-space: nowrap;
}
.opt-fold > summary::-webkit-details-marker { display: none; }
.opt-fold > summary::before {
  content: "";
  flex: none;
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
  border-top: 6px solid currentColor;
  transform: rotate(-90deg);
  transition: transform 0.15s var(--ease);
}
.opt-fold[open] > summary::before { transform: none; }
.opt-fold > summary:hover { color: var(--accent); }
.opt-fold > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: var(--radius-sm); }
/* 접는 줄이 이미 금을 긋는다 — 옵션 묶음의 윗금은 겹치므로 뺀다. */
.opt-fold > .options { margin-top: 0.8rem; padding-top: 0; border-top: 0; }

/* 결과 안 기술 지표 빠른 단추 — 설정 칸을 접었을 때만 보인다. */
.indicator-quick { display: none; }
.indicator-quick-label { color: var(--fg-soft); font-size: 0.8rem; font-weight: 700; margin-right: auto; }
.page-compare .page-layout.is-collapsed .indicator-quick {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.35rem;
  padding-top: 0.75rem;
  margin-top: 0.75rem;
  border-top: 1px solid var(--border);
}

/* 선택한 여섯 종목은 차트 색과 같은 테두리로 구분한다. */
.selected-companies { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0.65rem; }
.selected-company {
  min-width: 0;
  padding: 0.75rem 0.85rem;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-left: 3px solid var(--company-color);
  border-radius: var(--radius-md);
}
.selected-company-identity { display: flex; align-items: baseline; gap: 0.4rem; flex-wrap: wrap; min-width: 0; }
.selected-company-identity strong { color: var(--fg); overflow-wrap: anywhere; }
.selected-company-identity .code { color: var(--muted); font-size: 0.78rem; }
.selected-company-quote { display: flex; align-items: baseline; gap: 0.15rem 0.5rem; flex-wrap: wrap; margin-top: 0.55rem; font-variant-numeric: tabular-nums; }
.selected-company-price { color: var(--fg); font-size: 1.25rem; font-weight: 700; white-space: nowrap; }
.selected-company-change { font-size: 0.8rem; font-weight: 700; white-space: nowrap; }
@media (max-width: 900px) { .selected-companies { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px) { .selected-companies { grid-template-columns: 1fr; } }
.bulk { display: inline-flex; gap: 0.3rem; }
.btn-xs { padding: 0.14rem 0.5rem; font-size: 0.74rem; }

.segmented {
  display: inline-flex;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  padding: 3px;
  gap: 3px;
}

.segmented button {
  font: inherit;
  font-size: 0.9rem;
  font-weight: 700;
  cursor: pointer;
  color: var(--muted);
  background: transparent;
  border: 0;
  border-radius: var(--radius-pill);
  padding: 0.3rem 0.95rem;
  /* 위 `.seg-wrap` 의 모서리 계산이 이 줄높이를 전제한다. 물려받지 않고 못 박는다. */
  line-height: 1.65;
  white-space: nowrap;
  transition: background 0.15s var(--ease), color 0.15s var(--ease);
}
.segmented button:hover { color: var(--fg); }
.segmented button[aria-pressed="true"] {
  color: var(--accent);
  background: var(--accent-soft);
  box-shadow: var(--shadow-xs);
}
/* 단추가 넷인 옵션(2페이지 '주가 눈금')은 좁은 사이드바에서 줄을 넘겨야 한다.
   `.segmented` 는 inline-flex(nowrap) 라 그냥 두면 카드 밖으로 삐져나간다.

   이름이 `seg-wrap` 인 이유: 예전 이름은 그냥 `wrap` 이었는데, 그건 이미 쪽
   전체를 감싸는 바깥 상자의 이름(`.wrap`, 224줄)이다. 같은 이름을 쓰는 바람에
   `.segmented.wrap` 이 쪽 상자의 `max-width`·`margin: 0 auto` 를 통째로 물려받고,
   680px 아래에서는 `.wrap { padding: 0.9rem 0.7rem 3rem }` 까지 이겨 버려서
   손바닥 화면의 '기술 지표' 알약 상자가 단추 높이의 세 배로 부풀었다.
   레이아웃 클래스와 부품 클래스는 이름을 겹치지 않는다.

   모서리도 같이 푼다: 줄이 접히면 상자가 두세 줄만큼 높아지는데 알약 반지름
   (999px)은 "높이의 절반" 으로 풀리므로 모서리가 크게 휘어 **왼쪽 위 단추의
   알약이 그 곡선 밖으로 삐져나온다**. 여러 줄 상자는 "단추 알약 + 안쪽 여백"
   만큼만 휘게 한다 — 단추 높이 2.085rem(글자 0.9rem × 줄높이 1.65 + 위아래
   0.3rem)의 절반에 상자 안쪽 여백 3px. 한 줄일 때는 그 값이 곧 알약이다. */
.segmented.seg-wrap {
  flex-wrap: wrap;
  border-radius: calc(1.05rem + 3px);
}

/* 3열 격자로 배치 (클러스터링 페이지 시장 선택 등에서 긴 글자 잘림 방지).
   칸이 넷 이상이면 이 격자도 두 줄이 되므로 모서리는 `.seg-wrap` 과 같은
   값으로 맞춘다(3열 단추도 위아래 여백이 0.3rem 으로 같다). */
.segmented.grid-3 {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  border-radius: calc(1.05rem + 3px);
}
.segmented.grid-4 {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  border-radius: calc(1.05rem + 3px);
}
.segmented.grid-3 button, .segmented.grid-4 button { width: 100%; min-width: 0; padding: 0.3rem 0.2rem; overflow: hidden; text-overflow: ellipsis; }
/* 옵션 줄 안의 3열 격자는 제 줄을 통째로 쓴다 — 내용 폭으로 줄면 1fr 이 풀려
   칸이 들쭉날쭉해진다(지표 칩과 같은 이유). */
.options .opt:has(.grid-3), .options .opt:has(.grid-4) { flex: 1 0 100%; }

/* 지표 칩 — 고정 4열, 칸마다 같은 너비(`1fr`). 칩 하나하나의 글자 길이가 다
   달라서(매출액 3자 vs 영업활동현금흐름 8자) flex-wrap 만으로는 줄마다 오른쪽
   끝이 들쭉날쭉해진다. 격자로 묶어야 폭이 통일된다.

   2열이었을 때는 지표가 일곱 개 + 관리자 키워드 지표까지 붙어 사이드바가 세로로
   길어졌다. 4열이 되면 한 칸이 좁아지므로 **글자를 줄이고 색점을 뺐다** — 점은
   켜짐/꺼짐을 색으로 두 번 말하던 것이라(칩 전체가 이미 계열 색으로 차오른다)
   빼도 잃는 정보가 없고, 그 자리(약 1rem)가 8자 라벨이 들어갈 여유를 만든다. */
/* `.options` 는 wrap 하는 flex 라 각 `.opt` 가 내용 너비로 줄어든다 — 그대로 두면
   칩 격자도 내용 너비가 돼(1fr 이 max-content 로 풀린다) 카드 오른쪽이 비고,
   옆에 다른 옵션이 끼어들어 줄이 어긋난다. 지표 줄은 늘 제 줄을 통째로 쓴다. */
.options .opt:has(.chips) { flex: 1 0 100%; }

.chips {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0.35rem;
}

.chip {
  font: inherit;
  /* 4열 한 칸이 약 149px 이다. 가장 긴 라벨 '영업활동현금흐름'(8자)이
     좌우 여백과 함께 그 안에 앉는 크기로 맞췄다. */
  font-size: 0.8rem;
  font-weight: 600;
  cursor: pointer;
  color: var(--muted);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  padding: 0.34rem 0.35rem;
  min-width: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: border-color 0.15s var(--ease), color 0.15s var(--ease);
}

/* 관리자가 키워드로 만든 지표는 라벨 길이를 알 수 없다 — 넘치면 자르고, 전체는
   `title` 로 남긴다(칸 너비가 라벨 하나 때문에 벌어지면 통일이 깨진다). */
.chip-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.chip[aria-pressed="true"] {
  color: var(--chip-color, var(--accent));
  border-color: currentColor;
  background: color-mix(in srgb, currentColor 12%, var(--surface));
}

/* 종목 태그(2·3페이지) */

.tags { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-top: 0.7rem; }
.tags:empty { display: none; }

.tag {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.9rem;
  font-weight: 700;
  color: var(--tag-color, var(--fg));
  background: color-mix(in srgb, var(--tag-color, var(--accent)) 12%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--tag-color, var(--accent)) 32%, transparent);
  border-radius: var(--radius-pill);
  padding: 0.28rem 0.5rem 0.28rem 0.85rem;
}
.tag .code { color: var(--muted); font-weight: 600; font-size: 0.82rem; }
.tag button {
  font: inherit;
  line-height: 1;
  cursor: pointer;
  color: var(--muted);
  background: transparent;
  border: 0;
  padding: 0.1rem 0.3rem;
  border-radius: var(--radius-pill);
}
.tag button:hover { color: var(--danger); background: var(--surface-2); }

/* ─────────────────────────────────────────────────────────────── 배지 */

.badges { display: flex; flex-wrap: wrap; gap: 0.35rem; }

.badge {
  --tone: var(--muted);
  color: var(--tone);
  background: color-mix(in srgb, var(--tone) 14%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--tone) 28%, transparent);
  border-radius: var(--radius-pill);
  padding: 0.14rem 0.62rem;
  font-size: 0.82rem;
  font-weight: 700;
  white-space: nowrap;
}
.badge.cfs { --tone: var(--tone-cfs); }
.badge.ofs { --tone: var(--tone-ofs); }
.badge.delayed { --tone: var(--tone-delayed); }
.badge.na { --tone: var(--tone-na); }
.badge.adjusted { --tone: var(--tone-adjusted); }

/* ───────────────────────────────────────────────────────────── 종목 헤더 */

.quote-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 1rem; flex-wrap: wrap; }
.quote-name { display: flex; align-items: baseline; gap: 0.55rem; flex-wrap: wrap; }
.quote-name .code { color: var(--muted); font-size: 0.88rem; }

.quote-price { display: flex; align-items: baseline; gap: 0.6rem; font-variant-numeric: tabular-nums; }
.quote-price .now { color: var(--fg); font-size: 1.75rem; font-weight: 700; }
.quote-price .delta { font-size: 1rem; font-weight: 700; }

.up { color: var(--up); }
.down { color: var(--down); }
.flat { color: var(--muted); }

/* ─────────────────────────────────────────────────────────────── 차트 */

.chart-wrap { position: relative; }
.chart-wrap svg { display: block; width: 100%; height: auto; overflow: visible; touch-action: none; }

.grid-line { stroke: var(--border); stroke-width: 1; }
.axis-line { stroke: var(--border-strong); stroke-width: 1; }
.zero-line { stroke: var(--border-strong); stroke-width: 1.5; stroke-dasharray: 5 4; }
.axis-text { fill: var(--muted); font-size: 16px; font-variant-numeric: tabular-nums; }
.axis-title { fill: var(--muted); font-size: 15px; font-weight: 700; }
.zero-text { fill: var(--fg-soft); font-size: 16px; font-weight: 700; }

/* 막대 위(전기 대비 증감률) — docs/DESIGN.md 상승 빨강 / 하락 파랑 관례를 그대로 쓴다 */
.bar-change-label { font-size: 13px; font-weight: 700; font-variant-numeric: tabular-nums; }
.bar-change-label.up { fill: var(--up); }
.bar-change-label.down { fill: var(--down); }
.bar-change-label.na { fill: var(--muted); font-weight: 600; }
.fy-line { stroke: var(--border); stroke-width: 1; stroke-dasharray: 2 4; }

.series-line { fill: none; stroke-width: 2.2; stroke-linejoin: round; stroke-linecap: round; }
.series-bar { stroke: var(--surface); stroke-width: 1; }
/* 1페이지 "주가 · 재무 추이" 는 주가 선과 재무 막대가 한 그림에 겹친다 — 막대를
   연하게 깔아 선이 앞에 읽히게 한다. 보조 지표 그림(#sub-charts)은 건드리지 않는다. */
.page-analysis .chart-wrap .series-bar { fill-opacity: 0.45; }
.series-marker { stroke: var(--surface); stroke-width: 2; }
.crosshair { stroke: var(--border-strong); stroke-width: 1; }

/* ── 이동평균 오버레이 ── */
.ma-line { fill: none; stroke-width: 1.2; stroke-linecap: round; stroke-linejoin: round; opacity: .7; }

/* ── 다이버전스 화살표 ── */
.div-arrow-bull { fill: var(--div-bull); font-size: 13px; font-weight: 700; }
.div-arrow-bear { fill: var(--div-bear); font-size: 13px; font-weight: 700; }
.div-hidden { opacity: .55; }

/* 주가 선 위(메인 차트)에 얹히는 화살표. 서브 플롯과 달리 격자·막대·주가 선이
   깔린 자리에 놓이므로, 배경색으로 테를 둘러 글자를 떼어 낸다(paint-order 로
   테를 글자 **뒤에** 칠한다 — 안 그러면 테가 글자를 갉아먹는다). */
.div-overlay text {
  paint-order: stroke fill;
  stroke: var(--surface);
  stroke-width: 3px;
  stroke-linejoin: round;
}
/* 어느 지표가 말했는지(R·C·M). 화살표보다 작고, 화살표 색을 그대로 물려받는다. */
.div-arrow-tag { font-size: 9.5px; letter-spacing: .04em; }

/* ── 서브 차트 (기술 지표 여덟) ── */
.sub-charts { margin-top: 0.3rem; display: flex; flex-direction: column; gap: 2px; }
/* 서브 차트도 제 툴팁을 제 안에 띄운다(indicators.js) — 기준 상자가 필요하다. */
.sub-chart-wrap { border-top: 1px solid var(--border); position: relative; }
.sub-chart-svg { display: block; width: 100%; height: auto; overflow: visible; }
/* `stroke` 를 **여기서 못 박는다.** 예전에는 색이 전용 클래스에만 있어서, 클래스를
   안 준 지표는 `stroke: none` 으로 그려졌다 — 경로는 멀쩡히 있는데 화면에는 화살표만
   뜬다(MOBV·+DI·−DI·ADX 가 그랬다). 새 지표가 조용히 안 보이는 일이 없도록
   기본색을 두고, 지표별 색이 그 위를 덮는다. */
.sub-indicator-line { fill: none; stroke: var(--fg-soft); stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.sub-indicator-line.rsi-line { stroke: var(--series-rsi); }
.sub-indicator-line.cci-line { stroke: var(--series-cci); }
.sub-indicator-line.obv-line { stroke: var(--series-obv); }
.sub-indicator-line.pdi-line { stroke: var(--series-pdi); }
.sub-indicator-line.mdi-line { stroke: var(--series-mdi); }
.sub-indicator-line.adx-line { stroke: var(--series-adx); }
.sub-macd-line { fill: none; stroke: var(--series-macd); stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.sub-signal-line { fill: none; stroke: var(--series-macd-signal); stroke-width: 1.2; stroke-linecap: round; stroke-linejoin: round; }
.macd-hist-up { fill: var(--series-macd-hist-up); }
.macd-hist-dn { fill: var(--series-macd-hist-dn); }
.vol-bar-up { fill: var(--series-volume-up); }
.vol-bar-dn { fill: var(--series-volume-dn); }
.sub-threshold { stroke: var(--border-strong); stroke-width: 1; stroke-dasharray: 4 3; }
.sub-threshold-label { fill: var(--muted); font-size: 11px; }
.sub-label { fill: var(--fg-soft); font-size: 13px; font-weight: 700; }
.sub-axis-text { fill: var(--muted); font-size: 12px; font-variant-numeric: tabular-nums; }

.chart-empty {
  display: grid;
  place-items: center;
  min-height: 13rem;
  color: var(--muted);
  background: var(--surface-2);
  border-radius: var(--radius-lg);
  text-align: center;
  padding: 1.6rem;
}

/* 차트 팝업 — `body` 에 하나만 있고 화면 좌표로 놓인다(common.js 의 `Sm.hoverTip`).
   폭은 화면을 넘지 않게 묶는다: 폰에서 12rem + 긴 계열명이 화면보다 넓었다. */
.tooltip {
  position: fixed;
  z-index: 60;
  pointer-events: none;
  min-width: min(12rem, calc(100vw - 16px));
  max-width: min(24rem, calc(100vw - 16px));
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  padding: 0.5rem 0.7rem;
  font-size: 0.86rem;
}
.tooltip[hidden] { display: none; }
.tooltip .tt-date { color: var(--muted); font-size: 0.8rem; margin-bottom: 0.3rem; }
.tooltip .tt-row { display: flex; align-items: center; gap: 0.5rem; justify-content: space-between; font-variant-numeric: tabular-nums; }
.tooltip .tt-label { display: flex; align-items: center; gap: 0.35rem; color: var(--fg-soft); }
.tooltip .tt-value { color: var(--fg); font-weight: 700; }

.swatch { width: 0.62rem; height: 0.62rem; border-radius: 2px; flex: none; }
.swatch.bar { border-radius: 1px; }
.swatch.line { height: 0.22rem; border-radius: 2px; }

/* 기간 조절 */

.range-bar {
  display: flex;
  align-items: center;
  gap: 0.6rem 0.9rem;
  flex-wrap: wrap;
  margin-bottom: 0.7rem;
}
.range-presets { display: inline-flex; gap: 3px; background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--radius-pill); padding: 3px; }
.range-presets button {
  font: inherit; font-size: 0.85rem; font-weight: 700; cursor: pointer;
  color: var(--muted); background: transparent; border: 0;
  border-radius: var(--radius-pill); padding: 0.22rem 0.8rem;
}
.range-presets button:hover { color: var(--fg); }
.range-presets button[aria-pressed="true"] { color: var(--accent); background: var(--accent-soft); }

/* 공시 검색 설정의 날짜 입력과 빠른 기간을 같은 좌우 폭에 맞춘다. */
.page-timeline .search-card .options > .opt { flex: 1 0 100%; min-width: 0; }
.page-timeline .search-card .opt input[type="date"] { width: 100%; min-width: 0; }
.page-timeline .search-card .range-presets {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  width: 100%;
}
.page-timeline .search-card .range-presets button { min-width: 0; padding-inline: 0.2rem; }

.range-dates { display: flex; align-items: center; gap: 0.4rem; color: var(--muted); font-size: 0.85rem; }
.range-dates input[type="date"] { padding: 0.3rem 0.5rem; font-size: 0.85rem; }

/* 선 계열(주가) 두께 · 색 조절 */

/* 차트 카드 안의 "선 스타일" 접기 — 설정 칸의 접기와 같은 모양, 여백만 좁게. */
.line-style-fold { margin: 0.5rem 0 0.4rem; }
.line-style-fold > summary { padding-top: 0.5rem; }
.line-style-fold > .line-style-bar { margin-top: 0.5rem; }
.line-style-bar {
  display: flex;
  align-items: center;
  gap: 0.6rem 1.1rem;
  flex-wrap: wrap;
  margin-bottom: 0.7rem;
  font-size: 0.85rem;
  color: var(--muted);
}
.line-style-field { display: inline-flex; align-items: center; gap: 0.45rem; }
.line-style-field input[type="range"] { width: 7rem; accent-color: var(--accent); }
.line-style-field input[type="color"] {
  width: 1.9rem; height: 1.9rem; padding: 0; border: 1px solid var(--border);
  border-radius: var(--radius-sm); background: none; cursor: pointer;
}
.line-style-field .num { min-width: 2.4em; color: var(--fg-soft); }
.btn-sm { padding: 0.32rem 0.75rem; font-size: 0.82rem; }

.brush { position: relative; margin-top: 0.5rem; cursor: crosshair; user-select: none; }
.brush svg { display: block; width: 100%; height: 58px; }
.brush-track { fill: var(--surface-2); }
.brush-spark { fill: none; stroke: var(--border-strong); stroke-width: 1.4; }
.brush-window { fill: var(--accent-ring); stroke: var(--accent); stroke-width: 1; }
.brush-veil { fill: var(--surface); opacity: 0.55; }
.brush-handle { fill: var(--accent); cursor: ew-resize; }
.brush-hint { fill: var(--muted); font-size: 11px; }

/* 범례 — 계열마다 축(좌/우) 를 바로 바꿀 수 있다 */

.legend {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem 0.7rem;
  margin-top: 0.9rem;
  padding-top: 0.85rem;
  border-top: 1px solid var(--border);
}

.legend-item {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.9rem;
  font-variant-numeric: tabular-nums;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  padding: 0.16rem 0.5rem 0.16rem 0.16rem;
}
.legend-item.off { opacity: 0.45; }
.legend-item .lg-toggle {
  font: inherit;
  display: flex;
  align-items: center;
  gap: 0.42rem;
  background: none;
  border: 0;
  padding: 0.18rem 0.45rem;
  cursor: pointer;
  border-radius: var(--radius-pill);
  color: var(--legend-color, var(--fg-soft));
  font-weight: 700;
}
.legend-item .lg-toggle:hover { background: var(--surface); }
.legend-item .lg-value { color: var(--fg); font-weight: 700; padding-right: 0.2rem; }
.legend-item .lg-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* 비교 주가 범례는 회사 이름 길이와 관계없이 같은 너비의 칸에 놓는다.
   긴 영문 이름도 칸 안에서 접어 작은 화면의 가로 넘침을 막는다. */
#price-legend {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 15rem), 1fr));
  gap: 0.55rem;
}
#price-legend .legend-item { min-width: 0; border-radius: var(--radius-md); }
#price-legend .lg-toggle { flex: 1; min-width: 0; text-align: left; }
#price-legend .lg-name {
  white-space: normal;
  overflow: visible;
  text-overflow: clip;
  overflow-wrap: anywhere;
  line-height: 1.35;
}
#price-legend .lg-value { flex: none; }

.axis-pick {
  font: inherit;
  font-size: 0.76rem;
  font-weight: 700;
  cursor: pointer;
  color: var(--muted);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  padding: 0.06rem 0.45rem;
  white-space: nowrap;
}
.axis-pick:hover { color: var(--accent); border-color: var(--accent); }
.axis-pick[data-axis="left"]::before { content: "좌축"; }
.axis-pick[data-axis="right"]::before { content: "우축"; }

/* ─────────────────────────────────────────────────────────────── 표 */

.table-scroll { overflow-x: auto; }

table { width: 100%; border-collapse: collapse; font-size: 0.9rem; font-variant-numeric: tabular-nums; }

th, td { padding: 0.48rem 0.7rem; text-align: right; white-space: nowrap; border-bottom: 1px solid var(--border); }

th {
  color: var(--muted);
  font-size: 0.84rem;
  font-weight: 700;
  background: var(--surface-2);
  position: sticky;
  top: 0;
}
th:first-child, td:first-child { text-align: left; }
thead th:first-child { border-top-left-radius: var(--radius-sm); }
thead th:last-child { border-top-right-radius: var(--radius-sm); }
tbody tr:last-child td { border-bottom: 0; }
tbody tr:hover td { background: var(--surface-2); }
td .metric-name { color: var(--fg); font-weight: 600; }

/* 좁은 화면의 표 — 가로로 밀어 보는 대신 **줄마다 카드**로 쌓는다(`.stack-table`).
   폰에서는 첫 칸(종목·지표 이름)만 보이고 숫자가 전부 화면 밖이라 표를 읽을 수
   없었다. 카드 = 이름 한 줄 + 칸 두 열, 칸마다 머리글 대신 제 이름표(`data-label`,
   화면 스크립트가 단다)를 위에 적는다. 폭은 표를 품은 `.table-scroll` 기준이다. */
.table-scroll { container-type: inline-size; }
@container (width < 36rem) {
  .stack-table thead { display: none; }
  .stack-table, .stack-table tbody { display: block; }
  .stack-table tr {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.45rem 0.9rem;
    padding: 0.75rem 0.1rem;
    border-bottom: 1px solid var(--border);
  }
  .stack-table tbody tr:last-child { border-bottom: 0; }
  .stack-table td {
    display: block;
    min-width: 0;
    padding: 0;
    border: 0;
    text-align: left;
    white-space: normal;
  }
  .stack-table tbody tr:hover td { background: none; }
  .stack-table td:first-child { grid-column: 1 / -1; font-size: 0.95rem; }
  .stack-table td[data-label]::before {
    content: attr(data-label);
    display: block;
    color: var(--muted);
    font-size: 0.7rem;
    font-weight: 600;
  }
  /* 증감률은 값 아래 줄로 — 옆에 붙이면 반 칸 폭을 넘는다. */
  .stack-table td > .hint { display: block; font-size: 0.74rem; }
}

/* ─────────────────────────────────────────────────────── 타임라인(3페이지) */

/* 날짜 한 줄 × 종목 한 열의 표. 같은 날 공시는 같은 줄에 나란히 앉는다 —
   열마다 따로 쌓으면 셋째 카드가 종목마다 다른 날이라 견줄 수가 없었다.
   종목이 늘어 화면보다 넓어지면 페이지가 아니라 **이 상자만** 가로로 민다.
   머리줄(종목)은 위에, 날짜 칸은 왼쪽에 붙어 있어 어디를 굴려도 좌표를 잃지 않는다. */

.timeline-grid {
  max-width: 100%;
  max-height: calc(100vh - 8rem);
  overflow: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}

.tl-table {
  display: grid;
  --date-w: 4.2rem;
  --col-min: 8.5rem;
  grid-template-columns: var(--date-w) repeat(var(--cols, 1), minmax(var(--col-min), 1fr));
  /* 폭은 상자에 맞추고, 열이 최소 폭 아래로 줄어야 할 때만 가로로 민다.
     `max-content` 로 두면 긴 보고서명에 열이 제멋대로 늘어난다. */
  width: 100%;
  min-width: calc(var(--date-w) + var(--cols, 1) * var(--col-min));
}
.tl-row { display: contents; }
.tl-row > * { border-bottom: 1px solid var(--border); }
.tl-row > * + * { border-left: 1px solid var(--border); }

.tl-date-cell {
  position: sticky;
  left: 0;
  z-index: 2;
  background: var(--surface);
  padding: 0.4rem 0.5rem;
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--fg);
  display: flex;
  flex-direction: column;
  line-height: 1.25;
}
.tl-year { font-size: 0.66rem; font-weight: 500; color: var(--muted); }

.tl-header > * { position: sticky; top: 0; z-index: 3; }
.tl-header > .tl-date-cell { z-index: 4; color: var(--muted); font-size: 0.74rem; justify-content: center; }

.tl-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem;
  min-width: 0;
  padding: 0.5rem 0.6rem;
  background: color-mix(in srgb, var(--tag-color, var(--accent)) 12%, var(--surface));
  box-shadow: inset 0 -2px 0 var(--tag-color, var(--accent));
}
.tl-head .name { color: var(--tag-color, var(--fg)); font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tl-head .count { flex: none; color: var(--muted); font-size: 0.8rem; }

/* 달이 바뀌는 자리의 가름줄. 표 전체 폭을 차지하되 글자는 왼쪽에 붙어 있게 한다. */
.tl-month {
  grid-column: 1 / -1;
  padding: 0.55rem 0.6rem 0.25rem;
  background: var(--surface-2);
  border-bottom: 1px solid var(--border);
  font-size: 0.74rem;
  font-weight: 700;
  color: var(--muted);
  letter-spacing: 0.04em;
}

.tl-cell {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  min-width: 0;
  padding: 0.35rem 0.4rem;
}
.tl-cell.is-empty { background: color-mix(in srgb, var(--surface-2) 45%, transparent); }

/* 정기보고서는 왼쪽 띠를 그 종목 색으로 칠하고 글자를 굵게 한다. */
.tl-card {
  display: flex;
  align-items: flex-start;
  gap: 0.35rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 3px solid var(--border-strong);
  border-radius: var(--radius-sm);
  padding: 0.3rem 0.5rem;
  text-decoration: none;
  transition: border-color 0.15s var(--ease), box-shadow 0.15s var(--ease);
}
.tl-card.periodic { border-left-color: var(--tag-color, var(--accent)); }
.tl-card:hover { border-color: var(--border-strong); box-shadow: var(--shadow-sm); text-decoration: none; }
.tl-card .tl-name { min-width: 0; color: var(--fg-soft); font-size: 0.84rem; line-height: 1.4; }
.tl-card.periodic .tl-name { color: var(--fg); font-weight: 700; }
.tl-empty { color: var(--muted); font-size: 0.88rem; padding: 1rem 0.7rem; }

/* 좁은 화면 — 날짜별 목록(timeline.js 의 `fitTimeline` 이 `is-feed` 를 단다).
   격자는 종목 수만큼 열이 늘어 폰에서는 옆으로 밀어야 했다. 목록은 날짜 칸 하나 +
   그날의 공시를 종목별로(종목 색 점 · 이름표) 쌓아서 세로로만 내려간다. */
.tl-feed { display: none; }
/* 목록일 때는 상자 안 스크롤을 풀고 페이지 하나로 내려간다 — 폰에서 스크롤 안의
   스크롤은 손가락이 어느 쪽을 굴리는지 헷갈린다. 종목 이름표 줄은 화면 위에 붙는다. */
.timeline-grid.is-feed { max-height: none; overflow: visible; }
.timeline-grid.is-feed .tl-table { display: none; }
.timeline-grid.is-feed .tl-feed { display: block; }
.tl-feed-legend {
  position: sticky;
  top: 0;
  z-index: 2;
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem 0.7rem;
  padding: 0.5rem 0.6rem;
  background: var(--surface);
  border-bottom: 1px solid var(--border-strong);
  font-size: 0.8rem;
}
.tl-feed-co-chip { display: inline-flex; align-items: center; gap: 0.3rem; color: var(--tag-color, var(--fg)); font-weight: 700; white-space: nowrap; }
.tl-feed-co-chip .num { color: var(--muted); font-weight: 600; font-size: 0.74rem; }
.tl-dot { flex: none; display: inline-block; width: 0.5rem; height: 0.5rem; border-radius: 50%; background: var(--tag-color, var(--accent)); }
.tl-day { display: grid; grid-template-columns: 3.7rem minmax(0, 1fr); border-bottom: 1px solid var(--border); }
.tl-day > .tl-date-cell { position: static; border-right: 1px solid var(--border); white-space: nowrap; }
/* 띄어쓰기 없는 긴 보고서명(임원ㆍ주요주주특정증권등소유상황보고서)도 칸 안에서 접는다. */
.tl-feed .tl-card .tl-name { overflow-wrap: anywhere; }
.tl-day-items { display: grid; gap: 0.45rem; padding: 0.4rem 0.5rem; min-width: 0; }
.tl-feed-co { display: grid; gap: 0.25rem; min-width: 0; }
.tl-feed-name { display: flex; align-items: center; gap: 0.3rem; color: var(--tag-color, var(--fg)); font-size: 0.74rem; font-weight: 700; }

/* 공시 카드의 유형 표시 — 열이 여섯이면 라벨을 적을 자리가 없어 코드 한 글자만
   찍는다. 뜻은 사이드바의 유형 배지(같은 네모 + 라벨)와 title 이 알려 준다. */
.tl-type {
  flex: none;
  min-width: 1.15rem;
  text-align: center;
  color: var(--muted);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0 0.28rem;
  font-size: 0.72rem;
  font-weight: 700;
  line-height: 1.5;
}

/* ── 공시 유형 토글(3페이지 사이드바) ────────────────────────────────
   관리자가 열어 둔 유형 중 지금 볼 것을 고른다. 켬/끔이 한눈에 보여야 해서
   상태를 색 하나에 걸지 않는다 — 켠 것은 accent 로 차오르고 코드 네모가
   반전되며 건수가 붙고, 끈 것은 가라앉은 채 건수가 사라진다. */
.type-panel .card-head { margin-bottom: 0.3rem; }
/* 전부 켜져 있으면 누를 일이 없어 잠근다 — 기다리는 게 아니니 progress 커서는 뺀다. */
.type-panel .card-head .btn[disabled] { cursor: default; }
.type-panel .type-lead { margin: 0 0 0.6rem; }
.type-panel .type-foot { margin: 0.55rem 0 0; font-variant-numeric: tabular-nums; }

.type-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(9.5rem, 1fr));
  gap: 0.4rem;
}

.type-badge {
  font: inherit;
  cursor: pointer;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 0.4rem;
  text-align: left;
  color: var(--muted);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  padding: 0.26rem 0.5rem 0.26rem 0.3rem;
  transition: color 0.15s var(--ease), border-color 0.15s var(--ease),
    background 0.15s var(--ease);
}
.type-badge:hover { color: var(--fg-soft); border-color: var(--border-strong); }

.type-badge-code {
  flex: none;
  width: 1.3rem;
  height: 1.3rem;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--surface);
  border: 1px solid var(--border);
  font-size: 0.76rem;
  font-weight: 700;
}
.type-badge-label {
  font-size: 0.84rem;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.type-badge-count {
  font-size: 0.76rem;
  font-weight: 700;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.type-badge-count:empty { display: none; }

.type-badge[aria-pressed="true"] {
  color: var(--accent);
  background: var(--accent-soft);
  border-color: var(--accent);
  box-shadow: var(--shadow-xs);
}
.type-badge[aria-pressed="true"] .type-badge-code {
  color: var(--on-accent);
  background: var(--accent);
  border-color: var(--accent);
}
.type-badge[aria-pressed="true"] .type-badge-count { color: var(--accent); }
.type-badge[aria-pressed="false"] { opacity: 0.72; }
.type-badge[aria-pressed="false"]:hover { opacity: 1; }

/* ─────────────────────────────────────────────────────── 관리자(4페이지) */

/* 종목 분석·비교·타임라인 카드 3장을 고정 3열로. 섹션을 각각 접을 수 있어서
   높이는 stretch 가 아니라 start 다 — 하나를 접었을 때 그 카드만 줄어야 한다. */
.admin-grid { display: grid; grid-template-columns: repeat(3, 1fr); align-items: start; gap: 1rem; }
.admin-grid > .card { margin-bottom: 0; display: flex; flex-direction: column; }
.field { display: flex; flex-direction: column; gap: 0.35rem; margin-bottom: 0.85rem; }
.field > label { color: var(--fg); font-weight: 700; font-size: 0.92rem; }
.field .hint { font-size: 0.82rem; }

/* 고정 2열 — 라벨 길이가 달라도(예: "매출액" vs "영업활동현금흐름") 칸 크기가
   같아야 버튼처럼 깔끔하게 정렬된다. */
.check-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 0.35rem; }
.check {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.88rem;
  padding: 0.3rem 0.7rem;
  border: 1px solid var(--border);
  /* 알약(999px)이 아니라 "한 줄 높이의 절반" 이다. 손바닥 화면에서 두 열이 좁아지면
     긴 라벨(영업활동현금흐름)이 두 줄로 접히는데, 알약이면 그때 상자가 높이의
     절반만큼 휘어 달걀처럼 부푼다. 한 줄일 때는 이 값이 곧 알약이고, 두 줄이
     되면 모서리만 둥근 네모로 남는다. 0.88rem × 줄높이 1.65 + 위아래 0.3rem. */
  border-radius: calc(1.03rem + 1px);
  background: var(--surface-2);
  cursor: pointer;
}
.check input { accent-color: var(--accent); margin: 0; }
.check:has(input:checked) { color: var(--accent); border-color: var(--accent); background: var(--accent-soft); }

/* 키워드 배지 — 관리자 화면에서 직접 타이핑하는 대신 자주 쓰는 낱말을
   클릭으로 켜고 끈다. 격자로 줄을 맞춰서 길이가 들쭉날쭉해도 정렬돼 보인다. */
.badge-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 0.35rem;
  margin-bottom: 0.5rem;
}
.badge-grid:empty { display: none; }

.kw-badge {
  font: inherit;
  font-size: 0.84rem;
  font-weight: 600;
  cursor: pointer;
  color: var(--muted);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  padding: 0.24rem 0.7rem;
  text-align: center;
  transition: border-color 0.15s var(--ease), color 0.15s var(--ease), background 0.15s var(--ease);
}
.kw-badge:hover { border-color: var(--border-strong); }
.kw-badge[aria-pressed="true"] {
  color: var(--accent);
  font-weight: 700;
  background: var(--accent-soft);
  border-color: var(--accent);
}

/* 직접 입력 — Enter 만으로는 "이걸 어떻게 넣지" 싶다는 피드백. 오른쪽에
   버튼을 붙이고, 쉼표로 여러 개를 한 번에 넣을 수 있다고 placeholder 에 적는다. */
.badge-add-row { display: flex; gap: 0.4rem; align-items: stretch; }
.badge-add-row .badge-add-input { flex: 1; min-width: 0; }
.badge-add-row .btn { white-space: nowrap; flex: none; }
.badge-add-input { font-size: 0.84rem; padding: 0.4rem 0.65rem; }

/* ── 키워드 점검 ───────────────────────────────────────────────────
   저장하기 전에 "이 지표가 이 회사에서 실제로 잡히나" 를 보여 주는 상자.
   잡힌 것(✓)은 어떤 계정·얼마인지, 못 잡은 것(✗)은 왜 못 잡았는지와 대신 쓸
   계정 후보를 보여 준다 — 후보는 그대로 눌러서 추가 배지로 넣을 수 있다. */
.kw-check-search { flex: 1; min-width: 0; }

.kw-check-result:empty { display: none; }
.kw-check-result {
  margin-top: 0.5rem;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 0.55rem 0.65rem;
  font-size: 0.82rem;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}

.kw-check-head { color: var(--muted); }

.kw-check-row {
  display: grid;
  grid-template-columns: 1rem minmax(0, 8rem) minmax(0, 1fr);
  gap: 0.35rem 0.5rem;
  align-items: baseline;
}
/* 제외 안내 줄은 라벨 칸이 없다 — 설명이 두 칸을 이어 쓴다. */
.kw-check-row > .kw-check-miss:nth-child(2) { grid-column: 2 / -1; }

.kw-check-mark { font-weight: 700; line-height: 1.2; }
/* 국내 관례상 --up 은 빨강이라 '잘 잡혔다' 에 쓰면 경고로 읽힌다.
   여기서는 성공/주의 뜻 그대로인 --success / --tone-na 를 쓴다. */
.kw-check-mark.is-ok { color: var(--success); }
.kw-check-mark.is-no { color: var(--tone-na); }

.kw-check-label { font-weight: 600; overflow-wrap: anywhere; }
.kw-check-kind {
  font-size: 0.7rem;
  color: var(--muted);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  padding: 0 0.35rem;
  margin-left: 0.3rem;
}

.kw-check-hit { display: flex; flex-wrap: wrap; gap: 0.35rem; align-items: baseline; }
.kw-check-account { overflow-wrap: anywhere; }

.kw-check-miss { color: var(--muted); overflow-wrap: anywhere; }
.kw-check-suggest {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
  align-items: center;
  margin-top: 0.3rem;
}
.kw-check-suggest .kw-badge { font-size: 0.78rem; padding: 0.14rem 0.55rem; }

@media (max-width: 900px) {
  .kw-check-row { grid-template-columns: 1rem minmax(0, 1fr); }
  .kw-check-row > .kw-check-hit,
  .kw-check-row > .kw-check-miss { grid-column: 2 / -1; }
}

/* ── 섹션 접기/펴기 ─────────────────────────────────────────────────
   제목 전체가 토글 버튼이다. 삼각형은 CSS 로 그린다(아이콘 폰트를 안 쓴다). */
.section-toggle {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  /* 바탕 폭을 제목 길이로 잡는다(`flex: 1` 이면 0 에서 시작해 옆 힌트에 밀려
     제목이 '제외된 / 종목' 으로 접혔다). 자리가 모자라면 힌트가 다음 줄로 간다. */
  flex: 1 1 auto;
  min-width: 0;
  font: inherit;
  color: inherit;
  text-align: left;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}
.section-toggle h2 { margin: 0; }
.section-toggle:hover h2 { color: var(--accent); }
.section-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: var(--radius-sm); }

.caret {
  width: 0;
  height: 0;
  flex: none;
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
  border-top: 6px solid var(--muted);
  transition: transform 0.15s var(--ease);
}
.section-toggle[aria-expanded="false"] .caret { transform: rotate(-90deg); }

/* 접힌 카드는 제목 한 줄만 남는다 — 제목 아래 여백(`.card-head` 의 margin-bottom)이
   남아 있으면 글자가 카드 위쪽으로 쏠려 보인다. 카드마다 따로 지우던 것을
   여기 한 줄로 모은다(`is-collapsed` 는 common.js 의 `collapsiblePanel` 이 단다). */
.card.is-collapsed > .card-head { margin-bottom: 0; }

.admin-section.is-collapsed .card-head { margin-bottom: 0; }
.admin-section.is-collapsed .status-box { margin-bottom: 0; }
.admin-section.is-dirty { border-color: var(--accent); }

.dirty-flag {
  flex: none;
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--on-accent);
  background: var(--accent);
  border-radius: var(--radius-pill);
  padding: 0.14rem 0.55rem;
}

/* ── 현황 상자 ──────────────────────────────────────────────────────
   접어도 남는다 — "지금 무엇이 적용 중인가"는 접힌 채로도 보여야 한다.
   편집 중인 값이 아니라 **저장된** 값을 그린다. */
.status-box {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 0.6rem 0.75rem;
  margin-bottom: 0.85rem;
}
.status-title {
  color: var(--muted);
  font-size: 0.76rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  margin-bottom: 0.4rem;
}
.status-row { display: flex; gap: 0.5rem; align-items: baseline; padding: 0.18rem 0; }
.status-row + .status-row { border-top: 1px solid var(--border); }
.status-key { flex: none; width: 5.4rem; color: var(--fg-soft); font-size: 0.8rem; font-weight: 700; }
.status-val { display: flex; flex-wrap: wrap; gap: 0.25rem; min-width: 0; }
.status-none { color: var(--muted); font-size: 0.8rem; }

.status-chip {
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--accent);
  background: var(--accent-soft);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  padding: 0.1rem 0.5rem;
}
/* 추가해 뒀지만 제외 키워드에 걸려 실제로는 빠지는 낱말 */
.status-chip.is-dropped {
  color: var(--muted);
  background: transparent;
  text-decoration: line-through;
}

.section-actions {
  display: flex;
  gap: 0.5rem;
  align-items: center;
  flex-wrap: wrap;
  margin-top: 0.9rem;
  padding-top: 0.8rem;
  border-top: 1px solid var(--border);
}
/* 단추 줄 바로 아래에 본문이 붙어 있었다 — 위쪽 구분선은 있는데 아래가 0 이라
   '저장하고 적용' 과 '기본 지표' 가 맞닿아 보인다. 여백은 본문 쪽에 준다:
   섹션을 접어 본문이 사라지면 그 여백도 같이 사라져야 하기 때문이다. */
.section-actions + .section-body { margin-top: 0.9rem; }

/* 섹터 패널 편집 — 관리자가 섹터마다 종목을 검색해 담고 순서(=시가총액 순)를
   위/아래로 조정한다. 카드 하나 = 섹터 하나. */
/* minmax 최솟값을 둔다 — 섹터가 3개 미만이면 빈 트랙이 내용 없이 쪼그라들어
   앞 카드가 좁아지고, 그 안의 종목명이 한 글자씩 줄바꿈되는 문제가 있었다. */
#sector-editor { display: grid; grid-template-columns: repeat(3, minmax(14rem, 1fr)); gap: 0.8rem; }

.sector-edit-card {
  min-width: 0;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 0.8rem 0.85rem;
}

.sector-edit-head { display: flex; gap: 0.5rem; align-items: center; margin-bottom: 0.6rem; }
.sector-label-input { flex: 1; font-weight: 700; }

.sector-stock-list { list-style: none; margin: 0 0 0.6rem; padding: 0; display: flex; flex-direction: column; gap: 0.3rem; }
.sector-stock-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 0.32rem 0.5rem;
}
.sector-stock-name {
  flex: 1;
  min-width: 0;
  font-weight: 600;
  font-size: 0.9rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sector-stock-actions { display: flex; gap: 0.2rem; }
.sector-stock-actions button {
  font: inherit;
  color: var(--muted);
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  width: 1.7rem;
  height: 1.7rem;
  cursor: pointer;
  transition: color 0.15s var(--ease), border-color 0.15s var(--ease);
}
.sector-stock-actions button:hover:not(:disabled) { color: var(--accent); border-color: var(--border); }
.sector-stock-actions button:disabled { opacity: 0.35; cursor: default; }

.sector-stock-add { max-width: 100%; }

/* 섹터 패널 표시 — 분석·비교·타임라인 오른쪽. 섹터 기준 3열, 열마다 종목이
   시가총액 큰 순으로 최대 6개 쌓인다(관리자 화면에서 정한 순서 그대로). */
.sector-panel .card-head { margin-bottom: 0.6rem; }
.sector-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.6rem; }

.sector-card {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 0.55rem 0.5rem 0.6rem;
  display: flex;
  flex-direction: column;
  gap: 0.32rem;
  min-width: 0;
}
.sector-card-label {
  font-size: 0.76rem;
  font-weight: 700;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.02em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sector-stock-btn {
  display: block;
  width: 100%;
  text-align: left;
  font: inherit;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--fg-soft);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0.26rem 0.45rem;
  cursor: pointer;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  transition: border-color 0.15s var(--ease), color 0.15s var(--ease), background 0.15s var(--ease);
}
.sector-stock-btn:hover, .sector-stock-btn:focus-visible {
  border-color: var(--accent);
  color: var(--accent);
  background: var(--accent-soft);
}

.sector-empty { color: var(--muted); font-size: 0.85rem; margin: 0; }
.sector-empty a { color: var(--accent); }

@media (max-width: 900px) {
  .admin-grid { grid-template-columns: 1fr; }
  #sector-editor { grid-template-columns: 1fr; }
}

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

.toast {
  position: fixed;
  right: 1.2rem;
  bottom: 1.2rem;
  z-index: 60;
  color: var(--on-accent);
  background: var(--success);
  border-radius: var(--radius-md);
  padding: 0.6rem 1rem;
  font-weight: 700;
  box-shadow: var(--shadow-lg);
}
.toast[hidden] { display: none; }

/* ─────────────────────────────────────────────────────────────── 안내 */

.notes { display: flex; flex-direction: column; gap: 0.4rem; }

.note {
  display: flex;
  gap: 0.5rem;
  align-items: flex-start;
  font-size: 0.88rem;
  color: var(--fg-soft);
  background: var(--surface-2);
  border-left: 3px solid var(--border-strong);
  border-radius: var(--radius-sm);
  padding: 0.42rem 0.65rem;
}
.note.warn { border-left-color: var(--tone-na); }
.note.cfs { border-left-color: var(--tone-cfs); }
.note.ofs { border-left-color: var(--tone-ofs); }
.note.delayed { border-left-color: var(--tone-delayed); }
.note.adjusted { border-left-color: var(--tone-adjusted); }

.error {
  color: var(--danger);
  background: color-mix(in srgb, var(--danger) 10%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--danger) 30%, transparent);
  border-radius: var(--radius-lg);
  padding: 0.9rem 1rem;
  margin-bottom: 1rem;
}
.error strong { display: block; color: var(--danger); margin-bottom: 0.2rem; }
.error .hint { color: var(--fg-soft); }

.footer {
  color: var(--muted);
  font-size: 0.82rem;
  text-align: center;
  margin-top: 1.6rem;
  line-height: 1.7;
}

.spinner {
  width: 0.9rem;
  height: 0.9rem;
  border: 2px solid var(--accent-ring);
  border-top-color: var(--on-accent);
  border-radius: 50%;
  display: inline-block;
  vertical-align: -2px;
  margin-right: 0.4rem;
  animation: spin 0.7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

.skeleton {
  background: linear-gradient(90deg, var(--surface-2), var(--surface), var(--surface-2));
  background-size: 200% 100%;
  animation: shimmer 1.3s var(--ease) infinite;
  border-radius: var(--radius-md);
  min-height: 13rem;
}
@keyframes shimmer { to { background-position: -200% 0; } }

/* ─────────────────────────────────────────────────── 지표별 소형 차트(2페이지) */

/* "종목 비교" 의 재무 지표 모드는 지표마다 별도 차트를 그린다(예: 매출액 비교 차트,
   영업이익 비교 차트, …). 각 차트 안에서는 회사별로 막대를 나란히 세운다.
   x축(기간)은 위쪽 공유 기간 컨트롤 하나로 전부 맞춘다. */

.metric-chart {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 0.9rem 1rem 1rem;
}
/* 지표 카드 사이 · 카드 묶음과 다음 카드 사이는 페이지의 다른 카드 사이와 같은
   1rem 이다(.card 의 margin-bottom). 예전에는 0.9 · 1.1 · 0(좁은 화면의 마지막 카드
   아래)이 섞여 있어 섹션 간격이 들쭉날쭉했다. */
#metric-charts { display: grid; gap: 1rem; margin-bottom: 1rem; }
#metric-charts:empty { display: none; }

/* 큰 모니터에서는 지표 카드를 두 열로 세운다. 한 열이면 순위 막대가 본문 폭을
   다 먹어 색 막대가 길게만 늘어나고, 지표끼리의 경계도 흐려진다. 두 열이면
   매출액 | 영업이익 이 나란히 서고, 카드 안쪽은 폭이 줄어 보드가 위아래로 접힌다.
   순서는 그대로 왼쪽→오른쪽, 위→아래다. 좁은 화면은 지금처럼 한 열이다. */
@media (min-width: 1400px) {
  #metric-charts { grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: start; }
}

.metric-chart-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.6rem;
  padding-bottom: 0.5rem;
  margin-bottom: 0.9rem;
  border-bottom: 1px solid var(--border);
}
.metric-chart-head h3 { color: var(--fg); font-size: 1.02rem; }
.metric-chart { container-type: inline-size; }

/* 순위 보드 — 지표 카드 맨 위. "최근 공통 기간의 규모" 와 "같은 종류 기간끼리의
   성장률" 두 덩이다(compare.js 의 `boardHtml`). 넓으면 나란히, 좁으면 위아래로.
   막대라서 폭이 줄어도 잘리거나 옆으로 밀리지 않는다. */
.cmp-board { display: grid; grid-template-columns: minmax(0, 1fr); gap: 0.9rem; }
/* 순위 보드는 두 열 격자다(compare.js 의 `boardHtml`) — 1줄: 규모 | 빈칸,
   2줄: 성장률 순위 | 그 흐름, 분기별이면 3줄: 직전 분기 대비 순위 | 그 흐름.
   줄 사이에 금을 그어 "무엇을 재는 줄인지" 를 가른다. 좁으면 한 열로 같은 차례대로
   쌓고 빈칸은 감춘다. 흐름 칸이 숫자 넷이라 조금 더 넓게 준다.
   두 열로 가르는 문턱은 31rem 이다 — 28rem 에서는 칸 하나가 너무 좁아 "카카오게임즈"
   같은 이름이 글자를 최소로 줄여도(`fitNames`) 잘렸다. 그 사이는 한 열이 더 읽힌다. */
.cmp-spacer { display: none; }
.cmp-growth-cell { padding-top: 0.9rem; border-top: 1px solid var(--border); min-width: 0; }
.cmp-flow-cell:empty { display: none; }
/* 한 열일 때 흐름은 바로 위 순위 막대의 이어짐이다 — 금을 긋지 않는다. */
.cmp-flow-cell { padding-top: 0; border-top: 0; }
.cmp-flow-cell .cmp-flow { margin-top: 0; }
.cmp-growth-cell > .cmp-sec { white-space: normal; }
@container (width >= 31rem) {
  .cmp-board {
    /* 흐름 칸에 더 준다(1 : 1.5) — 숫자 넷이 칸을 먼저 가져가 이름 칸이 "카카오…" 로
       줄었다. 순위 막대 쪽은 막대를 짧게 해서 이름 폭을 지킨다(아래 .cmp-row). */
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.5fr);
    column-gap: 1.2rem;
    row-gap: 0.9rem;
  }
  .cmp-spacer { display: block; }
  .cmp-flow-cell, .cmp-flow-cell:empty { display: block; padding-top: 0.9rem; border-top: 1px solid var(--border); }
  /* 흐름 칸에서는 종목 이름을 줄여도 된다 — 색점이 왼쪽 순위 막대와 같은 종목을 가리킨다. */
  .cmp-flow-cell .cmp-flow { font-size: 0.74rem; }
  .cmp-flow-cell .cmp-flow { column-gap: 0.3rem; }
  /* 두 열이면 한 칸이 카드의 절반이다 — 순위 줄의 칸을 조여 이름과 막대가 같이 산다.
     남는 폭은 이름에 더 준다(2 : 1) — 막대는 짧아도 길이로 견줄 수 있지만 이름은
     잘리면 누구인지 모른다("카카오…" 가 넷). 그래도 넘치면 글자를 줄인다(`fitNames`). */
  .cmp-board .cmp-row, .cmp-board .cmp-axis {
    grid-template-columns: 0.7rem minmax(0, 2fr) minmax(1.8rem, 1fr) 3.3rem;
    gap: 0.3rem;
  }
  .cmp-board .cmp-row { font-size: 0.78rem; }
}
@container (width >= 48rem) {
  .cmp-board { column-gap: 1.6rem; }
  .cmp-flow-cell .cmp-flow { font-size: 0.8rem; }
  .cmp-board .cmp-row, .cmp-board .cmp-axis {
    grid-template-columns: 1rem minmax(0, 8rem) minmax(3rem, 1fr) 4.4rem;
    gap: 0.5rem;
  }
  .cmp-board .cmp-row { font-size: 0.84rem; }
}
.cmp-sec { color: var(--muted); font-size: 0.76rem; font-weight: 700; margin-bottom: 0.3rem; white-space: nowrap; }
.cmp-empty { margin: 0 0 0.8rem; }

/* 막대 순위 한 줄 = 순위 · 종목(색점) · 막대 · 값. 칸 폭을 못 박아 줄마다 막대의
   출발점이 같다 — 그래야 길이로 견줄 수 있다. */
.cmp-bars { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.28rem; }
.cmp-row {
  display: grid;
  grid-template-columns: 1rem minmax(0, 7.6rem) minmax(2.4rem, 1fr) 4.4rem;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.84rem;
}
.cmp-rank { color: var(--muted); font-size: 0.74rem; font-weight: 700; text-align: right; }
.cmp-name { display: flex; align-items: center; gap: 0.35rem; min-width: 0; color: var(--fg-soft); font-weight: 600; }
/* 이름은 줄바꿈하지 않는다 — 줄마다 높이가 달라진다. 칸보다 길면 compare.js 의
   `fitNames` 가 **그 이름만** 글자를 줄여(최소 0.72em) 칸에 맞추고, 그래도 넘치는
   드문 경우만 말줄임한다. */
.cmp-name-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cmp-dot { flex: none; display: inline-block; width: 0.55rem; height: 0.55rem; border-radius: 50%; }
td .metric-name .cmp-dot { margin-right: 0.35rem; vertical-align: 0.05em; }
.cmp-track { display: block; height: 0.62rem; background: var(--surface); border-radius: var(--radius-pill); overflow: hidden; }
.cmp-fill { display: block; height: 100%; border-radius: var(--radius-pill); }
/* 양쪽 막대(성장률) — 가운데 세로 금이 0 이다. 막대는 그 금에서 오른쪽(+) ·
   왼쪽(−)으로 뻗는다. 금은 막대 위에 얹어 0 이 늘 보이게 한다. */
.cmp-track.is-diverge { position: relative; overflow: visible; }
.cmp-track.is-diverge .cmp-fill { position: absolute; top: 0; }
.cmp-track.is-diverge::after {
  content: "";
  position: absolute;
  left: 50%;
  top: -0.18rem;
  bottom: -0.18rem;
  width: 1px;
  background: var(--border-strong);
}
/* 성장률 흐름 — 회사 한 줄 · 최근 기간 네 칸의 전년 대비 %. 칸 폭은 JS 가 기간 수로
   정한다(`flowHtml`). */
.cmp-flow { margin-top: 0.7rem; display: grid; column-gap: 0.35rem; row-gap: 0.2rem; font-size: 0.76rem; }
/* 줄은 표의 칸을 그대로 쓴다 — 그래야 열마다 숫자의 오른쪽 끝이 한 줄로 선다. */
.cmp-flow-row { display: grid; grid-column: 1 / -1; grid-template-columns: subgrid; align-items: center; }
/* 숫자 칸은 칸 오른쪽 끝에 붙인다 — 그래야 줄마다 % 가 한 세로줄에 선다. */
.cmp-flow-row > .num { justify-self: stretch; text-align: right; white-space: nowrap; font-weight: 700; }
/* 머리글 크기는 표를 따라간다(em) — rem 으로 박아 두면 표 글자를 줄여도(`fitNames`)
   "2025 3Q" 가 칸 폭을 붙잡고 있어 이름 칸이 돌아오지 않는다. */
.cmp-flow-head { color: var(--muted); font-size: 0.88em; font-weight: 700; padding-bottom: 0.15rem; border-bottom: 1px solid var(--border); }
.cmp-flow-head > span:first-child { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cmp-flow-head > .num { font-weight: 700; }
.cmp-flow .up { color: var(--up); }
.cmp-flow .down { color: var(--down); }
.cmp-flow .muted { color: var(--muted); font-weight: 500; }
/* 양쪽 막대 아래의 눈금 − · 0 · + — 막대 칸과 같은 격자에 맞춘다. */
.cmp-axis {
  display: grid;
  grid-template-columns: 1rem minmax(0, 7.6rem) minmax(2.4rem, 1fr) 4.4rem;
  gap: 0.5rem;
  margin-top: 0.15rem;
  color: var(--muted);
  font-size: 0.66rem;
}
.cmp-axis > span:nth-child(1) { grid-column: 3; justify-self: start; }
.cmp-axis > span:nth-child(2) { grid-column: 3; justify-self: center; }
.cmp-axis > span:nth-child(3) { grid-column: 3; justify-self: end; }
.cmp-axis > span { grid-row: 1; }
.cmp-fill.is-neg { opacity: 0.55; }
/* 값 칸은 **고정 폭**이다. auto 였을 때는 "1,209조" 줄과 "93.5조" 줄의 값 칸 폭이
   달라 막대 칸이 줄마다 늘고 줄었고, 가운데(0)도 줄마다 다른 자리에 섰다. 고정하면
   모든 줄의 막대 길이와 0 의 자리가 같다. 드물게 더 긴 값은 칸 안에서 말줄임 —
   옆 칸(막대)을 밀거나 덮지 않는다(전체 값은 손을 얹으면 뜬다). */
.cmp-val { text-align: right; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; color: var(--fg); font-weight: 700; }
.cmp-val.up { color: var(--up); }
.cmp-val.down { color: var(--down); }
/* 1위 줄 — 이름과 값을 조금 더 진하게. 판정이 아니라 "가장 큰 값" 표시다. */
.cmp-row.is-first .cmp-name { color: var(--fg); }
.cmp-row.is-first .cmp-rank { color: var(--accent); }

/* ─────────────────────────────────────────────── 재무제표 카드(1페이지) */

/* "종목 분석" 의 재무제표 — 표 대신 지표마다 카드 하나(analysis.js 의
   `drawFinCards`). 막대 · 트랙 모양은 2페이지 순위 보드(.cmp-track/.cmp-fill)를
   그대로 쓴다. 카드는 20rem 안팎에서 멈추고 남는 폭은 **열을 늘리는 데** 쓴다 —
   큰 모니터에서 막대가 본문 폭만큼 늘어나지 않게. 좁은 화면은 한 열이다.
   auto-fill 이라 지표가 하나뿐이어도 카드가 한 칸 폭을 넘지 않는다. */
.fin-cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 19rem), 1fr));
  gap: 0.9rem;
  align-items: start;
}
.fin-card {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 0.75rem 0.9rem 0.85rem;
  min-width: 0;
  container-type: inline-size;
}
/* 분기별은 칸이 다섯(전기비까지)이라 카드의 최소 폭을 넓힌다 — 19rem 에서는 긴 금액
   ("149조 3,858억") 줄의 전기비가 카드 밖으로 밀려났다. */
.fin-cards.has-qoq { grid-template-columns: repeat(auto-fill, minmax(min(100%, 22rem), 1fr)); }
.fin-card-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.6rem;
  padding-bottom: 0.45rem;
  margin-bottom: 0.5rem;
  border-bottom: 1px solid var(--border);
}
.fin-card-head h3 { display: flex; align-items: center; gap: 0.4rem; color: var(--fg); font-size: 0.98rem; }
.fin-card-head .hint { font-size: 0.72rem; white-space: nowrap; }
/* 한 줄 = 기간 · 막대 · 값 · 전년 대비. 칸은 목록(.fin-rows)이 한 번 정하고 줄은
   subgrid 로 물려받는다 — 줄마다 값 칸 폭이 달라지면 막대 끝이 들쭉날쭉해져
   길이로 견줄 수 없다. */
.fin-rows {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: auto minmax(2rem, 1fr) auto auto;
  column-gap: 0.55rem;
  row-gap: 0.3rem;
  font-size: 0.82rem;
}
.fin-row { display: grid; grid-column: 1 / -1; grid-template-columns: subgrid; align-items: center; }
/* 분기별이면 "전기비"(직전 분기 대비) 칸이 하나 더 붙는다. */
.fin-rows.has-qoq { grid-template-columns: auto minmax(2rem, 1fr) auto auto auto; }
/* 열 이름 줄 — 한 단어씩(기간 · 금액 · 전년비 · 전기비). 뜻은 카드 위 캡션에 있다. */
.fin-row.fin-cols {
  color: var(--muted);
  font-size: 0.68rem;
  font-weight: 700;
  padding-bottom: 0.2rem;
  border-bottom: 1px solid var(--border);
}
.fin-row.fin-cols > span { white-space: nowrap; }
.fin-when { color: var(--muted); font-size: 0.76rem; font-weight: 600; white-space: nowrap; }
.fin-val { text-align: right; white-space: nowrap; color: var(--fg-soft); font-weight: 600; }
.fin-yoy { text-align: right; white-space: nowrap; font-size: 0.76rem; font-weight: 700; }
.fin-yoy .up { color: var(--up); }
.fin-yoy .down { color: var(--down); }
.fin-yoy .flat { color: var(--muted); }
.fin-derived { color: var(--muted); margin-left: 0.1rem; }
.fin-row.is-latest .fin-when { color: var(--fg); }
.fin-row.is-latest .fin-val { color: var(--fg); font-weight: 800; }
.fin-row.is-empty .fin-val { color: var(--muted); font-weight: 500; }
.fin-row.is-empty .cmp-track { visibility: hidden; }
.fin-card > .hint { margin: 0; }
/* 카드가 좁으면(폰 · 분기별 다섯 칸) 칸 사이와 글자를 조이고, **막대 칸이 0 까지
   줄 수 있게** 한다. 숫자가 카드 밖으로 나가느니 막대가 짧아지는 편이 낫다 —
   막대는 모양이고, 숫자는 내용이다. */
@container (width < 24rem) {
  .fin-rows { column-gap: 0.4rem; font-size: 0.78rem; }
  .fin-rows { grid-template-columns: auto minmax(0, 1fr) auto auto; }
  .fin-rows.has-qoq { grid-template-columns: auto minmax(0, 1fr) auto auto auto; }
  .fin-when, .fin-yoy { font-size: 0.72rem; }
}
@container (width < 18rem) {
  .fin-rows { column-gap: 0.3rem; font-size: 0.74rem; }
  .fin-when, .fin-yoy { font-size: 0.68rem; }
}

/* "재무 지표 비교" 표 — 지표마다 소제목 하나 + 그 아래 회사별 행.
   지표 덩이들은 **최대 세 열**로 선다(매출액 | 영업이익 | 순이익 → 다음 줄). 한 칸의
   최소는 17rem 과 "폭의 1/3" 중 큰 쪽이라 넷째 열은 생기지 않고, 좁으면 둘 · 하나로
   준다. auto-fit 이라 지표가 하나 둘뿐이면 남는 폭을 나눠 가진다. 칸 안에서 표가
   다 들어가면 표(히트맵), 넘치면 기간별 막대 덩이다(`fitFinTables` 가 칸마다 잰다). */
#fin-tables {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, max(17rem, calc((100% - 2 * 1.4rem) / 3))), 1fr));
  gap: 1.2rem 1.4rem;
  align-items: start;
}
#fin-tables > .hint { grid-column: 1 / -1; }
.fin-table-group { min-width: 0; }
.fin-table-title {
  color: var(--fg);
  font-size: 0.95rem;
  font-weight: 700;
  margin: 0 0 0.5rem;
  padding-bottom: 0.35rem;
  border-bottom: 1px solid var(--border);
}
/* 표 ↔ 기간별 덩이. 표가 칸에 다 들어가면 표, 넘치면 덩이다 — 기준 폭을 못 박지
   않고 compare.js(`fitFinTables`)가 실제로 재서 `is-narrow` 를 단다. 기간이 열둘이면
   노트북 폭에서도 표가 넘친다. */
.fin-switch .fin-narrow { display: none; }
.fin-switch.is-narrow .fin-wide { display: none; }
.fin-switch.is-narrow .fin-narrow { display: grid; gap: 0.8rem; }
/* 히트맵 칸 — 바탕은 compare.js 가 종목 색으로 깐다(`heat`). 1위 칸은 바탕을 덮지
   않고 굵기로만 가린다. 칸 사이 가는 틈이 있어야 같은 색 칸들이 한 덩이로 뭉개지지 않는다. */
.fin-wide td.fin-heat { color: var(--fg); box-shadow: inset 0 0 0 1px var(--surface); }
.fin-wide tbody tr:hover td.fin-heat { filter: brightness(1.06); }
.fin-wide td.is-top { color: var(--fg); font-weight: 800; }
.fin-wide td.is-neg { color: var(--down); }
/* 세 열 격자의 한 칸(약 1/3 폭)에서도 기간이 넷·다섯이면 표(히트맵)가 들어가도록 조인다.
   종목 이름은 말줄임(손을 얹으면 전체). 그래도 넘치면 기간별 막대 덩이로 바뀐다. */
#fin-tables .fin-wide th, #fin-tables .fin-wide td { padding: 0.32rem 0.4rem; font-size: 0.78rem; }
#fin-tables .fin-wide td:first-child, #fin-tables .fin-wide th:first-child { max-width: 5.6rem; }
#fin-tables .fin-wide .metric-name { display: flex; align-items: center; min-width: 0; }
#fin-tables .fin-wide .metric-name-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fin-period { padding-bottom: 0.7rem; border-bottom: 1px solid var(--border); }
.fin-period:last-child { padding-bottom: 0; border-bottom: 0; }
/* 기간 덩이 접기 — 접힌 줄은 ▸ 기간 · 색점+값 들. 삼각형은 카드 접기(.caret)와 같은
   모양이다. 펼치면 그 아래에 막대 순위가 선다. */
.fin-switch.is-narrow .fin-narrow { gap: 0.45rem; }
.fin-period { padding-bottom: 0.45rem; }
.fin-period > summary {
  display: grid;
  grid-template-columns: auto max-content minmax(0, 1fr);
  align-items: center;
  column-gap: 0.4rem;
  list-style: none;
  cursor: pointer;
}
.fin-period > summary::-webkit-details-marker { display: none; }
.fin-period > summary::before {
  content: "";
  flex: none;
  align-self: center;
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
  border-top: 6px solid var(--muted);
  transform: rotate(-90deg);
  transition: transform 0.15s var(--ease);
}
.fin-period[open] > summary::before { transform: none; }
.fin-period > summary .cmp-sec { margin-bottom: 0; white-space: nowrap; }
.fin-period > summary:hover .cmp-sec { color: var(--fg-soft); }
.fin-period-vals { display: grid; column-gap: 0.5rem; min-width: 0; font-size: 0.8rem; }
.fin-period-val { display: flex; align-items: center; gap: 0.3rem; min-width: 0; color: var(--fg-soft); font-weight: 700; }
.fin-period-txt { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fin-period-val.down { color: var(--down); }
.fin-period-val.muted { color: var(--muted); font-weight: 500; }
/* 종목 넷 이상이면 한 줄에 들어가도록 글자 · 칸 사이 · 색점을 줄인다. 그래도 칸보다
   긴 값만 말줄임이다(1/3 폭 칸에서 다섯 종목의 "93.5조" 가 다 들어가는 크기). */
.fin-period-vals.n4 { column-gap: 0.4rem; font-size: 0.74rem; }
.fin-period-vals.n5, .fin-period-vals.n6 { column-gap: 0.25rem; font-size: 0.68rem; letter-spacing: -0.02em; }
.fin-period-vals.n5 .fin-period-val, .fin-period-vals.n6 .fin-period-val { gap: 0.18rem; }
.fin-period-vals.n5 .cmp-dot, .fin-period-vals.n6 .cmp-dot { width: 0.42rem; height: 0.42rem; }
.fin-period-vals.n6 { font-size: 0.62rem; }
.fin-period-body { padding-top: 0.5rem; }


/* 브러시 손잡이 — 넓은 히트 영역 위에 마우스를 올리면 손잡이가 밝아진다 */
.brush-handle-group:hover .brush-handle,
.brush-handle-group:active .brush-handle {
  fill: var(--accent-hover);
}

@media (max-width: 680px) {
  :is(.page-analysis, .page-divergence) .page-layout.is-collapsed .indicator-quick {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.35rem;
    padding: 0.45rem 0;
    margin-bottom: 0.55rem;
    border-bottom: 1px solid var(--border);
  }
  /* 폰에서는 검색 입력과 담아 둔 종목을 남기고 설정만 접는다. */
  :is(.page-analysis, .page-compare, .page-timeline)
    [data-settings-pane][data-collapsed] > .aside-body { display: block; }
  :is(.page-analysis, .page-compare, .page-timeline)
    [data-settings-pane][data-collapsed] > .aside-body > :not(.search-card) { display: none; }
  :is(.page-analysis, .page-compare, .page-timeline)
    [data-settings-pane][data-collapsed] .search-card [data-settings-extra] { display: none; }
  :is(.page-analysis, .page-compare, .page-timeline)
    [data-settings-pane][data-collapsed] > .aside-toggle { margin-bottom: 0.6rem; }
  html { font-size: 18px; }
  .wrap { padding: 0.9rem 0.7rem 3rem; }
  .card { padding: 0.85rem; border-radius: var(--radius-lg); }
  .quote-price .now { font-size: 1.4rem; }
  .options { gap: 0.8rem 1rem; }
  .tl-table { --date-w: 3.4rem; --col-min: 8rem; }
  .timeline-grid { max-height: 75vh; }
  .type-grid { grid-template-columns: repeat(auto-fill, minmax(8rem, 1fr)); }
  /* 폰 폭에서 4열은 한 칸이 라벨보다 좁아진다 — 2열로 되돌린다. */
  .chips { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}


/* ── 4페이지: 클러스터링 ─────────────────────────────────────────────
 *
 * 카드마다 SVG 하나. 한 축(%)에 구성원 선 수십~백 개를 깔고, 그 위에 평균·
 * 중앙값 실선 둘과 (골랐다면) 강조 종목 하나를 얹는다. 겹침이 심하므로
 * 굵기와 불투명도로 층을 나눈다 — 색만으로는 안 갈린다.
 */

.cluster-progress { display: flex; gap: .75rem; align-items: center; margin-bottom: .75rem; }
.cluster-progress strong { display: block; }

.cluster-stats {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(112px, 1fr));
  gap: .5rem; margin-bottom: 1rem;
}
.cluster-stats .stat {
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: 10px; padding: .5rem .6rem;
}
.cluster-stats .stat-label { display: block; font-size: .75rem; color: var(--muted); }
.cluster-stats .stat strong { font-size: 1.05rem; color: var(--fg); }
/* 4페이지 요약은 좁은 왼쪽 칸에 선다. auto-fit 이면 칸이 112px 까지 좁아져
   "k-means (barycenter)" 가 칸 밖으로 삐져나갔다 — 3열로 못 박고 글자는 접는다. */
.page-clusters .cluster-stats { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.page-clusters .cluster-stats .stat { min-width: 0; }
.page-clusters .cluster-stats .stat strong {
  display: block; font-size: 0.95rem; line-height: 1.3;
  overflow-wrap: anywhere; word-break: keep-all;
}

.card-head.sub h3 { font-size: .95rem; margin: 0; color: var(--fg); }

/* 실루엣 막대 — k 를 고른 근거를 그대로 보여 준다 */
.sil-bars { display: flex; align-items: flex-end; gap: .35rem; height: 132px; padding-top: .25rem; }
.sil-bar { flex: 1; display: flex; flex-direction: column; align-items: center;
           justify-content: flex-end; height: 100%; gap: .2rem; }
.sil-bar i {
  display: block; width: 100%; max-width: 34px; border-radius: 4px 4px 0 0;
  background: color-mix(in srgb, var(--accent) 34%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--accent) 48%, transparent);
}
.sil-bar.chosen i { background: linear-gradient(180deg, var(--accent-2), var(--accent)); border-color: var(--accent); }
.sil-bar.muted i { background: var(--surface-2); border-color: var(--border); }
.sil-bar .v { font-size: .7rem; color: var(--muted); font-variant-numeric: tabular-nums; }
.sil-bar.chosen .v { color: var(--accent); font-weight: 700; }
.sil-bar .k { font-size: .75rem; color: var(--fg-soft); font-variant-numeric: tabular-nums; }
.sil-bar.chosen .k { font-weight: 700; color: var(--fg); }
.sil-bar.muted .v, .sil-bar.muted .k { color: var(--muted); }

/* 클러스터 카드 */
.cluster-card.has-focus { border-color: color-mix(in srgb, var(--accent) 46%, var(--border)); }
/* 접는 손잡이 — 제목 앞의 삼각형. 제목 글자를 눌러도 접힌다(clusters.js). */
.cluster-card > .card-head { justify-content: flex-start; }
.cluster-fold {
  display: inline-flex; align-items: center; justify-content: center; flex: none;
  width: 1.5rem; height: 1.5rem; margin-right: -.45rem;
  background: none; border: 0; border-radius: var(--radius-sm); padding: 0; cursor: pointer;
}
.cluster-fold:hover .caret { border-top-color: var(--accent); }
.cluster-fold:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.cluster-fold[aria-expanded="false"] .caret { transform: rotate(-90deg); }
/* 제목은 삼각형과 **한 줄**에 선다 — 길면 줄바꿈하지 않고 줄어들어 말줄임된다
   (폰에서 제목이 다음 줄로 밀려 삼각형 혼자 한 줄을 차지했다). */
.cluster-card h2[data-cluster-title] { cursor: pointer; flex: 1 1 10rem; min-width: 0; }
.cluster-card h2[data-cluster-title]:hover { color: var(--accent); }
/* 접힌 카드에서는 보기 기준 단추가 바꿀 그림이 없다. */
.cluster-card.is-collapsed .mode-switch { display: none; }
.cluster-size {
  font-size: .78rem; font-weight: 600; color: var(--muted);
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: 999px; padding: .1rem .45rem; margin-left: .35rem; vertical-align: middle;
}
/* 그림 + 구성 종목 목록을 좌·우로 놓는다. 목록을 접었다 펴면 카드가 세로로
   길어져 그림이 화면 밖으로 밀려나기 때문이다 — 목록은 항상 보이되 제 상자
   안에서만 굴린다. */
.cluster-body {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: .75rem;
  align-items: start;
}

/* 높이를 **상자**에 준다. JS 가 이 상자의 픽셀 크기를 재서 viewBox 로 쓰므로
   그림이 늘어나지 않고, 축 글자가 지정한 크기 그대로 나온다. */
.cluster-chart { width: 100%; height: 380px; }
.cluster-chart svg { width: 100%; height: 100%; display: block; }
.cluster-chart .grid { stroke: var(--border); stroke-width: 1; vector-effect: non-scaling-stroke; }
.cluster-chart .grid.zero { stroke: var(--border-strong); stroke-width: 1.5; }
.cluster-chart .axis-label {
  fill: var(--fg-soft); font-size: 14px; font-variant-numeric: tabular-nums;
}

/* 층 나누기: 구성원(얇고 흐림) < 중앙값 < 평균 < 강조 종목 */
.cluster-chart .member-line {
  fill: none; stroke: var(--cluster-member); stroke-width: 1;
  vector-effect: non-scaling-stroke;
}
/* 케이싱: 같은 경로를 바탕색으로 한 번 더 굵게 깔아 아래 선들과 떼어 놓는다.
   구성원 선 100개 위에 그냥 얹으면 색이 아무리 달라도 묻힌다. */
.cluster-chart .casing {
  fill: none; stroke: var(--surface); vector-effect: non-scaling-stroke;
  stroke-linejoin: round; stroke-linecap: round; opacity: .85;
}
.cluster-chart .casing.for-stat { stroke-width: 5; }
.cluster-chart .casing.for-pick { stroke-width: 6; }
.cluster-chart .casing.for-focus { stroke-width: 7; }

.cluster-chart .stat-line { fill: none; stroke-width: 2.5; vector-effect: non-scaling-stroke;
                            stroke-linejoin: round; stroke-linecap: round; }
.cluster-chart .stat-line.mean { stroke: var(--cluster-mean); }
.cluster-chart .stat-line.median { stroke: var(--cluster-median); }
.cluster-chart .focus-line {
  fill: none; stroke: var(--accent); stroke-width: 3.5; vector-effect: non-scaling-stroke;
  stroke-linejoin: round; stroke-linecap: round;
}
/* 표에서 켠 종목. 색은 인라인 style 로 온다 — 회사마다 3.1 계열 색을
   순서대로 돌려 쓰기 때문이다(2·3페이지와 같은 규칙). */
.cluster-chart .pick-line {
  fill: none; stroke-width: 3; vector-effect: non-scaling-stroke;
  stroke-linejoin: round; stroke-linecap: round;
}

.cluster-legend { display: flex; flex-wrap: wrap; gap: .75rem; margin: .25rem 0 .5rem; }
.cluster-legend .lg { display: inline-flex; align-items: center; gap: .35rem;
                      font-size: .8rem; color: var(--fg-soft); }
.cluster-legend .lg.focus { color: var(--accent); font-weight: 600; }
.cluster-legend .lg.picked { font-weight: 600; }
.cluster-legend .lg.picked .sw { height: 4px; }
.cluster-legend .sw { width: 16px; height: 3px; border-radius: 2px; display: inline-block; }
.cluster-legend .sw.mean { background: var(--cluster-mean); }
.cluster-legend .sw.median { background: var(--cluster-median); }
.cluster-legend .sw.member { background: var(--cluster-member); height: 2px; }
.cluster-legend .sw.focus { background: var(--accent); height: 4px; }
.cluster-legend .lg.clipped {
  color: var(--tone-na); cursor: help;
  border-bottom: 1px dotted color-mix(in srgb, var(--tone-na) 50%, transparent);
}

/* 구성 종목 — 넓은 화면에서는 그림 오른쪽. 제 상자 안에서 굴린다.
   상자 폭으로 줄 모양을 고른다(아래 @container member) — 화면 폭이 아니라
   상자 폭이라야 넓은 화면의 반쪽 칸에서도, 폰에서도 같은 규칙이 맞는다. */
.member-panel {
  container: member / inline-size;
  border: 1px solid var(--border); border-radius: 10px;
  background: var(--surface-2); overflow: hidden;
  display: flex; flex-direction: column; height: 380px;
}
.member-panel-head {
  display: flex; align-items: baseline; gap: .4rem; flex-wrap: wrap;
  padding: .45rem .6rem; font-size: .82rem; color: var(--fg-soft);
  border-bottom: 1px solid var(--border); background: var(--surface);
}
.member-panel-head b { color: var(--fg); font-size: .95rem; }
/* 전부 선택·해제는 종목 수 바로 옆에 붙인다 — "N종목" 을 읽고 그 자리에서
   전부 켤 수 있어야 한다. 안내 문구는 그 아래 줄로 접힌다. */
.member-panel-actions { display: flex; gap: .25rem; margin-left: auto; }
.member-panel-head .btn-sm { padding: .16rem .48rem; font-size: .74rem; }
.member-panel-head .muted { font-size: .72rem; flex-basis: 100%; }

/* 휠이 바깥 열까지 끌고 가지 않게 가둔다 — 묶음이 여럿이라 그러면 못 쓴다. */
.member-scroll {
  flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}
/* 한 줄 = 이름 · 수익률 · 군집 점수 · 단추 둘. 머리(.member-cols)도 같은 격자다. */
.member-cols, .member-item {
  display: grid; align-items: center; gap: .5rem;
  grid-template-columns: minmax(0, 1fr) 4.4rem 4rem 5.6rem;
  padding: .3rem .6rem;
}
.member-cols {
  position: sticky; top: 0; z-index: 1;
  background: var(--surface-2); border-bottom: 1px solid var(--border);
  font-size: .72rem; color: var(--muted);
}
.member-cols span:nth-child(2), .member-cols span:nth-child(3) { text-align: right; }
.member-list { list-style: none; margin: 0; padding: 0; font-size: .82rem; }
.member-item { border-bottom: 1px solid var(--border); }
.member-item:last-child { border-bottom: 0; }
.member-item.is-focus { background: var(--accent-soft); font-weight: 600; }
.member-item.is-picked { background: var(--surface); }
.member-item.is-picked .pick { font-weight: 700; color: var(--fg); }
/* 이름이 길면 줄을 늘리지 않고 말줄임으로 자른다. 코드는 자르지 않는다. */
.member-item .mi-name { display: flex; min-width: 0; max-width: 100%; white-space: nowrap; }
.member-item .mi-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.member-item .mi-code { flex: none; font-size: .72rem; }
.member-item .mi-ret, .member-item .mi-sil {
  text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap;
}
.member-item .mi-ret { font-weight: 600; }
.member-item .mi-sil-k { display: none; }
/* 차트 · 뉴스 — 따라가기 표의 .tk-open 을 그대로 쓴다. */
.member-item .mi-acts { display: grid; grid-template-columns: 1fr 1fr; gap: .25rem; }
.member-item .tk-open { font-size: .72rem; line-height: 1.7; }

/* 좁은 상자(폰, 또는 좁은 반쪽 칸): 두 줄로 접는다.
     1줄  이름 코드 ………… 수익률
     2줄  군집 점수 0.42 …… [차트][뉴스]
   가로로 밀지 않고 한 화면에 다 들어오고, 단추는 손가락으로 누를 만큼 크다. */
@container member (width < 27rem) {
  .member-cols { display: none; }
  .member-item {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: "name ret" "sil acts";
    row-gap: .3rem; padding: .5rem .7rem;
  }
  .member-item .mi-name { grid-area: name; }
  .member-item .mi-ret { grid-area: ret; font-size: .88rem; }
  .member-item .mi-sil { grid-area: sil; text-align: left; font-size: .72rem; color: var(--muted); }
  .member-item .mi-sil-k { display: inline; }
  .member-item .mi-acts { grid-area: acts; width: 7.2rem; gap: .35rem; }
  .member-item .tk-open { font-size: .78rem; line-height: 2.1; }
}

/* 보기 기준 단추 — 카드 머리에 들어가는 작은 세그먼트 */
.segmented.sm { padding: 2px; }
.segmented.sm button { font-size: .78rem; font-weight: 600; padding: .2rem .55rem; }
.segmented.sm button[disabled] { opacity: .4; cursor: not-allowed; }
.mode-switch { margin-left: auto; }

/* 이름 칸 전체가 단추다. 표 안에서 단추처럼 보이되 줄 높이는 그대로 둔다. */
.pick {
  display: inline-flex; align-items: center; gap: .4rem;
  background: none; border: 0; padding: 0; margin: 0;
  font: inherit; color: inherit; text-align: left; cursor: pointer;
}
.pick:hover { color: var(--accent); }
.pick:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
/* 꺼져 있을 때의 스와치는 구성원 선과 같은 옅은 색이다 — 지금 그 선이 화면에서
   어떤 색으로 그려져 있는지를 그대로 보여 준다. */
.pick .sw {
  width: 14px; height: 3px; border-radius: 2px; flex: none;
  background: var(--cluster-member);
}
.pick[aria-pressed="true"] .sw { height: 4px; }

/* ── 흐름도 + 종목 표 + 묶음 카드 ────────────────────────────────
   가운데 칸은 공통 묶음 → 기간별 흐름 → 한 종목 따라가기,
   오른쪽 칸은 시장 요약 → 각 묶음 → 제외된 종목 순서다. */

.flow-row { display: grid; column-gap: 1rem; grid-template-columns: minmax(0, 1fr); }
/* 한 줄로 세워질 때도 가운데 칸 다음에 오른쪽 칸을 읽는다. */
.links-card { order: 1; }
.flow-card { order: 2; }
.track-card { order: 3; }
/* 좁은 화면에서는 오른쪽 칸을 풀어 요약 → 묶음 카드 → 제외 순으로 쌓는다. */
.clu-side { display: contents; }
.clu-side > #result { order: 4; }
.clu-side > #cluster-cards { order: 5; }
.clu-side > #result-tail { order: 6; }

/* 옆에 세우는 것은 화면이 꽤 넓을 때뿐이다. 왼쪽 사이드바가 이미 한 뼘을
   가져가서, 1400px 아래에서 둘로 쪼개면 그림이 손바닥만 해진다.
   가운데 칸에는 흐름도·도넛·종목 표가 쌓인다. */
@media (min-width: 1400px) {
  .flow-row {
    grid-template-columns: minmax(0, 1fr) minmax(19rem, 24rem);
    align-items: start;
  }
  .links-card, .flow-card, .track-card { grid-column: 1; }
  /* 넓은 화면: 오른쪽 칸 하나로 묶어 시장 요약 아래에 묶음 카드들을 세운다. */
  .clu-side { display: block; grid-column: 2; grid-row: 1 / span 3; min-width: 0; }
  /* 오른쪽 칸에서는 그림과 구성원 목록을 한 줄에 둘 폭이 없다. */
  .clu-side .cluster-body { grid-template-columns: minmax(0, 1fr); }
}
/* 화면이 더 넓으면 종목 이름에 자리를 더 준다 — 여기서부터는 그림도 좁아지지
   않는다(왼쪽 칸이 이미 넉넉하다). */
@media (min-width: 1700px) {
  .flow-row { grid-template-columns: minmax(0, 1fr) minmax(22rem, 28rem); }
}
/* 설정을 접어 생긴 폭을 가운데·오른쪽 칸이 똑같이 나눠 쓴다. */
@media (min-width: 1400px) {
  .page-clusters .page-layout.is-collapsed .flow-row {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* ── 시장 간 공통 패턴 ──────────────────────────────────────────
   한 줄 = 패턴 하나, 한 칸 = 그 패턴을 가진 시장의 묶음 번호. 색을 새로 만들지
   않는다 — 대표 모양은 카드의 평균선과 같은 색, 시장별 모양은 흐린 글자색,
   "지금 보고 있는 시장" 은 accent 다(docs/DESIGN.md 3.3). */
.links-guide { margin: 0 0 .6rem; }
.links-table { width: 100%; border-collapse: collapse; font-size: .85rem; }
.links-table th, .links-table td { padding: .3rem .35rem; border-bottom: 1px solid var(--border); text-align: center; }
.links-table thead th { vertical-align: bottom; font-weight: 600; color: var(--fg-soft); }
.links-market { min-width: 3.4rem; }
.links-market button {
  font: inherit; font-weight: 700; color: inherit; background: none; border: 0; padding: 0;
  cursor: pointer; line-height: 1.2;
}
.links-market button:hover:not(:disabled) { color: var(--accent); }
.links-market button:disabled { cursor: default; color: var(--muted); }
.links-sub { display: block; font-size: .7rem; font-weight: 400; color: var(--muted); white-space: nowrap; font-variant-numeric: tabular-nums; }
.links-table .here { background: color-mix(in srgb, var(--accent) 8%, transparent); }
.links-market.here button { color: var(--accent); }
.links-id { font-weight: 800; color: var(--fg); width: 2.2rem; }
.links-shape { text-align: left !important; white-space: nowrap; }
.links-spark { width: 5.5rem; height: 1.9rem; display: block; }
.links-spark .links-member { fill: none; stroke: var(--muted); stroke-width: 1; opacity: .45; vector-effect: non-scaling-stroke; }
.links-spark .links-mean { fill: none; stroke: var(--cluster-mean); stroke-width: 2.2; vector-effect: non-scaling-stroke; }
.links-words { display: block; font-size: .7rem; color: var(--muted); }
.links-hit, .links-near {
  font: inherit; background: none; border: 1px solid transparent; border-radius: 8px;
  padding: .15rem .35rem; cursor: pointer; color: var(--fg);
}
.links-hit b { font-size: 1rem; font-variant-numeric: tabular-nums; }
.links-hit:hover, .links-near:hover { border-color: var(--accent); }
.links-hit:focus-visible, .links-near:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.links-near { color: var(--muted); font-size: .8rem; }
.links-none { color: var(--muted); }
.links-divider td { text-align: left !important; font-size: .75rem; color: var(--muted); padding-top: .8rem; }
.links-row.lone .links-id { color: var(--muted); }
.links-row.flash { background: var(--accent-soft); transition: background .4s; }

/* 좁은 칸(폰) — 표를 옆으로 밀지 않고 한 화면에 여덟 열을 다 세운다.
   폭은 화면이 아니라 표를 품은 `.table-scroll` 기준이다(위 stack-table 과 같은 자).
   열 폭을 고정(table-layout: fixed)해 시장 여섯 칸이 남는 폭을 똑같이 나누고,
   칸 안의 글자는 줄을 넘겨 접는다 — 전역 th/td 의 nowrap 을 그대로 두면 긴 칸이
   옆 칸 위로 넘쳐 글자가 겹친다. 문턱 32rem 은 표가 본래 모양으로 차지하는 폭
   (시장 여섯 칸 기준 약 31.5rem)이다 — 그보다 넓으면 원래 표 그대로 들어간다. */
@container (width < 32rem) {
  .links-table { table-layout: fixed; font-size: .72rem; }
  .links-table th, .links-table td {
    padding: .3rem .05rem; white-space: normal;
    word-break: keep-all; overflow-wrap: anywhere; overflow: hidden;
  }
  /* 폰(375px)에서 "코스피" · "129종목" 이 한 줄에 들도록 앞 두 열을 조인다. */
  .links-table thead th:first-child, .links-id { width: 1.75rem; }
  .links-table thead th:nth-child(2), .links-shape { width: 3rem; }
  /* 전역 th 글자 크기가 표의 것을 덮으므로 머리 칸은 따로 적는다. */
  .links-table thead th { font-size: .62rem; }
  .links-shape { white-space: normal; }
  .links-spark { width: 100%; height: 1.5rem; }
  .links-words { font-size: .54rem; line-height: 1.25; }
  .links-market { min-width: 0; }
  .links-market button { font-size: .6rem; line-height: 1.15; letter-spacing: -.02em; }
  .links-sub { font-size: .5rem; white-space: normal; line-height: 1.2; letter-spacing: -.02em; }
  .links-hit, .links-near { display: block; width: 100%; padding: .1rem 0; }
  .links-hit b { font-size: .86rem; }
  .links-near { font-size: .7rem; }
  .links-divider td { font-size: .66rem; }
}

/* 표 밑의 도넛 — 지금 고른 시장 한 열의 속살. 표와 같은 카드 안이라 선 하나로만 가른다. */
.links-mix { margin-top: 1rem; padding-top: .8rem; border-top: 1px solid var(--border); }
.links-mix-head {
  display: flex; align-items: center; justify-content: space-between; gap: .5rem;
  margin-bottom: .5rem;
}
.links-mix-title { margin: 0; font-size: .92rem; }

/* 시장마다 도넛 한 상자. 격자는 늘이지 않는다(align-items: start) — 늘이면 펼친
   이웃의 높이만큼 접힌 상자가 빈 채로 서서 접은 보람이 없다. */
.mix-grid {
  display: grid; gap: .5rem; align-items: start;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 250px), 1fr));
}
.mix-box {
  border: 1px solid var(--border); border-radius: 10px; background: var(--surface);
  min-width: 0;
}
.mix-box.here { border-color: color-mix(in srgb, var(--accent) 45%, transparent); }
.mix-box.off { background: var(--surface-2); }
/* 머리 — 접혔을 때 남는 전부. 이름 · 수 한 줄, 조각 글자, 비율 막대.
   조각 글자의 줄 수는 **상자 폭이 정한다**(아래 .mix-labels). 예전에는 한 줄에 넷을
   못 박고 높이를 줄 수만큼 고정해, 상자가 좁은 아이패드·폰에서 칸이 60px 남짓이 되어
   "A 48 24%" 의 비율이 잘리고 겹쳐 보였다. */
.mix-box-head {
  --mix-label-h: 1.15rem;
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  /* 높이를 맞춘 뒤 남는 자리는 조각 글자 줄이 먹는다 — 이름은 위, 비율 막대는
     바닥에 붙어 이웃 상자와 줄이 맞는다(가운데 정렬이면 이름이 상자마다 들쭉날쭉). */
  grid-template-rows: auto 1fr 6px;
  align-content: stretch; column-gap: .5rem; row-gap: .3rem;
  box-sizing: border-box; padding: .45rem .65rem .55rem;
  list-style: none; cursor: pointer; user-select: none;
}
/* 조각 글자 — 막대와 같은 차례, 같은 폭의 칸. 칸마다 색 표시 · 패턴 · 종목 수 · 비율.
   칸 수는 고정하지 않는다: 가장 긴 "■ A 151 9.5%" 가 온전히 들어가는 폭(5.6rem)을
   칸의 최소로 두고, 상자 폭에 들어가는 만큼 한 줄에 세운다(폰 2칸 · 보통 3~4칸).
   글자는 자르지 않는다 — 잘릴 바에는 줄을 하나 더 쓴다. */
.mix-labels {
  grid-column: 1 / -1; display: grid;
  grid-template-columns: repeat(auto-fill, minmax(5.6rem, 1fr));
  grid-auto-rows: var(--mix-label-h); column-gap: .5rem; row-gap: .05rem; align-content: start;
}
.mix-label {
  display: flex; align-items: center; gap: .25rem; min-width: 0;
  white-space: nowrap; font-size: .68rem; line-height: var(--mix-label-h);
  color: var(--fg-soft); font-variant-numeric: tabular-nums;
}
.mix-label .sw { width: 8px; height: 8px; border-radius: 2px; flex: none; }
.mix-label b { color: var(--fg); font-weight: 800; }
.mix-label-pct { color: var(--muted); margin-left: auto; padding-left: .2rem; flex: none; }
.mix-box-head::-webkit-details-marker { display: none; }
.mix-box.off .mix-box-head { cursor: default; }
/* 시장 이름은 자르지 않는다 — "코스피 200 보는 중" 이 칸보다 길면 줄을 바꾼다. */
.mix-box-title {
  font-size: .84rem; font-weight: 700; color: var(--fg); line-height: 1.3; min-width: 0;
}
.mix-here { white-space: nowrap; }
.mix-box-title::before {
  content: "▸"; display: inline-block; width: .9em; color: var(--muted);
  transition: transform .15s;
}
details[open] > .mix-box-head .mix-box-title::before { transform: rotate(90deg); }
.mix-box.off .mix-box-title::before { content: ""; }
.mix-here {
  font-style: normal; font-size: .66rem; font-weight: 700; color: var(--accent);
  margin-left: .2rem;
}
.mix-box-meta {
  font-size: .72rem; color: var(--muted); white-space: nowrap;
  font-variant-numeric: tabular-nums; align-self: center;
}
.mix-box-head:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; border-radius: 10px; }
/* 비율 막대 — 접어 두어도 "어느 패턴에 몰렸나" 는 읽힌다. */
.mix-strip {
  grid-column: 1 / -1; display: flex; height: 6px; border-radius: 3px; overflow: hidden;
  background: var(--surface-2); gap: 1px;
}
.mix-strip i { display: block; min-width: 2px; }
.mix-box-body { padding: .2rem .65rem .6rem; border-top: 1px solid var(--border); }
/* 상자가 좁아 도넛과 범례를 위아래로 쌓는다. */
.mix-box .mix-wrap { flex-direction: column; align-items: stretch; gap: .5rem; padding-top: .5rem; }
.mix-box .mix-pie { width: 136px; height: 136px; }
.mix-box .mix-legend { grid-template-columns: 1fr; flex: none; }
/* 펼친 몸통의 높이를 시장끼리 맞춘다 — 범례 한 줄을 고정 높이로 두고, 가장 묶음이
   많은 시장의 줄 수(--mix-max-items, clusters.js)만큼 모든 범례에 자리를 둔다.
   묶음이 적은 시장은 범례 아래가 비지만 상자의 바닥선이 나란히 맞는다.
   (접힌 머리의 높이는 폭에 따라 줄 수가 바뀌어 clusters.js 가 재어 맞춘다.) */
.mix-box .mix-item { height: 1.75rem; box-sizing: border-box; }
.mix-box .mix-legend {
  align-content: start;
  min-height: calc(var(--mix-max-items, 1) * 1.75rem + (var(--mix-max-items, 1) - 1) * .25rem);
}
.mix-box-head { box-sizing: border-box; }

/* 패턴 카드 머리 — "패턴 A (상승 · 상승 · 상승)" 뒤에 그 시장의 묶음 번호를 작게. */
.cluster-shape { font-size: .8rem; font-weight: 600; color: var(--muted); margin-left: .2rem; }

/* 묶음 카드 머리의 "패턴 B · 4개 시장" — 누르면 위 표의 그 줄로 간다. */
.cluster-pattern {
  font: inherit; font-size: .74rem; font-weight: 700; color: var(--accent);
  background: var(--accent-soft); border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent);
  border-radius: 999px; padding: .1rem .5rem; margin-left: .35rem; vertical-align: middle; cursor: pointer;
}
.cluster-pattern.lone { color: var(--muted); background: var(--surface-2); border-color: var(--border); }
.cluster-pattern:hover { border-color: var(--accent); }

/* ── 기간별 묶음 흐름 (Sankey) ───────────────────────────────────
   칸 머리는 그림과 **같은 수의 균등 그리드**다. 그래야 머리의 가운데와
   SVG 칸의 가운데가 정확히 맞는다(clusters.js 의 centerOf 와 짝이다). */

/* 색을 무엇으로 칠할지 — 그림 바로 위, 칸 머리보다 앞에 둔다. 작은 단추라
   눈에 먼저 들어오지 않지만, 색이 낯설 때 곧바로 손이 닿는 자리다. */
.flow-tones {
  display: flex; gap: .25rem; align-items: center; flex-wrap: wrap;
  margin-bottom: .35rem;
}
.flow-tone-lead { font-size: .72rem; color: var(--muted); }
/* 켜 둔 색이 무슨 뜻인지 — 단추 옆에 늘 펴 둔다. 좁은 화면에서는 단추 아래로
   내려가되 사라지지는 않는다(설명이 없으면 색은 그냥 무늬가 된다). */
.flow-tone-note { font-size: .72rem; color: var(--fg-soft); margin-left: .15rem; }
.flow-tone {
  background: var(--surface-2); border: 1px solid var(--border); border-radius: 999px;
  padding: .12rem .55rem; font: inherit; font-size: .72rem; color: var(--muted);
  cursor: pointer;
}
.flow-tone:hover { border-color: var(--accent); color: var(--fg); }
.flow-tone:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.flow-tone[aria-pressed="true"] {
  color: var(--accent); font-weight: 700;
  border-color: color-mix(in srgb, var(--accent) 45%, transparent);
  background: color-mix(in srgb, var(--accent) 12%, var(--surface));
}

.flow-heads { display: grid; gap: .25rem; margin-bottom: .35rem; }
.flow-head {
  display: flex; flex-direction: column; align-items: center; gap: .05rem;
  background: var(--surface-2); border: 1px solid var(--border); border-radius: 8px;
  padding: .3rem .2rem; font: inherit; color: var(--fg-soft); cursor: pointer;
  min-width: 0; overflow: hidden;
}
.flow-head:hover { border-color: var(--accent); color: var(--fg); }
.flow-head:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* 지금 보고 있는 칸. 아래 도넛·묶음 카드가 전부 이 칸의 것이다. */
.flow-head[aria-pressed="true"] {
  color: var(--accent); font-weight: 700;
  border-color: color-mix(in srgb, var(--accent) 45%, transparent);
  background: color-mix(in srgb, var(--accent) 12%, var(--surface));
}
.flow-head-label { font-size: .8rem; white-space: nowrap; }
.flow-head-sub { font-size: .68rem; color: var(--muted); font-variant-numeric: tabular-nums; }
.flow-head[aria-pressed="true"] .flow-head-sub { color: inherit; }

.flow-plot { width: 100%; }
.flow-svg { width: 100%; height: auto; display: block; overflow: visible; }

/* 띠는 옅게 깐다 — 100개 넘는 띠가 겹치므로 진하면 그림이 통째로 뭉갠다.
   하나에 손을 얹으면 그것만 진해져, 어디서 어디로 갔는지가 드러난다. */
/* 실오라기처럼 얇은 띠(한두 종목)는 그대로면 손이 닿지 않는다. 투명한 테두리를
   둘러 잡을 자리를 넓힌다 — 눈에는 그대로이고 손에만 넓어진다. */
.flow-link {
  opacity: .38; transition: opacity .12s; cursor: pointer;
  stroke: transparent; stroke-width: 5px; pointer-events: all;
}
.flow-link:hover, .flow-link:focus-visible { opacity: .85; }
.flow-link:focus-visible { outline: none; stroke: var(--accent); stroke-width: 1.5px; }

/* 띠에 실린 종목 목록. 한 종목에 한 줄 — 이름·가격·수익률뿐이다.
   목록이 길면 이 안에서 굴려 본다(그래서 말풍선도 손을 받는다). */
.flow-tip {
  position: fixed; z-index: 60; max-width: min(22rem, 92vw); max-height: 60vh;
  overflow-y: auto; overscroll-behavior: contain;
  background: var(--surface); border: 1px solid var(--border); border-radius: 10px;
  box-shadow: 0 8px 24px rgb(0 0 0 / .28); padding: .5rem .6rem;
}
.ft-head { font-size: .78rem; font-weight: 700; color: var(--fg); }
.ft-sub {
  font-size: .68rem; color: var(--muted); margin: .1rem 0 .35rem;
  padding-bottom: .3rem; border-bottom: 1px solid var(--border);
}
.ft-list { list-style: none; margin: 0; padding: 0; }
.ft-list li {
  display: grid; grid-template-columns: 1fr auto auto; gap: .5rem;
  align-items: baseline; padding: .12rem 0; font-size: .74rem;
}
.ft-list li + li { border-top: 1px dotted color-mix(in srgb, var(--border) 70%, transparent); }
.ft-name { color: var(--fg); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ft-price { color: var(--fg-soft); font-variant-numeric: tabular-nums; }
.ft-pct { font-variant-numeric: tabular-nums; min-width: 3.4rem; text-align: right; }
.ft-pct.up { color: var(--up); }
.ft-pct.down { color: var(--down); }
.flow-node { stroke: var(--surface); stroke-width: 1; cursor: pointer; }
.flow-node:hover { stroke: var(--fg); stroke-width: 1.5; }
/* 이름표는 띠 위에 얹힌다. 바탕색 테두리를 글자 **뒤로** 깔아 묻히지 않게 한다. */
.flow-label {
  fill: var(--fg-soft); font-size: 13px; font-weight: 700;
  font-variant-numeric: tabular-nums; pointer-events: none;
  paint-order: stroke; stroke: var(--surface); stroke-width: 3px; stroke-linejoin: round;
}
/* 순위 아래에 붙는 중앙값. 순위만으로는 "1등이 얼마짜리였나" 를 칸끼리
   견줄 수 없어서, 자리가 넉넉한 마디에만 한 줄 더 적는다. */
.flow-label-sub { font-size: 11px; font-weight: 600; fill: var(--muted); }
.flow-foot { margin: .5rem 0 0; }

/* 종목 하나를 따라갈 때 — 그 길만 남기고 나머지는 흐린다. 지우지는 않는다:
   무리 전체의 모양 안에서 그 하나가 어디였는지가 보여야 한다. */
.flow-link.is-dim { opacity: .06; }
.flow-link.is-trail { opacity: .92; }
.flow-node.is-dim { opacity: .22; }
.flow-node.is-trail { stroke: var(--fg); stroke-width: 2; }

/* ── 종목 하나 따라가기 (흐름 아래 표) ───────────────────────────
   칸 색은 흐름도에서 그대로 이어받는다. 다만 원색을 그대로 깔면 밝은 색 위의
   검은 글자와 어두운 색 위의 흰 글자를 한 벌로 맞출 수 없어, 바탕 쪽으로 조금
   눕히고 테두리에 원색을 남긴다(색은 그대로 읽힌다). */

.tk-tools { display: flex; gap: .35rem; margin-bottom: .5rem; }
.tk-filter {
  flex: 1; min-width: 0; background: var(--surface-2); color: var(--fg);
  border: 1px solid var(--border); border-radius: 8px; padding: .3rem .5rem;
  font: inherit; font-size: .78rem;
}
.tk-filter:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.tk-clear {
  background: var(--surface-2); border: 1px solid var(--border); border-radius: 8px;
  padding: .3rem .55rem; font: inherit; font-size: .72rem; color: var(--fg-soft);
  cursor: pointer; white-space: nowrap;
}
.tk-clear:hover { border-color: var(--accent); color: var(--fg); }

.tk-scroll { max-height: 27rem; overflow: auto; }

/* 칸 너비를 표에 맡기면 이름 칸이 제 마음대로 늘어나 마지막 기간이 밀려
   나간다. 기간 칸 여섯은 알약 하나 크기로, 차트 단추는 단추 하나 크기로 못
   박고, 남는 자리를 전부 이름이 쓴다. 칸마다 overflow 를 닫아 두는 것은, 글자가
   칸을 넘으면 옆 칸 위로 삐져나가 표가 어긋나 보이기 때문이다. */
.tk-table { width: 100%; border-collapse: collapse; font-size: .74rem; table-layout: fixed; }
.tk-table th, .tk-table td { overflow: hidden; }
.tk-table thead th + th { width: 1.4rem; }
.tk-table thead th.tk-h-open { width: 2.05rem; }
.tk-table thead th {
  position: sticky; top: 0; z-index: 1;
  background: var(--surface); color: var(--muted); font-size: .64rem;
  font-weight: 600; text-align: center; padding: .25rem .05rem;
  border-bottom: 1px solid var(--border); white-space: nowrap;
}
.tk-table thead th:first-child { text-align: left; padding-left: .25rem; }

/* 머리글은 통째로 정렬 단추다 — 어디를 눌러도 그 줄로 세워진다. 화살표는 지금
   세운 칸에만 붙는다: 여섯 칸이 전부 화살표를 달고 있으면 어느 것으로 세웠는지가
   되레 안 보인다. 기간 칸은 알약 하나 너비라 화살표를 글자 아래에 깐다. */
.tk-sort {
  width: 100%; display: flex; flex-direction: column; align-items: center; gap: 0;
  background: none; border: 0; padding: 0; margin: 0; line-height: 1.1;
  font: inherit; color: inherit; cursor: pointer;
}
.tk-table .tk-h-name .tk-sort {
  flex-direction: row; justify-content: flex-start; align-items: center; gap: .2rem;
}
.tk-sort:hover { color: var(--fg); }
.tk-sort:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.tk-table th[aria-sort="ascending"] .tk-sort,
.tk-table th[aria-sort="descending"] .tk-sort { color: var(--accent); font-weight: 700; }
.tk-caret { font-size: .45rem; line-height: 1; }
.tk-table tbody tr { cursor: pointer; }
.tk-table tbody tr:hover { background: var(--surface-2); }
.tk-table tbody tr.is-track {
  background: color-mix(in srgb, var(--accent) 16%, var(--surface));
}
/* 화살표로 옮겨 다니는 줄. 초점 테두리를 칸 밖으로 두면 표가 흔들려 보여서,
   안쪽 그림자로 그린다. */
.tk-table tbody tr:focus { outline: none; }
.tk-table tbody tr:focus-visible th:first-child { box-shadow: inset 2px 0 0 var(--accent); }
.tk-table tbody tr.is-track th:first-child { box-shadow: inset 2px 0 0 var(--accent); }
/* 한 종목은 **한 줄**이다. 이름 아래 코드를 한 줄 더 깔았더니 줄 높이가 두 배가
   되어, 화면 가득한 표에 열 종목밖에 들어오지 않았다. 코드도 이름 옆에서
   자리를 뺏어 이름이 "BNK…" 로 잘렸다 — 둘 다 줄에 얹은 title 로 내렸다. */
.tk-name {
  display: flex; align-items: baseline; text-align: left;
  font-weight: 600; color: var(--fg); padding: .1rem .25rem; line-height: 1.25;
}
.tk-name > span:first-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tk-cell { text-align: center; padding: .1rem .05rem; }
.tk-chip {
  display: inline-block; min-width: 1.05rem; padding: 0 .15rem; line-height: 1.35;
  border: 1px solid transparent; border-radius: 5px;
  font-weight: 700; font-variant-numeric: tabular-nums; color: var(--fg);
}

/* 줄 끝의 단추 둘 — 차트(1페이지, 새 창)와 뉴스(그때 기사, 팝업).
   칸을 가득 채워 두면 200줄이 흘러가도 세로줄이 곧게 보인다. */
.tk-open {
  display: block; width: 100%; padding: 0 .1rem; border: 1px solid var(--border);
  border-radius: 5px; font: inherit; font-size: .6rem; font-weight: 600;
  line-height: 1.5; color: var(--fg-soft); text-decoration: none;
  white-space: nowrap; text-align: center; background: none; cursor: pointer;
}
.tk-open:hover {
  color: var(--accent); border-color: var(--accent); background: var(--accent-soft);
}
.tk-open:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.tk-none { color: var(--muted); }

/* ── 그때 무슨 일이 있었나 (뉴스 팝업) ─────────────────────────────
   제목과 원문 링크만 있는 창이다. 시점 여섯을 위에서부터 긴 기간 → 짧은
   기간으로 쌓아, 표의 칸 차례와 눈이 같은 순서로 흐른다. */

.tk-modal { position: fixed; inset: 0; z-index: 80; display: flex;
  align-items: center; justify-content: center; padding: 1.25rem; }
.tk-modal-back {
  position: absolute; inset: 0; background: var(--scrim);
  backdrop-filter: blur(2px);
}
body.tk-modal-open { overflow: hidden; }
.tk-modal-box {
  position: relative; z-index: 1; width: min(78rem, 100%); max-height: 88vh;
  display: flex; flex-direction: column; overflow: hidden;
  background: var(--surface); border: 1px solid var(--border-strong);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-lg);
}
.tk-modal-head {
  display: flex; align-items: center; justify-content: space-between; gap: .5rem;
  padding: .8rem 1rem; background: var(--surface-2);
  border-bottom: 1px solid var(--border-strong);
}
.tk-modal-title { font-size: .95rem; font-weight: 700; color: var(--fg); }
.tk-modal-x {
  background: var(--surface); border: 1px solid var(--border-strong); border-radius: 8px;
  padding: .15rem .5rem; font: inherit; font-size: .85rem; color: var(--fg-soft);
  cursor: pointer; flex: none;
}
.tk-modal-x:hover { color: var(--on-accent); background: var(--accent); border-color: var(--accent); }
.tk-modal-x:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.tk-modal-body {
  padding: .9rem 1rem 1rem; overflow-y: auto;
  display: flex; flex-direction: column; gap: .6rem;
}

/* 시점 여섯이 **가로로** 선다(3년 → 3개월). 세로로 쌓으면 한 칸을 보려고
   다른 칸을 화면 밖으로 밀어내야 해서, 정작 보러 온 것 — 구간마다 말결이
   어떻게 달랐나 — 를 맞댈 수가 없다. 칸이 좁으면 옆으로 밀어 본다. */
.tk-news-rail {
  display: grid; grid-auto-flow: column; grid-auto-columns: minmax(11rem, 1fr);
  gap: .6rem; overflow-x: auto; padding-bottom: .3rem;
}
/* 넉넉한 화면에서는 여섯 칸이 **한 화면에 다 들어온다** — 옆으로 밀어야
   보이는 칸이 있으면 구간끼리 맞대 보라는 이 배치의 뜻이 반쯤 죽는다. */
@media (min-width: 1180px) {
  .tk-news-rail { grid-auto-columns: minmax(0, 1fr); }
}
.tk-news-col {
  display: flex; flex-direction: column; min-width: 0;
  background: var(--bg-2); border: 1px solid var(--border);
  border-radius: var(--radius-sm); overflow: hidden;
}
.tk-news-head {
  display: flex; align-items: center; flex-wrap: wrap; gap: .25rem .4rem;
  padding: .5rem .55rem; background: var(--surface-2);
  border-bottom: 1px solid var(--border);
}
.tk-news-stage {
  display: inline-block; padding: .1rem .45rem; border-radius: 999px;
  background: var(--accent-soft); color: var(--accent-hover);
  font-size: .78rem; font-weight: 700;
}
/* 그 구간에 주가가 간 거리. 국내 관례대로 상승 빨강 · 하락 파랑. */
.tk-news-move {
  font-size: .76rem; font-weight: 700; font-variant-numeric: tabular-nums;
}
.tk-news-up { color: var(--up); }
.tk-news-down { color: var(--down); }
.tk-news-move-none { color: var(--muted); font-weight: 500; cursor: help; text-decoration: underline dotted; }
.tk-news-span {
  flex-basis: 100%; font-size: .66rem; color: var(--fg-soft);
  font-variant-numeric: tabular-nums;
}
.tk-news-colbody { padding: .4rem; min-width: 0; }

.tk-news-list { list-style: none; margin: 0; padding: 0; display: grid; gap: .15rem; min-width: 0; }
.tk-news-list a {
  display: block; padding: .35rem .4rem; border: 1px solid transparent;
  border-radius: var(--radius-sm); text-decoration: none;
}
.tk-news-title {
  display: block; color: var(--fg); font-size: .78rem; line-height: 1.4;
  font-weight: 500;
  /* 좁은 칸이라 긴 제목이 칸을 밀어내면 안 된다. 한국어는 낱말을 지키고
     (keep-all), 그래도 넘치는 긴 영문·URL 만 아무 데서나 끊는다. */
  word-break: keep-all; overflow-wrap: anywhere;
}
.tk-news-list a:hover {
  background: var(--accent-soft); border-color: var(--border-strong);
}
.tk-news-list a:hover .tk-news-title { color: var(--accent-hover); text-decoration: underline; }
.tk-news-list a:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.tk-news-meta {
  display: flex; align-items: center; flex-wrap: wrap; gap: .15rem .3rem;
  margin-top: .15rem; font-size: .66rem; color: var(--muted);
}
.tk-news-day {
  color: var(--fg-soft); font-weight: 700; font-variant-numeric: tabular-nums;
}
.tk-news-src { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 기사의 결(실적·수주·투자·시장·수급…). 한 칸의 다섯 줄이 같은 결로 채워지지
   않게 골라 담는데, 그 골랐다는 사실이 눈에도 보여야 훑을 때 결이 잡힌다. */
.tk-news-topic {
  flex: none; padding: 0 .25rem; border-radius: 4px;
  background: var(--accent-soft); color: var(--accent-hover);
  font-weight: 700; white-space: nowrap;
}
/* 시점에서 멀리 떨어진 기사임을 표시한다 — 좁은 창에 걸린 기사가 없어
   구간을 넓혀 찾아온 줄이다. */
.tk-news-gap {
  font-style: normal; flex: none; white-space: nowrap; padding: 0 .25rem;
  border-radius: 4px;
  background: var(--surface); border: 1px solid var(--border);
  color: var(--fg-soft);
}
.tk-news-none { margin: .2rem; font-size: .72rem; color: var(--fg-soft); }
.tk-news-foot {
  margin: 0; padding-top: .5rem; border-top: 1px solid var(--border);
  font-size: .7rem; line-height: 1.5; color: var(--muted);
}
.tk-news-foot b { color: var(--fg-soft); font-weight: 700; }

/* 좁은 화면에서는 가로로 미는 대신 위에서 아래로 쌓는다 — 손가락으로
   가로 스크롤을 더듬는 것보다 낫다. */
@media (max-width: 860px) {
  .tk-news-rail { grid-auto-flow: row; grid-auto-columns: auto; overflow-x: visible; }
}
.tk-foot { margin: .45rem 0 0; }

/* 좁은 화면에서는 여섯 칸이 다 들어오도록 이름 칸과 알약을 줄인다. 옆으로
   밀어야 3개월이 보이면 "가장 가까운 기간" 을 매번 찾아 밀어야 한다. */
@media (max-width: 680px) {
  .tk-table { font-size: .7rem; }
  .tk-name { font-size: .72rem; padding-left: .1rem; }
  .tk-chip { min-width: 1.15rem; padding: .05rem .1rem; }
  .tk-cell { padding: .2rem .05rem; }
  /* 손바닥 화면에서는 알약과 단추를 한 번 더 조여, 남는 자리를 이름에 준다. */
  .tk-table thead th + th { width: 1.3rem; }
  .tk-table thead th.tk-h-open { width: 1.85rem; }
  .tk-open { font-size: .56rem; }
}

/* ── 도넛이 무엇을 보고 있는지 ───────────────────────────────────── */

.mix-ctx-row {
  display: flex; flex-wrap: wrap; gap: .3rem; margin-bottom: .6rem;
}
.mix-ctx {
  display: flex; align-items: baseline; gap: .3rem;
  border: 1px solid var(--border); border-radius: 8px;
  background: var(--surface-2); padding: .2rem .45rem;
}
.mix-ctx-label { font-size: .68rem; color: var(--muted); }
.mix-ctx strong {
  font-size: .78rem; color: var(--fg); font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

@media (max-width: 680px) {
  .flow-head-sub { display: none; }
  .flow-head-label { font-size: .72rem; }
  .flow-tone-note { flex-basis: 100%; margin-left: 0; }
}

/* ── 묶음별 종목 비율 (도넛) ─────────────────────────────────────── */

.mix-wrap { display: flex; gap: 1rem; align-items: center; flex-wrap: wrap; }
/* 가운데 정렬 — 범례가 옆에 설 때는 범례가 남는 폭을 다 먹어 자동 여백이 0 이 되고,
   좁아져 범례가 아래 줄로 내려가면 도넛 혼자 한 줄이라 여백이 양쪽으로 갈린다. */
.mix-pie { width: 168px; height: 168px; flex: none; margin-inline: auto; }
.mix-slice { stroke: var(--surface); stroke-width: 1.5; cursor: pointer; }
.mix-slice:hover { opacity: .8; }
.mix-total { fill: var(--fg); font-size: 26px; font-weight: 700; font-variant-numeric: tabular-nums; }
.mix-total-label { fill: var(--muted); font-size: 11px; }

.mix-legend {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(196px, 1fr));
  gap: .25rem; flex: 1 1 260px; min-width: 0;
}
.mix-item {
  display: flex; align-items: center; gap: .4rem;
  background: none; border: 1px solid transparent; border-radius: 8px;
  padding: .2rem .35rem; font: inherit; font-size: .8rem; color: var(--fg-soft);
  cursor: pointer; text-align: left;
}
.mix-item:hover { border-color: var(--border); background: var(--surface-2); color: var(--fg); }
.mix-item .sw { width: 12px; height: 12px; border-radius: 3px; flex: none; }
.mix-item > span { white-space: nowrap; }
.mix-item .mix-name {
  font-weight: 600; color: var(--fg); min-width: 0; overflow: hidden; text-overflow: ellipsis;
}
.mix-item .mix-size { margin-left: auto; font-variant-numeric: tabular-nums; }
.mix-item .mix-pct {
  color: var(--muted); font-variant-numeric: tabular-nums; min-width: 2.6em; text-align: right;
}

.focus-hit { margin: 0; color: var(--fg-soft); }
.focus-hit a { font-weight: 600; }

.method-list { margin: .75rem 0 0; font-size: .85rem; }
.method-list dt { font-weight: 700; color: var(--fg); margin-top: .6rem; }
.method-list dd { margin: .15rem 0 0; color: var(--fg-soft); }

.precomputed-hint { margin: .35rem 0 0; }
.ready-grid { display: flex; flex-wrap: wrap; gap: .3rem; margin-top: .4rem; }
.ready {
  font-size: .72rem; padding: .15rem .4rem; border-radius: 999px;
  border: 1px solid var(--border); color: var(--muted); background: var(--surface-2);
}
.ready.on {
  color: var(--tone-cfs); background: color-mix(in srgb, var(--tone-cfs) 14%, var(--surface));
  border-color: color-mix(in srgb, var(--tone-cfs) 28%, transparent);
}

/* ── 전체 갱신 ─────────────────────────────────────────────────────
   기간 단추와 같은 카드에 산다. 단추 하나가 수 분짜리 배치를 부르므로,
   지금 몇 개째인지가 단추 바로 아래에서 보여야 한다. */
/* 기간 · 계산 상태 · 갱신이 한 카드에 쌓인다. 붙어 있으면 어디까지가 한
   덩어리인지 안 보인다. */
.cluster-range { margin-top: 0.9rem; }
/* 기간 여섯 — 고른 칸 격자다. 줄을 넘기게 두면 좁은 칸에서 5 + 1 로 갈린다.
   폰에서는 3 × 2. */
.cluster-range .range-presets {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  border-radius: calc(1rem + 3px);
}
.cluster-range .range-presets button { padding: 0.22rem 0; white-space: nowrap; }
@media (max-width: 480px) {
  .cluster-range .range-presets { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* 4페이지 시장 표 — 시장 · 최근 계산 · 다음 자동 갱신 · 단추 네 칸.
   격자는 **목록 하나**에 두고 줄은 subgrid 로 열을 나눠 쓴다(5페이지와 같은 짜임).
   줄마다 제 격자에 rem 폭을 못 박으면 카드가 좁을 때 시각이 칸을 넘어 옆 칸과
   겹친다. 이제 열 폭은 글자가 정하고, 모자라면 날짜와 시각 사이(.mu-stamp)에서만
   접는다. 시장 이름은 낱말 단위로 접는다. */
.market-updated.with-actions {
  display: grid; grid-template-columns: minmax(3.2rem, 1fr) auto auto minmax(3.4rem, auto);
  column-gap: 0.55rem;
}
.market-updated.with-actions li {
  display: grid; grid-column: 1 / -1; grid-template-columns: subgrid;
  align-items: center; row-gap: 0;
}
.market-updated.with-actions li > span:first-child {
  white-space: normal; word-break: keep-all; overflow-wrap: anywhere; min-width: 0;
}
.market-updated.with-actions li > :not(:first-child) { text-align: right; white-space: nowrap; }
.market-updated.with-actions li > .mu-stamp { white-space: normal; }
.market-updated.with-actions .mu-stamp .num > span { white-space: nowrap; }
.market-updated.with-actions .mu-next { color: var(--muted); }
.market-updated.with-actions .market-updated-head > span { white-space: normal; word-break: keep-all; }
.market-updated.with-actions .btn-xs { width: 100%; justify-content: center; }
.market-updated li.is-stale .mu-date { color: var(--danger); }
.rebuild-bar .warn-note { flex-basis: 100%; color: var(--danger); }

/* 자동 갱신 일정 · 최근 갱신 작업 — 시장 표 바로 아래. */
.rebuild-schedule { margin-top: .7rem; font-size: .8rem; color: var(--fg-soft); }
.rebuild-schedule .rs-title { margin: 0 0 .25rem; font-weight: 700; color: var(--fg); }
.rs-list { list-style: none; margin: 0; padding: 0; }
.rs-list li {
  display: grid; grid-template-columns: 2.4rem minmax(0, 1fr) auto;
  column-gap: .5rem; padding: .12rem 0; align-items: baseline;
}
.rs-list .rs-label { font-weight: 700; color: var(--fg); }
.rs-list .rs-markets { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rs-list .rs-when { white-space: nowrap; }
.rs-list .rs-next { grid-column: 2 / -1; color: var(--muted); }
.rs-list .rs-next b { color: var(--fg); font-weight: 600; }
.rebuild-schedule .rs-last { margin: .4rem 0 0; }
.rebuild-schedule .rs-last.warn { color: var(--danger); }

.rebuild-bar {
  display: flex; align-items: center; gap: .7rem; flex-wrap: wrap;
  margin-top: .9rem; padding-top: .9rem; border-top: 1px solid var(--border);
}
.rebuild-bar .hint { flex: 1 1 16rem; margin: 0; }
.rebuild-progress { margin-top: .7rem; }
.rebuild-progress .hint { margin: .35rem 0 0; }
.rebuild-progress .hint.warn { color: var(--danger); }
.rebuild-track {
  height: 6px; border-radius: 999px; overflow: hidden;
  background: var(--surface-2); border: 1px solid var(--border);
}
.rebuild-track i {
  display: block; height: 100%; background: var(--accent);
  transition: width .3s var(--ease);
}

/* ── 2페이지 기술 지표 — 지표마다 작은 그림, 종목마다 선(종목 색). ─────────────── */
.ti-line { fill: none; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; opacity: .9; }
/* 지표 그림의 신호 표시 — 종류 색(매수 초록 · 매도 빨강)으로 채우고 테를 종목 색으로 두른다. */
.ti-mark { font-size: 12px; stroke-width: .8px; paint-order: stroke fill; }
.ti-count { fill: var(--muted); font-weight: 600; }
.ti-wrap { padding-top: 4px; }
.ti-wrap .ti-missing, .ti-wrap .ti-empty { margin: .1rem 0 .4rem; font-size: .76rem; }
.ti-wrap .ti-label { margin: .3rem 0 0; font-size: .82rem; font-weight: 700; color: var(--fg-soft); }
.ti-legend { margin: .45rem 0 0; font-size: .76rem; line-height: 1.55; }
.ti-legend .ti-bull { color: var(--div-bull); }
.ti-legend .ti-bear { color: var(--div-bear); }

/* ── 다이버전스 종목 — 날짜는 접고, 각 날짜의 시장 목록은 따로 스크롤 ─────
   단추 끝의 ▲n R·V 는 방향별 신호 수와 지표 머리글자다. */
.dpick-card .card-head { margin-bottom: .5rem; }
.dpick-bar { display: flex; gap: .45rem; align-items: center; margin-bottom: .55rem; }
.dpick-bar .segmented { flex: 1 1 auto; min-width: 0; }
.dpick-bar .segmented button { font-size: .8rem; line-height: 1.4; }
.dpick-bar select { flex: 0 1 7.2rem; min-width: 0; font-size: .8rem; padding: .3rem .45rem; }
.dpick-list { margin: 0 -.2rem; padding: 0 .2rem; }
.dpick-list > .hint { margin: .2rem 0; font-size: .82rem; }
.dpick-day { border-top: 1px solid var(--border); }
.dpick-day:first-child { border-top: 0; }
.dpick-day > summary {
  display: flex; justify-content: space-between; align-items: baseline; gap: .5rem;
  cursor: pointer; padding: .42rem .1rem; font-size: .86rem; font-weight: 700;
  list-style: none;
}
.dpick-day > summary::-webkit-details-marker { display: none; }
.dpick-day > summary::before { content: "▸"; color: var(--muted); margin-right: .35rem; }
.dpick-day[open] > summary::before { content: "▾"; }
.dpick-day > summary > .num { margin-right: auto; }
.dpick-day > summary .hint { font-size: .74rem; font-weight: 600; }
.dpick-day[open] { padding-bottom: .5rem; }
.dpick-market-group + .dpick-market-group { margin-top: .45rem; }
.dpick-mkt { margin: .3rem 0 .25rem; font-size: .72rem; font-weight: 700; color: var(--muted); }
.dpick-market-scroll {
  max-height: min(12rem, 34vh); overflow-y: auto; overflow-x: hidden;
  padding: .1rem .3rem .2rem 0; -webkit-overflow-scrolling: touch;
  scrollbar-width: thin; overscroll-behavior-y: auto;
}
.dpick-market-scroll:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.dpick-chips { display: flex; flex-wrap: wrap; gap: .3rem; }
.dpick-btn {
  display: inline-flex; align-items: baseline; gap: .25rem; max-width: 100%;
  font: inherit; font-size: .78rem; font-weight: 600; color: var(--fg-soft);
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-pill);
  padding: .16rem .55rem; cursor: pointer;
}
.dpick-btn:hover { border-color: var(--accent); color: var(--accent); }
.dpick-btn[aria-pressed="true"] { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); }
.dpick-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dpick-btn i { flex: none; white-space: nowrap; font-style: normal; font-size: .68rem; font-weight: 700; }
.dpick-up { color: var(--div-bull); }
.dpick-dn { color: var(--div-bear); }

/* ── 최근 검색 ─────────────────────────────────────────────────────
   네 화면이 같은 목록을 쓴다. 칩 하나가 종목 하나. */
.recent-card .card-head { margin-bottom: .4rem; }
.recent-card .hint { margin: 0 0 .55rem; }
.recent-list { display: flex; flex-wrap: wrap; gap: .3rem; }
.recent-item {
  display: inline-flex; align-items: center; gap: .35rem;
  font: inherit; font-size: .8rem; font-weight: 600;
  color: var(--fg-soft); background: var(--surface-2);
  border: 1px solid var(--border); border-radius: var(--radius-pill);
  padding: .22rem .6rem; cursor: pointer; max-width: 100%;
  transition: border-color .15s var(--ease), color .15s var(--ease), background .15s var(--ease);
}
.recent-item:hover, .recent-item:focus-visible {
  border-color: var(--accent); color: var(--accent); background: var(--accent-soft);
}
.recent-item .recent-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.recent-item .code { color: var(--muted); font-weight: 600; font-size: .74rem; }

/* 좁으면 목록을 그림 아래로 내린다. 옆에 두면 둘 다 못 읽는다.
   그림 아래에서는 목록 높이를 그림에 맞출 까닭이 없다 — 화면 높이의 절반
   남짓을 준다. 넉넉해야 목록 안에서 굴리기 좋고, 그래도 화면을 다 덮지 않아야
   목록 밖을 잡고 페이지를 굴릴 자리가 남는다. 목록 끝에 닿으면 페이지가 이어서
   굴러간다(contain 을 풀었다) — 폰에서 손가락이 목록에 갇히지 않게. */
@media (max-width: 900px) {
  .cluster-body { grid-template-columns: minmax(0, 1fr); }
  .member-panel { height: auto; }
  .member-scroll { max-height: min(62vh, 34rem); overscroll-behavior: auto; }
}

@media (max-width: 680px) {
  .cluster-chart { height: 240px; }
  .cluster-chart .axis-label { font-size: 12px; }
  .sil-bars { height: 104px; }
  .sil-bar .v { display: none; }
  .mix-pie { width: 132px; height: 132px; }
}


/* ── 5페이지 다이버전스 ──────────────────────────────────────────────
   이 화면의 규칙 하나: **글자를 접지 않는다.** 가격·날짜가 제멋대로
   줄바꿈되면 목록을 훑는 눈이 매 줄에서 멈춘다. 그래서 숫자 칸은 `nowrap`
   이고, 한글은 `keep-all` 로 낱말 안에서 끊기지 않게 한다. 폭이 모자라면
   접는 대신 목록을 통째로 가로 스크롤한다(`.div-scroll`). 예외는 둘 — 긴
   종목명은 두 줄까지, 신호 칩은 칩 단위로 넘긴다. */

/* 시장별 마지막 갱신 — 4·5페이지 시장 카드 아래. 시장 이름과 시각이 한 줄씩. */
.market-updated {
  list-style: none;
  margin: 0.7rem 0 0;
  padding: 0.5rem 0.7rem;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  font-size: 0.8rem;
}
.market-updated li { display: flex; justify-content: space-between; gap: 0.6rem; padding: 0.16rem 0; }
/* 5페이지 — 시장 · 스캔한 시각 · 일봉 기준일 세 열.
   격자는 **목록 하나**에 두고 줄은 subgrid 로 그 열을 나눠 쓴다 — 줄마다 제 격자를
   만들고 뒤 두 칸 폭을 rem 으로 못 박았더니, 카드가 좁을 때 시각이 칸보다 길고
   한 줄로 묶인 시장 이름이 옆 칸 위로 넘어가 글자가 겹쳤다. 이제 열 폭은 글자가
   정한다. 연도는 적지 않는다(title 에 온전한 값) — 한 줄에 두 번 나오는 연도가
   칸을 가장 많이 먹었다. 그래도 모자라면 접는다: 시장 이름은 낱말 단위로, 시각은
   날짜와 시간 사이에서만(.mu-stamp) — 숫자 한가운데서 끊기지는 않는다. */
.page-divergence .market-updated {
  display: grid; grid-template-columns: minmax(3.2rem, 1fr) auto auto auto;   /* 시장 · 스캔 · 다음 스캔 · 일봉 */
  column-gap: 0.55rem;
}
.page-divergence .market-updated .mu-next { color: var(--muted); }
.page-divergence .market-updated li {
  display: grid; grid-column: 1 / -1; grid-template-columns: subgrid;
  align-items: baseline; row-gap: 0;   /* 열 간격은 목록의 column-gap 을 물려받는다 */
}
.page-divergence .market-updated li > span:first-child {
  white-space: normal; word-break: keep-all; overflow-wrap: anywhere; min-width: 0;
}
.page-divergence .market-updated li > :not(:first-child) { text-align: right; white-space: nowrap; }
.page-divergence .market-updated li > .mu-stamp { white-space: normal; }
.page-divergence .market-updated .mu-stamp > span { white-space: nowrap; }
.page-divergence .market-updated li > .mu-wide { grid-column: 2 / -1; white-space: normal; }
/* 머리글도 좁으면 낱말 사이에서 접는다 — 한 줄로 묶어 두면 머리글이 열 폭을 정해
   값보다 넓은 칸이 카드 밖으로 밀려난다. */
.page-divergence .market-updated .market-updated-head > span { white-space: normal; word-break: keep-all; }

/* 5페이지 목록 머리의 종목 찾기 */
.div-list-head { flex-wrap: wrap; }
.div-list-head .hint { margin-right: 0; }
.div-list-head .section-toggle { flex: 0 0 auto; }
.div-list-meta { display: inline-flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 0.4rem; margin-left: auto; min-width: 0; }
.div-list-latest { color: var(--fg-soft); font-size: 0.82rem; font-weight: 700; white-space: nowrap; }
.div-list-tools { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem; margin-bottom: 0.5rem; }
.div-search { width: 14rem; max-width: 100%; font-size: 0.85rem; padding: 0.32rem 0.6rem; }
.market-updated li > span:first-child { font-weight: 600; white-space: nowrap; }
.market-updated li > :last-child { text-align: right; }
.market-updated .market-updated-head { color: var(--muted); font-size: 0.72rem; font-weight: 700; border-bottom: 1px solid var(--border); margin-bottom: 0.2rem; }
.market-updated .market-updated-head > span:first-child { font-weight: 700; }
.market-updated li.is-current > span:first-child { color: var(--accent); }
.market-updated li.is-current > span:first-child::before { content: "▸ "; }
.key-points { margin: 0.4rem 0 0; padding-left: 1.1rem; font-size: 0.86rem; line-height: 1.6; }

.div-markets { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.4rem; }

.div-market {
  font: inherit;
  font-size: 0.82rem;
  font-weight: 700;
  cursor: pointer;
  text-align: left;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.4rem;
  min-width: 0;
  color: var(--fg-soft);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0.45rem 0.6rem;
  transition: border-color 0.15s var(--ease), color 0.15s var(--ease), background 0.15s var(--ease);
}
.div-market:hover { border-color: var(--border-strong); }
.div-market:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.div-market-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; word-break: keep-all; }
.div-market-state { flex: none; font-size: 0.72rem; font-weight: 600; color: var(--muted); white-space: nowrap; }

.div-market[aria-pressed="true"] {
  color: var(--accent);
  border-color: var(--accent);
  background: var(--accent-soft);
}
.div-market[aria-pressed="true"] .div-market-state { color: var(--accent); }
.div-market[data-status="loading"] .div-market-state { color: var(--muted); }
.div-market[data-status="error"] { border-color: var(--danger); color: var(--danger); }
.div-market[data-status="error"] .div-market-state { color: var(--danger); }

/* 신호 종류 칩 — 색은 1페이지 화살표와 같은 토큰이다(docs/DESIGN.md 3.1-1).
   라벨이 '매수 다이버전스'(8자)라 기본 4열에서는 잘린다. 두 열로 편다. */
#kinds { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.div-chip-bull, .div-chip-hidden_bull { --chip-color: var(--div-bull); }
.div-chip-bear, .div-chip-hidden_bear { --chip-color: var(--div-bear); }

/* 목록 */
.div-list-card .card-head { margin-bottom: 0.5rem; }
.div-scroll { overflow-x: auto; container: divlist / inline-size; }
/* 열 폭의 합이 곧 이 표의 최소 폭이다. 이보다 좁아지면 가로로 민다 — 글자를
   잘라 읽을 수 없게 만드는 것보다 옆으로 미는 편이 낫다. */
/* 최소 폭은 **아래 격자에서 계산한다** — 손으로 적은 숫자(예전 50rem + n × 2.8rem)는
   열 폭보다 2rem 남짓 좁아서, 맨 오른쪽 '차트' 단추가 카드 밖으로 삐져나갔다.
   고정 열의 합(48rem) + 신호등 열 + 열 간격 9개 + 좌우 여백 1rem 이다. 열 폭을
   고치면 `--fixed-w` 도 같이 고친다. */
.div-table {
  --ind-count: 8;
  --lamp-w: 2.25rem;
  --col-gap: 0.5rem;
  --fixed-w: 48rem;
  min-width: calc(var(--fixed-w) + var(--ind-count) * var(--lamp-w) + 9 * var(--col-gap) + 1rem);
}

/* 한 줄 = 같은 날 · 같은 종목. 열은 종목 · 신호등 묶음(켠 지표 수만큼, `--ind-count`
   는 divergence.js 가 넘긴다) · 신호 수 · 가격 둘 · 비율 셋 · 경과 · 차트다.
   고정 열 합: 3.6 + 6.2 + 6.2 + 4.3 + 4.6 + 4.6 + 2.8 + 3.2 + 종목 최소 12.5 = 48rem. */
.div-head, .div-row {
  display: grid;
  grid-template-columns:
    minmax(12.5rem, 1fr)
    calc(var(--ind-count) * var(--lamp-w))
    3.6rem
    6.2rem 6.2rem 4.3rem
    4.6rem 4.6rem
    2.8rem 3.2rem;
  align-items: center;
  column-gap: var(--col-gap);
  padding: 0.5rem 0.5rem;
  word-break: keep-all;
}
/* 숫자 여섯 칸의 묶음 — 넓은 표에서는 풀려서(contents) 제 열에 선다. 좁은 화면
   규칙(아래 `@container divlist`)이 이것을 이름표 달린 작은 격자로 바꾼다. */
.div-nums { display: contents; }
/* 불 아래 지표 이름 — 넓은 표에서는 머리줄이 적으므로 숨긴다. */
.div-lamp-name { display: none; }
/* 신호등 묶음 — 한 칸 안의 작은 격자. 바깥 열 간격을 받지 않아 불끼리 촘촘하다. */
.div-lamps {
  display: grid;
  grid-template-columns: repeat(var(--ind-count), var(--lamp-w));
  align-items: center;
}

.div-head {
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--fg-soft);
  border-bottom: 1px solid var(--border-strong);
  white-space: nowrap;
}
.div-head .right { text-align: right; }

.div-row {
  font-size: 0.92rem;
  color: var(--fg);
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
.div-price, .div-current-price, .div-change { text-align: right; }
.div-row:hover { background: var(--surface-2); }
/* 표가 가로로 밀려도 종목 칸은 왼쪽에 붙어 있다 — 신호등 열만 보고는 어느 종목의
   줄인지 알 수 없다. */
.div-row > .div-name, .div-head > .div-head-name {
  position: sticky;
  left: 0;
  z-index: 1;
  align-self: stretch;
  justify-content: center;
  margin-left: -0.5rem;
  padding-left: 0.5rem;
  background: var(--surface);
  /* 밀려 들어간 숫자가 잘린 채 붙어 보이지 않게 경계선 한 줄 */
  box-shadow: 1px 0 0 var(--border);
}
.div-head > .div-head-name { display: flex; align-items: center; justify-content: flex-start; }
.div-row:hover > .div-name { background: var(--surface-2); }
.div-disappeared {
  display: block;
  width: fit-content;
  margin-top: 0.15rem;
  color: var(--danger);
  font-size: 0.72rem;
  font-weight: 700;
  white-space: normal;
}
/* 날짜 머리글도 같은 이유로 글자만 왼쪽에 붙인다(바탕 띠는 표 폭 그대로). */
.div-day-label { position: sticky; left: 0.5rem; display: inline-flex; align-items: baseline; gap: 0.6rem; flex-wrap: wrap; }

/* 날짜 덩이 — 하루가 한 덩이고, 최신이 맨 위다. 머리글은 누르면 그날 줄을
   접었다 펴는 단추다(기본은 접힘). 생김새는 예전 그대로 두고, 단추가 얹는
   기본 모양만 지운다. */
/* 머리띠 — 접었다 펴는 단추(.div-day)가 폭을 다 쓰고, 오른쪽 끝에 "메일 보내기".
   바탕·모서리는 머리띠가 갖는다(두 단추가 한 띠로 보이게). */
.div-day-bar {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin: 0.9rem 0 0.2rem;
  padding-right: 0.35rem;
  background: var(--surface-2);
  border-radius: var(--radius-sm);
}
.div-day-bar:hover { background: color-mix(in srgb, var(--accent) 12%, var(--surface-2)); }
.div-list > .div-day-group:first-child .div-day-bar { margin-top: 0.2rem; }
.div-day {
  display: flex;
  align-items: baseline;
  /* 건수를 날짜 옆에 붙인다. 예전에는 표 너비만큼 오른쪽 끝으로 밀려 있어서,
     표가 가로로 밀린 상태(좁은 화면)에서는 화면 밖이었다 — 접힌 날은 건수가
     그 안에 무엇이 들었는지 알려 주는 유일한 표시라 보이지 않으면 안 된다. */
  gap: 0.6rem;
  flex: 1 1 auto;
  min-width: 0;
  padding: 0.3rem 0.5rem;
  background: transparent;
  border: 0;
  border-radius: var(--radius-sm);
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
  white-space: nowrap;
}
.div-day:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* 메일 보내기 — 표가 가로로 밀려도 오른쪽 끝에 붙어 있게 sticky 로 둔다. */
.div-mail {
  position: sticky;
  right: 0.35rem;
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  white-space: nowrap;
  background: var(--surface);
}
.div-mail-icon { font-size: 0.85em; line-height: 1; color: var(--accent); }
/* 좁은 목록(폰)에서는 건수가 단추에 가려지지 않게 날짜 아래 줄로 내린다. */
@container divlist (width < 30rem) {
  .div-day { white-space: normal; }
  .div-day-label { flex-wrap: wrap; row-gap: 0.05rem; column-gap: 0.6rem; }
  .div-day-date, .div-day-count, .div-day-stocks { white-space: nowrap; }
  .div-day-count { padding-left: 0.9rem; }
}
.div-mail[data-state="sending"] { opacity: 0.7; cursor: progress; }
.div-mail[data-state="sent"] { color: var(--success); border-color: var(--success); }
.div-mail[data-state="sent"] .div-mail-icon { color: var(--success); }
.div-mail[data-state="error"] { color: var(--danger); border-color: var(--danger); }
.div-day-date { font-weight: 700; color: var(--fg); font-size: 0.9rem; }
.div-day-age { font-size: 0.8rem; font-weight: 700; color: var(--accent); white-space:nowrap; }
.div-day-count, .div-day-stocks { font-size: 0.8rem; font-weight: 700; color: var(--fg-soft); }
.div-day-holiday { font-size: 0.8rem; font-weight: 700; color: var(--danger); white-space: normal; }
/* 접힘·펴짐 표시. 폭을 고정해 날짜가 좌우로 흔들리지 않게 한다. */
.div-day-mark {
  display: inline-block;
  width: 0.9rem;
  color: var(--muted);
  font-size: 0.72rem;
}

.div-kind {
  justify-self: start;
  font-size: 0.74rem;
  font-weight: 700;
  white-space: nowrap;
  padding: 0.14rem 0.45rem;
  border-radius: var(--radius-pill);
  border: 1px solid currentColor;
  background: color-mix(in srgb, currentColor 12%, var(--surface));
}
.div-kind-bull, .div-kind-hidden_bull { color: var(--div-bull); }
.div-kind-bear, .div-kind-hidden_bear { color: var(--div-bear); }
/* 히든은 같은 색 계열을 쓰되 테두리만 남긴다 — 정규 신호와 한눈에 갈린다. */
.div-kind-hidden_bull, .div-kind-hidden_bear { background: transparent; border-style: dashed; }

.div-ind { font-size: 0.76rem; font-weight: 700; color: var(--muted); white-space: nowrap; }

/* 종목 — 이름은 **두 줄까지** 접고, 그 아래에 코드 · 시장을 적는다.
   이 화면의 "접지 않는다" 규칙에서 종목명만 예외다. 미국 종목은 'Credo Technology
   Group Holding Ltd Ordinary Shares' 처럼 이름 자체가 길어서, 한 줄로 자르면
   앞 두 낱말만 남아 서로 구별이 안 된다. 두 줄이면 거의 다 읽히고, 그래도 넘치면
   말줄임표로 끝난다(전체 이름은 마우스를 올리면 뜬다). 코드는 이름과 다른 줄이라
   이름이 길어도 잘리지 않는다. */
.div-name {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  color: var(--fg);
}
.div-name .div-name-text {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
  white-space: normal;
  overflow-wrap: anywhere;
  font-weight: 700;
  line-height: 1.3;
}
.div-sub { display: flex; align-items: baseline; gap: 0.45rem; white-space: nowrap; min-width: 0; }
.div-name .div-code { flex: none; font-size: 0.78rem; font-weight: 700; color: var(--fg-soft); }

.div-mkt { font-size: 0.76rem; font-weight: 500; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* 신호등 — 지표마다 한 열, 칸마다 동그란 불 하나. 매수 초록 · 매도 빨강.
   켜진 불은 가운데가 살짝 밝고(유리알) 둘레로 같은 색이 번진다. 꺼진 칸은 작고
   흐린 점이라, 켜진 불만 눈에 들어온다. 색은 `--div-bull` / `--div-bear` 하나뿐 —
   1페이지 화살표와 같은 토큰이다(docs/DESIGN.md 3.1-1). */
/* 신호등 머리글 — 열이 2.25rem 이라 '거래량' · 'MACD' 가 빠듯하다. 자르면 이름을
   못 읽으니 자르지 않고, 글자를 조금 줄여 이웃 칸과 겹치지 않게 한다. */
.div-head-ind { text-align: center; font-size: 0.62rem; letter-spacing: -0.03em; white-space: nowrap; }
.div-lamp-cell { display: flex; justify-content: center; align-items: center; cursor: default; }
.div-lamp {
  --lamp: var(--border-strong);
  display: block;
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: color-mix(in srgb, var(--lamp) 70%, var(--surface));
}
.div-lamp.is-buy { --lamp: var(--div-bull); }
.div-lamp.is-sell { --lamp: var(--div-bear); }
.div-lamp.is-buy, .div-lamp.is-sell, .div-lamp.is-mixed {
  width: 1rem;
  height: 1rem;
  background: radial-gradient(circle at 35% 30%,
    color-mix(in srgb, var(--lamp) 55%, #fff) 0%, var(--lamp) 58%);
  box-shadow:
    0 0 0 3px color-mix(in srgb, var(--lamp) 16%, transparent),
    0 0 9px color-mix(in srgb, var(--lamp) 45%, transparent);
}
/* 같은 날 한 지표에서 매수·매도가 함께 — 반반으로 칠한다. */
.div-lamp.is-mixed {
  background: linear-gradient(90deg, var(--div-bull) 50%, var(--div-bear) 50%);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--border-strong) 35%, transparent);
}
/* 히든 — 같은 색의 고리만. 채운 불과 한눈에 갈리되 새 색은 만들지 않는다. */
.div-lamp.is-hidden {
  box-sizing: border-box;
  background: transparent;
  border: 3px solid var(--lamp);
  box-shadow: none;
}

/* 신호 수 — 굵은 합계 아래에 매수 · 매도 갈래를 작게. */
.div-count { display: flex; flex-direction: column; align-items: flex-end; line-height: 1.15; }
.div-count strong { font-size: 0.98rem; font-weight: 800; }
.div-count-split { font-size: 0.7rem; font-weight: 700; white-space: nowrap; }
.div-count-buy { color: var(--div-bull); }
.div-count-sell { color: var(--div-bear); }

.div-price, .div-current-price, .div-change, .div-value, .div-elapsed { text-align: right; white-space: nowrap; }
.div-price { font-weight: 800; color: var(--fg); }
.div-current-price { font-weight: 700; color: var(--fg); }
.div-value { color: var(--muted); font-size: 0.8rem; }
.div-change { font-weight: 700; }
.div-change .up { color: var(--up); }
.div-change .down { color: var(--down); }
.div-change .flat, .div-change .muted { color: var(--muted); font-weight: 500; }
.div-max-up, .div-max-down { font-size: 0.88rem; }
.div-elapsed { font-size: 0.82rem; font-weight: 600; color: var(--fg-soft); }
.div-elapsed .muted { color: var(--muted); }

.div-multi[aria-pressed="true"] { color: var(--accent); border-color: var(--accent); background: var(--accent-soft); }

/* 데일리 자동 메일 토글 — '걸러 보기' 와 신호 목록 머리 두 곳에 같은 모양으로 선다.
   켜짐은 accent 트랙에 손잡이가 오른쪽. 글자(켜짐 · 꺼짐)를 늘 같이 적는다 — 색만으로
   상태를 말하지 않는다. */
.daily-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.25rem 0.6rem 0.25rem 0.35rem;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-pill);
  background: var(--surface);
  color: var(--fg-soft);
  font: inherit;
  font-size: 0.8rem;
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
}
.daily-toggle:hover { border-color: var(--accent); }
.daily-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.daily-toggle[disabled] { opacity: 0.6; cursor: progress; }
.daily-track {
  position: relative;
  flex: none;
  width: 2rem;
  height: 1.1rem;
  border-radius: var(--radius-pill);
  background: var(--border-strong);
  transition: background 0.15s;
}
.daily-knob {
  position: absolute;
  top: 0.15rem;
  left: 0.15rem;
  width: 0.8rem;
  height: 0.8rem;
  border-radius: 50%;
  background: var(--surface);
  box-shadow: var(--shadow-xs);
  transition: transform 0.15s;
}
.daily-toggle[aria-checked="true"] { color: var(--accent); border-color: var(--accent); background: var(--accent-soft); }
.daily-toggle[aria-checked="true"] .daily-track { background: var(--accent); }
.daily-toggle[aria-checked="true"] .daily-knob { transform: translateX(0.9rem); }
.daily-state { color: var(--muted); font-weight: 700; }
.daily-toggle[aria-checked="true"] .daily-state { color: var(--accent); }
.daily-note { margin: 0.35rem 0 0; line-height: 1.5; }
/* 폰 폭에서 이름표가 한 줄을 고집해 카드 밖으로 밀렸다 — 이 칸만 줄바꿈을 허락한다. */
.daily-opt { min-width: 0; }
.daily-opt .opt-head { flex-wrap: wrap; row-gap: 0.35rem; }
.daily-opt .opt-head label { white-space: normal; min-width: 0; }
.daily-sync { margin-top: 0.35rem; }
/* 토글 둘(국내용 · 해외용) — 이름 · 보내는 시각 · 상태를 한 단추에. 시각은 옅게. */
.daily-slot { margin-top: 0.55rem; min-width: 0; }
.daily-slot .daily-toggle { max-width: 100%; white-space: normal; flex-wrap: wrap; row-gap: 0.15rem; }
.daily-when { color: var(--muted); font-weight: 500; font-variant-numeric: tabular-nums; }
.daily-toggle[aria-checked="true"] .daily-when { color: var(--accent); opacity: 0.8; }
.daily-pair { display: inline-flex; flex-wrap: wrap; gap: 0.35rem; }

/* 누를 수 있는 머리줄 — 머리글처럼 보이되 단추처럼 눌린다. */
.div-sort {
  appearance: none;
  border: 0;
  background: none;
  padding: 0;
  font: inherit;
  color: inherit;
  cursor: pointer;
  white-space: nowrap;
}
.div-sort:hover { color: var(--fg); text-decoration: underline; }
.div-sort:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.div-sort[aria-pressed="true"] { color: var(--fg); }
.div-sort-mark { margin-left: 0.15rem; font-size: 0.66rem; }

/* 값으로 줄을 세우면 날짜 덩이가 사라진다. 그때 신호일이 여기에 붙는다. */
.div-price-day {
  display: block;
  font-size: 0.7rem;
  font-weight: 500;
  color: var(--muted);
}

/* 상태 — 모양만 맞은 신호와 확정을 통과한 신호를 한눈에 가른다.
   색은 등록된 토큰만 쓴다(AGENTS 3-6): 무효는 muted, 확정 뒤는 강조색이다. */
.div-state {
  justify-self: start;
  font-size: 0.72rem;
  font-weight: 700;
  white-space: nowrap;
  padding: 0.1rem 0.4rem;
  border-radius: var(--radius-pill);
  border: 1px solid var(--border);
  color: var(--muted);
}
.div-state-waiting { color: var(--fg-soft); border-style: dashed; }
.div-state-open { color: var(--accent); border-color: var(--accent); background: var(--accent-soft); }
.div-state-closed { color: var(--fg); border-color: var(--border-strong); }
.div-state-void { color: var(--muted); opacity: 0.75; }

.div-open {
  justify-self: end;
  box-sizing: border-box;
  max-width: 100%;
  font-size: 0.74rem;
  font-weight: 700;
  white-space: nowrap;
  color: var(--muted);
  text-decoration: none;
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  padding: 0.12rem 0.45rem;
}
.div-open:hover { color: var(--accent); border-color: var(--accent); background: var(--accent-soft); }

@media (max-width: 680px) {
  .div-markets { grid-template-columns: minmax(0, 1fr); }
}

/* 목록이 표 폭(`.div-table` 의 min-width, 지표 8개면 71.5rem)보다 좁으면 표를 버리고
   **줄마다 카드**로 바꾼다. 예전에는 가로 스크롤로 버텼는데, 오른쪽 열(최대 −% ·
   경과 · 차트)이 늘 화면 밖이라 머리글이 잘려 보였고, 폰에서는 붙박이 종목 칸이
   화면을 거의 다 먹어 숫자가 하나도 안 보였다.
     1줄: 종목 · 신호등 · 신호 수 · 차트
     2줄: 숫자 여섯 칸 — 칸마다 제 이름표(`data-label`)를 단다
   머리줄은 정렬 단추만 남긴다(열 이름은 칸마다 따라다니므로). 폭은 `.div-scroll`
   (container) 기준이라 사이드바 폭 · 화면 폭 어느 쪽으로 좁아져도 같이 반응한다. */
@container divlist (width < 71.5rem) {
  .div-table { min-width: 0; }

  .div-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.3rem 1rem;
    padding: 0.35rem 0.5rem 0.5rem;
  }
  .div-head > :not(.div-head-sort) { display: none; }
  .div-head::before { content: "정렬"; color: var(--muted); font-weight: 600; font-size: 0.74rem; }

  .div-row {
    grid-template-columns: minmax(0, 1fr) auto auto auto;
    grid-template-areas:
      "name lamps count open"
      "nums nums  nums  nums";
    column-gap: 0.9rem;
    row-gap: 0.5rem;
    padding: 0.7rem 0.5rem;
  }
  .div-row > .div-name {
    grid-area: name;
    position: static;
    margin-left: 0;
    padding-left: 0;
    background: none;
    box-shadow: none;
  }
  .div-row:hover > .div-name { background: none; }
  .div-row > .div-lamps { grid-area: lamps; }
  .div-row > .div-count { grid-area: count; }
  .div-row > .div-open-acts { grid-area: open; }

  /* 불 칸 = 불 한 줄 + 이름 한 줄. 켜진 불(1rem)과 꺼진 점(0.5rem)의 크기가 달라도
     이름이 같은 높이에 서도록 불 자리 높이를 못 박는다. */
  .div-lamp-cell {
    display: grid;
    grid-template-rows: 1.35rem auto;
    justify-items: center;
    align-items: center;
    row-gap: 0.1rem;
  }
  .div-lamp-name {
    display: block;
    font-size: 0.58rem;
    font-weight: 600;
    letter-spacing: -0.03em;
    line-height: 1;
    color: var(--muted);
    white-space: nowrap;
  }

  .div-nums {
    grid-area: nums;
    display: grid;
    grid-template-columns: repeat(6, minmax(0, 1fr));
    gap: 0.35rem 0.8rem;
  }
  .div-nums > * { text-align: left; min-width: 0; }
  .div-nums > [data-label]::before {
    content: attr(data-label);
    display: block;
    margin-bottom: 0.08rem;
    font-size: 0.68rem;
    font-weight: 600;
    color: var(--muted);
  }
}

/* 폰 — 신호등을 종목 옆에 둘 자리도 없다. 신호등은 제 줄로 내려 폭 전체에 고르게
   펴고, 숫자는 세 칸씩 두 줄로 접는다. */
@container divlist (width < 40rem) {
  .div-row {
    grid-template-columns: minmax(0, 1fr) auto auto;
    grid-template-areas:
      "name  count open"
      "lamps lamps lamps"
      "nums  nums  nums";
    column-gap: 0.7rem;
  }
  .div-row > .div-lamps { grid-template-columns: repeat(var(--ind-count), minmax(0, 1fr)); }
  .div-nums { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* 일기: 신호를 짧게 모으고 가격·거래일 변화는 종목마다 한 벌만 표시한다. */
.div-table { min-width: 0; }
.div-head { display: flex; gap: 1rem; flex-wrap: wrap; }
.div-head::before { content: "정렬"; color: var(--muted); }
.div-row.diary-row {
  grid-template-columns: minmax(0, 1fr) auto auto auto;
  grid-template-areas: "name marks count open" "values values values values";
  gap: .55rem .85rem;
  padding: .8rem .5rem;
  white-space: normal;
}
.diary-row > .div-name {
  grid-area: name; position: static; box-shadow: none; background: none;
  padding-left: 0; margin-left: 0;
}
.diary-row > .div-count { grid-area: count; }
.diary-row > .div-open-acts { grid-area: open; }
.diary-marks { grid-area: marks; font-weight: 700; font-size: .9rem; max-width: 12rem; }
.diary-marks > span { display: inline-block; white-space: nowrap; }
.diary-positive { color: var(--accent); }
.diary-negative { color: var(--danger); }
.diary-values { grid-area: values; min-width: 0; font-weight: 700; }
.diary-values .div-nums { display: grid; grid-template-columns: .8fr repeat(4, minmax(0, 1fr)); gap: .5rem .8rem; }
.diary-values .diary-instrument { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.diary-values .div-nums > [data-label]::before {
  content: attr(data-label); display: block; color: var(--fg-soft); font-size: .76rem; font-weight: 700;
}
.diary-values .div-price-day { white-space: normal; overflow-wrap: anywhere; font-size: .7rem; font-weight: 700; color: var(--fg-soft); }
.diary-values .div-price-day.diary-negative { color: var(--danger); }
.diary-step-basis { margin-top: .55rem; color: var(--fg-soft); font-size: .7rem; font-weight: 700; }
.diary-steps { display: grid; grid-template-columns: minmax(4.5rem, auto) repeat(13, minmax(2.85rem, 1fr)); overflow-x: auto; margin-top: .55rem; }
.diary-step { display: flex; flex-direction: column; align-items: center; padding: .3rem .15rem; border-top: 1px solid var(--border); }
.diary-step small { color: var(--fg-soft); font-size: .76rem; font-weight: 700; white-space: nowrap; }
.diary-step strong { font-size: .82rem; font-weight: 800; white-space: nowrap; font-variant-numeric: tabular-nums; }
.diary-step-after { margin-top: .3rem; }
.diary-step strong.diary-step-unavailable { max-width: 4rem; white-space: normal; overflow-wrap: anywhere; font-size: .7rem; }
.diary-step-signals strong { max-width: 9rem; white-space: normal; text-align: center; }
.diary-step-signals strong > span { display: inline-block; white-space: nowrap; }
.diary-step.is-base { background: var(--accent-soft); border-radius: var(--radius-sm); }
@container divlist (width < 28rem) {
  .div-row.diary-row {
    grid-template-columns: minmax(0, 1fr) auto auto;
    grid-template-areas: "name count open" "marks marks marks" "values values values";
  }
  .diary-marks { max-width: none; }
  .diary-values .div-nums { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .diary-business { grid-column: 1 / -1; }
}

/* ─────────────────────────────────────────────────────── 회원 (ggeolmu)

   로그인·가입·설정 화면과 머리말의 계정 칩. 새 색을 만들지 않는다 —
   전부 등록된 토큰이다(docs/DESIGN.md 2장). */

.brand .wordmark {
  font-weight: 800;
  font-size: 1.15rem;
  letter-spacing: -0.02em;
  color: var(--fg);
}
.brand:hover .wordmark { color: var(--accent); }

/* 로그인·가입 카드는 화면 한가운데 좁게 선다. 폼 하나가 전부인 화면에서
   본문 폭을 다 쓰면 입력칸이 화면만큼 길어져 어디를 봐야 할지 흐려진다. */
.auth-card { max-width: 24rem; margin: 6vh auto 0; }
.auth-card .field:last-of-type { margin-bottom: 1.1rem; }
.auth-submit { width: 100%; }
.auth-alt { margin: 0.9rem 0 0; text-align: center; }

/* 맛보기 — 로그인 카드 아래 "또는" 금 하나와 조용한 단추. 로그인보다 앞서
   보이면 안 되므로 테두리 단추(btn-ghost)다. */
.auth-or {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  margin: 1.1rem 0 0.9rem;
  color: var(--muted);
  font-size: 0.8rem;
}
.auth-or::before,
.auth-or::after { content: ""; flex: 1; border-top: 1px solid var(--border); }
.auth-guest-note { margin: 0.45rem 0 0; text-align: center; }

.auth-notice {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  margin: 0 0 1rem;
  padding: 0.6rem 0.8rem;
  border-radius: var(--radius-md);
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  background: var(--accent-soft);
  font-size: 0.9rem;
}
.auth-notice strong { color: var(--accent); }

/* 머리말의 "맛보기" 표. 회원 이름 자리에 선다. */
.guest-badge {
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--accent);
  background: var(--accent-soft);
  border-radius: var(--radius-pill);
  padding: 0.18rem 0.6rem;
}
a.account-out { text-decoration: none; }

/* 맛보기에서 잠긴 것을 누르면 뜨는 안내 한 장. */
.guest-dialog {
  width: min(24rem, calc(100vw - 2rem));
  padding: 1.4rem 1.4rem 1.1rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface);
  color: var(--fg);
  box-shadow: var(--shadow-lg);
}
.guest-dialog::backdrop { background: var(--scrim); }
.guest-dialog h2 { margin: 0 0 0.5rem; font-size: 1.1rem; }
.guest-dialog p { margin: 0 0 0.5rem; line-height: 1.6; }
.guest-dialog-actions {
  display: flex;
  justify-content: flex-end;
  gap: 0.5rem;
  margin-top: 1rem;
}
.guest-dialog-actions .btn { text-decoration: none; }
.guest-dialog-alt { margin: 0.8rem 0 0; text-align: right; font-size: 0.82rem; }

.auth-error {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  margin-bottom: 0.9rem;
  padding: 0.6rem 0.8rem;
  border-radius: var(--radius-md);
  border: 1px solid var(--border);
  border-left: 3px solid var(--danger);
  background: var(--surface-2);
  font-size: 0.9rem;
}
.auth-error strong { color: var(--danger); }

/* 설정 화면 */

.stack-form { max-width: 26rem; }
.account-facts { display: grid; gap: 0.5rem; margin: 0; }
.account-facts > div { display: flex; gap: 0.8rem; align-items: baseline; }
.account-facts dt { color: var(--muted); font-size: 0.85rem; font-weight: 700; min-width: 7rem; }
.account-facts dd { margin: 0; color: var(--fg); }

.state-list { list-style: none; margin: 0.6rem 0 0; padding: 0; display: grid; gap: 0.5rem; }
.state-list li {
  display: flex;
  gap: 0.7rem;
  align-items: baseline;
  flex-wrap: wrap;
  padding: 0.5rem 0.7rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface-2);
}
.state-list li[data-empty] { border-style: dashed; background: none; }
.state-list a { font-weight: 700; }
.state-list .num { word-break: break-all; font-size: 0.8rem; }

/* ── 손바닥 화면 ─────────────────────────────────────────────────────
   폭이 400px 도 안 되는 화면에서는 여백 몇 밀리미터가 곧 그림의 폭이다.
   `.wrap` 좌우 여백과 카드 안쪽 여백을 함께 줄여, 줄어든 만큼을 전부 내용에
   준다(1.1rem × 2 + 1.2rem × 2 ≈ 74px — 375px 화면의 5분의 1이다). */
@media (max-width: 720px) {
  .wrap { padding-left: 0.6rem; padding-right: 0.6rem; }
  .card { padding: 0.85rem 0.8rem; }

  /* SVG 안의 글자 크기는 **화면 px 그대로**다 — viewBox 폭을 컨테이너 폭과
     같게 잡아 1:1 로 그리기 때문이다(chart.js). 그래서 16px 짜리 축 글자가
     데스크톱에서는 알맞아도 320px 짜리 그림 위에서는 눈금 여백을 통째로
     잡아먹는다. 좁은 화면에서만 한 단계씩 줄인다 — 여백을 줄인 chart.js 의
     `axisSlot` 과 한 벌이라, 한쪽만 고치면 글자가 여백 밖으로 삐져나간다. */
  .axis-text { font-size: 12px; }
  .zero-text { font-size: 12px; }
  .sub-label { font-size: 11px; }
  .sub-axis-text { font-size: 10px; }
  .sub-threshold-label { font-size: 9px; }
  .div-arrow-bull, .div-arrow-bear { font-size: 11px; }
  .div-arrow-tag { font-size: 8px; }
  .bar-change-label { font-size: 9px; }

  /* 기간 알약 다섯과 날짜칸 둘은 한 줄에 안 들어간다. 알약은 두 줄로 접고
     (알약 안에서 글자가 접히면 "6개 / 월" 이 된다), 날짜칸은 남는 폭을 반씩
     나눠 갖는다 — 예전에는 오른쪽 날짜칸이 화면 밖으로 밀려 나가 있었다. */
  .range-presets { flex-wrap: wrap; justify-content: center; border-radius: var(--radius-lg); }
  .range-presets button { padding: 0.22rem 0.6rem; white-space: nowrap; }
  .range-dates { flex: 1 1 100%; font-size: 0.78rem; }
  .range-dates input[type="date"] { flex: 1 1 0; min-width: 0; font-size: 0.78rem; padding: 0.3rem 0.35rem; }
  .line-style-bar { gap: 0.5rem 0.8rem; }
  .line-style-field input[type="range"] { width: 5rem; }
}

/* ── 웹앱으로 저장하기 ───────────────────────────────────────────────
   머리말 오른쪽, 계정 앞. 로그아웃처럼 조용한 글자 단추로 두면 눈에 안 띄고,
   큰 채운 단추로 두면 마크보다 시끄럽다 — 옅은 강조색 알약 하나로 둔다. */
.install-btn {
  appearance: none;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font: inherit;
  font-size: 0.82rem;
  font-weight: 700;
  white-space: nowrap;
  color: var(--accent);
  background: var(--accent-soft);
  border: 1px solid var(--accent-ring);
  border-radius: var(--radius-pill);
  padding: 0.32rem 0.75rem 0.32rem 0.6rem;
  cursor: pointer;
  transition: background 0.15s var(--ease), color 0.15s var(--ease), border-color 0.15s var(--ease);
}
.install-btn[hidden] { display: none; }
.install-btn svg { width: 1rem; height: 1rem; flex: none; }
.install-btn:hover { color: var(--on-accent); background: var(--accent); border-color: var(--accent); }
.install-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* 누른 뒤 브라우저의 설치 신호를 잠깐 기다리는 동안. */
.install-btn[disabled] { opacity: 0.6; cursor: progress; }

.install-dialog { width: min(26rem, calc(100vw - 2rem)); }
.install-device { color: var(--muted); font-size: 0.85rem; }
.install-steps { margin: 0.4rem 0 0.6rem; padding-left: 1.3rem; line-height: 1.7; }
.install-steps li { margin: 0.2rem 0; }
.install-steps b { color: var(--accent); }
.install-glyph {
  width: 1.05em;
  height: 1.05em;
  vertical-align: -0.18em;
  color: var(--accent);
}

/* 단추가 들어오면서 계정 칸이 넓어졌다 — 마크를 가운데 두고 계정을 오른쪽에
   절대 배치하는 머리말은 폭이 1180px 아래로 내려가면 둘이 겹친다. 태블릿·작은
   노트북에서는 마크를 왼쪽, 계정을 오른쪽에 흐름대로 세운다(메뉴는 그대로). */
@media (max-width: 1180px) {
  .topbar-row { flex-wrap: wrap; gap: 0.6rem; }
  .topbar-row .account { position: static; transform: none; margin-left: auto; }
  .topbar-row .brand { margin-right: auto; }
}

/* 폰에서는 머리말 한 줄에 마크 · 단추 · 계정이 다 서야 한다 — 글자를 줄인다. */
@media (max-width: 720px) {
  .install-btn { font-size: 0.78rem; padding: 0.28rem 0.6rem 0.28rem 0.5rem; }
  .account { gap: 0.7rem; }
}
@media (max-width: 600px) {
  .install-btn .install-label { font-size: 0; }
  .install-btn .install-label::after { content: "앱 저장"; font-size: 0.78rem; }
  .account { gap: 0.55rem; }
  .account-name { max-width: 7rem; }
}
@media (max-width: 400px) {
  .account { gap: 0.35rem; }
  .account-name { max-width: 5rem; }
  .account-out { font-size: 0.8rem; }
}

/* ── 당겨서 새로고침 (pull-refresh.js) ───────────────────────────────
   터치 기기에서만 켜진다(`html.ptr-on`). 브라우저 기본 새로고침·바운스는 끈다 —
   켜 두면 우리 것과 함께 두 번 새로고침된다. 표시는 화면 위 가운데의 작은
   원 하나: 끌수록 내려오며 화살표가 돌고, 놓으면 새로고침되는 지점부터
   강조색으로 찬다. */
html.ptr-on, html.ptr-on body { overscroll-behavior-y: none; }
.ptr {
  position: fixed;
  top: env(safe-area-inset-top, 0px);
  left: 50%;
  z-index: 1000;
  width: 2.5rem;
  height: 2.5rem;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--surface);
  color: var(--accent);
  border: 1px solid var(--border);
  box-shadow: var(--shadow);
  transform: translate(-50%, -56px);
  opacity: 0;
  pointer-events: none;
}
.ptr-icon { width: 1.3rem; height: 1.3rem; grid-area: 1 / 1; }
.ptr.is-ready { background: var(--accent); color: var(--on-accent); border-color: var(--accent); }
.ptr-spin {
  grid-area: 1 / 1;
  width: 1.2rem;
  height: 1.2rem;
  border-radius: 50%;
  border: 2.5px solid currentColor;
  border-right-color: transparent;
  display: none;
}
.ptr.is-loading .ptr-icon { display: none; }
.ptr.is-loading .ptr-spin { display: block; animation: ptr-spin 0.7s linear infinite; }
@keyframes ptr-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .ptr.is-loading .ptr-spin { animation-duration: 1.6s; }
}

/* ── 차트 팝업 (popups.js) ───────────────────────────────────────────
   1페이지를 iframe 으로 띄운다. 거의 화면 가득 — 차트를 보러 연 창이다.
   머리: 종목 이름 · "새 창" · ✕(오른쪽 위). */
.tk-modal-head .tk-modal-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tk-modal-acts { display: flex; align-items: center; gap: .4rem; flex: none; }
.tk-modal-acts:empty { display: none; }
.tk-modal-new {
  font-size: .8rem; font-weight: 700; color: var(--fg-soft); text-decoration: none;
  border: 1px solid var(--border-strong); border-radius: 8px; padding: .15rem .55rem;
  background: var(--surface);
}
.tk-modal-new:hover { color: var(--accent); border-color: var(--accent); background: var(--accent-soft); }
.tk-modal-x { font-size: 1rem; padding: .2rem .6rem; }
.tk-chart-modal { padding: 1.5vh 1.5vw; }
.tk-chart-modal .tk-modal-box { width: min(110rem, 100%); height: 97vh; max-height: 97vh; }
.tk-chart-modal .tk-modal-body { flex: 1; padding: 0; overflow: hidden; display: block; }
.tk-chart-frame { display: block; width: 100%; height: 100%; border: 0; background: var(--bg); }
/* 폰 — 화면 전체. 가장자리 여백도 아깝다. 노치 아래로 내려 ✕ 가 가리지 않게. */
@media (max-width: 720px) {
  .tk-chart-modal { padding: 0; }
  .tk-chart-modal .tk-modal-box {
    height: 100vh; height: 100dvh; max-height: none; border-radius: 0; border: 0;
    padding-top: env(safe-area-inset-top, 0px);
  }
}

/* 팝업 안의 1페이지(?embed=1) — 머리말 · 메뉴 · 제목 · 꼬리말을 빼고 차트만. */
body.is-embed .topbar-band,
body.is-embed .page-head,
body.is-embed .footer { display: none; }
body.is-embed .wrap { padding-top: .8rem; }

/* 다이버전스 줄 끝 — 차트 위, 뉴스 아래. 두 단추가 같은 폭으로 쌓인다. */
.div-open-acts {
  justify-self: end; display: flex; flex-direction: column; align-items: stretch; gap: .25rem;
}
.div-open-acts .div-open { justify-self: auto; text-align: center; }
button.div-open {
  font-family: inherit; background: none; cursor: pointer; line-height: inherit;
}

/* 제목 줄 — 제목 왼쪽, 단추(1 · 2페이지 "메일 보내기") 오른쪽 끝. 폭이 모자라면 단추가
   아래 줄로 내려가고 제목과 겹치지 않는다. */
.page-head-row { display: flex; align-items: center; justify-content: space-between; gap: 0.6rem; flex-wrap: wrap; }
.page-head-row h1 { min-width: 0; }
.report-mail { flex: none; display: inline-flex; align-items: center; gap: 0.35rem; white-space: nowrap; }
.report-mail-icon { color: var(--accent); font-size: 0.9em; line-height: 1; }
.report-mail[data-state="sending"] { opacity: 0.7; cursor: progress; }
.report-mail[data-state="sent"] { color: var(--success); border-color: var(--success); }
.report-mail[data-state="error"] { color: var(--danger); border-color: var(--danger); }

/* ── 2페이지 분석 조합(회원 계정에 저장 · 같은 이름 = 새 버전) ── */
.combo-card .card-head { margin-bottom: .4rem; }
.combo-save { display: flex; gap: .4rem; }
.combo-save input {
  flex: 1; min-width: 0; padding: .45rem .6rem; font: inherit; font-size: .85rem;
  border: 1px solid var(--border-strong); border-radius: var(--radius-sm); background: var(--surface); color: var(--fg);
}
.combo-save input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-ring); }
.combo-save .btn { white-space: nowrap; }
.combo-status { margin: .35rem 0 0; min-height: 1.1em; font-size: .76rem; color: var(--muted); }
.combo-status.is-ok { color: var(--success); }
.combo-status.is-error { color: var(--danger); }
.combo-list { display: flex; flex-direction: column; gap: .4rem; margin-top: .35rem; }
.combo-empty { margin: 0; font-size: .8rem; color: var(--muted); }
.combo {
  border: 1px solid var(--border); border-radius: var(--radius-md); background: var(--surface);
  overflow: hidden; transition: border-color .15s var(--ease), box-shadow .15s var(--ease);
}
.combo:hover { border-color: var(--border-strong); }
.combo.is-active { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-ring); }
.combo-main {
  display: block; width: 100%; padding: .5rem .6rem .35rem; border: 0; background: none; text-align: left;
  font: inherit; color: var(--fg); cursor: pointer;
}
.combo-main:hover .combo-name, .combo-main:focus-visible .combo-name { color: var(--accent); }
.combo-top { display: flex; align-items: center; gap: .35rem; flex-wrap: wrap; }
.combo-name { font-weight: 800; font-size: .9rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }
.combo-ver {
  font-size: .68rem; font-weight: 700; color: var(--accent); background: var(--accent-soft);
  padding: .05rem .38rem; border-radius: var(--radius-pill);
}
.combo-flag {
  font-size: .68rem; font-weight: 700; color: var(--muted); background: var(--surface-2);
  padding: .05rem .38rem; border-radius: var(--radius-pill);
}
.combo-flag.is-changed { color: var(--danger); background: color-mix(in srgb, var(--danger) 10%, var(--surface)); }
.combo-items {
  display: block; margin-top: .15rem; font-size: .76rem; color: var(--fg-soft);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.combo-acts {
  display: flex; align-items: center; justify-content: space-between; gap: .4rem;
  padding: .15rem .45rem .4rem .6rem;
}
.combo-date { font-size: .7rem; color: var(--muted); }
.combo-del { margin-left: auto; }
.combo-del.is-armed, .combo-x.is-armed { color: var(--danger); border-color: var(--danger); }
.combo-versions { list-style: none; margin: 0; padding: .25rem .45rem .45rem; border-top: 1px dashed var(--border);
  display: flex; flex-direction: column; gap: .2rem; background: var(--surface-2); }
.combo-versions li { display: flex; align-items: center; gap: .3rem; border-radius: var(--radius-sm); }
.combo-versions li.is-active { background: var(--accent-soft); }
.combo-ver-load {
  flex: 1; min-width: 0; padding: .3rem .35rem; border: 0; background: none; text-align: left; font: inherit;
  font-size: .78rem; color: var(--fg); cursor: pointer;
}
.combo-ver-load b { color: var(--accent); }
.combo-ver-load .combo-items { font-size: .72rem; }
.combo-x {
  flex: none; width: 1.6rem; height: 1.6rem; border: 1px solid transparent; border-radius: var(--radius-sm);
  background: none; color: var(--muted); cursor: pointer; font-size: .75rem; white-space: nowrap;
}
.combo-x.is-armed { width: auto; padding: 0 .35rem; }
.combo-x:hover { color: var(--danger); }

/* ── 설정 · 회원 탈퇴, 개인정보처리방침 · 계정 삭제 안내 (구글 플레이 요구) ── */
.danger-card { border-color: color-mix(in srgb, var(--danger) 35%, var(--border)); }
.danger-card .card-head h2 { color: var(--danger); }
.btn-danger { background: var(--danger); border-color: var(--danger); color: var(--on-accent); }
.policy h2 { font-size: 1rem; margin: 1.4rem 0 0.5rem; }
.policy h2:first-child { margin-top: 0; }
.policy p, .policy li { line-height: 1.65; }
.policy ul, .policy ol { padding-left: 1.3rem; margin: 0.3rem 0 0.6rem; }
.policy-table { width: 100%; border-collapse: collapse; font-size: 0.9rem; }
.policy-table th, .policy-table td { border-bottom: 1px solid var(--border); padding: 0.45rem 0.5rem; text-align: left; vertical-align: top; }
.policy-table th { color: var(--muted); font-weight: 700; white-space: nowrap; }
