:root {
  --bg: #050b0f;
  --cyan: #4ff2e8;
  --cyan-dim: #1b7f7a;
  --cyan-glow: rgba(79, 242, 232, 0.55);
  --panel-bg: rgba(6, 20, 24, 0.72);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  width: 100%;
  height: 100%;
  background: var(--bg);
  color: var(--cyan);
  font-family: "Consolas", "Courier New", monospace;
  overflow: hidden;
  -webkit-tap-highlight-color: transparent;
}

.hud-screen {
  position: fixed;
  inset: 0;
  display: flex;
  flex-direction: column;
}

/* [hidden] 속성이 .hud-screen의 display:flex보다 항상 이기도록 명시 */
.hud-screen[hidden] {
  display: none;
}

/* 배경 스캔라인 + 격자 장식 */
.scanlines {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: repeating-linear-gradient(
    to bottom,
    rgba(79, 242, 232, 0.035) 0px,
    rgba(79, 242, 232, 0.035) 1px,
    transparent 2px,
    transparent 4px
  );
  z-index: 5;
}

.grid-bg {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image:
    linear-gradient(rgba(79, 242, 232, 0.08) 1px, transparent 1px),
    linear-gradient(90deg, rgba(79, 242, 232, 0.08) 1px, transparent 1px);
  background-size: 34px 34px;
  z-index: 0;
}

/* 별처럼 흩뿌려진 작은 점들이 은은하게 깜빡임 — 배경에 깊이감을 더함(화면마다 .grid-bg 하나씩
   있어서 클래스 하나로 전 화면에 자동 적용됨). 좌표는 격자처럼 안 보이게 손으로 흩어놓음. */
.grid-bg::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    radial-gradient(1px 1px at 7% 18%, rgba(79, 242, 232, 0.9), transparent 60%),
    radial-gradient(1px 1px at 14% 63%, rgba(79, 242, 232, 0.6), transparent 60%),
    radial-gradient(1.5px 1.5px at 22% 41%, rgba(79, 242, 232, 0.8), transparent 60%),
    radial-gradient(1px 1px at 31% 82%, rgba(79, 242, 232, 0.5), transparent 60%),
    radial-gradient(1px 1px at 38% 12%, rgba(79, 242, 232, 0.7), transparent 60%),
    radial-gradient(1.5px 1.5px at 47% 55%, rgba(79, 242, 232, 0.9), transparent 60%),
    radial-gradient(1px 1px at 54% 27%, rgba(79, 242, 232, 0.5), transparent 60%),
    radial-gradient(1px 1px at 61% 76%, rgba(79, 242, 232, 0.7), transparent 60%),
    radial-gradient(1.5px 1.5px at 68% 9%, rgba(79, 242, 232, 0.6), transparent 60%),
    radial-gradient(1px 1px at 74% 48%, rgba(79, 242, 232, 0.9), transparent 60%),
    radial-gradient(1px 1px at 81% 88%, rgba(79, 242, 232, 0.5), transparent 60%),
    radial-gradient(1.5px 1.5px at 87% 33%, rgba(79, 242, 232, 0.8), transparent 60%),
    radial-gradient(1px 1px at 93% 64%, rgba(79, 242, 232, 0.6), transparent 60%),
    radial-gradient(1px 1px at 4% 92%, rgba(79, 242, 232, 0.7), transparent 60%),
    radial-gradient(1px 1px at 97% 15%, rgba(79, 242, 232, 0.5), transparent 60%);
  animation: star-twinkle 5s ease-in-out infinite;
}
@keyframes star-twinkle {
  0%, 100% { opacity: 0.4; }
  50% { opacity: 0.95; }
}


/* ---------- 로그인 화면 ---------- */
#login-screen {
  align-items: center;
  justify-content: center;
  background: radial-gradient(ellipse at center, #0a1a1e 0%, #030608 80%);
}

.login-box {
  position: relative;
  z-index: 10;
  border: 1px solid var(--cyan-dim);
  background: var(--panel-bg);
  padding: 40px 48px;
  text-align: center;
  box-shadow: 0 0 30px var(--cyan-glow);
  min-width: 280px;
}

.login-title {
  font-size: 22px;
  letter-spacing: 4px;
  text-shadow: 0 0 12px var(--cyan-glow);
  margin-bottom: 6px;
}

.login-sub {
  font-size: 11px;
  letter-spacing: 2px;
  color: var(--cyan-dim);
  margin-bottom: 24px;
}

#login-form { display: flex; flex-direction: column; gap: 14px; }

.login-box input,
.chat-form input {
  background: rgba(0, 0, 0, 0.4);
  border: 1px solid var(--cyan-dim);
  color: var(--cyan);
  padding: 10px 12px;
  font-family: inherit;
  font-size: 14px;
  letter-spacing: 2px;
  outline: none;
}

.login-box input:focus,
.chat-form input:focus {
  border-color: var(--cyan);
  box-shadow: 0 0 10px var(--cyan-glow);
}

.login-box button,
.chat-form button {
  background: transparent;
  border: 1px solid var(--cyan);
  color: var(--cyan);
  padding: 10px 12px;
  letter-spacing: 3px;
  cursor: pointer;
  font-family: inherit;
  transition: 0.15s;
}

.login-box button:hover,
.chat-form button:hover {
  background: var(--cyan);
  color: #04100f;
}

.login-error {
  margin-top: 12px;
  font-size: 12px;
  color: #ff5b5b;
  min-height: 16px;
}

/* ---------- 대시보드 ---------- */
.hud-header {
  position: relative;
  z-index: 6;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 14px 0 6px;
}

.hud-title {
  font-size: 16px;
  letter-spacing: 6px;
  text-shadow: 0 0 10px var(--cyan-glow);
}

.hud-clock {
  position: absolute;
  right: 24px;
  top: 16px;
  font-size: 12px;
  color: var(--cyan-dim);
}

/* PROTOCOL — 원형 오브 대신 제목 바로 아래 가운데에 놓는 텍스트 버튼(.nav-btn과 같은 톤) */
.protocol-btn {
  position: absolute;
  left: 50%;
  top: 42px;
  transform: translateX(-50%);
  z-index: 7;
  background: transparent;
  border: 1px solid var(--cyan-dim);
  color: var(--cyan);
  font-family: inherit;
  font-size: 10px;
  letter-spacing: 2px;
  padding: 5px 14px;
  border-radius: 2px;
  cursor: pointer;
  white-space: nowrap;
}
.protocol-btn:hover { background: var(--cyan); color: #04100f; }

.corner {
  position: absolute;
  width: 26px;
  height: 26px;
  border-color: var(--cyan);
  border-style: solid;
  z-index: 6;
  opacity: 0.85;
}
.corner-tl { top: 10px; left: 10px; border-width: 2px 0 0 2px; }
.corner-tr { top: 10px; right: 10px; border-width: 2px 2px 0 0; }
.corner-bl { bottom: 10px; left: 10px; border-width: 0 0 2px 2px; }
.corner-br { bottom: 10px; right: 10px; border-width: 0 2px 2px 0; }

.hud-main {
  position: relative;
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  /* 좌우 계기판이 CORE/SIGNAL 같은 오브 버튼과 겹쳐 보인다는 피드백(2026-08-04) — 그 버튼들이
     지구본(hud-center) 기준 -13~-19% 만큼 바깥으로 튀어나와 있어서 64px로도 부족했다. */
  gap: 130px;
  min-height: 0;
  z-index: 3;
}

.hud-side {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  width: 130px;
}
/* "우측은 더 위로, 좌측은 더 아래로"라는 피드백(2026-08-04) — hud-main이 기본적으로 좌우 카드를
   세로 중앙에 두길래, align-self로 각 칸을 hud-main 세로축의 위/아래 끝으로 밀어붙임. */
.hud-side-right { align-self: flex-start; margin-top: 26px; }
.hud-side-left { align-self: flex-end; margin-bottom: 26px; }


/* 아이언맨 자비스 HUD 참고 이미지의 우측 하단 "로그가 계속 타이핑되는" 연출(2026-08-04) — 실제
   로그가 아니라 순수 장식이라 aria-hidden 처리. "움직이는 느낌이 없다, 노출을 훨씬 많이"라는
   피드백으로 한 줄만 썼다 지우던 방식에서 여러 줄이 콘솔처럼 계속 쌓이며 스크롤되는 방식으로
   교체 — 줄 수/속도/불투명도를 전부 올려서 항상 뭔가 타이핑되고 있는 게 눈에 띄게 함.
   문구 목록/타이핑 로직은 app.js의 typeHudLogLine()에 있음. */
.hud-log {
  width: 100%;
  min-height: 58px;
  padding: 2px 0;
  text-align: right;
  font-size: 9px;
  letter-spacing: 0.5px;
  color: var(--cyan-dim);
  opacity: 0.8;
  overflow: hidden;
}
/* "타이핑을 훨씬 많이 보여달라"는 반복된 피드백(2026-08-04)으로 줄 수/높이/불투명도를 한 번 더
   올린 버전 — 좌우 양쪽 모두에 이 크기로 적용한다. */
.hud-log-tall {
  min-height: 150px;
  opacity: 0.95;
}
.hud-side-left .hud-log {
  text-align: left;
}
/* "우측 코드가 명령어만 있는거 같다"는 피드백(2026-08-04) — 실제 함수 시그니처/조건문처럼 보이게
   문구 자체를 길게 바꿨는데, 130px 폭에서는 줄바꿈 없이 다 못 보여줘서 패널 폭을 넓히고
   왼쪽 정렬로 바꿈(코드는 오른쪽 정렬보다 왼쪽 정렬이 자연스러움). */
.hud-log-code {
  width: 190px;
  text-align: left;
}
.hud-log-lines {
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.hud-log-row {
  white-space: nowrap;
}
.hud-log-caret {
  display: inline-block;
  margin-left: 2px;
  animation: hud-log-cursor 0.9s steps(1) infinite;
}
@keyframes hud-log-cursor {
  0%, 49% { opacity: 1; }
  50%, 100% { opacity: 0; }
}

.hud-center {
  position: relative;
  width: min(46vh, 46vw);
  height: min(46vh, 46vw);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: width 0.25s ease, height 0.25s ease;
  cursor: grab;
  touch-action: pan-y;
}
.hud-center.dragging { cursor: grabbing; }

/* 지구본 주변 버튼이 늘어나면서(신규 업무 허브 4개) 자리가 부족해져, 클릭 위치(1/2/3/6시)를
   재사용하는 2페이지 구조로 나눴다 — 지구본을 드래그/스와이프하면 페이지가 바뀐다. 이 점들은
   지금 몇 페이지인지 보여주고, 클릭해서 바로 이동할 수도 있게 한다. */
.hud-page-dots {
  position: absolute;
  left: 50%;
  /* 6시 방향 FORECAST 버튼(bottom:-9%)이 지구본 테두리보다 훨씬 아래까지 내려와 있어서,
     처음 값(-22px)으로는 겹쳤다(Playwright 실측 확인, 2026-08-25). FORECAST의 실제 바닥
     끝보다 넉넉히 더 아래로 내린다. */
  bottom: -70px;
  transform: translateX(-50%);
  display: flex;
  gap: 8px;
  z-index: 10;
}
.hud-page-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  border: 1px solid var(--cyan-dim);
  background: transparent;
  padding: 0;
  cursor: pointer;
  transition: 0.2s;
}
.hud-page-dot.active { background: var(--cyan); border-color: var(--cyan); box-shadow: 0 0 6px var(--cyan-glow); }

/* .info-orb/.gauge/.mini-bars 등이 각자 display:flex 등을 지정해서, 브라우저 기본 [hidden]{display:none}
   보다 author 스타일이 우선 적용돼(hidden 속성 자체의 낮은 명시도 문제가 아니라 UA/author 우선순위
   문제) hidden="" 이 걸려도 안 사라지고 클릭까지 먹는 버그가 있었다(Playwright로 실측 확인,
   2026-08-25 — 겉보기엔 사라진 듯해도 같은 자리 페이지1 버튼 클릭이 안 눌렸음). 페이지 전환용
   버튼은 이 규칙으로 확실히 숨긴다. */
[data-orb-page][hidden] { display: none !important; }

/* 페이지 전환 시 버튼이 흩어지며 사라지고, 새 버튼이 흩어진 상태에서 제자리로 모여드는
   애니메이션(2026-08-25, 사용자 요청). app.js가 전환 순간에 .orb-scatter를 붙였다 떼면서
   흩어진 상태 ↔ 제자리 상태를 전환한다 — 방향은 각 버튼 자신의 시계 위치에서 바깥쪽으로
   향하게 JS가 --scatter-x/--scatter-y를 미리 계산해 인라인으로 넣어둔다(버튼마다 달라야
   자연스러워서 고정값 하나로는 안 됨). */
[data-orb-page] {
  transition: transform 0.32s cubic-bezier(0.34, 1.56, 0.64, 1), opacity 0.26s ease;
}
[data-orb-page].orb-scatter {
  /* translate를 scale보다 먼저 적용해야(오른쪽에 써야) 축소율(0.15)에 밀려 이동거리가
     같이 줄어들지 않는다 — scale이 먼저면 5.4px밖에 안 움직여서 실측 확인해보니 거의
     티가 안 났다(2026-08-25, translate 36px가 5.4px로 줄어든 걸 getComputedStyle로 확인). */
  transform: translate(var(--scatter-x, 0px), var(--scatter-y, 0px)) scale(0.15);
  opacity: 0;
}

/* 채팅 결과가 쌓여 하단 채팅창이 커지면 hud-main의 세로 여백이 줄어드는데, hud-center는 vh 기준
   고정 크기라 그만큼 줄어들지 않아 위쪽 헤더(PROTOCOL)와 12시 방향 오브(USAGE)가 겹쳤다(실측 확인).
   결과가 있을 때는 지구본을 더 작게 줘서 항상 헤더 아래로 여유 있게 들어오게 한다. */
#dashboard.has-chatted .hud-center {
  width: min(30vh, 34vw);
  height: min(30vh, 34vw);
}

/* 지구본이 작아질 때 둘레 버튼들도 같이 작아지게 — 버튼 위치는 hud-center 기준 %라 이미
   따라 오지만, 버튼 자체 크기(px 고정)는 안 줄어들어서 작아진 원 대비 버튼만 커 보였다
   (실측 확인). 위치 이동과 자연스럽게 맞물리도록 트랜지션도 같이 건다. */
#dashboard.has-chatted .info-orb { width: 44px; height: 44px; }
#dashboard.has-chatted .info-orb-pictogram .orb-icon { width: 22px; height: 19px; }
#dashboard.has-chatted .info-orb-pictogram .orb-icon-signal { width: 25px; }
#dashboard.has-chatted .gauge { width: 50px; height: 50px; }
#dashboard.has-chatted .gauge-label { font-size: 9px; }
#dashboard.has-chatted .radar { width: 30px; height: 30px; }
#dashboard.has-chatted .mini-bars { height: 25px; gap: 4px; }
#dashboard.has-chatted .mini-bars span { width: 4px; }

#globe {
  width: 100%;
  height: 100%;
}

.globe-ring {
  position: absolute;
  border: 1px solid var(--cyan-dim);
  border-radius: 50%;
  pointer-events: none;
}
.globe-ring-1 { inset: -18px; animation: spin 18s linear infinite; border-style: dashed; }
.globe-ring-2 { inset: -34px; animation: spin 30s linear infinite reverse; opacity: 0.5; }
.globe-ring-3 { inset: -48px; animation: spin 46s linear infinite; opacity: 0.3; border-style: dotted; }

@keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }

/* 화면 여기저기서 레이더에 뭔가 잡힌 것처럼 은은하게 핑(ping)하는 점들 — 배경이 계속
   살아있다는 느낌을 주는 장식용 요소 (클릭 불가, 실제 데이터와 무관) */
.radar-blip {
  position: absolute;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--cyan);
  box-shadow: 0 0 6px var(--cyan-glow);
  pointer-events: none;
  z-index: 2;
  animation: blip-ping 3.6s ease-out infinite;
}
@keyframes blip-ping {
  0% { opacity: 0.9; box-shadow: 0 0 4px var(--cyan-glow); }
  70% { opacity: 0; box-shadow: 0 0 16px 10px transparent; }
  100% { opacity: 0; }
}

/* 지구본 뒤로 은은하게 숨쉬는 광원 — 배경에 깊이감을 더함 */
.hud-center::before {
  content: "";
  position: absolute;
  inset: -25%;
  background: radial-gradient(circle, var(--cyan-glow) 0%, transparent 65%);
  opacity: 0.1;
  z-index: -1;
  pointer-events: none;
  animation: glow-breathe 4.5s ease-in-out infinite;
}
@keyframes glow-breathe {
  0%, 100% { opacity: 0.07; }
  50% { opacity: 0.18; }
}

/* 지구본 옆의 Protocol(에이전트 규칙 안내) 진입 버튼 (원형) */
/* PROTOCOL 버튼: 사이드 컬럼에 들어가는 작은 원형 버튼 */
.info-orb {
  width: 60px;
  height: 60px;
  border-radius: 50%;
  border: 1px solid var(--cyan-dim);
  background: rgba(6, 20, 24, 0.65);
  color: var(--cyan);
  font-family: inherit;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  text-align: center;
  padding: 4px;
  transition: width 0.25s ease, height 0.25s ease, color 0.4s ease, border-color 0.4s ease, box-shadow 0.4s ease;
}
.info-orb-label {
  font-size: 8px;
  letter-spacing: 1px;
  text-shadow: 0 0 6px var(--cyan-glow);
}
.info-orb-label .label-short { display: none; }

/* 버튼 안에 들어가는 작은 애니메이션 아이콘 (NEWS 게이지/DAU 바 차트와 톤을 맞춤) */
.orb-icon { width: 22px; height: 20px; overflow: visible; }

/* 텍스트 라벨 없이 아이콘만으로 읽히는 픽토그램 버튼 (radar/mini-bars와 같은 방식) —
   라벨이 빠진 만큼 아이콘을 키워서 원 안에서 존재감 있게 보이도록 한다. */
.info-orb-pictogram { gap: 0; }
.info-orb-pictogram .orb-icon { width: 30px; height: 26px; }
.info-orb-pictogram .orb-icon-signal { width: 34px; }

/* ANALYTICS — 도넛형 링이 채워졌다 비워지길 반복 (옆의 GA/DAU 막대그래프 버튼과 겹치지 않게
   막대 대신 원형 차트 느낌으로) */
.orb-icon-pie { transform: rotate(-90deg); }
.orb-icon-pie .pie-track { fill: none; stroke: rgba(79, 242, 232, 0.15); stroke-width: 2.4; }
.orb-icon-pie .pie-fill {
  fill: none;
  stroke: var(--cyan);
  stroke-width: 2.4;
  stroke-linecap: round;
  stroke-dasharray: 56.5;
  stroke-dashoffset: 56.5;
  filter: drop-shadow(0 0 3px var(--cyan-glow));
  animation: pie-fill 2.4s ease-in-out infinite;
}
@keyframes pie-fill {
  0% { stroke-dashoffset: 56.5; }
  50% { stroke-dashoffset: 14; }
  100% { stroke-dashoffset: 56.5; }
}

/* CORE — 중심점에서 링이 계속 퍼져나가는 펄스(레이더 핑 느낌) */
.orb-icon-core { overflow: visible; }
.orb-icon-core .core-dot { fill: var(--cyan); filter: drop-shadow(0 0 3px var(--cyan-glow)); }
.orb-icon-core .core-ring {
  fill: none;
  stroke: var(--cyan);
  stroke-width: 1;
  opacity: 0;
  transform-origin: 12px 12px;
  animation: core-pulse 2.2s ease-out infinite;
}
.orb-icon-core .core-ring-2 { animation-delay: 1.1s; }
@keyframes core-pulse {
  0% { opacity: 0.9; transform: scale(0.5); }
  100% { opacity: 0; transform: scale(1.6); }
}

/* SIGNAL — 모니터 화면 안에서 파형이 그려졌다 사라지길 반복 (SIGNAL 화면 제목이 "MARKET
   MONITOR"라 모니터 프레임 모양으로 — 프레임은 고정, 안의 파형만 애니메이션) */
.orb-icon-signal {
  fill: none;
  stroke: var(--cyan);
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.orb-icon-signal .signal-screen,
.orb-icon-signal .signal-stand {
  stroke: var(--cyan-dim);
}
.orb-icon-signal .signal-wave {
  stroke: var(--cyan);
  filter: drop-shadow(0 0 3px var(--cyan-glow));
  stroke-dasharray: 20;
  stroke-dashoffset: 20;
  animation: signal-draw 2s linear infinite;
}
@keyframes signal-draw {
  0% { stroke-dashoffset: 20; }
  55% { stroke-dashoffset: 0; }
  100% { stroke-dashoffset: -20; }
}

/* 광고 — 메가폰 모양, 음파 부분만 은은하게 깜빡임 */
.orb-icon-ad {
  fill: none;
  stroke: var(--cyan);
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.orb-icon-ad .ad-horn { stroke: var(--cyan-dim); }
.orb-icon-ad .ad-wave {
  stroke: var(--cyan);
  filter: drop-shadow(0 0 3px var(--cyan-glow));
  animation: ad-wave-pulse 1.8s ease-in-out infinite;
}
@keyframes ad-wave-pulse {
  0%, 100% { opacity: 0.3; }
  50% { opacity: 1; }
}

/* 금리 전망 — 상승 추세선 + 화살표, 선이 그려지는 효과(SIGNAL의 signal-draw와 같은 방식) */
.orb-icon-forecast {
  fill: none;
  stroke: var(--cyan);
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.orb-icon-forecast .forecast-line {
  stroke-dasharray: 24;
  stroke-dashoffset: 24;
  animation: forecast-draw 2.4s linear infinite;
}
.orb-icon-forecast .forecast-arrow {
  stroke: var(--cyan-dim);
}
@keyframes forecast-draw {
  0% { stroke-dashoffset: 24; }
  60% { stroke-dashoffset: 0; }
  100% { stroke-dashoffset: -24; }
}

/* TREND — 돋보기(검색) 안에서 트렌드 선이 은은하게 떠오르듯 움직임. "Search Trend" 화면이라
   검색 아이콘 쪽이 화살표보다 더 직관적이라는 피드백으로 교체 — 렌즈/손잡이는 고정, 안의
   파형만 애니메이션 */
.orb-icon-search {
  fill: none;
  stroke: var(--cyan);
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.orb-icon-search .search-lens,
.orb-icon-search .search-handle {
  stroke: var(--cyan-dim);
}
.orb-icon-search .search-wave {
  stroke: var(--cyan);
  filter: drop-shadow(0 0 3px var(--cyan-glow));
  animation: trend-float 1.8s ease-in-out infinite;
}
@keyframes trend-float {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-1.5px); }
}

.info-orb:hover {
  border-color: var(--cyan);
  color: var(--cyan);
  animation: orb-pulse 2.4s ease-in-out infinite;
}
@keyframes orb-pulse {
  0%, 100% { box-shadow: 0 0 6px rgba(79, 242, 232, 0.35); }
  50% { box-shadow: 0 0 20px rgba(79, 242, 232, 0.95); }
}

/* 채팅 답변이 시각화 가능한 지표를 다뤘을 때, 호버 없이도 계속 반짝이며 활성화됨을 표시 */
.info-orb.is-ready {
  border-color: var(--cyan);
  color: var(--cyan);
  animation: orb-pulse 1.6s ease-in-out infinite;
}

/* 클릭 가능한 HUD 원형 위젯 공통 리셋 (버튼 기본 스타일 제거) */
.gauge, .radar {
  background: transparent;
  padding: 0;
  font: inherit;
  color: inherit;
  cursor: pointer;
  transition: filter 0.2s ease, width 0.25s ease, height 0.25s ease;
}
.gauge:hover, .radar:hover {
  filter: brightness(1.35);
}

/* 원형 게이지 — 84px가 다른 오브(60px)보다 지나치게 커서 68px로 줄임(2026-08-04) */
.gauge { position: relative; width: 68px; height: 68px; border: none; }

.gauge svg { width: 100%; height: 100%; transform: rotate(-90deg); }
.gauge-track { fill: none; stroke: rgba(79, 242, 232, 0.15); stroke-width: 6; }
.gauge-fill {
  fill: none;
  stroke: var(--cyan);
  stroke-width: 6;
  stroke-linecap: round;
  stroke-dasharray: 264;
  stroke-dashoffset: 180;
  filter: drop-shadow(0 0 4px var(--cyan-glow));
  transition: stroke-dashoffset 0.6s ease;
}
.gauge-label {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  letter-spacing: 2px;
}

.mini-bars {
  display: flex;
  gap: 5px;
  align-items: flex-end;
  height: 33px;
  background: transparent;
  border: none;
  padding: 0;
  cursor: pointer;
  transition: filter 0.2s ease, height 0.25s ease, gap 0.25s ease;
}
.mini-bars:hover { filter: brightness(1.35); }
.mini-bars span {
  width: 5px;
  background: var(--cyan);
  opacity: 0.7;
  animation: bar-bounce 1.4s ease-in-out infinite;
  box-shadow: 0 0 4px var(--cyan-glow);
}
.mini-bars span:nth-child(1) { height: 30%; animation-delay: 0s; }
.mini-bars span:nth-child(2) { height: 70%; animation-delay: 0.15s; }
.mini-bars span:nth-child(3) { height: 45%; animation-delay: 0.3s; }
.mini-bars span:nth-child(4) { height: 90%; animation-delay: 0.45s; }
.mini-bars span:nth-child(5) { height: 55%; animation-delay: 0.6s; }
.mini-bars span:nth-child(6) { height: 35%; animation-delay: 0.75s; }
@keyframes bar-bounce { 0%, 100% { transform: scaleY(0.6); } 50% { transform: scaleY(1); } }

.radar {
  width: 40px;
  height: 40px;
  border: 1px solid var(--cyan-dim);
  border-radius: 50%;
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}
.radar-sweep {
  position: absolute;
  inset: 0;
  background: conic-gradient(from 0deg, var(--cyan-glow), transparent 30%);
  animation: spin 2.4s linear infinite;
}
.radar-icon {
  position: relative;
  width: 46%;
  height: 46%;
  fill: var(--cyan);
  filter: drop-shadow(0 0 3px var(--cyan-glow));
  pointer-events: none;
}

/* 지구본 옆에 원형 위젯을 겹쳐 놓기 위한 위치 지정 (현재는 NET 게이지가 사용).
   .gauge/.radar가 자체적으로 position:relative를 갖고 있어서, 이 규칙이 반드시
   그 뒤에(소스 순서상 나중에) 와야 이긴다 — 순서를 바꾸지 말 것.
   모든 오프셋은 px가 아니라 %(hud-center 크기 기준)로 준다 — 채팅 결과가 쌓여 지구본이 작아질 때
   (has-chatted) px 고정값은 안 줄어들어서 버튼이 테두리 안쪽으로 들어가 보이는 문제가 있었다
   (실측 확인). %는 부모(hud-center) 크기에 비례해 자동으로 같이 줄어든다. */
.orb-position {
  position: absolute;
  right: -3.8%;
  bottom: 0.54%;
  z-index: 6;
}

/* 큰 원(지구본) 기준 7시 방향 (아래쪽으로 살짝 치우친 왼쪽) */
.orb-position-7oc {
  position: absolute;
  left: -1.63%;
  bottom: -3.8%;
  z-index: 6;
}

/* 큰 원(지구본) 기준 1시 방향, 원 테두리에 걸치는 정도로 — CORE (SIGNAL(2oc)과 너무 붙어 보여서
   기존보다 위·왼쪽으로 옮기되, 원 밖으로 완전히 벗어나지는 않게 함) */
.orb-position-1oc {
  position: absolute;
  top: -8.7%;
  right: 3.8%;
  z-index: 6;
}

/* 큰 원(지구본) 기준 12시에 가깝게 — NEWS (원래 10시 방향이었는데 더 위·중앙 쪽으로 이동, 2026-08-04) */
.orb-position-10oc {
  position: absolute;
  top: -9%;
  left: 0%;
  z-index: 6;
}

/* 큰 원(지구본) 기준 9시에서 7시 쪽으로 더 내림(정왼쪽 → 왼쪽 아래) — GA/그래프(미니바), 2026-08-04 */
.orb-position-9oc {
  position: absolute;
  left: -16%;
  top: 72%;
  transform: translateY(-50%);
  z-index: 6;
}

/* 큰 원(지구본) 기준 3시 방향(정오른쪽) — ANALYTICS */
.orb-position-3oc {
  position: absolute;
  right: -19.02%;
  top: 61%;
  transform: translateY(-50%);
  z-index: 6;
}

/* 큰 원(지구본) 기준 2시 방향 (1시와 3시의 ANALYTICS 사이) — 지금은 안 쓰지만 자리는 남겨둠 */
.orb-position-2oc {
  position: absolute;
  top: 22.5%;
  right: -13.04%;
  z-index: 6;
}

/* 큰 원(지구본) 기준 11시 방향, 광고 — 처음엔 CORE(1oc)와 대칭으로 뒀다가 NEWS(10oc)와 겹쳐서
   중앙 쪽으로 밀었더니 이번엔 테두리에서 떨어져 나머지 버튼들과 안 어울려 보인다는 피드백이
   있었다(2026-08-04). 그래서 반대쪽의 SIGNAL(2oc: top:22.5%, right:-13.04%)과 정확히 대칭되는
   값으로 바꿨다 — 오른쪽에서 이미 검증된 "테두리에 걸치는" 거리(-13.04%)를 그대로 왼쪽에 쓰고,
   top도 2oc와 동일하게 둬서 NEWS(top:-2.17%)와 mini-bars/DAU(top:50%) 사이 빈 자리에 자연스럽게
   들어가게 한다. */
.orb-position-11oc {
  position: absolute;
  top: 22.5%;
  left: -13.04%;
  z-index: 6;
}

/* 큰 원(지구본) 기준 6시 방향(정중앙 아래) — FORECAST, 2026-08-06 추가. 다른 버튼들이 이미
   1/2/3/7/9/10/11시와 5시 근처(orb-position 기본값)를 다 쓰고 있어 비어있는 6시로 넣는다. */
.orb-position-6oc {
  position: absolute;
  bottom: -9%;
  left: 50%;
  transform: translateX(-50%);
  z-index: 6;
}

/* TREND 버튼 + 그 밑 hex 표시를 한 덩어리로 묶어서, hex가 버튼 폭 기준
   정중앙 아래에 오게 한다. */
.net-cluster {
  display: flex;
  flex-direction: column;
  align-items: center;
}
.net-below { margin-top: 6px; }

.hex-readout {
  font-size: 12px;
  letter-spacing: 2px;
  color: var(--cyan-dim);
}

/* 로그아웃 버튼 (자물쇠 아이콘, 좌측 상단 — 실수로 누르기 쉬운 위치를 피함) */
.lock-btn {
  position: absolute;
  left: 44px;
  top: 12px;
  z-index: 7;
  width: 30px;
  height: 30px;
  border: 1px solid var(--cyan-dim);
  border-radius: 50%;
  background: rgba(6, 20, 24, 0.5);
  color: var(--cyan-dim);
  padding: 0;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: color 0.2s ease, border-color 0.2s ease;
}
.lock-btn:hover { color: var(--cyan); border-color: var(--cyan); }
.lock-btn svg {
  width: 15px;
  height: 15px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* 등록자료 버튼 — 로그아웃 버튼 바로 오른쪽에 나란히 배치 */
.register-shortcut-btn { left: 84px; }

@media (max-width: 640px) {
  /* 이 파일 뒤쪽(모바일 헤더 조정 구간)에 .lock-btn { left: 16px; ... }가 따로 있는데, 이 버튼은
     class="lock-btn register-shortcut-btn"라 두 규칙이 동시에 걸린다. 우선순위(specificity)가
     같은 단일 클래스라 소스 순서상 뒤에 있는 .lock-btn이 이겨서 로그아웃 버튼과 같은 자리(16px)로
     겹쳐버리는 문제가 실제로 있었다(2026-08-03, 모바일 실기기 확인) — 그래서 두 클래스를 합친
     선택자로 우선순위를 확실히 높여, 파일 순서와 무관하게 이 위치가 항상 이기게 한다. 새 버튼을
     헤더에 추가할 때는 항상 이 compound 선택자 패턴을 따를 것. */
  .lock-btn.register-shortcut-btn { left: 46px; top: 15px; width: 22px; height: 22px; }
  .lock-btn.register-shortcut-btn svg { width: 11px; height: 11px; }
}

/* ---------- 하단 티커 바 (메인 화면이 정적으로 느껴진다는 피드백, 2026-08-04 —
   DAU/금리/뉴스/검색트렌드 같은 실제 데이터가 계속 흘러가면서 "살아있는" 느낌을 준다) ---------- */
.hud-ticker {
  position: relative;
  z-index: 5;
  width: min(720px, 92vw);
  /* PROTOCOL 버튼(헤더 안, top:42px 절대위치)이 헤더의 일반 흐름 높이보다 아래로 튀어나와 있어서,
     티커를 헤더 바로 다음(일반 흐름)에 놓으면 PROTOCOL과 겹쳐 보였다(2026-08-04) — 위 여백을
     넉넉히 줘서 PROTOCOL 아래로 확실히 내린다. */
  margin: 50px auto 8px;
  height: 26px;
  overflow: hidden;
  border-top: 1px solid var(--cyan-dim);
  border-bottom: 1px solid var(--cyan-dim);
  background: rgba(6, 20, 24, 0.5);
  mask-image: linear-gradient(to right, transparent, #000 6%, #000 94%, transparent);
  -webkit-mask-image: linear-gradient(to right, transparent, #000 6%, #000 94%, transparent);
}
.hud-ticker-track {
  display: flex;
  width: max-content;
  height: 100%;
  animation: hud-ticker-scroll 45s linear infinite;
}
.hud-ticker-track:hover { animation-play-state: paused; }
.hud-ticker-content {
  display: flex;
  align-items: center;
  gap: 28px;
  padding-right: 28px;
  white-space: nowrap;
  font-size: 11px;
  letter-spacing: 0.3px;
  color: var(--cyan-dim);
}
.hud-ticker-content .ticker-sep { color: var(--viz-gridline); }
.hud-ticker-content .ticker-up { color: #4fd67a; }
.hud-ticker-content .ticker-down { color: #e2543f; }
/* 콘텐츠를 통째로 두 번 반복해두고 정확히 절반(-50%)만큼 왼쪽으로 이동시키면, 두 번째 사본이
   첫 번째가 있던 자리를 그대로 이어받아서 끊김 없이 무한 반복되는 것처럼 보인다(고전적인 마퀴 기법). */
@keyframes hud-ticker-scroll {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}

@media (max-width: 640px) {
  .hud-ticker { width: 94vw; height: 22px; }
  .hud-ticker-content { font-size: 10px; gap: 20px; padding-right: 20px; }
}

/* ---------- 채팅 패널 ---------- */
.chat-panel {
  position: relative;
  z-index: 6;
  margin: 0 auto 16px;
  width: min(720px, 92vw);
  max-height: 34vh;
  display: flex;
  flex-direction: column;
  border: 1px solid var(--cyan-dim);
  background: var(--panel-bg);
  box-shadow: 0 0 24px var(--cyan-glow);
}

.chat-log {
  flex: 1;
  overflow-y: auto;
  padding: 12px 14px;
  font-size: 13px;
  line-height: 1.5;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.chat-msg { max-width: 90%; white-space: pre-wrap; }
.chat-msg.user { align-self: flex-end; color: #fff; opacity: 0.9; }
.chat-msg.bot { align-self: flex-start; color: var(--cyan); text-shadow: 0 0 6px var(--cyan-glow); }
.chat-msg.pending { color: var(--cyan-dim); font-style: italic; }

/* 답변 속 파일 링크 — 브라우저 기본 파란 밑줄 대신 본문 톤에 맞춘 은은한 스타일 */
.chat-msg a {
  color: inherit;
  text-decoration: underline;
  text-decoration-color: var(--cyan-dim);
  text-underline-offset: 2px;
  text-shadow: none;
}
.chat-msg a:hover { text-decoration-color: var(--cyan); }

.chat-form {
  display: flex;
  border-top: 1px solid var(--cyan-dim);
}
.chat-form input { flex: 1; border: none; border-radius: 0; }
.chat-form button { border: none; border-left: 1px solid var(--cyan-dim); }

.chat-attach-btn {
  flex: 0 0 auto;
  font-size: 16px;
  padding: 10px 12px !important;
}

/* 첨부한 파일이 있을 때 입력창 바로 위에 뜨는 작은 칩 */

.chat-attachment-chip {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px;
  border-top: 1px solid var(--cyan-dim);
  background: rgba(79, 242, 232, 0.06);
  color: var(--cyan);
  font-size: 12px;
}
.chat-attachment-chip[hidden] { display: none; }
#chat-attachment-name { flex: 1; overflow-wrap: anywhere; }
#chat-attachment-remove {
  background: transparent;
  border: 1px solid var(--cyan-dim);
  color: var(--cyan);
  font-size: 14px;
  line-height: 1;
  width: 20px;
  height: 20px;
  cursor: pointer;
  border-radius: 2px;
}
#chat-attachment-remove:hover { background: var(--cyan); color: #04100f; }

/* ---------- 상태 모달 ---------- */
.status-overlay {
  position: fixed;
  inset: 0;
  z-index: 30;
  background: rgba(2, 6, 8, 0.75);
  display: flex;
  align-items: center;
  justify-content: center;
}
.status-overlay[hidden] { display: none; }

.status-box {
  width: min(360px, 88vw);
  border: 1px solid var(--cyan-dim);
  background: var(--panel-bg);
  box-shadow: 0 0 30px var(--cyan-glow);
  padding: 24px;
  text-align: center;
}
.status-title {
  font-size: 14px;
  letter-spacing: 4px;
  text-shadow: 0 0 10px var(--cyan-glow);
  margin-bottom: 18px;
}
.status-rows { display: flex; flex-direction: column; gap: 12px; margin-bottom: 20px; }
.status-row {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 12px;
  text-align: left;
}
.status-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--cyan-dim);
  flex-shrink: 0;
}
.status-row.ok .status-dot { background: #3ee06a; box-shadow: 0 0 6px #3ee06a; }
.status-row.error .status-dot { background: #ff5b5b; box-shadow: 0 0 6px #ff5b5b; }
.status-name { width: 60px; letter-spacing: 1px; flex-shrink: 0; }
.status-detail { color: var(--cyan-dim); font-size: 11px; overflow-wrap: anywhere; }
.status-close-btn { position: static; }

/* 레이더 새로고침 등 순간적인 피드백용 */
.flash-feedback { animation: flash-once 0.7s ease; }
@keyframes flash-once {
  0% { box-shadow: 0 0 0 rgba(79, 242, 232, 0); }
  40% { box-shadow: 0 0 26px rgba(79, 242, 232, 1); }
  100% { box-shadow: 0 0 0 rgba(79, 242, 232, 0); }
}

/* ---------- 분석 화면 ---------- */
.nav-btn {
  position: absolute;
  right: 70px;
  top: 14px;
  z-index: 7;
  background: transparent;
  border: 1px solid var(--cyan-dim);
  color: var(--cyan);
  font-family: inherit;
  font-size: 11px;
  letter-spacing: 2px;
  padding: 6px 12px;
  cursor: pointer;
}
.nav-btn:hover { background: var(--cyan); color: #04100f; }

/* HUD 버튼 왼쪽에 나란히 놓는 아이콘 전용 버전 — 헤더는 콘텐츠 카드와 달리 스크롤이 안 되는
   고정 영역이라, 카드 테두리와 겹칠 걱정 없이 놓을 수 있는 자리다(2026-08-13, 카드 위에 떠
   있던 깔때기 버튼이 테두리와 겹쳐 보인다는 지적으로 헤더 쪽으로 옮김).
   선택자를 ".nav-btn.nav-btn-icon"(복합 선택자)로 써서 일부러 우선순위를 ".nav-btn" 단독
   선택자보다 높여둔다 — 아래 모바일 미디어쿼리의 ".nav-btn { right: 44px; ... }"가 소스 순서상
   더 뒤에 있어서, 단일 클래스 선택자끼리는 이 규칙이 이겨버려 깔때기/별 버튼이 HUD 버튼과
   똑같은 자리로 겹쳐버리는 문제가 있었다(모바일 실기기 확인 2026-08-14) — .lock-btn.register-
   shortcut-btn과 같은 이유, 같은 해법(아래 참고). */
.nav-btn.nav-btn-icon {
  right: 140px;
  width: 30px;
  height: 30px;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
.nav-btn-icon svg { width: 16px; height: 16px; fill: currentColor; }
/* nav-btn-icon 두 번째 자리 — 같은 헤더에 아이콘 버튼이 여러 개일 때 겹치지 않게 하나 더 왼쪽에 둔다. */
.nav-btn.nav-btn-icon-2 { right: 180px; }
/* 세 번째 자리(2026-08-20, COUPON 대시보드 버튼 추가) — 반드시 .nav-btn과 합친 복합 선택자를
   써야 한다(register-shortcut-btn/.nav-btn-icon에서 두 번 났던 것과 같은 겹침 버그, 위 주석 참고). */
.nav-btn.nav-btn-icon-3 { right: 220px; }
/* CROSS-SELL 버튼은 처음엔 여기(ANALYTICS 헤더) 네 번째 자리에 있었는데, "상품연계가 GA DATA
   안에 있는 게 이상하다"는 지적(2026-08-20)으로 IDEATION 화면 헤더로 옮겼다(그 화면엔 아이콘이
   이거 하나뿐이라 기본 .nav-btn-icon 첫 자리를 그대로 쓴다) — 그래서 icon-4 자리는 더 안 쓴다. */

/* 화면 한구석에 조용히 붙는 작은 아이콘 버튼 (자주 안 쓰는 하위 대시보드 진입용) */
.mini-icon-btn {
  position: absolute;
  z-index: 7;
  width: 30px;
  height: 30px;
  border: 1px solid var(--cyan-dim);
  border-radius: 50%;
  background: rgba(6, 20, 24, 0.5);
  color: var(--cyan-dim);
  padding: 0;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
.mini-icon-btn:hover { color: var(--cyan); border-color: var(--cyan); }
.mini-icon-btn svg { width: 14px; height: 14px; fill: currentColor; }
.mini-icon-btn-bl { left: 16px; bottom: 16px; }
.mini-icon-btn-tl { left: 50px; top: 12px; }
/* 본문(analytics-body) 바로 위, 우측 정렬 — 헤더 타이틀/HUD 버튼과 안 겹치면서도 눈에 잘 띄게
   기본 mini-icon-btn보다 한 단계 키우고 배경/테두리를 밝게 함 */
.mini-icon-btn-body-tr {
  top: 52px;
  /* 화면 끝이 아니라, 실제 콘텐츠 카드(.viz-root, width: min(720px, 92vw))의 오른쪽 끝에 맞춤 */
  right: calc(50% - 360px);
  width: 38px;
  height: 38px;
  background: rgba(6, 20, 24, 0.85);
  border-color: var(--cyan);
  color: var(--cyan);
  box-shadow: 0 0 8px var(--cyan-glow);
}
.mini-icon-btn-body-tr svg { width: 18px; height: 18px; }

.analytics-body {
  position: relative;
  z-index: 3;
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden; /* 좌우로는 스크롤 안 되게 — 세로 스크롤만 허용 */
  -webkit-overflow-scrolling: touch;
  padding: 60px 20px 30px;
  display: flex;
  flex-direction: column;
  gap: 24px;
  align-items: center;
}

/* dataviz 스킬 레퍼런스 팔레트(dark 모드 시퀀셜 블루)를 기존 다크 HUD 표면에 맞게 적용 */
.viz-root {
  color-scheme: dark;
  --viz-surface: rgba(6, 20, 24, 0.72);
  --viz-text-primary: #ffffff;
  --viz-text-secondary: #c3c2b7;
  --viz-muted: #898781;
  --viz-gridline: #2c2c2a;
  --viz-baseline: #383835;
  --viz-series: #3987e5;
  --viz-series-light: #6da7ec;
  --viz-series-dark: #1c5cab;

  width: min(720px, 92vw);
  border: 1px solid var(--cyan-dim);
  border-radius: 6px;
  background:
    linear-gradient(180deg, rgba(57, 135, 229, 0.06), transparent 40%),
    var(--viz-surface);
  box-shadow: 0 0 24px rgba(57, 135, 229, 0.22), inset 0 0 30px rgba(57, 135, 229, 0.04);
  padding: 16px 18px 12px;
}

.viz-title {
  font-size: 12px;
  letter-spacing: 2px;
  color: var(--viz-text-primary);
  margin-bottom: 10px;
  padding-left: 10px;
  border-left: 2px solid var(--viz-series);
}

/* 여러 선을 겹친 차트(renderMultiLineChart)의 범례 — 5~6개 시리즈는 직접 라벨 대신 범례로
   식별한다(dataviz 가이드). */
.viz-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 14px;
  margin-bottom: 8px;
  font-size: 11px;
  color: var(--viz-text-secondary);
}
.viz-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}
.viz-legend-swatch {
  display: inline-block;
  width: 9px;
  height: 9px;
  border-radius: 50%;
}

.viz-empty {
  color: var(--viz-muted);
  font-size: 12px;
  padding: 20px 0;
  text-align: center;
}

.viz-svg { display: block; width: 100%; height: auto; overflow: visible; }
.viz-svg text {
  font-family: "Consolas", "Courier New", monospace;
  fill: var(--viz-muted);
  font-size: 10px;
}
.viz-svg .viz-value-label {
  fill: var(--viz-text-primary);
  font-size: 10.5px;
  font-weight: bold;
  text-shadow: 0 0 6px rgba(57, 135, 229, 0.8);
}
.viz-svg .viz-gridline { stroke: var(--viz-gridline); stroke-width: 1; }
.viz-svg .viz-baseline { stroke: var(--viz-baseline); stroke-width: 1; }
.viz-svg .viz-area { opacity: 0.9; }
.viz-svg .viz-line {
  fill: none;
  stroke: var(--viz-series);
  stroke-width: 2.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  filter: drop-shadow(0 0 4px rgba(57, 135, 229, 0.85));
  transition: stroke-dashoffset 1s ease;
}
/* 실측/예측 구간 구분(예측 시뮬레이션 그래프, 2026-08-06) — 예측 구간은 점선 + 살짝 흐리게 */
.viz-svg .viz-line-dashed {
  stroke-dasharray: 6 5;
  opacity: 0.75;
  transition: none;
}
/* "현재" 기준선(2026-08-06 요청) — 실측/예측 경계를 점선 스타일만으론 부족해서 세로선으로 추가 */
.viz-svg .viz-marker-line {
  stroke: var(--viz-text-secondary);
  stroke-width: 1;
  stroke-dasharray: 3 3;
  opacity: 0.6;
}
.viz-svg .viz-marker-label {
  fill: var(--viz-text-secondary);
  font-size: 9px;
}
/* 분기별 세로선 + 값 라벨(2026-08-06 요청) — "현재" 기준선보다는 옅게, 격자선보다는 눈에 띄게 */
.viz-svg .viz-quarter-line {
  stroke: var(--viz-series-light);
  stroke-width: 1;
  stroke-dasharray: 2 3;
  opacity: 0.35;
}
.viz-svg .viz-quarter-dot {
  fill: var(--viz-series-light);
  opacity: 0.8;
}
.viz-svg .viz-quarter-value {
  fill: var(--viz-text-secondary);
  font-size: 9px;
}
.viz-svg .viz-dot {
  fill: var(--viz-series);
  stroke: var(--viz-surface);
  stroke-width: 2;
  filter: drop-shadow(0 0 5px rgba(57, 135, 229, 0.9));
}
.viz-svg .viz-bar {
  transition: height 0.6s cubic-bezier(0.22, 1, 0.36, 1), y 0.6s cubic-bezier(0.22, 1, 0.36, 1),
    width 0.6s cubic-bezier(0.22, 1, 0.36, 1), fill 0.2s ease;
  filter: drop-shadow(0 0 4px rgba(57, 135, 229, 0.55));
}
.viz-svg .viz-bar:hover { fill: var(--viz-series-light) !important; }

.viz-tooltip {
  position: fixed;
  z-index: 20;
  pointer-events: none;
  background: #04100f;
  border: 1px solid var(--cyan-dim);
  border-radius: 4px;
  box-shadow: 0 0 14px rgba(57, 135, 229, 0.4);
  color: var(--viz-text-primary);
  font-size: 11px;
  padding: 6px 10px;
  white-space: nowrap;
  display: none;
}

.viz-table-toggle {
  background: transparent;
  border: none;
  color: var(--viz-muted);
  font-family: inherit;
  font-size: 10px;
  letter-spacing: 1px;
  cursor: pointer;
  padding: 6px 0;
  text-decoration: underline;
}

.viz-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 11px;
  margin-top: 6px;
}
.viz-table th, .viz-table td {
  border-bottom: 1px solid var(--viz-gridline);
  padding: 4px 8px;
  text-align: right;
  color: var(--viz-text-secondary);
  font-variant-numeric: tabular-nums;
}
.viz-table th:first-child, .viz-table td:first-child { text-align: left; color: var(--viz-text-primary); }
.viz-table tr.is-me { background: rgba(57, 135, 229, 0.1); }
.viz-table tr.is-me td:first-child { font-weight: bold; }

/* 금리 전망(FORECAST) 화면 — 표 열이 많고("판단 근거"/"제안 사유" 등 문장형 칸이 있어서) 기본
   .viz-root 폭(720px)에서 글자가 테두리 밖으로 삐져나갔다(2026-08-06 실측). 폭을 넓히는 대신
   다른 화면과 폭을 통일해달라는 요청(2026-08-06)으로, 폭은 기본값 그대로 두고 표만
   table-layout:fixed + 줄바꿈으로 좁은 폭에 맞춘다. 글자가 너무 작다는 피드백(2026-08-06)으로
   10px→12px로 다시 키우고, 대신 잘리지 않게 줄바꿈은 유지 + 여백은 과하지 않게 살짝만 늘림.*/
.forecast-table {
  table-layout: fixed;
  word-break: keep-all;
  overflow-wrap: break-word;
  white-space: normal;
  font-size: 12px;
}
.forecast-table th, .forecast-table td { text-align: left; padding: 6px 7px; line-height: 1.4; }

.drive-card-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.drive-card {
  display: block;
  padding: 10px 12px;
  border: 1px solid var(--viz-gridline);
  border-left: 2px solid var(--viz-series);
  border-radius: 4px;
  background: rgba(57, 135, 229, 0.05);
  text-decoration: none;
  transition: background 0.2s ease, border-color 0.2s ease;
}
.drive-card:hover {
  background: rgba(57, 135, 229, 0.12);
  border-left-color: var(--viz-series-light);
}
.drive-card-name {
  color: var(--viz-text-primary);
  font-size: 13px;
}
.drive-card-meta {
  color: var(--viz-muted);
  font-size: 11px;
  margin-top: 3px;
}

/* ---------- 저축은행 업권 대시보드 ---------- */
/* #savi-content 자신은 박스가 아니라, 안에 쌓이는 카드(.viz-root)들 사이 간격만 잡아주는 그릇이다 —
   analytics-body가 자기 직계 자식 차트 카드들 사이에 gap을 주는 것과 같은 방식. */
#savi-content {
  display: flex;
  flex-direction: column;
  gap: 24px;
  align-items: center;
}

.savi-section-title {
  color: var(--viz-text-primary);
  font-size: 13px;
  letter-spacing: 1px;
  margin: 22px 0 10px;
  border-left: 2px solid var(--viz-series);
  padding-left: 8px;
}
.savi-section-title:first-child { margin-top: 0; }

.savi-meta {
  color: var(--viz-muted);
  font-size: 12px;
  margin-bottom: 4px;
}

.savi-notice {
  color: var(--viz-muted);
  font-size: 11px;
  line-height: 1.5;
  margin: 8px 0 16px;
  padding: 8px 10px;
  border-left: 2px solid var(--viz-gridline);
  background: rgba(255, 255, 255, 0.02);
}

.register-name-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 12px;
  font-size: 12px;
  color: var(--viz-muted);
}
.register-name-row input {
  flex: 1;
  max-width: 220px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--viz-gridline);
  color: var(--viz-text-secondary, #ddd);
  padding: 6px 8px;
  font-family: inherit;
  font-size: 12px;
}
.register-upload-form {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
}
.register-upload-form button {
  background: transparent;
  border: 1px solid var(--cyan-dim);
  color: var(--cyan);
  font-family: inherit;
  font-size: 11px;
  padding: 6px 14px;
  cursor: pointer;
}
.register-upload-form button:hover { background: var(--cyan); color: #04100f; }
.register-upload-status { font-size: 11px; color: var(--viz-muted); margin-bottom: 10px; min-height: 14px; }
.register-file-table .register-delete-btn {
  background: transparent;
  border: 1px solid rgba(255, 100, 100, 0.5);
  color: #ff8a8a;
  font-family: inherit;
  font-size: 10px;
  padding: 3px 8px;
  cursor: pointer;
}
.register-file-table .register-delete-btn:hover { background: rgba(255, 100, 100, 0.5); color: #fff; }

.savi-notice.savi-alert {
  border-left-color: #e2543f;
  color: #e2a08f;
  background: rgba(226, 84, 63, 0.08);
  margin-bottom: 6px;
}

/* JOURNEY 화면의 상품/서비스 섹션 — 문제점(경고색)/개선점(강조색) 두 열로 나눠 카드 목록으로
   보여준다. 좁은 화면에서는 한 열로 쌓이게 grid 대신 flex+wrap을 쓴다. */
.journey-finding-cols {
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
}
.journey-finding-col {
  flex: 1 1 260px;
  min-width: 0;
}
.journey-finding-heading {
  font-size: 11px;
  letter-spacing: 1px;
  margin-bottom: 8px;
  font-weight: bold;
}
.journey-finding-heading.journey-finding-problem { color: #e2a08f; }
.journey-finding-heading.journey-finding-improvement { color: var(--cyan); }
.journey-finding-card {
  font-size: 11px;
  line-height: 1.5;
  padding: 8px 10px;
  border-left: 2px solid var(--viz-gridline);
  background: rgba(255, 255, 255, 0.02);
  margin-bottom: 8px;
}
.journey-finding-card strong {
  display: block;
  color: var(--viz-text-primary);
  font-size: 12px;
  margin-bottom: 3px;
}
.journey-finding-card p { color: var(--viz-muted); margin: 0; }
.journey-finding-card.journey-finding-problem {
  border-left-color: #e2543f;
  background: rgba(226, 84, 63, 0.06);
}
.journey-finding-card.journey-finding-improvement {
  border-left-color: var(--cyan);
  background: rgba(79, 242, 232, 0.05);
}

/* ---------- 쿠폰 서비스 현황 화면 ---------- */
.coupon-tag {
  display: inline-block;
  font-size: 9px;
  letter-spacing: 0.5px;
  color: var(--cyan);
  border: 1px solid var(--cyan-dim);
  border-radius: 999px;
  padding: 1px 8px;
  margin-bottom: 5px;
}
.coupon-benchmark-source {
  color: var(--viz-muted) !important;
  font-size: 10px !important;
  margin-top: 4px !important;
}
.coupon-portfolio-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 12px;
}
.coupon-portfolio-item {
  padding: 12px 14px;
  border: 1px solid var(--viz-gridline);
  border-top: 2px solid var(--cyan);
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.02);
}
.coupon-portfolio-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 6px;
}
.coupon-portfolio-head strong { color: var(--viz-text-primary); font-size: 13px; }
.coupon-portfolio-type {
  font-size: 10px;
  color: var(--viz-muted);
  border: 1px solid var(--viz-gridline);
  border-radius: 999px;
  padding: 1px 8px;
  white-space: nowrap;
}
.coupon-portfolio-item p { color: var(--viz-text-secondary, #ddd); font-size: 11px; line-height: 1.5; margin: 4px 0 0; }
.coupon-portfolio-item p.coupon-portfolio-purpose { color: var(--viz-muted); }

/* ---------- 상품 간 크로스셀 분석 화면 ---------- */
.cross-sell-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 14px;
}
.cross-sell-card {
  padding: 14px 16px 12px;
  border: 1px solid var(--viz-gridline);
  border-top: 2px solid var(--cyan);
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.02);
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.cross-sell-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.cross-sell-card-head strong { color: var(--viz-text-primary); font-size: 14px; }
.cross-sell-badge {
  flex-shrink: 0;
  font-size: 10px;
  font-weight: bold;
  padding: 2px 9px;
  border-radius: 999px;
  border: 1px solid var(--cyan-dim);
  color: var(--cyan);
  white-space: nowrap;
}
.cross-sell-badge-high { border-color: var(--cyan); color: var(--cyan); }
.cross-sell-badge-mid { border-color: #e2a03f; color: #e2a03f; }
.cross-sell-badge-low { border-color: var(--viz-gridline); color: var(--viz-muted); }
.cross-sell-reasoning { color: var(--viz-text-secondary, #ddd); font-size: 12px; line-height: 1.5; margin: 0; }

.viz-table tr.is-warn { background: rgba(226, 84, 63, 0.08); }
.viz-table tr.is-warn td:last-child { color: #e2543f; font-weight: bold; }

.viz-table tr.is-self { background: rgba(79, 242, 232, 0.1); }
.viz-table tr.is-self td:first-child { color: var(--cyan); font-weight: bold; }

.kpi-tile-row {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}
.kpi-tile {
  flex: 1 1 130px;
  min-width: 120px;
  padding: 10px 12px;
  border: 1px solid var(--viz-gridline);
  border-left: 2px solid var(--viz-series);
  border-radius: 4px;
  background: rgba(57, 135, 229, 0.05);
}
.kpi-tile-value {
  color: var(--viz-text-primary);
  font-size: 18px;
  font-variant-numeric: tabular-nums;
}
.kpi-tile-label {
  color: var(--viz-muted);
  font-size: 11px;
  margin-top: 2px;
}
.kpi-tile-sub {
  color: var(--viz-text-secondary);
  font-size: 11px;
  margin-top: 4px;
}

/* svg 기본 width:100%를 그대로 두면 다른 640px짜리 넓은 차트와 같은 폭까지 늘어나면서
   세로로 지나치게 커져버려서, 정사각형에 가까운 사분면 차트만 최대 폭을 따로 제한한다. */
.savi-quadrant-wrap { display: flex; flex-direction: column; align-items: center; }
.savi-quadrant-wrap .viz-svg { max-width: 480px; }
.savi-quadrant-wrap .viz-svg text { fill: var(--viz-muted); font-size: 10px; }
.savi-quadrant-axis-label { fill: var(--viz-text-secondary) !important; font-size: 11px !important; }
.savi-quadrant-dot { fill: var(--viz-series-light); stroke: var(--viz-surface); stroke-width: 1.5; cursor: default; }
.savi-quadrant-dot.is-me { fill: var(--viz-text-primary); stroke: var(--viz-series); stroke-width: 2; }
.savi-quadrant-quad-line { stroke: var(--viz-gridline); stroke-width: 1; }

/* ---------- 광고 (문구 생성 / 심의 검증) ---------- */
.ad-agent-tabs {
  display: flex;
  gap: 8px;
  margin-bottom: 14px;
  border-bottom: 1px solid var(--viz-gridline);
}
.ad-agent-tab-btn {
  background: transparent;
  border: none;
  border-bottom: 2px solid transparent;
  color: var(--viz-muted);
  font-family: inherit;
  font-size: 12px;
  padding: 8px 4px;
  cursor: pointer;
}
.ad-agent-tab-btn.active { color: var(--cyan); border-bottom-color: var(--cyan); }

.ad-copy-form {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 8px;
}
.ad-copy-form label {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 11px;
  color: var(--viz-muted);
}
.ad-copy-form input,
.ad-copy-form select,
.ad-copy-form textarea,
.ad-verify-textarea {
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--viz-gridline);
  color: var(--viz-text-secondary, #ddd);
  padding: 6px 8px;
  font-family: inherit;
  font-size: 12px;
  resize: vertical;
}
.ad-copy-form textarea,
.ad-verify-textarea { min-height: 60px; }
.ad-copy-form button,
#ad-verify-submit-btn {
  align-self: flex-start;
  background: transparent;
  border: 1px solid var(--cyan-dim);
  color: var(--cyan);
  font-family: inherit;
  font-size: 11px;
  padding: 6px 14px;
  cursor: pointer;
}
.ad-copy-form button:hover,
#ad-verify-submit-btn:hover { background: var(--cyan); color: #04100f; }

#ad-agent-tab-verify #ad-verify-file-input { margin-bottom: 10px; display: block; }
#ad-agent-tab-verify .ad-verify-textarea { width: 100%; box-sizing: border-box; margin-bottom: 10px; }

.ad-copy-results {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 14px;
  margin-top: 12px;
}
.ad-copy-variant-card {
  padding: 14px 16px 12px;
  border: 1px solid var(--viz-gridline);
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.02);
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.18);
  display: flex;
  flex-direction: column;
  gap: 10px;
}
/* 스타일별로 살짝 다른 톤을 줘서(안정형=차분한 시안, 균형형=기본 시안, 마케팅형=따뜻한 톤)
   세 변형을 한눈에 구분하기 쉽게 한다. */
.ad-copy-variant-card.style-safe { border-top: 2px solid var(--cyan-dim); }
.ad-copy-variant-card.style-balanced { border-top: 2px solid var(--cyan); }
.ad-copy-variant-card.style-bold { border-top: 2px solid #e2a03f; }

.ad-copy-variant-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.ad-copy-actions { display: flex; align-items: center; gap: 10px; }
.ad-copy-variant-style-badge {
  font-size: 10px;
  font-weight: bold;
  letter-spacing: 0.5px;
  padding: 3px 9px;
  border-radius: 999px;
  border: 1px solid var(--cyan-dim);
  color: var(--cyan);
}
.ad-copy-variant-card.style-bold .ad-copy-variant-style-badge {
  border-color: #e2a03f;
  color: #e2a03f;
}
.ad-copy-copy-btn {
  background: transparent;
  border: none;
  color: var(--viz-muted);
  font-family: inherit;
  font-size: 10px;
  cursor: pointer;
  padding: 2px 4px;
}
.ad-copy-copy-btn:hover { color: var(--cyan); }
.ad-copy-copy-btn.copied { color: var(--cyan); }

/* 실제 앱 배너 스크린샷(밝은 카드, 왼쪽 타이틀+설명, 오른쪽 이미지/캐릭터, 버튼 없이 카드 전체가
   탭 영역) 참고해서 맞춤 — 처음엔 텍스트만 세로로 쌓아뒀는데, 팝업/배너 모두 실제 예시처럼 이미지
   영역이 오른쪽에 따로 있어야 한다는 피드백으로 가로 배치 + 이미지 박스를 추가했다(2026-08-04). */
.ad-copy-banner-preview {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  border-radius: 12px;
  background: #fbfbf8;
  border: 1px solid rgba(0, 0, 0, 0.08);
}
.ad-copy-banner-text {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.ad-copy-banner-title {
  color: #1a1a1a;
  font-size: 15px;
  font-weight: 800;
  line-height: 1.3;
}
.ad-copy-banner-body {
  color: #4a4a4a;
  font-size: 12px;
  line-height: 1.45;
}
/* 실제 이미지/캐릭터 일러스트가 들어갈 자리 — 지금은 담당자가 나중에 채울 자리라는 걸 보여주는
   플레이스홀더 박스로만 표시한다. */
.ad-copy-banner-image-box {
  flex-shrink: 0;
  width: 60px;
  height: 60px;
  border-radius: 10px;
  border: 1px dashed rgba(0, 0, 0, 0.2);
  background: rgba(0, 0, 0, 0.04);
  display: flex;
  align-items: center;
  justify-content: center;
  color: rgba(0, 0, 0, 0.35);
  font-size: 10px;
}
.ad-copy-cta-caption {
  color: var(--viz-muted);
  font-size: 10px;
}

/* 소형 배너: 리스트에 여러 개가 나란히 뜨는 느낌으로 작고 낮게 */
.banner-small .ad-copy-banner-preview { padding: 10px 12px; border-radius: 10px; }
.banner-small .ad-copy-banner-title { font-size: 13px; }
.banner-small .ad-copy-banner-body { font-size: 11px; }
.banner-small .ad-copy-banner-image-box { width: 44px; height: 44px; }

/* 대형 배너: 화면 상단을 크게 차지하는 메인/히어로 배너 느낌으로 크고 여유 있게 */
.banner-large .ad-copy-banner-preview { padding: 20px 20px; border-radius: 14px; min-height: 90px; }
.banner-large .ad-copy-banner-title { font-size: 19px; }
.banner-large .ad-copy-banner-body { font-size: 13px; }
.banner-large .ad-copy-banner-image-box { width: 80px; height: 80px; }

/* 문자/카카오톡: 배너 박스 없이 실제 메시지처럼 문단으로 길게 나열 */
.ad-copy-message-text {
  white-space: pre-wrap;
  font-size: 12px;
  line-height: 1.7;
  color: var(--viz-text-secondary, #ddd);
  padding: 10px 12px;
  border-radius: 6px;
  background: rgba(255, 255, 255, 0.03);
  border-left: 2px solid var(--viz-series);
}

.ad-copy-char-count { color: var(--viz-muted); font-size: 10px; white-space: nowrap; }

.ad-copy-variant-disclaimer {
  color: var(--viz-muted);
  font-size: 10px;
  line-height: 1.4;
  padding-top: 8px;
  border-top: 1px dashed var(--viz-gridline);
}

/* 아이데이션 버튼 — 등록자료 버튼 바로 오른쪽에 나란히 배치(같은 lock-btn 헤더 아이콘 패턴).
   새 헤더 버튼은 항상 .lock-btn과 modifier를 합친 compound 선택자를 써야 한다 — 그렇지 않으면
   모바일 미디어쿼리의 .lock-btn 규칙에 소스 순서상 밀려서 로그아웃 버튼과 겹쳐버린다(실제로
   register-shortcut-btn/.nav-btn-icon 두 번 발생한 버그, style.css 789/798 주석 참고). */
.ideation-shortcut-btn { left: 124px; }
@media (max-width: 640px) {
  .lock-btn.ideation-shortcut-btn { left: 78px; top: 15px; width: 22px; height: 22px; }
  .lock-btn.ideation-shortcut-btn svg { width: 11px; height: 11px; }
}

/* ---------- 서비스 아이데이션 ---------- */
.ideation-tabs {
  display: flex;
  gap: 8px;
  margin-bottom: 14px;
  border-bottom: 1px solid var(--viz-gridline);
  flex-wrap: wrap;
}
.ideation-tab-btn {
  background: transparent;
  border: none;
  border-bottom: 2px solid transparent;
  color: var(--viz-muted);
  font-family: inherit;
  font-size: 12px;
  padding: 8px 4px;
  cursor: pointer;
}
.ideation-tab-btn.active { color: var(--cyan); border-bottom-color: var(--cyan); }

.ideation-conditions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 14px;
  margin-bottom: 12px;
}
.ideation-conditions label {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 11px;
  color: var(--viz-muted);
  flex: 1 1 160px;
}
.ideation-conditions label:has(textarea) { flex-basis: 100%; }
.ideation-conditions select,
.ideation-conditions textarea {
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--viz-gridline);
  color: var(--viz-text-secondary, #ddd);
  padding: 6px 8px;
  font-family: inherit;
  font-size: 12px;
  resize: vertical;
}
.ideation-conditions textarea { min-height: 40px; }

.ideation-idea-diff {
  color: var(--viz-muted);
  font-size: 11px;
  line-height: 1.5;
  margin: 0;
  padding: 6px 8px;
  border-left: 2px solid var(--cyan-dim);
  background: rgba(79, 242, 232, 0.03);
}

.ideation-regenerate-btn {
  display: block;
  margin-bottom: 12px;
  background: transparent;
  border: 1px solid var(--cyan-dim);
  color: var(--cyan);
  font-family: inherit;
  font-size: 11px;
  padding: 6px 14px;
  cursor: pointer;
}
.ideation-regenerate-btn:hover { background: var(--cyan); color: #04100f; }
.ideation-regenerate-btn:disabled { opacity: 0.5; cursor: default; }

.ideation-trend-summary {
  color: var(--viz-text-secondary, #ddd);
  font-size: 12px;
  line-height: 1.6;
  margin-bottom: 14px;
  padding: 10px 12px;
  border-left: 2px solid var(--cyan-dim);
  background: rgba(79, 242, 232, 0.04);
}

.ideation-idea-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 14px;
}
.ideation-idea-card {
  padding: 14px 16px 12px;
  border: 1px solid var(--viz-gridline);
  border-top: 2px solid var(--cyan);
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.02);
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.18);
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.ideation-idea-card.is-top3 { border-top-color: #e2a03f; }
.ideation-idea-card.is-clickable,
.cross-sell-card.is-clickable { cursor: pointer; transition: box-shadow 0.15s ease, transform 0.15s ease; }
.ideation-idea-card.is-clickable:hover,
.cross-sell-card.is-clickable:hover { box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3); transform: translateY(-1px); }
.ideation-idea-head {
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.ideation-idea-head strong { color: var(--viz-text-primary); font-size: 14px; line-height: 1.3; }
.ideation-idea-target { color: var(--viz-muted); font-size: 10px; line-height: 1.3; }
.ideation-idea-score {
  align-self: flex-start;
  font-size: 10px;
  font-weight: bold;
  padding: 2px 8px;
  border-radius: 999px;
  border: 1px solid var(--cyan-dim);
  color: var(--cyan);
}
.ideation-idea-score.is-top3 { border-color: #e2a03f; color: #e2a03f; }
.ideation-idea-concept { color: var(--viz-text-secondary, #ddd); font-size: 12px; line-height: 1.5; margin: 0; }
.ideation-idea-trend {
  color: var(--viz-muted);
  font-size: 10px;
  line-height: 1.4;
  margin: 0;
  padding-top: 6px;
  border-top: 1px dashed var(--viz-gridline);
}

.ideation-sim-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 8px;
  margin-top: 4px;
}
.ideation-sim-item {
  padding: 6px 8px;
  border-left: 2px solid var(--viz-gridline);
  background: rgba(255, 255, 255, 0.02);
}
.ideation-sim-label {
  display: block;
  color: var(--cyan);
  font-size: 9px;
  letter-spacing: 0.5px;
  margin-bottom: 2px;
}
.ideation-sim-item p { color: var(--viz-muted); font-size: 11px; line-height: 1.4; margin: 0; }

/* 아이디어 상세 모달(.daily-briefing-box 재사용) 안 섹션 — idea_report.py의 12장 PPT와 같은 구조를
   화면에서도 그대로 보여준다. */
.ideation-detail-section { margin: 14px 0; }
.ideation-detail-section p { color: var(--viz-text-secondary, #ddd); font-size: 12px; line-height: 1.6; margin: 6px 0 0; }
.ideation-scenario-list { list-style: decimal; margin: 6px 0 0; padding-left: 18px; }
.ideation-scenario-list li { margin-bottom: 8px; }
.ideation-scenario-list li strong { color: var(--viz-text-primary); font-size: 12px; }
.ideation-scenario-list li p { margin: 2px 0 0; }
.ideation-scenario-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 8px;
  margin-top: 6px;
}

/* ---------- 브리핑 화면 ---------- */
.briefing-content {
  width: min(720px, 92vw);
  text-align: left;
  font-size: 13px;
  line-height: 1.7;
  color: var(--viz-text-secondary);
}
.briefing-content strong {
  color: var(--viz-text-primary);
  text-shadow: 0 0 6px rgba(57, 135, 229, 0.5);
}
.briefing-content a {
  color: var(--viz-series-light);
  text-decoration: underline;
}
.briefing-content p { margin: 0 0 14px; }
.briefing-content .insight {
  display: block;
  margin: 6px 0 14px;
  padding: 8px 10px;
  border-left: 2px solid var(--viz-series);
  background: rgba(57, 135, 229, 0.08);
  color: var(--viz-text-primary);
  font-size: 12px;
}
.briefing-loading {
  color: var(--viz-muted);
  font-size: 12px;
  text-align: center;
  padding: 30px 0;
}

/* ---------- 프로토콜(자비스가 말하는 듯한 타이핑) 화면 ---------- */
.rules-panel {
  opacity: 0;
  transform: translateY(8px);
  animation: rules-panel-in 0.6s ease forwards;
}
@keyframes rules-panel-in {
  to { opacity: 1; transform: translateY(0); }
}

.rules-typer { min-height: 40vh; }

.rules-header {
  margin: 22px 0 10px;
  font-size: 13px;
  letter-spacing: 3px;
  color: var(--cyan);
  text-shadow: 0 0 8px var(--cyan-glow);
}
.rules-header:first-child { margin-top: 0; }

.rules-line {
  margin: 0 0 12px;
  font-size: 13px;
  line-height: 1.7;
  color: var(--viz-text-secondary);
}
.rules-line strong { color: var(--viz-text-primary); }

.type-cursor {
  display: inline-block;
  color: var(--cyan);
  animation: cursor-blink 0.8s step-end infinite;
}
@keyframes cursor-blink { 50% { opacity: 0; } }

/* 헤더의 "말하는 중" 표시 (미니바와 같은 느낌의 작은 이퀄라이저) */
.speaking-bars {
  position: absolute;
  left: 84px;
  top: 20px;
  z-index: 7;
  display: flex;
  gap: 3px;
  align-items: flex-end;
  height: 16px;
}

/* 파일 원본 미리보기 팝업 — 새 탭으로 이동하는 대신 화면 안에서 바로 띄운다.
   클릭 전에는 아무것도 안 불러오고(<img>/<iframe>의 src를 비워둠), 열 때만 채워서 지연 로딩한다. */
.file-preview-modal {
  position: fixed;
  inset: 0;
  z-index: 300;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* [hidden] 속성이 위 display:flex보다 항상 이기도록 명시 (다른 모달들과 동일한 패턴) */
.file-preview-modal[hidden] {
  display: none;
}

.file-preview-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(4, 12, 16, 0.85);
}

.file-preview-box {
  position: relative;
  z-index: 1;
  max-width: 90vw;
  max-height: 90vh;
}

.file-preview-img {
  display: block;
  max-width: 90vw;
  max-height: 90vh;
  border: 1px solid var(--cyan-dim);
  box-shadow: 0 0 20px var(--cyan-glow);
}

.file-preview-frame {
  width: 82vw;
  height: 86vh;
  border: 1px solid var(--cyan-dim);
  box-shadow: 0 0 20px var(--cyan-glow);
  background: #fff;
}

.file-preview-close {
  position: absolute;
  top: -38px;
  right: -4px;
  background: transparent;
  border: 1px solid var(--cyan-dim);
  color: var(--cyan);
  font-size: 20px;
  line-height: 1;
  width: 32px;
  height: 32px;
  border-radius: 4px;
  cursor: pointer;
}

/* ---------- 오늘의 브리핑 모달 ---------- */
/* .viz-root 카드를 모달 안에 그대로 넣으면 어두운 배경 위에 또 어두운 반투명 배경이 겹쳐서
   (실측 확인 2026-07-31, 사용자 스크린샷) 글자가 거의 안 보일 정도로 대비가 낮아진다 —
   ANALYTICS 화면에서는 카드 하나만 떠 있어서 괜찮았지만, 모달은 바로 읽혀야 하니 이 안에서만
   글자색을 훨씬 밝게, 카드 배경은 불투명하게 덮어쓴다. */
.daily-briefing-box .viz-root {
  --viz-muted: #e2e0d4;
  --viz-text-secondary: #f2f0e6;
  background: #0f2126;
  /* .viz-root는 원래 자기 폭을 min(720px, 92vw)로 직접 정하는데, 이 모달 안에 그대로 두면
     부모(.daily-briefing-box)의 좌우 padding(20px씩)만큼 더 넓어져서 가로 스크롤이 생긴다
     (실측 지적 2026-07-31) — 모달 안에서는 폭을 부모에 맞춰 100%로 채우게 덮어쓴다. */
  width: 100%;
  box-sizing: border-box;
}
.daily-briefing-box .savi-notice {
  color: #e6e4da;
  background: rgba(255, 255, 255, 0.06);
}
.daily-briefing-box .kpi-tile-value {
  color: #ffffff;
}

.daily-briefing-box {
  position: relative;
  z-index: 1;
  width: min(720px, 92vw);
  max-height: 88vh;
  overflow-y: auto;
  overflow-x: hidden;
  background: var(--panel-bg, #0a1418);
  border: 1px solid var(--cyan-dim);
  box-shadow: 0 0 20px var(--cyan-glow);
  padding: 20px 22px;
}

/* ---------- 광고심의 체크 모달 ---------- */
.ad-checklist-box {
  position: relative;
  z-index: 1;
  width: min(860px, 94vw);
  max-height: 88vh;
  overflow-y: auto;
  background: var(--panel-bg, #0a1418);
  border: 1px solid var(--cyan-dim);
  box-shadow: 0 0 20px var(--cyan-glow);
  padding: 20px 22px;
}

.ad-checklist-header {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 10px;
}

.ad-checklist-title {
  color: var(--viz-text-primary);
  font-size: 14px;
  letter-spacing: 1px;
}

.ad-verdict-badge {
  display: inline-block;
  padding: 4px 12px;
  font-size: 13px;
  font-weight: bold;
  border-radius: 3px;
  border: 1px solid var(--viz-gridline);
  color: var(--viz-muted);
}
.ad-verdict-badge.verdict-ok { color: #4fd67a; border-color: #4fd67a; background: rgba(79, 214, 122, 0.1); }
.ad-verdict-badge.verdict-bad { color: #e2543f; border-color: #e2543f; background: rgba(226, 84, 63, 0.1); }

.ad-summary {
  color: var(--viz-text-secondary, var(--viz-muted));
  font-size: 12px;
  line-height: 1.6;
  margin: 0 0 14px;
}

/* 기본 .viz-table은 숫자 표(재무 지표 등) 기준으로 우측 정렬+자동 열너비인데, 이 표는 전부
   한글 텍스트라 그대로 쓰면 "판단"처럼 짧은 칸이 다른 칸에 밀려 극단적으로 좁아지면서 "적정"이
   "적/정"으로 줄바꿈되는 등 시인성이 나빠졌다(2026-08-04, 실제 화면 확인). 열 너비를 고정폭으로
   명시하고, 좁아도 되는 짧은 칸(유형/판단)은 줄바꿈을 아예 막는다. */
.ad-checklist-table {
  table-layout: fixed;
  word-break: keep-all;
  overflow-wrap: break-word;
}
.ad-checklist-table th,
.ad-checklist-table td { text-align: left; }
.ad-checklist-table th:nth-child(1), .ad-checklist-table td:nth-child(1) { width: 15%; white-space: nowrap; }
.ad-checklist-table th:nth-child(2), .ad-checklist-table td:nth-child(2) { width: 23%; }
.ad-checklist-table th:nth-child(3), .ad-checklist-table td:nth-child(3) { width: 11%; white-space: nowrap; text-align: center; }
.ad-checklist-table th:nth-child(4), .ad-checklist-table td:nth-child(4) { width: 51%; }
.ad-checklist-table td { vertical-align: top; line-height: 1.5; }
.ad-checklist-table tr.verdict-bad td:nth-child(3) { color: #e2543f; font-weight: bold; }
.ad-checklist-table tr.verdict-ok td:nth-child(3) { color: #4fd67a; }
.ad-checklist-table tr.verdict-check td:nth-child(3) { color: #d6b84f; }
.ad-checklist-table tr.verdict-na td:nth-child(3) { color: var(--viz-muted); }
.ad-checklist-table tr.verdict-na td { opacity: 0.6; }

.ad-show-image-btn { margin-top: 16px; }

.ad-source-docs { margin-top: 18px; display: flex; flex-direction: column; gap: 8px; }
.ad-source-doc-btn {
  text-align: left;
  background: rgba(6, 20, 24, 0.6);
  border: 1px solid var(--cyan-dim);
  color: var(--cyan);
  font-family: inherit;
  font-size: 12px;
  padding: 8px 12px;
  cursor: pointer;
}
.ad-source-doc-btn:hover { border-color: var(--cyan); background: rgba(79, 242, 232, 0.08); }

.file-preview-pager {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  margin-top: 10px;
}
.file-preview-nav {
  background: transparent;
  border: 1px solid var(--cyan-dim);
  color: var(--cyan);
  width: 30px;
  height: 30px;
  font-size: 16px;
  cursor: pointer;
}
.file-preview-nav:hover:not(:disabled) { border-color: var(--cyan); background: rgba(79, 242, 232, 0.08); }
.file-preview-nav:disabled { opacity: 0.3; cursor: default; }
.file-preview-page-label { font-size: 12px; letter-spacing: 1px; color: var(--cyan); min-width: 50px; text-align: center; }

.ad-image-box {
  position: relative;
  z-index: 1;
  max-width: 92vw;
  max-height: 90vh;
}

.ad-image-wrap {
  position: relative;
  display: inline-block;
  max-width: 92vw;
  max-height: 90vh;
}

.ad-image-img {
  display: block;
  max-width: 92vw;
  max-height: 90vh;
  border: 1px solid var(--cyan-dim);
  box-shadow: 0 0 20px var(--cyan-glow);
}

.ad-problem-box {
  position: absolute;
  border: 2px solid #e2543f;
  background: rgba(226, 84, 63, 0.15);
  box-sizing: border-box;
  pointer-events: none;
}

.ad-problem-label {
  position: absolute;
  top: -20px;
  left: -2px;
  background: #e2543f;
  color: #fff;
  font-size: 10px;
  padding: 2px 6px;
  white-space: nowrap;
  max-width: 200px;
  overflow: hidden;
  text-overflow: ellipsis;
}

.speaking-bars span {
  width: 3px;
  background: var(--cyan);
  box-shadow: 0 0 4px var(--cyan-glow);
  animation: bar-bounce 0.9s ease-in-out infinite;
}
.speaking-bars span:nth-child(1) { height: 40%; animation-delay: 0s; }
.speaking-bars span:nth-child(2) { height: 100%; animation-delay: 0.15s; }
.speaking-bars span:nth-child(3) { height: 65%; animation-delay: 0.3s; }
.speaking-bars span:nth-child(4) { height: 85%; animation-delay: 0.45s; }
.speaking-bars[hidden] { display: none; }

/* 프로토콜 화면 중앙의 파티클 구체 (말하는 동안 맥동) */
.rules-orb-wrap {
  position: relative;
  width: min(34vh, 180px);
  height: min(34vh, 180px);
  margin: 4px auto 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
#rules-orb { width: 100%; height: 100%; }

/* ---------- 모바일 대응 ---------- */
@media (max-width: 720px) {
  .hud-side { display: none; }
  .hud-center { width: 68vw; height: 68vw; }
  .hud-header { padding: 12px 0 26px; }
  .hud-title { font-size: 13px; letter-spacing: 3px; }
  /* 메인 화면(#dashboard)에만 좌측 로그아웃/등록자료/아이데이션 3개 버튼이 절대위치로 떠 있어서
     (right:100px까지 차지) flex 중앙정렬 폭 계산에서 빠짐 — 보정 없이는 제목이 그 자리를
     침범한다(GA DATA 화면에서 났던 것과 같은 겹침 버그, 위 analytics 헤더의 padding-right
     보정과 대칭되는 padding-left). 반드시 #dashboard로 범위를 좁혀야 한다 — 처음에 실수로
     기본 .hud-header에 걸었다가 다른 모든 화면 제목이 오른쪽으로 밀리면서 HUD 버튼과 새로
     겹치는 회귀 버그를 만들었었다(Playwright 실측으로 발견, 2026-08-25). */
  #dashboard .hud-header { padding-left: 120px; }
  /* 시계를 제목 옆(우측 고정)이 아니라 제목 바로 아래 가운데로 옮겨서 겹치지 않게 한다 */
  .hud-clock {
    right: auto;
    left: 50%;
    top: 32px;
    transform: translateX(-50%);
    font-size: 10px;
    letter-spacing: 1px;
  }
  /* PROTOCOL 버튼은 시계 바로 아래로 내려서 겹치지 않게 한다 */
  .protocol-btn { top: 52px; font-size: 9px; padding: 4px 10px; }
  /* 자물쇠(로그아웃) 버튼: 코너 장식(corner-tl)의 테두리 선(위쪽·왼쪽 2px)만 피하도록
     살짝 안쪽으로 들여서, 원래 있던 위치(상단 근처)에 가깝게 유지한다 */
  .lock-btn { left: 16px; top: 15px; width: 22px; height: 22px; }
  .lock-btn svg { width: 11px; height: 11px; }

  /* PROTOCOL/ANALYTICS는 단어가 길어서 작은 원 안에서 두 줄로 눌려 잘 안 보이니,
     모바일에서는 짧은 표기로 바꿔서 한 줄로 읽히게 한다 */
  .info-orb-label .label-full { display: none; }
  .info-orb-label .label-short { display: inline; }
  .chat-panel { max-height: 42vh; width: 94vw; }
  .nav-btn { right: 44px; top: 12px; font-size: 10px; padding: 5px 8px; }
  .viz-root { width: 96vw; }
  /* GA DATA 화면처럼 오른쪽에 아이콘 버튼이 2개 더 붙는 헤더는, 가운데 정렬된 제목이 좁은
     화면에서 그 버튼들과 겹친다(위 HUD 버튼과 겹치던 문제를 고치고 나니 이번엔 제목 글자와
     겹치는 게 실기기로 확인됨, 2026-08-14). 아이콘 버튼을 HUD 버튼(right:44px, 실측 너비
     ~40px) 바로 왼쪽에 촘촘히 붙이고(각각 8px 간격), 제목은 그대로 두되 헤더에 오른쪽 여백을
     버튼 묶음 너비보다 넉넉히 줘서 flex 가운데 정렬 축 자체를 왼쪽으로 밀어 버튼 자리를
     피하게 한다. */
  .nav-btn.nav-btn-icon { right: 92px; }
  .nav-btn.nav-btn-icon-2 { right: 130px; }
  .nav-btn.nav-btn-icon-3 { right: 168px; }
  #analytics-screen .hud-header { padding-right: 178px; }
  /* IDEATION 헤더도 이제 아이콘 버튼(CROSS-SELL)이 하나 생겨서, 같은 이유로 제목이 아이콘과
     겹치지 않게 오른쪽 여백을 준다(아이콘 1개 = analytics 2개(140px)보다 하나 적은 만큼 뺀 값). */
  #ideation-screen .hud-header { padding-right: 102px; }

  /* 로그인 화면: 좁은 화면에서 제목("J . A . R . V . I . S .")이 줄바꿈되지 않도록
     박스 폭에 맞춰 글자 크기/여백을 함께 줄인다. */
  .login-box { min-width: 0; width: min(300px, 88vw); padding: 30px 18px; }
  .login-title { font-size: 14px; letter-spacing: 1px; }
  .login-sub { font-size: 9px; letter-spacing: 1px; }

  /* 지구본(hud-center)이 커진 만큼(68vw), 둘레 버튼도 데스크톱보다는 작지만
     글자가 읽히는 선에서 줄인다. 라벨은 작을수록 잘 안 보이므로 볼드 처리로 보완. */
  .gauge { width: 52px; height: 52px; }
  .gauge-label { font-size: 9px; letter-spacing: 1px; font-weight: bold; }
  .info-orb { width: 50px; height: 50px; }
  .info-orb-label { font-size: 9px; letter-spacing: 1px; font-weight: bold; }
  .orb-icon { width: 16px; height: 14px; }
  .info-orb-pictogram .orb-icon { width: 24px; height: 20px; }
  .info-orb-pictogram .orb-icon-signal { width: 27px; }
  .radar { width: 34px; height: 34px; }
  .mini-bars { height: 27px; gap: 4px; }
  .mini-bars span { width: 4px; }
  .hex-readout { font-size: 11px; letter-spacing: 1px; }

  .orb-position { right: -8px; bottom: -2px; }
  .orb-position-7oc { left: -4px; bottom: -9px; }
  /* 모바일에서는 버튼 자체가 50px이라, 앵커 위치 차이가 그보다 작으면 서로 겹쳐 보인다 —
     CORE(1oc)는 더 위·왼쪽으로, SIGNAL(2oc)은 더 아래·오른쪽으로 벌려서 간격을 확보한다. */
  .orb-position-1oc { top: -40px; right: 22px; }
  .orb-position-10oc { top: -20px; left: -2px; }
  .orb-position-9oc { left: -28px; top: 72%; }
  .orb-position-3oc { right: -34px; }
  .orb-position-2oc { top: 10%; right: -30px; }
  .orb-position-11oc { top: 10%; left: -30px; }

  /* 채팅 결과가 쌓여 지구본이 작아지면(has-chatted), 데스크톱과 같은 min(30vh,34vw)까지 줄이면
     모바일에서는 원래 68vw 기준으로 잡아둔 버튼 위치 px 오프셋들과 비율이 너무 안 맞아서 버튼들이
     작아진 원 안쪽으로 몰려 보인다(실측 확인). 지구본을 덜 줄이고(50vw 정도, 원래의 ~74%),
     버튼 오프셋/크기도 같은 비율로만 줄여서 원래 배치 느낌을 유지한다. */
  #dashboard.has-chatted .hud-center { width: min(40vh, 50vw); height: min(40vh, 50vw); }
  #dashboard.has-chatted .info-orb { width: 37px; height: 37px; }
  #dashboard.has-chatted .gauge { width: 40px; height: 40px; }
  #dashboard.has-chatted .radar { width: 25px; height: 25px; }
  #dashboard.has-chatted .orb-position { right: -6px; bottom: -2px; }
  #dashboard.has-chatted .orb-position-7oc { left: -3px; bottom: -7px; }
  #dashboard.has-chatted .orb-position-1oc { top: -30px; right: 16px; }
  #dashboard.has-chatted .orb-position-10oc { top: -15px; left: -1px; }
  #dashboard.has-chatted .orb-position-9oc { left: -20px; top: 72%; }
  #dashboard.has-chatted .orb-position-3oc { right: -25px; }
  #dashboard.has-chatted .orb-position-2oc { top: 10%; right: -22px; }
  #dashboard.has-chatted .orb-position-11oc { top: 10%; left: -22px; }
}
