/* Kalibre landing — Phosphor Black, 앱 토큰(apps/app/src/theme/tokens.ts) 1:1.
   컬러 컨벤션: **상승=초록 / 하락=빨강** — 앱이 지원하는 두 컨벤션(Western green-up /
   Asia red-up, tokens.ts `marketTokens()`) 중 **Western**을 랜딩에 고정한 것이다. `--green`·
   `--red`는 앱 dataTokens 다크값과 동일하고 .q-up/.sent-up/.edge-up이 전부 초록을 쓴다.
   ⚠️ `상승=빨강`은 **SNS 카드 전용 하드룰**(tools/cards/CARD-RULES.md)이라 여기엔 해당 없음 —
   종전 주석이 그 규칙을 잘못 옮겨 적어 구현과 정반대였다(2026-07-31 정정).
   시안(--accent)은 브랜드/인터랙션 전용으로 등락 표현에 쓰지 않는다. */

:root {
  --bg: #000000;
  --surface: #101010;
  --elevated: #161616;
  --text: #f2f2f2; /* 순백 금지 (헐레이션 규칙) */
  --text-2: #a6a6a6;
  --muted: #8a8a8a;
  --prose: #cfcfcf;
  --border: #2a2a2a;
  --border-strong: #3a3a3a;
  --hairline: #1e1e1e;
  --accent: #2dd4ff;
  --accent-hover: #6be0ff;
  --accent-dim: rgba(45, 212, 255, 0.13);
  --green: #2bee34; /* 앱 기본(서구) 컨벤션 — status.success·data up과 동일 */
  --red: #ff5c5c;
  --yellow: #facc15; /* 앱 dataTokens.neutral */
  --yellow-text: #fde047; /* 앱 dataTokens.neutralText */
  --urgent: #fb923c;
  --sans: "Pretendard Variable", Pretendard, -apple-system, BlinkMacSystemFont,
    "Apple SD Gothic Neo", "Noto Sans KR", "Segoe UI", Roboto, sans-serif;
  --mono: "Roboto Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
}

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

html {
  color-scheme: dark;
  scroll-behavior: smooth;
}

body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
  word-break: keep-all; /* 한국어: 단어 중간 줄바꿈 방지 */
  overflow-wrap: break-word;
}

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

/* 키보드 포커스 링 — 종전엔 브라우저 기본값에만 맡겨져 있었다(outline을 죽이진 않았으니
   링 자체는 나왔다). 다만 순검정 배경에서 기본 링의 대비는 브라우저·OS마다 제각각이고,
   커스텀은 `.lang-btn:focus-visible`의 색 변화 하나뿐이라 아이콘 단독 버튼에선 약했다.
   :focus-visible 하나로 링크·summary·향후 추가될 버튼까지 전부 덮는다(마우스 클릭엔
   안 뜨고 키보드 탐색에서만 뜬다). outline은 border-radius를 자동으로 따라간다. */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}

a {
  color: var(--accent);
  text-decoration: none;
  transition: color 150ms var(--ease-out);
}

@media (hover: hover) and (pointer: fine) {
  a:hover {
    color: var(--accent-hover);
  }
}

/* ⚠️ 폴드 계약을 지키는 하한선 — 결정 변수는 뷰포트 폭이 아니라 **본문 폭**이다.
   본문이 좁아지면 히어로 h1·부제가 한 줄씩 늘어 목업이 폴드 아래로 밀리고 `.reveal`
   관찰자가 발동하지 않는다. 폰트 적용 후 실측: 본문 312px → 목업 537px(통과, EN 기준) ·
   292px → 566px(임계 552 초과). 그래서 여백을 폭별로 분기하지 말고 본문 폭이
   312px 밑으로 내려가지 않는 선에서만 24px를 준다 — 360px 이상은 그대로 24px,
   340px에선 14px, 320px에선 4px로 자동 수렴한다.
   ⚠️ 하한이 4px인 이유(오너 결정 2026-08-01): 8px이면 320px에서 본문이 304px로 줄어
   **영문판만** 임계(544)를 못 맞춘다(목업 611px). 영문은 같은 내용이 길어 본문 312px를
   그대로 요구하므로, 320px에서 폴드를 지키려면 여백이 정확히 4px여야 한다. 그 폭에서
   여백보다 첫 화면 제품 노출이 중요하다는 판단. 320px 초과에서는 곧바로 넉넉해진다.
   ⚠️ 이 값을 폭 기준 미디어쿼리로 되돌리지 말 것: 임계를 폭으로 잡으면 언어·폰트가
   바뀔 때마다 어긋난다 — 실제로 폰트 로드 전에 재는 바람에 임계를 두 번 잘못 잡았다.
   재측정할 땐 반드시 `await document.fonts.ready` 후에 잴 것. */
.container {
  max-width: 1040px;
  margin: 0 auto;
  padding: 0 clamp(4px, (100vw - 312px) / 2, 24px);
}

.mono {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
}

/* ---------------------------------------------------------------- header */

.site-header {
  padding: 28px 0;
}

/* baseline이 아니라 center — 언어 버튼이 아이콘 단독(텍스트 베이스라인이 없다)이라
   baseline 정렬에선 워드마크와 어긋난다. */
.site-header .container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}

.wordmark {
  display: inline-flex;
  align-items: center;
  font-family: var(--mono);
  font-weight: 700;
  font-size: 14px;
  letter-spacing: 0.3em;
  color: var(--text);
  white-space: nowrap;
}

/* 앱 정본 로고 — 탭바 선택 상태의 컬러 O 마크(apps/app/assets/calibre-nav-color@3x.png)에서
   좌우 투명 여백만 잘라낸 것(원본은 정사각 캔버스에 종횡비 0.56 마크가 들어 있어, 그대로
   쓰면 워드마크 사이에 죽은 공간이 생긴다). 재생성: sips -c 75 42 <원본> --out logo-nav.png.
   ⚠️ 높이만 지정하고 width:auto — 종횡비가 바뀌면 브랜드 마크가 찌그러진다.
   ⚠️ letter-spacing 0.3em이 img 뒤에도 붙으므로 margin은 그만큼 덜 준다. */
.wordmark .mark {
  height: 17px;
  width: auto;
  margin-right: 0.5em;
  flex: none;
}

/* 언어 선택 — 글로브 버튼을 누르면 목록이 열린다(네이티브 <details>).
   종전엔 `EN · 한국어 · 中文`을 헤더에 그대로 나열했는데, 워드마크와 폭을 나눠 갖다 보니
   좁은 화면·큰 글꼴 설정에서 오른쪽 항목(中文)이 잘렸다(오너 실기기 리포트 2026-08-01).
   버튼 하나로 접으면 항목 수·글자 길이와 무관하게 헤더 폭이 고정된다. */
.lang {
  position: relative;
  flex: none;
}

.lang-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  /* 세로 44px 터치 타깃 유지. 가로는 내용(아이콘 + 언어 코드)에 맞추고 padding으로
     여유를 준다 — 고정 44px로 두면 코드가 들어오며 찌그러진다.
     음수 margin은 그 패딩·높이가 헤더 레이아웃을 밀지 않게 되돌리는 용도. */
  height: 44px;
  padding: 0 8px;
  margin: -12px -8px;
  color: var(--muted);
  cursor: pointer;
  list-style: none; /* ▶ 마커 제거 (Firefox) */
  transition: color 150ms var(--ease-out);
}

.lang-btn::-webkit-details-marker {
  display: none; /* ▶ 마커 제거 (Safari/Chrome) */
}

.lang-btn .globe {
  width: 20px;
  height: 20px;
  stroke-linecap: round;
}

/* 현재 언어 표시 — 아이콘만 두면 열어보기 전엔 어느 언어인지 알 수 없다.
   aria-hidden인 이유: summary의 이름은 aria-label이 이미 갖고 있어 스크린리더가
   "언어 선택 KO"처럼 두 번 읽는 걸 막는다. 현재 언어는 메뉴 안 aria-current가 알린다.
   ⚠️ 라틴 2글자로 통일(KO/EN/ZH) — 「한국어」·「中文」로 두면 3벌 폭이 달라져,
   글로브로 바꾸기 전의 헤더 잘림 문제가 언어별로 재발한다.
   ⚠️ **561px 이상에서만 켠다.** 폰 폭에서 켜면 글꼴 배율이 큰 사용자에게 코드가 화면
   밖으로 밀린다(실측: 320px는 1.3배, 360·375px는 1.45배, 390px는 1.6배부터 잘림 —
   폰트 배율은 미디어쿼리로 잡을 수 없어 안전한 폭 경계가 없다). 561px 이상은 배율
   2.0배까지 안전. 폰에선 페이지 본문 자체가 이미 언어를 말해주므로 손실이 작다. */
.lang-code {
  display: none;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
}

@media (min-width: 561px) {
  .lang-code {
    display: inline;
  }
}

.lang[open] .lang-btn,
.lang-btn:focus-visible {
  color: var(--text);
}

@media (hover: hover) and (pointer: fine) {
  .lang-btn:hover {
    color: var(--text);
  }
}

/* ⚠️ display로 직접 여닫는다 — 닫힌 <details>가 내용을 감추는 건 슬롯의
   `content-visibility: hidden`인데, position:absolute인 자식은 컨테이닝 블록이 .lang
   자신(슬롯 바깥)이라 그 서브트리를 빠져나가 그대로 보인다(실측 확인). */
.lang-menu {
  display: none;
  position: absolute;
  top: calc(100% + 10px);
  right: 0;
  z-index: 20;
  flex-direction: column;
  min-width: 128px;
  padding: 6px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  white-space: nowrap;
}

.lang[open] .lang-menu {
  display: flex;
}

.lang-menu > * {
  padding: 9px 12px;
  border-radius: 8px;
  color: var(--muted);
  transition: color 150ms var(--ease-out), background 150ms var(--ease-out);
}

.lang-menu .current {
  color: var(--text);
  font-weight: 700;
}

@media (hover: hover) and (pointer: fine) {
  .lang-menu a:hover {
    color: var(--text);
    background: rgba(255, 255, 255, 0.06);
  }
}

/* ------------------------------------------------------------------ hero */

/* ⚠️ 세로만 longhand로 준다 — `padding: 88px 0 64px` 단축을 쓰면 .container의
   `padding: 0 24px`(같은 특이도, 앞선 선언)를 통째로 덮어 좌우가 0이 된다. 데스크톱은
   max-width가 여백을 만들어 안 드러나지만 모바일에선 글자가 화면 끝에 붙는다
   (오너 실기기 리포트 2026-08-01). .section · .mockup-wrap · .band .section도 동일. */
.hero {
  padding-top: 88px;
  padding-bottom: 64px;
  text-align: center;
  position: relative;
}

@keyframes pulse {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0.25;
  }
}

.hero h1 {
  font-size: clamp(38px, 6.4vw, 66px);
  font-weight: 700;
  line-height: 1.18;
  letter-spacing: -0.022em;
  text-wrap: balance;
}

.hero h1 .accent {
  color: var(--accent);
}

.hero .sub {
  margin: 22px auto 0;
  max-width: 560px;
  color: var(--text-2);
  font-size: 17px;
  line-height: 1.7;
  text-wrap: pretty;
}

.hero .sub-line {
  margin-top: 14px;
  font-family: var(--mono);
  font-size: 13px;
  letter-spacing: 0.14em;
  color: var(--muted);
}

.cta-row {
  margin-top: 36px;
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}

.store-chip {
  display: inline-flex;
  align-items: baseline;
  gap: 10px;
  font-family: var(--mono);
  font-size: 13px;
  letter-spacing: 0.06em;
  color: var(--text-2);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 12px 22px;
}

.cta-caption {
  margin-top: 16px;
  font-size: 13px;
  color: var(--muted);
}

/* --------------------------------------------------------------- mockup */

.mockup-wrap {
  position: relative;
  padding-top: 24px;
}

.mockup-glow {
  position: absolute;
  inset: -10% 15% auto;
  height: 420px;
  background: radial-gradient(closest-side, rgba(45, 212, 255, 0.09), transparent 70%);
  pointer-events: none;
}

/* 제목·설명 ↔ 목업 간격은 밴드의 `.panel-grid`(36px)와 같은 값으로 맞춘다 — 세 밴드가
   전부 sub 아래 24px(실측)로 떨어지는데 목업만 0이라 헤더가 목업에 붙어 보였다
   (오너 지적 2026-08-01). 값을 따로 정하지 않고 .panel-grid와 같은 선언값을 써서,
   한쪽만 바뀌어 어긋나는 일이 없게 한다. */
.terminal {
  position: relative;
  max-width: 760px;
  margin: 36px auto 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 16px;
  overflow: hidden;
  text-align: left;
}

.tape {
  display: flex;
  align-items: center;
  gap: 0;
  border-bottom: 1px solid var(--hairline);
  padding: 12px 0;
  overflow: hidden;
  position: relative;
}

.tape-live {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.18em;
  color: var(--green);
  padding: 0 16px;
  border-right: 1px solid var(--hairline);
  flex: none;
  background: var(--surface);
  z-index: 1;
}

.tape-live .dot {
  width: 5px;
  height: 5px;
  border-radius: 999px;
  background: var(--green);
  animation: pulse 2.4s var(--ease-in-out) infinite;
}

.tape-viewport {
  flex: 1;
  overflow: hidden;
  mask-image: linear-gradient(to right, transparent, #000 4%, #000 96%, transparent);
  -webkit-mask-image: linear-gradient(to right, transparent, #000 4%, #000 96%, transparent);
}

.tape-track {
  display: inline-flex;
  white-space: nowrap;
  animation: tape 46s linear infinite;
}

@keyframes tape {
  to {
    transform: translateX(-50%);
  }
}
.tape-group {
  display: inline-flex;
  gap: 30px;
  padding: 0 15px;
  font-family: var(--mono);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  color: var(--text-2);
}

.tape-group b {
  font-weight: 500;
  color: var(--muted);
  margin-right: 7px;
}

.q-up {
  color: var(--green);
}

.q-down {
  color: var(--red);
}

.feed-card {
  display: flex;
  gap: 14px;
  padding: 16px 18px 15px 16px;
  border-bottom: 1px solid var(--hairline);
}

.feed-card .edge {
  flex: none;
  width: 3px;
  border-radius: 2px;
  background: var(--border-strong);
}

/* 베이스(.feed-card .edge)보다 뒤에 같은 특이성으로 선언해야 색이 이긴다 */
.feed-card .edge-up {
  background: var(--green);
}

.feed-card .edge-down {
  background: var(--red);
}

.feed-card .edge-neutral {
  background: var(--yellow);
}

.feed-card .body {
  flex: 1;
  min-width: 0;
}

.feed-meta {
  display: flex;
  align-items: baseline;
  gap: 10px;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.1em;
}

.feed-meta .pub {
  font-weight: 700;
  color: var(--muted);
}

.feed-meta .time {
  color: var(--muted);
}

.feed-headline {
  margin-top: 6px;
  font-size: 15.5px;
  font-weight: 600;
  line-height: 1.45;
  letter-spacing: -0.01em;
}

.feed-tags {
  margin-top: 8px;
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.tag {
  font-size: 11.5px;
  color: var(--text-2);
  background: rgba(138, 138, 138, 0.12);
  border-radius: 6px;
  padding: 3px 8px;
}

.sent {
  margin-left: auto;
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
}

.sent-up {
  color: var(--green);
}

.sent-down {
  color: var(--red);
}

.sent-neutral {
  color: var(--yellow-text);
}

.ai-strip {
  padding: 16px 18px 18px;
  background: var(--elevated);
}

.ai-label {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.18em;
  color: var(--accent);
}

.ai-q {
  margin-top: 10px;
  font-size: 13.5px;
  color: var(--muted);
}

.ai-a {
  margin-top: 6px;
  font-size: 14px;
  line-height: 1.65;
  color: var(--prose);
}

/* 인용 = 위첨자 숫자만 (2026-08-01 오너 지적: 알약 칩이 너무 커서 본문을 끊었다).
   발행처명은 바로 위 피드 카드가 이미 보여주므로 번호만으로 충분하다.
   ⚠️ <sup> 기본 스타일(font-size: smaller + vertical-align: super)은 줄 높이를 밀어
   문단 행간이 들쭉날쭉해진다 → 크기·정렬을 직접 지정하고 line-height를 0으로 눌러
   위첨자가 본문 행 높이에 영향을 주지 않게 한다. */
.cite {
  font-family: var(--mono);
  font-size: 9px;
  font-weight: 700;
  line-height: 0;
  color: var(--accent);
  vertical-align: super;
  margin-left: 1.5px;
}

.mockup-caption {
  margin: 14px auto 0;
  text-align: center;
  font-size: 12px;
  color: var(--muted);
}

/* -------------------------------------------------------------- features */

.section {
  padding-top: 104px;
}

.section-kicker {
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.22em;
  color: var(--accent);
}

/* ⚠️ `.mockup-wrap`도 함께 받는다 — 목업 섹션은 `.section`이 아니라 `.mockup-wrap`이라,
   NEWS FEED 헤더를 붙였을 때 h2 크기·부제 max-width(560px)·간격이 전부 적용되지 않아
   혼자 다른 조판이 되고 있었다(2026-08-01 실측). `.section` 클래스를 붙이는 방법도 있지만
   그러면 `.section { padding-top: 104px }`까지 딸려와 히어로와의 간격이 무너진다. */
.section h2,
.mockup-wrap h2 {
  margin-top: 12px;
  font-size: clamp(26px, 3.6vw, 34px);
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.3;
  text-wrap: balance;
}

.section .section-sub,
.mockup-wrap .section-sub {
  margin-top: 12px;
  max-width: 560px;
  color: var(--text-2);
  text-wrap: pretty;
}

/* 능력 3종(FEED · AI · ALERTS) — 종전엔 3장짜리 카드 그리드였다. 페이지에서 유일하게
   "보여주지 않고 말로 설명하는" 블록이자 마지막 남은 박스 그리드라, 배경 밴드를 걷어낸
   뒤에도 혼자 이물감으로 남았다(2026-07-31 오너 지적). 게다가 바로 위 목업이 이미 피드
   화면 자체이고, 섹션 h2("필요한 것만, 한 화면에")는 히어로 h1과 사실상 같은 말이었다.
   → 섹션을 지우고, 목업 캡션 밑 한 줄로 녹인다. 박스·배경 없이 캡션 톤으로만 얹어
   페이지의 두 문법(히어로 · 실제 UI 패널)을 흐트러뜨리지 않는다. */
.capabilities {
  margin-top: 10px;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px 22px;
  font-size: 13px;
  line-height: 1.6;
  color: var(--text-2);
}

.cap {
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
}

.cap-k {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.2em;
  color: var(--accent);
}

/* ------------------------------------------- 데이터 밴드 (공시·브리핑·지표) */
/* 내부는 산문 카드가 아니라 앱의 실제 데이터 행을 재현한 모노 위주 조판.
   ⚠️ 배경·테두리를 주지 않는다(2026-07-31 오너 지적): 종전엔 밴드마다 배경을
   --bg에서 띄우고 방사광을 따로 깔아, 페이지가 한 장의 연속된 지면이 아니라
   서로 다른 판때기를 이어붙인 것처럼 뚝뚝 끊겨 읽혔다. 배경은 body 하나로
   흐르게 두고(빛의 출처도 히어로 하나), 장 구분은 여백·타이포 위계·카드
   대비(--surface)로만 낸다. */

/* 앱 화면 재현물은 드래그 선택 대상이 아니다 (2026-08-01 오너 지적).
   히어로 목업(.terminal)과 밴드 패널(.panel)은 실제 데이터가 아니라 UI 재현이라,
   드래그하면 가짜 티커·수치가 통째로 블록 선택돼 복사해 쓸 수 있는 값처럼 보인다.
   행 클래스(.trade-row/.hold-row/.mini-table/.ind-row/.brief-row/.rep-row)마다 붙이지
   않고 둘의 공통 컨테이너에서 한 번에 막는다 — 새 행 종류가 생겨도 자동 적용된다.
   ⚠️ 제목·부제·캡션은 패널 바깥이라 그대로 선택·복사된다(면책 문구 포함 — 법적 고지는
   복사 가능해야 한다). ⚠️ 막는 것은 선택뿐이고 번역·브라우저 찾기(Ctrl+F)·스크린리더는
   영향받지 않는다. -webkit- 접두사는 Safari/iOS에 여전히 필수. */
.terminal,
.panel {
  -webkit-user-select: none;
  user-select: none;
}

.band {
  margin-top: 104px;
}

.band .section {
  padding-top: 84px;
  padding-bottom: 72px;
}

.panel-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 18px;
  margin-top: 36px;
}

.panel {
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 16px;
  overflow: hidden;
}

.panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 14px 18px;
  border-bottom: 1px solid var(--hairline);
  background: var(--elevated);
}

.panel-title {
  font-size: 14px;
  font-weight: 700;
  letter-spacing: -0.01em;
}

.panel-src {
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.16em;
  color: var(--muted);
}

/* ---- 정치인 거래 행 (앱 PoliticianTradesScreen TradeRow 재현) ---- */

.trade-row {
  padding: 14px 18px 15px;
  border-bottom: 1px solid var(--hairline);
}

.tr-top {
  display: flex;
  align-items: baseline;
  gap: 10px;
}

.tr-filer {
  font-size: 13.5px;
  font-weight: 700;
}

.tr-dist {
  margin-left: 7px;
  font-weight: 600;
  color: var(--muted);
}

.tr-ago {
  margin-left: auto;
  font-size: 11px;
  color: var(--muted);
}

.tr-asset {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-top: 7px;
  min-width: 0;
}

.tr-ticker {
  flex: none;
  font-size: 13.5px;
  font-weight: 700;
  color: var(--accent);
}

.tr-name {
  font-size: 13.5px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tr-meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 9px;
}

.pill {
  border-radius: 6px;
  padding: 2px 8px;
  font-size: 11.5px;
  font-weight: 700;
}

/* 상승=초록 컨벤션(파일 헤더 주석) — 매수는 up, 매도는 down 토큰을 따른다 */
.pill-buy {
  color: var(--green);
  background: rgba(43, 238, 52, 0.14);
}

.pill-sell {
  color: var(--red);
  background: rgba(255, 92, 92, 0.14);
}

.tr-flag {
  border: 1px solid var(--border-strong);
  border-radius: 6px;
  padding: 1px 7px;
  font-size: 11px;
  font-weight: 600;
  color: var(--muted);
}

.tr-range {
  font-size: 12px;
  color: var(--text-2);
}

.tr-date {
  margin-left: auto;
  font-size: 11px;
  color: var(--muted);
}

/* ---- 13F 보유 행 (앱 fund/[cik] 보유 행 재현) ---- */

/* 13F 보유 행 — 어느 기관의 보유인지를 행 머리에 밝힌다(오너 지적 2026-08-01:
   "종목명만 보여줘서 부정확"). 13F는 기관별 공시라 소유 주체가 빠지면 데이터의
   의미 자체가 성립하지 않는다. 앱 fund/[cik] 상단바의 [기관명 + 인물명] 조합을
   행 안으로 가져온 것 — 옆 정치인 거래 패널이 [인물 + 지역구]를 행 머리에 두는
   것과 같은 문법이 된다. 평가액·비중은 각 기관의 실제 운용액과 앞뒤가 맞게 잡았다. */
.hold-row {
  padding: 12px 18px 13px;
  border-bottom: 1px solid var(--hairline);
}

.hr-fund {
  display: flex;
  align-items: baseline;
  gap: 6px;
  margin-bottom: 7px;
}

.hr-fund-name {
  font-size: 12px;
  font-weight: 700;
  color: var(--text);
}

/* 인물명은 기관명의 보조 — 앱도 같은 위계(기관 primary / 인물 secondary)다. */
.hr-fund-mgr {
  font-size: 11px;
  font-weight: 600;
  color: var(--text-2);
}

.hr-fund-q {
  margin-left: auto;
  font-size: 10px;
  color: var(--muted);
}

.hr-body {
  display: flex;
  align-items: center;
  gap: 12px;
}

.hr-left {
  flex: 1;
  min-width: 0;
}

.hr-name {
  display: flex;
  align-items: baseline;
  gap: 6px;
  min-width: 0;
}

.hr-ticker {
  flex: none;
  font-size: 12.5px;
  font-weight: 700;
  color: var(--accent);
}

.hr-issuer {
  font-size: 13.5px;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.hr-class {
  margin-top: 2px;
  font-size: 10px;
  color: var(--muted);
}

.hr-right {
  flex: none;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 3px;
}

.hr-val {
  font-size: 13px;
  font-weight: 600;
}

.hr-sub {
  display: flex;
  align-items: center;
  gap: 7px;
}

/* color는 방향색의 단일 출처 — 면(.spark-area)·도트(.spark-dot)가 currentColor로 따라온다. */
.spark {
  width: 40px;
  height: 14px;
  overflow: visible;
  color: var(--muted);
}

/* 선은 폴리라인이 아니라 Catmull-Rom → 베지어 곡선 + 면 채움 + 끝점 도트 3층 구조다
   (2026-08-01 오너 지적 "대충 그린 선 같다"). 7점 꺾은선은 각진 관절이 그대로 보여
   데이터가 아니라 아이콘처럼 읽혔다 — 점을 20개(소형 14개)로 늘리고 곡선으로 이어
   실제 시세 계열처럼 만들었다. 좌표는 `tools/landing/gen-sparklines.py`가 시드 고정으로
   생성해 3개 언어판에 같은 마크업이 들어간다(방향·드리프트는 각 행의 등락률과 일치).
   목업 수치를 바꾸면 그 스크립트의 SPECS 드리프트 부호도 함께 맞출 것. */
.spark-line {
  fill: none;
  stroke: var(--muted);
  stroke-width: 1.4;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}

/* 면은 선 아래를 아주 옅게만 채운다 — 금융 스파크라인의 관례이고, 선 하나보다
   추세의 방향이 먼저 읽힌다. currentColor로 두어 방향색 규칙 한 곳만 고치면 된다. */
/* ⚠️ 아래로 갈수록 사라지게 마스크를 건다 — 평면 채움은 바닥에서 딱 끊겨(직선 경계가
   그대로 보인다) 값싸 보인다. <defs>+linearGradient 20줄 대신 CSS 마스크 두 줄로 같은
   결과를 얻고, 색은 currentColor 하나로 계속 관리된다. */
.spark-area {
  fill: currentColor;
  opacity: 0.3;
  stroke: none;
  -webkit-mask-image: linear-gradient(to bottom, #000 8%, transparent 92%);
  mask-image: linear-gradient(to bottom, #000 8%, transparent 92%);
}

/* 끝점 = 최신값. 시선이 "지금 어디인지"에 먼저 닿게 하는 앵커. */
.spark-dot {
  fill: currentColor;
  stroke: none;
}

/* 앱과 동일하게 방향색으로 긋는다 — 회색(.spark 기본값)은 방향이 없는 행(신규 편입 등)만.
   color를 세팅하면 면·도트(currentColor)가 따라오고, 선만 따로 지정한다. */
.spark.up {
  color: var(--green);
}

.spark.down {
  color: var(--red);
}

.spark.up .spark-line {
  stroke: var(--green);
}

.spark.down .spark-line {
  stroke: var(--red);
}

.hr-pct {
  min-width: 34px;
  text-align: right;
  font-size: 10.5px;
  color: var(--text-2);
}

.badge {
  min-width: 40px;
  text-align: center;
  border-radius: 5px;
  padding: 2px 6px;
  font-size: 10.5px;
  font-weight: 700;
}

.badge-up {
  color: var(--green);
  background: rgba(43, 238, 52, 0.13);
}

.badge-down {
  color: var(--red);
  background: rgba(255, 92, 92, 0.13);
}

.badge-new {
  color: var(--accent);
  background: var(--accent-dim);
}

/* ---- 브리프 배너 행 (앱 BriefBanner 재현) ---- */

.brief-row {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 13px 18px;
  border-bottom: 1px solid var(--hairline);
}

/* 앱과 동일하게 accent 외곽선 칩 — 벨 종류(오프닝/클로징)를 나타내는 카테고리 라벨 */
.brief-tag {
  flex: none;
  border: 1px solid var(--accent);
  border-radius: 8px;
  padding: 1.5px 7px;
  font-size: 10.5px;
  font-weight: 700;
  color: var(--accent);
}

.brief-title {
  flex: 1;
  min-width: 0;
  font-size: 13.5px;
  font-weight: 700;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.brief-chev {
  flex: none;
  color: var(--muted);
  font-size: 15px;
  line-height: 1;
}

/* 브리프 본문의 마크다운 표 재현 (## 밤사이 미국장 → 지수/종가/전일 대비) */
.mini-head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 15px 18px 0;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-2);
}

.mini-head::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--hairline);
}

.mini-table {
  width: 100%;
  border-collapse: collapse;
  margin: 9px 0 4px;
}

/* 관전 포인트 · 주요 뉴스 — 앱 브리프의 실제 섹션 구성을 재현한다(오너 지시 2026-08-01).
   종전 목업은 지수 표만 보여줘, 브리프가 표 한 장짜리 산출물처럼 읽혔다.
   앱 brief 정본(supabase/functions/brief/index.ts)의 open 모드 순서를 그대로 따랐다:
   미국장 표 → 관전 포인트 → 주요 뉴스. 섹션 제목 문자열도 정본에서 가져왔다. */
.mini-list {
  margin: 9px 0 2px;
  padding: 0 18px;
  list-style: none;
}

.mini-list li {
  position: relative;
  padding-left: 11px;
  margin-bottom: 6px;
  font-size: 11.5px;
  line-height: 1.55;
  color: var(--text-2);
}

/* 불릿은 글머리 기호 대신 작은 사각 — 터미널 조판과 결이 같고, 줄바꿈 시 들여쓰기가
   흐트러지지 않는다(list-style은 마커 정렬을 브라우저가 제각각 처리한다). */
.mini-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 7.5px;
  width: 3px;
  height: 3px;
  background: var(--muted);
}

.mini-news {
  margin: 9px 0 2px;
  padding: 0 18px;
  list-style: none;
  counter-reset: mn;
}

.mini-news li {
  position: relative;
  padding-left: 17px;
  margin-bottom: 9px;
  counter-increment: mn;
}

.mini-news li::before {
  content: counter(mn);
  position: absolute;
  left: 0;
  top: 1px;
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 700;
  color: var(--accent);
}

.mn-title {
  font-size: 11.5px;
  font-weight: 600;
  line-height: 1.45;
  color: var(--text);
}

.mn-sum {
  margin-top: 2px;
  font-size: 10.5px;
  line-height: 1.5;
  color: var(--muted);
}

/* HARD RULE — 표시 출처는 언제나 원발행처다(집계원 금지). 목업도 같은 규칙을 따른다. */
.mn-pub {
  margin-right: 6px;
  font-size: 9.5px;
  letter-spacing: 0.1em;
  color: var(--text-2);
}

.mini-table th,
.mini-table td {
  padding: 6px 18px;
  text-align: right;
  font-size: 12.5px;
}

.mini-table th {
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--muted);
  border-bottom: 1px solid var(--hairline);
}

.mini-table th:first-child,
.mini-table td:first-child {
  text-align: left;
  color: var(--text-2);
}

.mini-table td {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  color: var(--text);
}

/* 등락 색은 여기서 다시 선언해야 한다 — `.mini-table td`(0,1,1)가 `.q-up`(0,1,0)을
   특이도로 이겨서, 클래스만 붙이면 색이 죽는다 */
.mini-table td.q-up {
  color: var(--green);
}

.mini-table td.q-down {
  color: var(--red);
}

/* ---- 리포트 행 (앱 ReportCard 재현) ---- */

.rep-row {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 14px 18px 15px;
  border-bottom: 1px solid var(--hairline);
}

.rep-top {
  display: flex;
  align-items: center;
  gap: 8px;
}

.rep-cat {
  border: 1px solid var(--accent);
  border-radius: 8px;
  padding: 1.5px 8px;
  font-size: 11px;
  font-weight: 700;
  color: var(--accent);
}

/* 최신 2편 외에는 Pro — 앱 ReportCard의 자물쇠 + PRO 배지.
   자물쇠는 이모지 대신 인라인 SVG(스파크라인과 같은 수법) — 이모지는 OS마다 색·형태가
   달라 모노 조판에서 튄다. currentColor를 물려받아 텍스트와 같은 톤으로 붙는다. */
.rep-pro {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 11px;
  font-weight: 700;
  color: var(--muted);
}

.rep-pro .lock {
  width: 11px;
  height: 11px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
}

.rep-title {
  font-size: 16px;
  font-weight: 800;
  line-height: 1.4;
  letter-spacing: -0.01em;
}

.rep-sum {
  font-size: 13px;
  line-height: 1.6;
  color: var(--text-2);
}

.rep-meta {
  font-size: 11.5px;
  color: var(--muted);
}

/* ---- 지표 행 (앱 IndicatorsScreen IndicatorRow 재현) ---- */
/* [이름 flex] [스파크라인 64×20] [값 mono + ▲/▼% — 폭 92 우측정렬 칼럼] */

.ind-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 18px;
  border-bottom: 1px solid var(--hairline);
}

.ind-name {
  flex: 1;
  min-width: 0;
  font-size: 13px;
  color: var(--text-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* 고정 폭 요소는 flex: none을 명시한다 — 안 하면 기본 shrink:1로 같이 찌그러진다 */
.spark-lg {
  flex: none;
  width: 64px;
  height: 20px;
}

.ind-val {
  flex: none;
  width: 92px;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  line-height: 1.25;
}

.ind-num {
  font-size: 15px;
  font-weight: 700;
}

.ind-pct {
  font-size: 11px;
  font-weight: 700;
}

/* ---- 캘린더 행 (앱 CalendarScreen renderEvent 재현) ---- */

.cal-day {
  padding: 15px 18px 4px;
  font-size: 13px;
  font-weight: 800;
  letter-spacing: 0.02em;
}

.cal-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 18px;
  border-bottom: 1px solid var(--hairline);
}

.cal-time {
  flex: none;
  width: 52px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}

.cal-hhmm {
  font-size: 13px;
  font-weight: 600;
}

/* 중요도 → 색 있는 느낌표 (앱 impactMark): high=!!! · medium=!! · low=! */
.cal-mark {
  font-size: 13px;
  font-weight: 900;
  letter-spacing: 1px;
}

.mark-high {
  color: var(--red);
}

.mark-mid {
  color: var(--urgent);
}

.mark-low {
  color: var(--green);
}

.cal-rule {
  flex: none;
  width: 1px;
  align-self: stretch;
  background: var(--hairline);
}

.cal-body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.cal-line {
  display: flex;
  align-items: flex-start;
  gap: 8px;
}

/* 카테고리는 전 종류가 오렌지 계열 — 앱 2026-07-03 피드백 반영분과 동일 */
.cal-cat {
  flex: none;
  margin-top: 3px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--urgent);
}

.cal-title {
  font-size: 14px;
  font-weight: 700;
  line-height: 1.35;
}

.cal-stats {
  font-size: 12px;
  color: var(--muted);
}

/* ---------------------------------------------------------------- footer */

.site-footer {
  border-top: 1px solid var(--hairline);
  margin-top: 104px;
  padding: 56px 0 48px;
}

/* 법무·피드백 페이지 푸터 — 종전엔 `.back-home` 하나뿐이라 약관에서 개인정보 처리방침으로
   가려면 홈을 거쳐야 했다. 법무 문서끼리 상호 링크는 관례다.
   index 푸터와 달리 면책·FRED 귀속문은 싣지 않는다(그 페이지들엔 해당 없는 문구다).
   폭은 본문(.doc 720px)에 맞춰 링크가 본문 왼쪽 끝과 정렬되게 한다. */
.doc-footer {
  margin-top: 0;
  padding: 28px 0 56px;
}

.doc-footer .container {
  max-width: 720px;
}

.footer-links .current {
  font-size: 13px;
  font-weight: 700;
  color: var(--text);
}

.disclaimer {
  max-width: 640px;
  margin: 0 auto;
  text-align: center;
  font-size: 12.5px;
  line-height: 1.7;
  color: var(--muted);
}

/* FRED 귀속문 — 카드 각주를 걷어내며 여기로 옮겼다(FRED 약관상 표기 필수). */
.fred-attr {
  max-width: 640px;
  margin: 10px auto 0;
  text-align: center;
  font-size: 11px;
  line-height: 1.6;
  color: var(--muted);
}

.footer-row {
  margin-top: 28px;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  border-top: 1px solid var(--hairline);
  padding-top: 24px;
}

.footer-links {
  display: flex;
  gap: 20px;
  flex-wrap: wrap;
}

.footer-links a {
  font-size: 13px;
  color: var(--text-2);
  transition: color 150ms var(--ease-out);
}

@media (hover: hover) and (pointer: fine) {
  .footer-links a:hover {
    color: var(--text);
  }
}

.footer-copy {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--muted);
}

/* -------------------------------------------------------------- doc pages */

.doc {
  max-width: 720px;
  margin: 0 auto;
  padding: 24px 24px 96px;
}

.doc-banner {
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: 10px;
  background: var(--surface);
  padding: 14px 18px;
  font-size: 13.5px;
  line-height: 1.65;
  color: var(--text-2);
  margin: 8px 0 40px;
}

.doc h1 {
  font-size: 27px;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.35;
  margin-top: 24px;
}

.doc .doc-meta {
  margin-top: 10px;
  font-family: var(--mono);
  font-size: 12.5px;
  color: var(--muted);
}

.doc h2 {
  font-size: 18px;
  font-weight: 700;
  letter-spacing: -0.01em;
  margin: 44px 0 0;
}

.doc h3 {
  font-size: 15px;
  font-weight: 700;
  color: var(--text);
  margin: 28px 0 0;
}

.doc p,
.doc li {
  font-size: 15px;
  line-height: 1.8;
  color: var(--prose);
}

.doc p {
  margin-top: 14px;
}

.doc ol,
.doc ul {
  margin-top: 14px;
  padding-left: 22px;
}

.doc li {
  margin-top: 6px;
}

.doc li::marker {
  color: var(--muted);
}

.doc strong {
  color: var(--text);
}

.doc table {
  width: 100%;
  margin-top: 16px;
  border-collapse: collapse;
  font-size: 13.5px;
  line-height: 1.6;
}

.doc th {
  text-align: left;
  font-weight: 600;
  color: var(--text-2);
  border-bottom: 1px solid var(--border);
  padding: 8px 12px 8px 0;
  white-space: nowrap;
}

.doc td {
  color: var(--prose);
  border-bottom: 1px solid var(--hairline);
  padding: 9px 12px 9px 0;
  vertical-align: top;
}

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

.doc .table-scroll table {
  min-width: 560px;
}

.doc hr {
  border: 0;
  border-top: 1px solid var(--hairline);
  margin: 44px 0 0;
}

.doc .addendum {
  margin-top: 20px;
  font-size: 14px;
  color: var(--muted);
}

.back-home {
  display: inline-block;
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.1em;
  color: var(--muted);
  margin-top: 48px;
  transition: color 150ms var(--ease-out);
}

@media (hover: hover) and (pointer: fine) {
  .back-home:hover {
    color: var(--accent);
  }
}

/* ------------------------------------------------------------ reveal (JS) */
/* 숨김 상태는 .js 스코프 — JS 미실행 환경에선 콘텐츠가 그냥 보인다 (점진적 향상) */

.reveal {
  transition: opacity 600ms var(--ease-out), transform 600ms var(--ease-out);
  transition-delay: var(--d, 0ms);
}

.js .reveal {
  opacity: 0;
  transform: translateY(12px);
}

.js .reveal.in {
  opacity: 1;
  transform: translateY(0);
}

/* ------------------------------------------------------------- responsive */

@media (max-width: 860px) {

  /* 데이터 행이 조밀해 2열로는 좁다 — 태블릿부터 이미 1열로 내린다 */
  .panel-grid {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 560px) {
  /* 히어로 압축 — 세로 640px대 기기에서 히어로가 화면을 통째로 먹어 제품 목업이 첫 화면에
     한 조각도 안 걸렸다(360×640 실측: 목업 시작 642px). 목업은 `.reveal` 관찰자
     (threshold 0.05 · rootMargin -60px)가 켜져야 보이므로 "조금 걸치기"로는 부족하고
     시작점을 552px(KO·ZH) / 544px(EN) 아래로 내려야 페이드인이 발동한다. */
  .hero {
    padding-top: 36px;
    padding-bottom: 36px;
  }

  /* 부제가 이미 "실시간 · AI"를 말하고 있어 모바일에선 중복이다. 데스크톱은 여백이 남아 유지. */
  .hero .sub-line {
    display: none;
  }

  .cta-row {
    margin-top: 24px;
  }

  /* 좁은 폭에선 항목 중간에서 접혀(EN 4줄) 지저분해진다 — 항목당 한 줄로 세운다 */
  .capabilities {
    flex-direction: column;
    align-items: center;
    gap: 7px;
  }


  .section {
    padding-top: 80px;
  }

  .site-footer {
    margin-top: 80px;
  }

  .feed-headline {
    font-size: 14.5px;
  }

  .band {
    margin-top: 80px;
  }

  .band .section {
    padding-top: 64px;
    padding-bottom: 56px;
  }

  /* 좁은 폭에서 거래 메타 4요소가 두 줄로 접히면 날짜의 auto 마진이 어색해진다 */
  .tr-date {
    margin-left: 0;
  }

  /* 스파크라인은 장식에 가깝고 여기서 폭을 가장 많이 먹는다 — 숫자를 살린다 */
  .spark {
    display: none;
  }

  /* 단, 지표 행의 스파크라인은 예외다 — 13F 보유 행(티커·발행사·평가액·비중·배지)과 달리
     지표 행은 [이름][스파크라인][값] 3단뿐이라 폭이 남고(360px에서 이름 칸 146px),
     추세선은 앱 IndicatorRow의 장식이 아닌 구성 요소다. */
  .ind-row .spark-lg {
    display: block;
  }
}

/* --------------------------------------------------------- reduced motion */

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  .tape-track {
    animation: none;
  }

  .tape-live .dot {
    animation: none;
  }

  .js .reveal {
    transform: none;
    transition: opacity 300ms ease;
  }
}
