@layer reset { /* 1~50 */
/* ══════════════════════════════════════════════════════════════════════════
   base.css v2 — 공통 컴포넌트 · 반응형 셸
   ──────────────────────────────────────────────────────────────────────────
   교체일 2026-07-25 · 백업: 대시보드디자인/_backup_20260725/base.css
   tokens.css 의 변수만 참조한다(하드코딩 색 금지).

   반응형 브레이크포인트 3개
     ≥1280      사이드바 240px
     1024~1279  아이콘 레일 64px
     640~1023   바텀 탭바 4 + 드로어
     ≤639       바텀 탭바 4 + 드로어 · 표 첫 열 고정 · 행 44px
   ══════════════════════════════════════════════════════════════════════════ */

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--surface-0);
  color: var(--ink-0);
  font: var(--fw-normal) var(--fs-14)/var(--lh-ui) var(--font-sans);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* 강조 태그를 정본에 못 박는다. 브라우저 기본값은 `bolder` 인데 그것은 **부모 기준
   상대값**이라, 700 짜리 안에 들어가면 CSS 스펙상 900 이 된다(600~700 → 900).
   2026-08-06 실측: 정본이 5단(400~800)인데 화면에 900 이 6곳 있었고, 원인이 이것이었다.
   상대값을 그대로 두면 손잡이를 돌려도 이 자리들만 따라오지 않아 다시 어긋난다. */
b, strong { font-weight: var(--fw-bold); }

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

/* 폼은 무조건 16px 이상 — 미만이면 iOS Safari 가 focus 시 자동 확대한다 */
/* 줄간격도 토큰에서 온다 — 브라우저 기본값 `normal` 은 서체·브라우저마다 달라
   같은 화면에서 정본에 없는 줄간격을 만든다(2026-08-28 실측: 이 화면만 38곳이 `normal`). */
input, select, textarea, button { font-family: var(--font-sans); line-height: var(--lh-ui); }
input, select, textarea { font-size: max(16px, 1em); }

code, kbd {
  background: var(--surface-2);
  color: var(--ink-1);
  padding: 1px 5px;
  border-radius: var(--radius-sm);
  font-family: var(--font-sans);
  font-size: var(--fs-12);
  font-variant-numeric: tabular-nums;
}

} /* @layer reset 끝 */
@layer components { /* 51~181 */
/* ══ Layer 0 — 헤더 ══════════════════════════════════════════════════════ */
.app-header {
  position: fixed; top: 0; left: 0; right: 0; height: var(--h-header);
  z-index: var(--z-header);
  display: flex; align-items: center; gap: var(--sp-3);
  padding: 0 var(--sp-4);
  /* 2026-08-24 사용자님 시안 v5: 초록 띠 · 검은 굵은 상표 */
  background: var(--brand-green-400);
  border-bottom: 0;
}
.app-header .app-brand a { color: #0b0f14; }
.app-header .icon-btn, .app-header .density-seg button, .app-header .theme-toggle { color: #0b0f14; }
.app-brand {
  font-weight: var(--fw-black); font-size: var(--fs-16);
  color: var(--ink-0); white-space: nowrap; letter-spacing: var(--ls-tight);
  flex-shrink: 0;
}
/* 누를 자리 24px 이상 (WCAG 2.2 2.5.8) — 실측 21px 였다. 글자는 그대로, 상자만 채운다. */
.app-brand a { color: inherit; text-decoration: none;
               display: inline-flex; align-items: center; min-height: 24px; }
.app-header-right { margin-left: auto; display: flex; align-items: center; gap: var(--sp-2); }
.icon-btn {
  width: 40px; height: 40px; display: none;
  align-items: center; justify-content: center;
  border: 0; background: none; color: var(--ink-1);
  cursor: pointer; border-radius: var(--radius); flex-shrink: 0;
}
.icon-btn:hover { background: var(--surface-2); color: var(--ink-0); }
.icon-btn svg { width: 20px; height: 20px; }
.theme-toggle {
  height: 32px; min-width: 44px; padding: 0 12px;
  border: 1px solid var(--border-default); border-radius: var(--radius);
  background: var(--surface-1); color: var(--ink-1);
  font: var(--fw-medium) var(--fs-13) var(--font-sans);
  cursor: pointer; white-space: nowrap;
}
.theme-toggle:hover { background: var(--surface-2); color: var(--ink-0); }

/* ══ Layer 1 — 사이드바 ══════════════════════════════════════════════════ */
.app-side {
  /* 2026-08-24 사용자님 시안 v5: 띠 아래 여백을 둔 테두리 상자 */
  position: fixed; top: calc(var(--h-header) + var(--sp-4)); bottom: var(--sp-4); left: var(--sp-3);
  width: calc(var(--w-sidebar) - var(--sp-3)); z-index: var(--z-side);
  background: var(--surface-1);
  border: 1px solid var(--border-subtle); border-radius: var(--radius);
  padding: var(--sp-4) var(--sp-3) calc(var(--sp-8) + var(--safe-b));
  overflow-y: auto;
  transition: transform .22s ease;
  /* 2026-08-23 사용자님: 사이드바 스크롤 막대가 너무 진하다 — 평소엔 숨기고, 마우스를 올렸을 때만 가는 막대 */
  scrollbar-width: none;
}
.app-side:hover { scrollbar-width: thin; scrollbar-color: var(--border-subtle) transparent; }
/* 사건형 갱신 알림 (2026-08-24 표준 5층 ⑤) — 상시 배지 대신, 교체 완료 순간 2.6초만 */
.te-update-toast {
  position: fixed; top: 12px; right: 14px; z-index: 9999;
  background: var(--surface-2); color: var(--text-0);
  border: 1px solid var(--border); border-radius: 999px;
  padding: 6px 14px; font-size: var(--fs-12); font-weight: var(--fw-semi);
  opacity: 0; transform: translateY(-6px);
  transition: opacity .18s ease, transform .18s ease;
  pointer-events: none;
}
.te-update-toast.on { opacity: .95; transform: none; }
@media (prefers-reduced-motion: reduce) { .te-update-toast { transition: none; } }

/* 바뀐 칸 표시 (2026-08-25 · 「값은 바뀌고, 화면은 서 있는다」) — refresh.js 가 글자가 달라진 잎 요소에만
   .te-changed 를 0.7초 붙인다. 배경색만 바뀌므로 밀림(CLS) 0 · 움직임 줄이기 설정은 아래 전역 규칙이 animation 을 끈다. */
@keyframes te-flash { from { background-color: color-mix(in srgb, var(--accent) 22%, transparent); } to { background-color: transparent; } }
.te-changed { animation: te-flash .6s ease-out; }
/* 공용 차트 렌더러(agchart) 뼈대 — 2026-08-24 차트 단일 형식. 값은 전부 토큰. */
.agchart-head { display: flex; gap: var(--sp-3); align-items: baseline; padding: 2px 2px var(--sp-2); font-size: var(--fs-13); color: var(--ink-0); }
.agchart-sym { font-weight: var(--fw-semi); }
.agchart-ohlc b { font-weight: var(--fw-semi); }
.agchart-prov { font-size: var(--fs-11); color: var(--ink-2); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 0 4px; margin-left: 4px; }
.agchart-foot { display: flex; justify-content: space-between; padding: var(--sp-2) 2px 0; }
/* 누를 자리는 24×24px 이상 (WCAG 2.2 AA 2.5.8 · 권장 44) — 2026-08-28 실측에서
   기간(1M·3M·6M·1Y·ALL)과 log/auto 가 22px 였다. 글자 크기는 그대로 두고 «위아래 여백» 만
   키워 높이를 채운다(모양은 거의 안 변한다). min-height 로 못 박아 여백을 줄여도 안 무너진다. */
.agchart-foot button { border: 0; background: none; font-family: var(--font-sans); font-size: var(--fs-12); color: var(--ink-1); padding: 5px 10px; min-height: 24px; border-radius: var(--radius-sm); cursor: pointer; }
.agchart-foot button.on { background: var(--surface-2); color: var(--ink-0); font-weight: var(--fw-semi); }
.app-side::-webkit-scrollbar { width: 0; }
.app-side:hover::-webkit-scrollbar { width: 6px; }
.app-side::-webkit-scrollbar-thumb { background: var(--border-subtle); border-radius: 3px; }
.app-side::-webkit-scrollbar-track { background: transparent; }
.side-grp {
  margin: var(--sp-5) 0 var(--sp-2); padding: 0 var(--sp-2);
  font-size: var(--fs-11); font-weight: var(--fw-bold);
  color: var(--ink-2); letter-spacing: .04em;
}
.side-grp:first-child { margin-top: 0; }
.app-side a {
  display: flex; align-items: center; gap: var(--sp-3);
  height: 36px; padding: 0 var(--sp-2);
  border-radius: var(--radius-sm);
  color: var(--ink-1); font-size: var(--fs-13); font-weight: var(--fw-medium);
  position: relative; text-decoration: none;
}
.app-side a:hover { background: var(--surface-2); color: var(--ink-0); text-decoration: none; }
.app-side a.active { background: var(--accent-bg); color: var(--accent-c); font-weight: var(--fw-semi); }
.app-side a.active::before {
  content: ""; position: absolute; left: -11px; top: 8px; bottom: 8px;
  width: 2px; background: var(--accent-c); border-radius: 1px;
}
.app-side .ic { width: 18px; flex-shrink: 0; text-align: center; font-size: var(--fs-12); opacity: .75; }

.app-scrim {
  position: fixed; inset: 0; background: var(--scrim); z-index: var(--z-scrim);
  opacity: 0; pointer-events: none; transition: opacity .2s;
}
body.drawer-open .app-scrim { opacity: 1; pointer-events: auto; }

/* ══ 바텀 탭바 (<1024) ═══════════════════════════════════════════════════
   NN/g(n=179): 전부 숨기는 내비는 발견성 -20%·과업시간 +15%.
   최고 성적은 combo(핵심 노출 + 나머지 숨김) — 모바일 86% vs 숨김 57%.
   탭 5개 상한은 Material·Apple·KRDS·NN/g 4자 만장일치. */
.app-tabbar {
  display: none; position: fixed; left: 0; right: 0; bottom: 0;
  z-index: var(--z-tabbar);
  height: calc(var(--h-tabbar) + var(--safe-b)); padding-bottom: var(--safe-b);
  background: var(--surface-1); border-top: 1px solid var(--border-subtle);
}
.app-tabbar nav { display: grid; grid-template-columns: repeat(4, 1fr); height: var(--h-tabbar); }
.app-tabbar a {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  color: var(--ink-2); font-size: var(--fs-11); font-weight: var(--fw-semi);
  min-height: 44px; text-decoration: none;
}
.app-tabbar a:hover { text-decoration: none; }
.app-tabbar a.active { color: var(--accent-c); }
.app-tabbar .ic { font-size: var(--fs-13); line-height: var(--lh-tight); }

} /* @layer components 끝 */
@layer base { /* 182~208 */
/* ══ 본문 컨테이너 — 3종 ═════════════════════════════════════════════════ */
.app-main { margin-left: var(--w-sidebar); }
.content {
  max-width: var(--w-app);
  margin: 0 auto;
  padding: calc(var(--h-header) + var(--sp-5)) var(--gutter) var(--sp-12);
}
.app-main > .content ~ .content { padding-top: 0; }   /* 푸터 등 후행 컨테이너 */
.content.prose, .te-doc { max-width: var(--w-prose); }

/* ══ 헤딩 ════════════════════════════════════════════════════════════════ */
h1 {
  font-size: var(--fs-20); font-weight: var(--fw-bold);
  line-height: var(--lh-title); letter-spacing: var(--ls-tight);
  color: var(--ink-0); border: 0; padding: 0; margin: 0 0 var(--sp-2);
}
h2 {
  font-size: var(--fs-16); font-weight: var(--fw-bold);
  letter-spacing: var(--ls-tight); color: var(--ink-0);
  background: none; border: 0; padding: 0;
  margin: var(--sp-8) 0 var(--sp-3);
}
h3 {
  font-size: var(--fs-14); font-weight: var(--fw-bold);
  color: var(--ink-0); margin: var(--sp-5) 0 var(--sp-2);
}

} /* @layer base 끝 */
@layer components { /* 209~310 */
/* ══ 카드 / 패널 ═════════════════════════════════════════════════════════
   ★ 여백 리듬: 내부 패딩(14~16) < 외부 마진(24~32) */
.summary, .card, .narrative-panel {
  background: var(--surface-1);
  border: 1px solid var(--border-subtle);
  border-left: 3px solid var(--accent-c);
  border-radius: var(--radius);
  padding: var(--sp-4);
  margin: var(--sp-6) 0;
  font-size: var(--fs-13);
  line-height: var(--lh-read);
  color: var(--ink-1);
}
.narrative-panel { line-height: var(--lh-read); }
.narrative-panel .src { color: var(--ink-2); font-size: var(--fs-11); }
.bignum {
  background: var(--surface-1);
  border: 1px solid var(--border-subtle);
  border-left: 3px solid var(--accent-c);
  border-radius: var(--radius);
  color: var(--ink-0);
  padding: var(--sp-4);
  margin: var(--sp-6) 0;
  font-size: var(--fs-16);
  font-weight: var(--fw-bold);
}
.warn, .caveat {
  background: var(--warn-c-bg);
  color: var(--warn-c);
  border: 1px solid transparent;
  border-left: 3px solid var(--warn-c);
  border-radius: var(--radius);
  padding: var(--sp-3) var(--sp-4);
  margin: var(--sp-5) 0;
  font-size: var(--fs-13);
  line-height: var(--lh-read);
}
.caveat ul { margin: var(--sp-1) 0 0; padding-left: 18px; }

/* ══ 표 ══════════════════════════════════════════════════════════════════
   ★ 원칙 3개 (근거: 연구자료 08_responsive_mobile.md)
     ① 모바일에서 카드 변환(display:block) 금지 — Safari 가 테이블 의미론을
        전부 버려 스크린리더가 표로 읽지 못한다(한국 iOS 웹 비중 약 34%).
        → 가로 스크롤 + 첫 열 sticky 로 대체.
     ② border-collapse: separate 필수 — collapse 는 sticky 셀과 상극이라
        보더가 사라진다. 보더는 box-shadow: inset 으로 그린다.
     ③ 표는 자체 스크롤 패널 — 페이지 스크롤 기준 sticky 를 쓰면 overflow
        래퍼가 스크롤 컨테이너가 되어 헤더가 첫 행을 덮는다(Koyfin·Datadog 방식).
   ※ .tbl-wrap 은 base.html 의 JS 가 모든 <table> 에 자동으로 씌운다. */
.tbl-wrap {
  background: var(--surface-1);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius);
  /* ★ 울타리 (2026-08-28) — `overflow: auto` 는 쌓임 맥락을 만들지 않아,
     상자 «안» 의 고정 칸(z 3·5·7)이 상자를 넘어 화면 붙박이와 겨룬다.
     숫자를 낮추는 것은 「오늘은 안 난다」이고 울타리는 「다시 못 난다」이다.
     겹침_감사가 이 네 곳을 「쌓임맥락 없음」으로 짚어 두었다. */
  isolation: isolate;
  overflow: auto;
  max-height: min(72svh, 760px);
  -webkit-overflow-scrolling: touch;
  position: relative;
  margin: var(--sp-3) 0 var(--sp-6);
}
table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: var(--fs-13);
  background: var(--surface-1);
}
thead th {
  position: sticky; top: 0; z-index: 5;
  background: var(--surface-2);
  color: var(--ink-1);
  font-weight: var(--fw-semi);
  font-size: var(--fs-12);
  text-align: left;
  text-transform: none;         /* ★ uppercase 폐기 — 한글에 무의미 */
  letter-spacing: 0;
  padding: 9px var(--sp-3);
  white-space: nowrap;
  box-shadow: inset 0 -1px 0 var(--border-default);
}
thead th.num, thead th.n { text-align: right; }
tbody td, tbody th {
  padding: 0 var(--sp-3);
  height: var(--row-h);
  line-height: var(--lh-cell);
  color: var(--ink-0);
  vertical-align: middle;
  background: var(--surface-1);
  box-shadow: inset 0 -1px 0 var(--border-subtle);
}
tbody tr:last-child td, tbody tr:last-child th { box-shadow: none; }
tbody tr:hover td, tbody tr:hover th { background: var(--surface-2); }
td.num, th.num, td.n, th.n {
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

} /* @layer components 끝 */
@layer utilities { /* 311~318 */
/* ══ 의미 색 유틸 — ★ 한국식 (상승 적 / 하락 청) ══════════════════════════ */
.num { font-variant-numeric: tabular-nums; font-feature-settings: "tnum" 1; }
.pos, .up { color: var(--up); }
.neg, .down { color: var(--down); }
.ok { color: var(--good); }
.muted, .empty, .none, .flat { color: var(--ink-2); }
.meta { color: var(--ink-2); font-size: var(--fs-12); line-height: var(--lh-read); }


  /* ★ 실시간 값을 못 받은 칸 — 지우지 않고 «낡았다» 고만 보인다 (2026-09-01).
     2026-09-01 장중, 값을 못 받으면 화면이 어제 시세를 **오늘 값인 양** 보여 줬다
     (그날 라이브값 창구가 166 번 실패했다). 지우면 「자료가 없다」로 오해되고,
     그냥 두면 거짓이 된다. 표준의 답은 「지우지 말고 밝혀라」다. */
  [data-stale="1"] {
    opacity: 0.5;
    text-decoration: underline dotted currentColor;
    text-underline-offset: 3px;
    cursor: help;
  }
} /* @layer utilities 끝 */
@layer components { /* 319~748 */
/* ══ 배지 · 칩 ═══════════════════════════════════════════════════════════
   ★ 배경색 + 흰 글자 폐기(대비 2.5:1) → 반투명 배경 + 진한 글자 */
.pill, .te-chip, .te-score {
  display: inline-flex; align-items: center; gap: 4px;
  height: 20px; padding: 0 8px;
  border-radius: var(--radius-full);
  font-size: var(--fs-11); font-weight: var(--fw-bold);
  line-height: var(--lh-tight); white-space: nowrap;
  background: var(--surface-3); color: var(--ink-1);
}
.pill.regime-on,  .te-chip.bull { background: var(--good-bg);     color: var(--good); }
.pill.regime-off, .te-chip.neu  { background: var(--warn-c-bg);   color: var(--warn-c); }
.pill.regime-mixed              { background: var(--surface-3);   color: var(--ink-1); }
.pill.regime-crisis, .te-chip.cri, .te-chip.bear { background: var(--critical-bg); color: var(--critical); }
.pill.sd-SB, .pill.sd-B { background: var(--good-bg);     color: var(--good); }
.pill.sd-S              { background: var(--warn-c-bg);   color: var(--warn-c); }
.pill.sd-C              { background: var(--surface-3);   color: var(--ink-1); }
.pill.sd-A              { background: var(--critical-bg); color: var(--critical); }
.pill.ai-rule   { background: var(--surface-3);   color: var(--ink-1); }
.pill.ai-llm    { background: var(--accent-bg);   color: var(--accent-c); }
.pill.ai-claude { background: rgba(109,63,196,.10); color: var(--ai-claude-c); }
.pill.ai-cache  { background: var(--good-bg);     color: var(--good); }
[data-theme="dark"] .pill.ai-claude { background: rgba(167,139,250,.16); }
.te-score.s-hi  { background: var(--good-bg);   color: var(--good); }
.te-score.s-mid { background: var(--accent-bg); color: var(--accent-c); }

/* ══ 종목코드 부가 조작 (복사 · 차트) ════════════════════════════════════
   2026-07-25 리디자인에서 제거("나중에 추가") → 2026-07-27 사용자 지시로 복원.
   `.stock-code` / `.pid` 셀에 base.html 이 자동 부착한다(화면별 마크업 0).
   이모지 금지 정책에 맞춰 글자 라벨("복사"·"차트")을 쓴다 — 기호 단독 표기 금지(§7-3). */
.copy-code-btn, .chart-code-lnk {
  margin-left: var(--sp-1);
  /* 누를 자리 24px 이상 (WCAG 2.2 2.5.8) — 2026-08-28 실측 17·19px 였다.
     inline-flex 로 세로 가운데를 잡아 글자는 그대로 두고 상자만 키운다. */
  display: inline-flex; align-items: center; min-height: 24px;
  padding: 0 6px;
  font-family: inherit;
  font-size: var(--fs-11);
  line-height: var(--lh-ui);
  background: var(--surface-2);
  color: var(--ink-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  text-decoration: none;
  white-space: nowrap;
  vertical-align: middle;
}
.copy-code-btn { cursor: pointer; }
.copy-code-btn:hover, .chart-code-lnk:hover { color: var(--ink-0); border-color: var(--accent); }
.copy-code-btn.copied { color: var(--good); border-color: var(--good); }
@media print { .copy-code-btn, .chart-code-lnk { display: none; } }

/* ══ te-* 컴포넌트 ═══════════════════════════════════════════════════════ */
.te-kpis { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--sp-3); margin: var(--sp-5) 0; }
.te-kpi {
  position: relative; background: var(--surface-1);
  border: 1px solid var(--border-subtle); border-radius: var(--radius);
  padding: var(--sp-3) var(--sp-4); overflow: hidden;
}
/* 2026-07-29 사용자 지시 — KPI 카드의 왼쪽 세로 색 띠 제거(전체 대시보드 디자인과 불일치).
   good/bad/warn-k 클래스는 마크업에 남아 있어도 무해하므로 템플릿은 건드리지 않는다.
   정보 손실 없음: 값 자체가 글자와 색으로 말한다(색으로만 표현 금지 · 적용기록 §0-3).
   되살릴 때는 아래 세 규칙과 ::before 를 함께 복원한다. */
.te-kpi .k { font-size: var(--fs-12); color: var(--ink-2); font-weight: var(--fw-medium); }
.te-kpi .v {
  font-size: var(--fs-24); font-weight: var(--fw-bold);
  letter-spacing: var(--ls-tighter); margin: 2px 0;
  line-height: var(--lh-title); font-variant-numeric: tabular-nums;
}
.te-kpi .v small { font-size: var(--fs-13); color: var(--ink-2); }
.te-kpi .s { font-size: var(--fs-11); color: var(--ink-2); }
.te-eyebrow {
  font-size: var(--fs-11); font-weight: var(--fw-bold);
  letter-spacing: .04em; color: var(--ink-2);
}
.te-fresh {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: var(--fs-12); color: var(--ink-1);
  border: 1px solid var(--border-default); border-radius: var(--radius-full);
  padding: 4px 10px;
}
.te-fresh .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--good); }

/* ══ te-scorecard — 성적표 표준 한 벌 (2026-08-23 · 머신러닝 수준진단 P0) ══════════════
   매크로 _te_scorecard.html 만 쓴다. 값은 scorecard.py 가 만들고 여기는 모양만.
   te- 접두 = 전역 한 단어 클래스 충돌 금지(적용기록 §0). 색은 부호(+/−) 글자의 보조일 뿐. */
.te-scorecard {
  background: var(--surface-1); border: 1px solid var(--border-subtle); border-radius: var(--radius);
  padding: var(--sp-3) var(--sp-4); margin: var(--sp-4) 0;
}
.te-scorecard-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--sp-1) var(--sp-3); margin-bottom: var(--sp-2); }
.te-scorecard-title { font-size: var(--fs-13); font-weight: var(--fw-semi); color: var(--ink-0); }
.te-scorecard-note { font-size: var(--fs-11); color: var(--ink-2); }
.te-scorecard-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(150px, 100%), 1fr));
  gap: var(--sp-2) var(--sp-3); margin: 0;
}
.te-scorecard-cell { min-width: 0; }
.te-scorecard-k {
  font-size: var(--fs-11); color: var(--ink-2); cursor: help;
  text-decoration: underline dotted; text-underline-offset: 2px;
}
.te-scorecard-v {
  margin: 2px 0 0; font-size: var(--fs-16); font-weight: var(--fw-semi); color: var(--ink-0);
  font-variant-numeric: tabular-nums; line-height: var(--lh-title); overflow-wrap: anywhere;
}
.te-scorecard-v.is-up { color: var(--up); }
.te-scorecard-v.is-down { color: var(--down); }
.te-scorecard-empty { margin: 0; font-size: var(--fs-13); color: var(--ink-2); }

/* ══ te-doc — 발행 문서 표준 (780px) ═════════════════════════════════════ */
.te-doc { max-width: var(--w-prose); margin: 0 auto; padding-bottom: var(--sp-12); }
.te-doc .doc-back {
  display: flex; justify-content: space-between; gap: var(--sp-3);
  flex-wrap: wrap; margin: 0 0 var(--sp-5); font-size: var(--fs-12);
}
.te-doc .doc-back a { color: var(--ink-1); }
.te-doc h1 {
  font-size: var(--fs-24); font-weight: var(--fw-black);
  line-height: var(--lh-title); color: var(--ink-0);
  border: 0; padding: 0; margin: var(--sp-2) 0 var(--sp-1);
  letter-spacing: var(--ls-tight); text-wrap: balance;
}
.te-doc h1 .sub { font-size: var(--fs-13); font-weight: var(--fw-semi); color: var(--ink-2); }
.te-doc .doc-meta, .te-doc .meta {
  color: var(--ink-2); font-size: var(--fs-12); line-height: var(--lh-read);
  margin: var(--sp-2) 0 var(--sp-6); padding-bottom: var(--sp-3);
  border-bottom: 1px solid var(--border-subtle);
}
.te-doc .doc-lead { font-size: var(--fs-14); line-height: var(--lh-read); color: var(--ink-0); margin: 0 0 var(--sp-6); }
.te-doc h2 {
  font-size: var(--fs-16); font-weight: var(--fw-bold); color: var(--accent-c);
  background: none; border: 0; padding: 0; margin: var(--sp-8) 0 var(--sp-2);
}
.te-doc h2 .sub { font-size: var(--fs-12); font-weight: var(--fw-normal); color: var(--ink-2); }
.te-doc h3 { font-size: var(--fs-14); font-weight: var(--fw-bold); color: var(--ink-0); margin: var(--sp-5) 0 var(--sp-2); }
.te-doc p, .te-doc .box {
  font-size: var(--fs-14); line-height: var(--lh-read); color: var(--ink-0); margin: 0 0 var(--sp-3);
}
.te-doc .box { white-space: pre-line; }
.te-doc figure.doc-fig { margin: var(--sp-5) 0 var(--sp-6); }
.te-doc figure.doc-fig img {
  display: block; max-width: 100%;
  border: 1px solid var(--border-subtle); border-radius: var(--radius); background: var(--surface-1);
}
.te-doc figure.doc-fig figcaption { margin-top: var(--sp-2); font-size: var(--fs-12); color: var(--ink-2); line-height: var(--lh-read); }
.te-doc .proto {
  background: var(--surface-1); color: var(--ink-1);
  border: 1px solid var(--border-subtle); border-left: 3px solid var(--accent-c);
  border-radius: var(--radius); padding: var(--sp-3) var(--sp-4);
  margin: var(--sp-5) 0; font-size: var(--fs-12); line-height: var(--lh-read);
}
.te-doc .seg {
  white-space: pre-line; border-left: 2px solid var(--border-default);
  padding: var(--sp-1) 0 var(--sp-1) var(--sp-3); margin: var(--sp-3) 0;
  font-size: var(--fs-13); line-height: var(--lh-read); color: var(--ink-0);
}
.te-doc .seg b { color: var(--accent-c); }
.te-doc .headline, .te-doc .lead, .te-doc .netview, .te-doc .weekly-change, .te-doc .insight {
  background: var(--surface-1);
  border: 1px solid var(--border-subtle); border-left: 3px solid var(--accent-c);
  border-radius: var(--radius);
  padding: var(--sp-4); margin: var(--sp-5) 0;
  font-size: var(--fs-14); line-height: var(--lh-read); color: var(--ink-0);
}
.te-doc .lead, .te-doc .netview, .te-doc .insight { white-space: pre-line; }
.te-doc .headline, .te-doc .netview { font-weight: var(--fw-bold); }
.te-doc .insight { border-left-color: var(--border-default); }
.te-doc .headline .sess {
  display: inline-block; font-size: var(--fs-11); font-weight: var(--fw-bold);
  padding: 2px 8px; margin-right: var(--sp-2); border-radius: var(--radius-sm);
  background: var(--accent-bg); color: var(--accent-c);
}
.te-doc .lead b, .te-doc .netview b, .te-doc .weekly-change b, .te-doc .insight b { color: var(--accent-c); }
.te-doc .tcard {
  background: var(--surface-1); border: 1px solid var(--border-subtle);
  border-radius: var(--radius); padding: var(--sp-3) var(--sp-4); margin: var(--sp-3) 0;
}
.te-doc .tcard h3 { margin: 0 0 var(--sp-2); font-size: var(--fs-14); color: var(--accent-c); }
.te-doc .tcard .trow { white-space: pre-line; margin: var(--sp-1) 0; font-size: var(--fs-13); line-height: var(--lh-read); }
.te-doc .tcard .k { display: inline-block; min-width: 54px; font-weight: var(--fw-bold); margin-right: var(--sp-1); }
.te-doc .k-demand { color: var(--good); }
.te-doc .k-supply { color: var(--warn-c); }
.te-doc .k-balance { color: var(--ink-1); }
.te-doc .k-korea { color: var(--accent-c); }
.te-doc .scenarios { display: flex; gap: var(--sp-4); flex-wrap: wrap; margin: var(--sp-5) 0; }
.te-doc .scenarios .card {
  flex: 1; min-width: 280px; margin: 0;
  border-left: 1px solid var(--border-subtle);
}
.te-doc .scenarios .card.up   { border-top: 3px solid var(--up); }
.te-doc .scenarios .card.down { border-top: 3px solid var(--down); }
.te-doc .scenarios .up h3   { color: var(--up); }
.te-doc .scenarios .down h3 { color: var(--down); }
.te-doc .wbar { height: 16px; border-radius: var(--radius-sm); background: var(--surface-3); overflow: hidden; margin: var(--sp-2) 0; }
.te-doc .wfill { height: 100%; line-height: 16px; font-size: var(--fs-11); text-align: right; padding-right: 8px; color: #fff; font-weight: var(--fw-bold); }
.te-doc .up .wfill   { background: var(--up); }
.te-doc .down .wfill { background: var(--down); }
.te-doc .thesis { white-space: pre-line; margin: var(--sp-2) 0; font-size: var(--fs-13); line-height: var(--lh-read); }
.te-doc ul.ev { list-style: none; padding: 0; margin: var(--sp-2) 0; }
.te-doc ul.ev li {
  padding: var(--sp-2) var(--sp-3); margin: var(--sp-1) 0;
  background: var(--surface-1); border: 1px solid var(--border-subtle);
  border-left: 2px solid var(--border-default); border-radius: var(--radius-sm);
  font-size: var(--fs-13); line-height: var(--lh-read); color: var(--ink-0);
}
.te-doc .src {
  display: inline-block; font-size: var(--fs-11); font-weight: var(--fw-bold);
  padding: 1px 6px; margin-right: 6px; border-radius: var(--radius-sm);
}
.te-doc .src-data { background: var(--accent-bg); color: var(--accent-c); }
.te-doc .src-ext  { background: var(--warn-c-bg); color: var(--warn-c); }
.te-doc ul.plain { list-style: none; margin: var(--sp-2) 0; padding-left: 2px; }
.te-doc ul.plain li { font-size: var(--fs-13); color: var(--ink-1); margin: var(--sp-1) 0; line-height: var(--lh-read); }
.te-doc ul.risk li { color: var(--critical); }
.te-doc details { margin: var(--sp-5) 0; color: var(--ink-1); font-size: var(--fs-12); }
.te-doc details pre {
  white-space: pre-wrap; background: var(--surface-0);
  border: 1px solid var(--border-subtle); border-radius: var(--radius);
  padding: var(--sp-3); font-size: var(--fs-11); color: var(--ink-1);
  line-height: var(--lh-ui); overflow-x: auto;
}

/* ══ 발굴탭 sticky 머리 · 서브내비 ═══════════════════════════════════════ */
.disc-stickyhead {
  position: sticky; top: var(--h-header); z-index: 40;
  background: var(--surface-0);
  border-bottom: 1px solid var(--border-default);
  margin: calc(var(--sp-5) * -1) 0 var(--sp-5);
  padding: var(--sp-4) 0 var(--sp-2);
}
.disc-stickyhead h1, .disc-stickyhead h2 { margin: 0 0 var(--sp-2); }
.disc-stickyhead .regime, .disc-stickyhead .regime-na { margin: 0; }
.disc-subnav, .subnav {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--sp-1) var(--sp-2);
  padding: var(--sp-2) 0; margin: 0;
  line-height: var(--lh-read);
  font-size: var(--fs-12);
}
.disc-subnav a, .subnav a {
  display: inline-flex; align-items: center;
  height: 30px; padding: 0 10px;
  border: 1px solid var(--border-default); border-radius: var(--radius-full);
  color: var(--ink-1); background: var(--surface-1);
  white-space: nowrap; font-weight: var(--fw-medium);
}
.disc-subnav a:hover, .subnav a:hover {
  border-color: var(--accent-c); color: var(--accent-c);
  background: var(--accent-bg); text-decoration: none;
}
.disc-subnav a.active, .subnav a.active {
  border-color: transparent; background: var(--accent-bg);
  color: var(--accent-c); font-weight: var(--fw-semi);
}
.disc-subnav .sep, .subnav .sep { display: none; }   /* 파이프 구분자 제거 */

/* ══ 푸터 ════════════════════════════════════════════════════════════════ */
.footer {
  margin-top: var(--sp-8);
  padding-top: var(--sp-4);
  border-top: 1px solid var(--border-subtle);
  color: var(--ink-2);
  font-size: var(--fs-12);
  line-height: var(--lh-read);
}

/* ══════════════════════════════════════════════════════════════════════════
   반응형
   ══════════════════════════════════════════════════════════════════════════ */

/* ── lg 1024~1279 : 아이콘 레일 64px ────────────────────────────────────── */
@media (max-width: 1279.98px) and (min-width: 1024px) {
  .app-side { width: var(--w-rail); padding: var(--sp-4) var(--sp-2); }
  .side-grp { font-size: 0; height: 1px; margin: var(--sp-4) 0; background: var(--border-subtle); }
  .app-side a { justify-content: center; gap: 0; padding: 0; }
  .app-side a .lbl, .app-side a .cnt { display: none; }
  .app-side a.active::before { left: -4px; }
  .app-main { margin-left: var(--w-rail); }
}

/* ── <1024 : 드로어 + 바텀 탭바 ─────────────────────────────────────────── */
@media (max-width: 1023.98px) {
  .icon-btn { display: flex; }
  .app-side {
    top: 0; width: min(280px, 86vw);
    transform: translateX(-100%);
    padding-top: calc(var(--h-header) + var(--sp-3));
    box-shadow: var(--shadow-float);
  }
  body.drawer-open .app-side { transform: none; }
  .app-main { margin-left: 0; }
  .content { padding-bottom: calc(var(--h-tabbar) + var(--safe-b) + var(--sp-8)); }
  .app-tabbar { display: block; }
  .te-kpis { grid-template-columns: repeat(2, 1fr); }

  /* 표 — 첫 열 sticky */
  .tbl-wrap { max-height: 74svh; }
  thead th:first-child { z-index: 7; background: var(--surface-2); }
  tbody td:first-child, tbody th:first-child, thead th:first-child { position: sticky; left: 0; z-index: 3; }
  tbody tr:hover td:first-child { background: var(--surface-2); }
  .tbl-wrap.scrolled tbody td:first-child,
  .tbl-wrap.scrolled tbody th:first-child { box-shadow: inset 0 -1px 0 var(--border-subtle), var(--shadow-stick); }
  .tbl-wrap.scrolled thead th:first-child { box-shadow: inset 0 -1px 0 var(--border-default), var(--shadow-stick); }
}

/* ── <640 : 폰 ──────────────────────────────────────────────────────────── */
@media (max-width: 639.98px) {
  .te-kpis { grid-template-columns: repeat(2, 1fr); gap: var(--sp-2); }
  .summary, .card, .narrative-panel, .bignum { padding: var(--sp-3); margin: var(--sp-5) 0; }
  .tbl-wrap { max-height: 70svh; }
  thead th, tbody td, tbody th { padding-left: 10px; padding-right: 10px; }
  td a, th a { white-space: nowrap; }
  .te-doc h1 { font-size: var(--fs-20); }
  .disc-stickyhead { padding: var(--sp-3) 0 var(--sp-1); }
  /* 저우선 열 접힘 — 템플릿에서 class="p1"/"p2" 로 표시 */
  .p1 { display: none; }
}
@media (max-width: 400px) { .p2 { display: none; } }

/* hover 없는 기기 — hover 의존 UI 대체 */
@media (hover: none) {
  tbody tr:hover td, tbody tr:hover th { background: var(--surface-1); }
  tbody tr:active td, tbody tr:active th { background: var(--surface-2); }
}
@media (prefers-reduced-motion: reduce) { * { transition: none !important; animation: none !important; } }
@media print { .app-header, .app-side, .app-tabbar, .app-scrim { display: none !important; } .app-main { margin: 0; } }

/* ══════════════════════════════════════════════════════════════════════════
   서브내비 v2 — 세그먼티드 컨트롤 + 「더보기」 드롭다운
   근거(연구자료 03/08): 데스크톱 탭 권장 3~5개 · 6개 초과 시 붐빔 ·
     2줄 스택은 공간 기억을 파괴 · 선택 표시 단서 최소 2개(색 단독 금지) ·
     1차 초과분은 다른 컴포넌트(드롭다운)로 내린다.
   ══════════════════════════════════════════════════════════════════════════ */
.subnav2 {
  display: flex; align-items: center; gap: var(--sp-2);
  flex-wrap: wrap; margin: var(--sp-3) 0;
}

/* 1차 — 세그먼티드 컨트롤 (5개) */
.subnav2 .seg {
  display: inline-flex; padding: 2px; gap: 2px;
  background: var(--surface-2); border-radius: var(--radius);
  max-width: 100%; overflow-x: auto; scrollbar-width: none;
}
.subnav2 .seg::-webkit-scrollbar { display: none; }
.subnav2 .seg a {
  display: inline-flex; align-items: center;
  height: 30px; padding: 0 14px;
  border-radius: var(--radius-sm);
  color: var(--ink-1); font-size: var(--fs-13); font-weight: var(--fw-medium);
  white-space: nowrap; text-decoration: none;
}
.subnav2 .seg a:hover { color: var(--ink-0); text-decoration: none; }
/* 선택 표시 단서 3개: 배경 + 굵기 + 미세 그림자 (색 단독 아님) */
.subnav2 .seg a.on {
  background: var(--surface-1); color: var(--ink-0); font-weight: var(--fw-semi);
  box-shadow: 0 1px 2px rgba(16,24,40,.10);
}
[data-theme="dark"] .subnav2 .seg a.on { box-shadow: 0 1px 2px rgba(0,0,0,.4); }

/* 2차 — 「더보기」 드롭다운 (<details> · JS 불필요) */
.subnav-more { position: relative; }
.subnav-more > summary {
  list-style: none; cursor: pointer;
  display: inline-flex; align-items: center; gap: 5px;
  height: 34px; padding: 0 12px;
  border: 1px solid var(--border-default); border-radius: var(--radius);
  background: var(--surface-1); color: var(--ink-1);
  font-size: var(--fs-13); font-weight: var(--fw-medium); white-space: nowrap;
}
.subnav-more > summary::-webkit-details-marker { display: none; }
.subnav-more > summary::after { content: "▾"; font-size: var(--fs-11); color: var(--ink-2); }
.subnav-more > summary:hover { background: var(--surface-2); color: var(--ink-0); border-color: var(--border-strong); }
.subnav-more[open] > summary { background: var(--accent-bg); color: var(--accent-c); border-color: transparent; }
.subnav-more[open] > summary::after { content: "▴"; }
.subnav-more .more-panel {
  position: absolute; top: calc(100% + 6px); left: 0; z-index: 45;
  min-width: 232px; padding: var(--sp-2);
  background: var(--surface-1);
  border: 1px solid var(--border-default); border-radius: var(--radius);
  box-shadow: var(--shadow-float);
}
.subnav-more .more-grp {
  padding: var(--sp-2) var(--sp-2) var(--sp-1);
  font-size: var(--fs-11); font-weight: var(--fw-bold);
  color: var(--ink-2); letter-spacing: .04em;
}
.subnav-more .more-panel a {
  display: block; padding: 7px var(--sp-2);
  /* 줄간격은 토큰에서만 (05B 원칙 6 · 타이포 단일 원천) — 20px 를 박아 두어
     13px 글자에 1.538 이라는 정본에 없는 비율이 생겼다(2026-08-28 실측). */
  min-height: 34px; line-height: var(--lh-ui);
  border-radius: var(--radius-sm);
  color: var(--ink-1); font-size: var(--fs-13); text-decoration: none;
}
.subnav-more .more-panel a:hover { background: var(--surface-2); color: var(--ink-0); text-decoration: none; }
.subnav-more .more-panel a.on { background: var(--accent-bg); color: var(--accent-c); font-weight: var(--fw-semi); }

/* 리서치 데스크 도메인 칩 격자 */
.subnav2-wrap { gap: var(--sp-3); }
.subnav2 .back, .subnav2 .past {
  font-size: var(--fs-12); color: var(--ink-1); white-space: nowrap;
  display: inline-flex; align-items: center; min-height: 30px;
}
.subnav2 .past { margin-left: auto; }
.subnav2 .chips { display: flex; flex-wrap: wrap; gap: var(--sp-1); }
.subnav2 .chips a {
  display: inline-flex; align-items: center;
  height: 28px; padding: 0 11px;
  border: 1px solid var(--border-default); border-radius: var(--radius-full);
  background: var(--surface-1); color: var(--ink-1);
  font-size: var(--fs-12); font-weight: var(--fw-medium);
  white-space: nowrap; text-decoration: none;
}
.subnav2 .chips a:hover { border-color: var(--border-strong); color: var(--ink-0); text-decoration: none; }
.subnav2 .chips a.on {
  border-color: transparent; background: var(--accent-bg);
  color: var(--accent-c); font-weight: var(--fw-semi);
}

@media (max-width: 639.98px) {
  .subnav2 { gap: var(--sp-2); }
  .subnav2 .seg { width: 100%; }
  .subnav-more { width: 100%; }
  .subnav-more > summary { width: 100%; justify-content: space-between; }
  .subnav-more .more-panel { left: 0; right: 0; min-width: 0; }
  .subnav2 .past { margin-left: 0; }
}

} /* @layer components 끝 */
@layer utilities { /* 749~764 */
/* ══════════════════════════════════════════════════════════════════════════
   상태 vs 등락 분리 교정 (2026-07-25 저녁)
   05B §2: status(good/warn/serious/critical) 와 등락(--up/--down) 겸용 금지.
   국면(regime)·발행 여부·적중 여부는 '상태'다 → 가격 방향색을 쓰지 않는다.
   ══════════════════════════════════════════════════════════════════════════ */
.te-kpi.good::before   { background: var(--good); }
.te-kpi.bad::before    { background: var(--critical); }
.te-kpi.warn-k::before { background: var(--warn-c); }

/* 카드 격자·목록형 index 화면 — 산문 폭(780)이 아니라 앱 폭(1400)을 쓴다.
   산문 폭은 '읽는 글'에만 정당하다. */
.te-doc.te-doc-wide { max-width: var(--w-app); }

/* 0 은 상승이 아니다 — base.html 의 __normalizeZeros 가 붙인다 */
.is-zero { color: var(--flat) !important; }


  /* ★ 실시간 값을 못 받은 칸 — 지우지 않고 «낡았다» 고만 보인다 (2026-09-01).
     2026-09-01 장중, 값을 못 받으면 화면이 어제 시세를 **오늘 값인 양** 보여 줬다
     (그날 라이브값 창구가 166 번 실패했다). 지우면 「자료가 없다」로 오해되고,
     그냥 두면 거짓이 된다. 표준의 답은 「지우지 말고 밝혀라」다. */
  [data-stale="1"] {
    opacity: 0.5;
    text-decoration: underline dotted currentColor;
    text-underline-offset: 3px;
    cursor: help;
  }
} /* @layer utilities 끝 */
@layer components { /* 765~768 */
/* 사이드바 — 항목 23 + 그룹 5 가 1080 화면에서 넘쳐 스크롤이 생겼다. 행 높이 축소. */
.app-side a { height: 32px; }
.side-grp { margin: var(--sp-4) 0 var(--sp-1); }

} /* @layer components 끝 */
@layer components { /* 769~790 */
/* ══════════════════════════════════════════════════════════════════════════
   종목 / 코드 표기 — 전 화면 통일 (2026-07-26)
   교체 전 4가지 패턴 혼재: 별도 열(15곳) · "이름 코드" · "코드 이름" · 이름↵코드
   → 별도 열 하나로 통일. 코드는 tabular-nums 로 자릿수가 세로 정렬된다.
   ※ td.* 로 특이도를 올려 템플릿 <style> 의 .stock-* 선언을 이긴다.
   ══════════════════════════════════════════════════════════════════════════ */
td.stock-name, td .stock-name {
  font-weight: var(--fw-semi);
  white-space: nowrap;
}
td.stock-code, td .stock-code, td .pid, td.pid {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
  white-space: nowrap;
  color: var(--ink-2);
  font-weight: var(--fw-normal);
}
th + th.stock-code, td + td.stock-code { text-align: left; }

/* .dn / .up 별칭 — 일부 템플릿이 축약형을 쓴다 (signals/index.html 등) */
.dn { color: var(--down); }

} /* @layer components 끝 */
@layer components { /* 791~831 */
/* ══════════════════════════════════════════════════════════════════════════
   표 정렬·간격 표준 (엑셀/회계 기준 · 2026-07-26 전수 감사 반영)
   ──────────────────────────────────────────────────────────────────────────
   ① 텍스트 좌 · 수치 우 · 헤더는 셀과 같은 쪽 (헤더 동기화는 base.html JS)
   ② 셀 좌우 여백은 한 값으로 통일 — 화면마다 4px/5px/6px/9px 로 제각각이었다
   ③ 수치는 tabular-nums 로 자릿수 세로 정렬
   ══════════════════════════════════════════════════════════════════════════ */
/* 템플릿의 개별 패딩 재정의를 이긴다(요소+클래스 특이도) */
table th, table td { padding-left: var(--sp-3); padding-right: var(--sp-3); }
table.compact th, table.compact td { padding-left: var(--sp-2); padding-right: var(--sp-2); }

/* 우측정렬 셀은 항상 tabular — 자릿수가 세로로 맞는다 */
td.num, th.num, td.n, th.n, td[align="right"] {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}
/* 우측정렬 셀 안의 보조 표기(단위·지연 등)가 숫자 끝을 밀지 않게 */
td.num > small, td.num > .meta { font-variant-numeric: tabular-nums; }

/* ══════════════════════════════════════════════════════════════════════════
   모바일 실측 교정 (2026-07-26) — 360 / 402 / 768 실화면 측정 결과
   ══════════════════════════════════════════════════════════════════════════ */

/* 래핑을 건너뛴 소형 표의 가로 스크롤 안전망. 카드 크롬 없이 스크롤만. */
.tbl-scroll { overflow-x: auto; max-width: 100%; -webkit-overflow-scrolling: touch; }

/* 긴 URI·파일 경로가 셀을 뚫는다. 단어가 셀보다 길 때만 끊긴다 —
   숫자·종목명 정렬에는 영향이 없다. */
table td, table th { overflow-wrap: break-word; }
td.num, th.num, td.stock-code, td.stock-name { overflow-wrap: normal; }

/* KPI 카드 — 값이 nowrap 이라 좁은 칸에서 카드를 뚫는다.
   폰에서는 값 줄바꿈을 허용한다. */
@media (max-width: 479.98px) {
  .kpi .val, .card .val { white-space: normal; }
}

/* 긴 토큰(파일 경로·URI·해시)이 든 셀만 강제 분절 — base.html 의 __breakLongCells 가 붙인다.
   2026-07-26 실측: /model/ 의 Tracking URI 가 360px 에서 페이지를 12px 밀어냈다. */
td.brk, th.brk { overflow-wrap: anywhere; word-break: break-word; }

} /* @layer components 끝 */
@layer components { /* 832~944 */
/* ══════════════════════════════════════════════════════════════════════════
   폼 컨트롤 · 버튼 (2026-07-26 신규)
   교체 전: 버튼·셀렉트 공통 스타일이 없어 화면마다 제각각이었다
   (blueprints/investor·sectors·stocks 는 각자 인라인 <style> 로 정의).
   터치 표적 44px(Apple HIG) · 라벨 텍스트는 절대 자르지 않는다.
   ══════════════════════════════════════════════════════════════════════════ */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2);
  min-height: 38px; padding: 0 var(--sp-4);
  border: 1px solid var(--border-default); border-radius: var(--radius-sm);
  background: var(--surface-1); color: var(--ink-0);
  font-size: var(--fs-13); font-weight: var(--fw-medium); font-family: inherit;
  line-height: var(--lh-tight); white-space: nowrap; cursor: pointer; text-decoration: none;
  transition: background .12s ease, border-color .12s ease;
}
.btn:hover { background: var(--surface-2); border-color: var(--border-strong); text-decoration: none; }
.btn:active { background: var(--surface-3, var(--surface-2)); }
.btn:focus-visible { outline: 2px solid var(--accent-c); outline-offset: 2px; }
.btn[disabled], .btn.is-disabled { opacity: .5; cursor: not-allowed; }

.btn-primary { background: var(--accent-c); border-color: var(--accent-c); color: #fff; }
.btn-primary:hover { background: var(--accent-strong, var(--accent-c)); border-color: var(--accent-strong, var(--accent-c)); filter: brightness(.94); }
.btn-ghost { background: transparent; border-color: transparent; color: var(--ink-1); }
.btn-ghost:hover { background: var(--surface-2); }
.btn-sm { min-height: 30px; padding: 0 var(--sp-3); font-size: var(--fs-12); }

select, input[type="text"], input[type="search"], input[type="number"], input[type="date"] {
  min-height: 38px; padding: 0 var(--sp-3);
  border: 1px solid var(--border-default); border-radius: var(--radius-sm);
  background: var(--surface-1); color: var(--ink-0);
}
select:focus-visible, input:focus-visible { outline: 2px solid var(--accent-c); outline-offset: 1px; }

/* 폰 — 터치 표적 44px */
@media (max-width: 639.98px) {
  .btn, select, input[type="text"], input[type="search"],
  input[type="number"], input[type="date"] { min-height: 44px; }
  .btn-sm { min-height: 36px; }
  .flow-form { flex-direction: column; align-items: stretch; }
  .flow-form label, .flow-form .btn, .flow-form select { width: 100%; }
}

/* ══════════════════════════════════════════════════════════════════════════
   조회 폼 + 강도 배지 (2026-07-26 공용화)
   sectors / stocks / investor 세 화면이 같은 CSS 를 각자 인라인으로 갖고 있었다.
   ══════════════════════════════════════════════════════════════════════════ */
.flow-form {
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--sp-3);
  background: var(--surface-1); border: 1px solid var(--border-subtle);
  border-radius: var(--radius); padding: var(--sp-4); margin: var(--sp-5) 0;
}
.flow-form label {
  display: flex; flex-direction: column; gap: var(--sp-1);
  font-size: var(--fs-12); color: var(--ink-2); font-weight: var(--fw-medium);
}

/* 강도 8단계 — 한국식(상승·순매수=적 / 하락·순매도=청).
   1~2 단계는 옅은 배경 + 유채색 글자, 3~4 단계는 채운 배경 + 흰 글자. */
.change, .net {
  display: inline-block; text-align: right;
  padding: 3px 8px; border-radius: var(--radius-sm);
  font-variant-numeric: tabular-nums; font-weight: var(--fw-semi);
}
.change { min-width: 78px; }
.net    { min-width: 92px; }
.change.up-1, .change.up-2, .net.up-1, .net.up-2 { background: var(--up-bg);   color: var(--up); }
.change.up-3, .change.up-4, .net.up-3, .net.up-4 { background: var(--up);      color: #fff; }
.change.dn-1, .change.dn-2, .net.dn-1, .net.dn-2 { background: var(--down-bg); color: var(--down); }
.change.dn-3, .change.dn-4, .net.dn-3, .net.dn-4 { background: var(--down);    color: #fff; }

.market-badge {
  display: inline-block; padding: 1px 7px; border-radius: 999px;
  font-size: var(--fs-11); color: var(--ink-2);
  background: var(--surface-2); border: 1px solid var(--border-subtle);
}
.mode-badge {
  display: inline-block; margin-left: var(--sp-2); vertical-align: middle;
  padding: 2px 8px; border-radius: 999px;
  font-size: var(--fs-11); font-weight: var(--fw-semi);
}
.mode-badge.live     { background: var(--good-bg); color: var(--good); }
.mode-badge.fallback { background: var(--warn-bg); color: var(--warn-c); }

/* 산문 블록의 긴 토큰(문서 경로·URL) 줄바꿈.
   일반 블록 레이아웃에서는 break-word 만으로 충분하다 —
   표의 auto 레이아웃과 달리 최소폭 계산에 걸리지 않는다.
   2026-07-26 실측: /progress/ footer 의 docs/…_v0.1.md 가 360px 에서 19px 넘침. */
p, li, dd, dt, figcaption, .meta, .footer, footer.content, blockquote, .desc, .note {
  overflow-wrap: break-word;
}

/* 터치 표적 44px (Apple HIG · Material 48dp 권고의 하한).
   실측: 햄버거 40px · 드로어 링크 32px 로 미달이었다.
   데스크톱은 그대로 둔다 — 마우스 표적은 작아도 되고, 사이드바 23개 항목이
   1080 화면에서 스크롤을 만들지 않아야 한다. */
@media (max-width: 1023.98px) {
  .icon-btn, .theme-toggle { width: 44px; height: 44px; }
  .app-side a { height: 44px; font-size: var(--fs-14); }
  .side-grp { margin-top: var(--sp-4); }
}

/* 접히는 경고/면책 박스 — 정직하게 남기되 화면의 주인공 자리는 표에 준다.
   2026-07-26: /verify/ 의 면책 슬래브가 첫 화면의 40%를 차지하고 있었다. */
details.caveat-fold { padding: var(--sp-2) var(--sp-4); }
details.caveat-fold > summary {
  cursor: pointer; list-style: none; padding: var(--sp-2) 0;
  font-weight: var(--fw-semi); display: flex; align-items: center; gap: var(--sp-2);
}
details.caveat-fold > summary::-webkit-details-marker { display: none; }
details.caveat-fold > summary::before { content: "▸"; font-size: .85em; transition: transform .15s ease; }
details.caveat-fold[open] > summary::before { transform: rotate(90deg); }
details.caveat-fold > ul { margin: 0 0 var(--sp-3); }

} /* @layer components 끝 */
@layer utilities { /* 945~967 */
/* ══════════════════════════════════════════════════════════════════════════
   밀도 3단 (2026-07-26 신규) — 점검표 14번
   근거: Pencil&Paper / Setproduct — 업무용 데이터 표는 사용자가 밀도를 고른다.
   같은 화면을 "훑는 날"과 "파고드는 날"의 요구가 다르다.
   compact 40 / regular 48 / relaxed 56 은 상용 제품 실측 3단이다.
   ※ WCAG 2.2 최소 타깃 24×24 는 compact 에서도 지킨다(행 40px).
   ※ 폰(≤639)에서는 44px 아래로 내려가지 않는다 — 터치 타깃이 우선한다.
   ══════════════════════════════════════════════════════════════════════════ */
:root, [data-density="regular"] { --row-h: 40px; --row-fs: var(--fs-13); }
[data-density="compact"] { --row-h: 32px; --row-fs: var(--fs-12); }
[data-density="relaxed"] { --row-h: 52px; --row-fs: var(--fs-14); }

[data-density] tbody td, [data-density] tbody th { height: var(--row-h); font-size: var(--row-fs); }
[data-density="compact"] thead th { padding-top: 6px; padding-bottom: 6px; }
[data-density="compact"] table th, [data-density="compact"] table td {
  padding-left: var(--sp-2); padding-right: var(--sp-2);
}
[data-density="relaxed"] thead th { padding-top: 12px; padding-bottom: 12px; }

@media (max-width: 639.98px) {
  /* 터치 타깃이 밀도보다 우선한다 */
  [data-density] tbody td, [data-density] tbody th { height: 44px; }
}

  /* ★ 실시간 값을 못 받은 칸 — 지우지 않고 «낡았다» 고만 보인다 (2026-09-01).
     2026-09-01 장중, 값을 못 받으면 화면이 어제 시세를 **오늘 값인 양** 보여 줬다
     (그날 라이브값 창구가 166 번 실패했다). 지우면 「자료가 없다」로 오해되고,
     그냥 두면 거짓이 된다. 표준의 답은 「지우지 말고 밝혀라」다. */
  [data-stale="1"] {
    opacity: 0.5;
    text-decoration: underline dotted currentColor;
    text-underline-offset: 3px;
    cursor: help;
  }
} /* @layer utilities 끝 */
@layer components { /* 968~984 */

/* 헤더의 밀도 선택기 */
.density-seg {
  display: inline-flex; background: var(--surface-2);
  border: 1px solid var(--border-subtle); border-radius: var(--radius-sm); padding: 2px;
}
.density-seg button {
  border: 0; background: transparent; color: var(--ink-2); cursor: pointer;
  width: 30px; height: 28px; border-radius: calc(var(--radius-sm) - 1px);
  font-family: inherit; font-size: var(--fs-11); line-height: var(--lh-tight);
  display: inline-flex; align-items: center; justify-content: center;
}
.density-seg button[aria-pressed="true"] { background: var(--surface-1); color: var(--ink-0); }
.density-seg button:focus-visible { outline: 2px solid var(--accent-c); outline-offset: 1px; }
.density-seg button:hover { color: var(--ink-0); }
@media (max-width: 639.98px) { .density-seg { display: none; } }  /* 폰은 터치 타깃 고정 */

} /* @layer components 끝 */
/* ── 층 밖 (의도) — 985~1001 ───────────────────────────── */
/* ── 화면 전환 — 겉틀은 제자리, 본문만 바뀐다 (2026-08-22 · 25번 §6 2단계) ────────────
   인베스팅닷컴 실측: 빠르게 느껴지는 이유는 서버(1.0~1.5초)가 아니라 ① 누른 뒤 18~29ms 첫 반응
   ② 머리·옆줄이 사라지지 않음 ③ 흰 화면 없음. 우리는 다중 페이지를 그대로 두고 이 둘로 같은 체감을 얻는다.
   문서 간 뷰 트랜지션(Chrome/Edge 126+ · Safari 18.2+): 양쪽 페이지가 같은 CSS 를 쓰므로 전부 참여한다.
   안 되는 브라우저는 그냥 평범하게 뜬다(점진적 향상). 전환 중 겉틀은 같은 이름끼리 짝지어 **움직이지 않고**,
   본문(root)만 120ms 짧게 섞인다 — 21번 §2-5 「색 전이만 짧게, 위치·크기는 애니메이션하지 않는다」. */
@view-transition { navigation: auto; }
.app-header { view-transition-name: app-header; }
.app-side   { view-transition-name: app-side; }
.app-tabbar { view-transition-name: app-tabbar; }
::view-transition-old(root), ::view-transition-new(root) { animation-duration: 120ms; }
::view-transition-old(app-header), ::view-transition-new(app-header),
::view-transition-old(app-side),   ::view-transition-new(app-side),
::view-transition-old(app-tabbar), ::view-transition-new(app-tabbar) { animation: none; }
@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) { animation: none !important; }
}
@layer components { /* 1002~1012 */

/* 누른 순간의 반응 — 상단 2px 진행 줄. 내부 링크를 누르면 base.html 이 <html> 에 is-navigating 을 붙인다.
   새 문서가 뜨면(또는 bfcache 복귀) 저절로 사라진다. te- 접두 = 전역 한 단어 클래스 충돌 금지(적용기록 §0). */
.te-nav-progress {
  position: fixed; top: 0; left: 0; height: 2px; width: 0;
  background: var(--accent-c); opacity: 0; pointer-events: none;
  z-index: calc(var(--z-header) + 1);
  transition: width .6s cubic-bezier(.2,.7,.3,1), opacity .15s linear;
}
html.is-navigating .te-nav-progress { opacity: 1; width: 72%; }

} /* @layer components 끝 */
@layer utilities { /* 1013~1022 */
/* ★ 손가락으로 만지는 기기에서만 44px (Apple·KRDS 권장 · 2026-08-28).
   마우스에서는 24px 로 충분하고(WCAG 2.2 AA 최소), 전부 44px 로 키우면 조밀한 금융 화면의
   정보 밀도가 무너진다. 그래서 «입력 장치» 로 가른다 — 이것이 두 요구를 다 만족시키는 표준 길이다.
   ※ 채점기(design-auditor)는 데스크톱에서만 재므로 이 규칙을 못 보고 계속 「44px 미만」이라 문다.
      그 경고는 알고 남겨 두는 것이다. */
@media (pointer: coarse) {
  .agchart-foot button { min-height: 44px; padding: 8px 14px; }
  .copy-code-btn, .chart-code-lnk { min-height: 44px; padding: 0 10px; }
  .app-brand a { min-height: 44px; }
}

  /* ★ 실시간 값을 못 받은 칸 — 지우지 않고 «낡았다» 고만 보인다 (2026-09-01).
     2026-09-01 장중, 값을 못 받으면 화면이 어제 시세를 **오늘 값인 양** 보여 줬다
     (그날 라이브값 창구가 166 번 실패했다). 지우면 「자료가 없다」로 오해되고,
     그냥 두면 거짓이 된다. 표준의 답은 「지우지 말고 밝혀라」다. */
  [data-stale="1"] {
    opacity: 0.5;
    text-decoration: underline dotted currentColor;
    text-underline-offset: 3px;
    cursor: help;
  }
} /* @layer utilities 끝 */
