/*
 * port-bizinfo 관리자 화면 스타일. 규칙과 이탈 기록의 SSOT는 docs/conventions/ui.md 다.
 *
 * 토큰은 2계층이다: Layer 1 `--p-*`(팔레트 원본, 색 리터럴은 이 블록에서만) →
 * Layer 2 시맨틱(컴포넌트가 참조하는 유일한 레이어). 값의 출처는 Portlogics 디자인 시스템
 * (DESIGN.md, 이 저장소 밖) — port-mailroom `src/public/assets/app.css`의 팔레트를 그대로
 * 미러한다(같은 조직 제품군은 같은 토큰을 쓴다. 새 팔레트를 만들지 않는다).
 *
 * 폰트는 CDN에서 받지 않는다 — 제품 페이지에 외부 CDN을 물리면 런타임 외부 의존이 생기고
 * CSP(`default-src 'self'`)를 넓혀야 한다. 선언만 두고 설치된 경우에만 적용시킨다.
 * 다크모드는 지원하지 않는다 — `color-scheme: light`를 명시한다.
 */

/* ------------------------------------------------------------------ */
/* Layer 1 — primitive palette (컴포넌트에서 직접 사용 금지)          */
/* ------------------------------------------------------------------ */
:root {
  /* primary (trust blue H=260.5) */
  --p-primary-50: oklch(0.97 0.02 260.5);
  --p-primary-100: oklch(0.93 0.045 260.5);
  --p-primary-400: oklch(0.68 0.185 260.5);
  --p-primary-500: oklch(0.604 0.215 260.5);
  --p-primary-600: oklch(0.52 0.205 260.5);
  --p-primary-700: oklch(0.42 0.175 260.5);
  --p-primary-800: oklch(0.32 0.13 260.5);

  /* neutral (cool-tinted, 브랜드와 같은 H) */
  --p-neutral-50: oklch(0.98 0.005 260.5);
  --p-neutral-100: oklch(0.94 0.01 260.5);
  --p-neutral-200: oklch(0.88 0.012 260.5);
  --p-neutral-300: oklch(0.8 0.015 260.5);
  --p-neutral-400: oklch(0.68 0.015 260.5); /* 텍스트 금지 — 2.88:1 */
  --p-neutral-500: oklch(0.56 0.015 260.5); /* 텍스트 최소선 — 4.65:1 */
  --p-neutral-700: oklch(0.34 0.01 260.5);
  --p-neutral-800: oklch(0.24 0.008 260.5);
  --p-neutral-900: oklch(0.16 0.006 260.5);

  /* semantic — bg/border/text 3쌍은 대비가 검증된 조합이다 */
  --p-success: oklch(0.55 0.15 145);
  --p-success-bg: oklch(0.96 0.03 145);
  --p-success-border: oklch(0.65 0.13 145);
  --p-success-text: oklch(0.3 0.12 145);
  --p-warning: oklch(0.68 0.16 78);
  --p-warning-bg: oklch(0.96 0.04 78);
  --p-warning-border: oklch(0.78 0.14 78);
  --p-warning-text: oklch(0.38 0.13 78);
  --p-danger: oklch(0.55 0.21 25);
  --p-danger-bg: oklch(0.96 0.04 25);
  --p-danger-border: oklch(0.7 0.18 25);
  --p-danger-text: oklch(0.38 0.17 25);
  --p-danger-hover: oklch(0.48 0.21 25);
  --p-danger-active: oklch(0.42 0.21 25);
}

/* ------------------------------------------------------------------ */
/* Layer 2 — semantic tokens (컴포넌트가 참조하는 유일한 레이어)      */
/* ------------------------------------------------------------------ */
:root {
  color-scheme: light;

  --surface-app: var(--p-neutral-50);
  --surface-card: #ffffff;
  --surface-subtle: var(--p-neutral-100);
  --surface-hover: var(--p-neutral-100);

  --border-default: var(--p-neutral-200);
  --border-strong: var(--p-neutral-300);

  --text-primary: var(--p-neutral-900);
  --text-body: var(--p-neutral-800);
  --text-secondary: var(--p-neutral-500);
  /* placeholder는 텍스트다 — neutral-400(2.88:1)은 텍스트 금지선 아래. neutral-500(4.65:1)로 */
  --text-placeholder: var(--p-neutral-500);
  /* 비활성 요소 전용 — 대비 규정 면제 대상(버튼·입력의 disabled 상태) */
  --text-disabled: var(--p-neutral-400);
  --text-error: var(--p-danger);

  --brand: var(--p-primary-500);
  --brand-hover: var(--p-primary-600);
  --brand-active: var(--p-primary-700);
  --brand-press: var(--p-primary-800);
  --brand-50: var(--p-primary-50);
  --brand-100: var(--p-primary-100);
  --brand-focus-ring: oklch(0.604 0.215 260.5 / 0.15);
  --brand-glow:
    radial-gradient(ellipse 60% 40% at 50% -10%, oklch(0.93 0.045 260.5 / 0.5), transparent 70%),
    radial-gradient(ellipse 40% 30% at 80% 90%, oklch(0.93 0.02 260.5 / 0.3), transparent 70%);

  --danger-solid: var(--p-danger);
  --danger-solid-hover: var(--p-danger-hover);
  --danger-solid-active: var(--p-danger-active);

  --illustration: var(--p-neutral-300);

  --callout-info-bg: var(--brand-50);
  --callout-info-border: var(--p-primary-400);
  --callout-info-text: var(--p-primary-800);
  --callout-success-bg: var(--p-success-bg);
  --callout-success-border: var(--p-success-border);
  --callout-success-text: var(--p-success-text);
  --callout-warning-bg: var(--p-warning-bg);
  --callout-warning-border: var(--p-warning-border);
  --callout-warning-text: var(--p-warning-text);
  --callout-danger-bg: var(--p-danger-bg);
  --callout-danger-border: var(--p-danger-border);
  --callout-danger-text: var(--p-danger-text);

  --badge-success-bg: var(--p-success-bg);
  --badge-success-text: var(--p-success-text);
  --badge-warning-bg: var(--p-warning-bg);
  --badge-warning-text: var(--p-warning-text);
  --badge-danger-bg: var(--p-danger-bg);
  --badge-danger-text: var(--p-danger-text);
  --badge-brand-bg: var(--brand-100);
  --badge-brand-text: var(--brand-hover);
  --badge-neutral-bg: var(--p-neutral-100);
  /* neutral-500 on neutral-100 실효 약 4.1:1(AA 미달) — neutral-700로 */
  --badge-neutral-text: var(--p-neutral-700);

  --shadow-1:
    0 0 0 1px oklch(0.2 0.01 260.5 / 0.03), 0 1px 2px oklch(0.2 0.01 260.5 / 0.04),
    0 4px 12px oklch(0.2 0.01 260.5 / 0.04);
  --shadow-2:
    0 0 0 1px oklch(0.2 0.01 260.5 / 0.03), 0 2px 4px oklch(0.2 0.02 260.5 / 0.03),
    0 12px 32px -8px oklch(0.2 0.02 260.5 / 0.08);

  --duration-fast: 100ms;
  --ease-default: cubic-bezier(0.4, 0, 0.2, 1);

  --radius-sm: 0.25rem;
  --radius-md: 0.375rem;
  --radius-lg: 0.5rem;
  --radius-xl: 0.75rem;

  --font-sans:
    'Pretendard Variable', Pretendard, -apple-system, BlinkMacSystemFont, system-ui, 'Segoe UI',
    'Apple SD Gothic Neo', 'Malgun Gothic', sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;
}

/* ------------------------------------------------------------------ */
/* Layer 1.5 — dimension tokens (spacing · type · layout)             */
/* 값의 출처는 기존 리터럴이다 — 이 커밋은 리터럴을 토큰으로 회수만 한다(시각 변화 0) */
/* ------------------------------------------------------------------ */
:root {
  /* spacing — 4px 그리드 */
  --space-05: 0.125rem;
  --space-1: 0.25rem;
  --space-15: 0.375rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.25rem;
  --space-6: 1.5rem;
  --space-8: 2rem;

  /* type */
  --text-2xs: 0.6875rem;
  --text-xs: 0.75rem;
  --text-sm: 0.8125rem;
  --text-base: 0.875rem;
  --text-md: 0.9375rem;
  --text-lg: 1.0625rem;
  --text-xl: 1.5rem;
  /* 리포트 등급 상자 한 자리에만 쓴다 — 문서에서 제일 먼저 읽혀야 하는 값이다 */
  --text-2xl: 2rem;

  --leading-tight: 1.4;
  --leading-snug: 1.5;
  --leading-normal: 1.6;
  --weight-normal: 400;
  --weight-medium: 500;
  --weight-semibold: 600;
  --weight-bold: 700;

  /* layout */
  --sidebar-w: 15rem;
  --topbar-h: 3.5rem;
  --row-h: 2.25rem;
  --control-h: 2.25rem;
  --control-h-sm: 1.875rem;
  --content-max: 90rem;

  --radius-pill: 9999px;
  --shadow-0: none;
  --duration-base: 150ms;

  /* ui.md §9 강제 */
  --label-size: var(--text-2xs);
  --label-weight: var(--weight-bold);
  --label-color: var(--text-secondary);
  --value-size: var(--text-sm);
  --value-color: var(--text-body);
}

/* ------------------------------------------------------------------ */
/* Base                                                               */
/* ------------------------------------------------------------------ */
*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

body {
  font-family: var(--font-sans);
  font-size: 1rem;
  line-height: var(--leading-normal);
  word-break: keep-all;
  overflow-wrap: break-word;
  background: var(--surface-app);
  color: var(--text-body);
  min-height: 100dvh;
  -webkit-font-smoothing: antialiased;
}

h1,
h2 {
  color: var(--text-primary);
}

a {
  color: inherit;
}

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

[hidden] {
  display: none !important;
}

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

/* ------------------------------------------------------------------ */
/* Shell — 좌측 고정 nav + 우측 콘텐츠                                 */
/* ------------------------------------------------------------------ */
.shell {
  display: flex;
  min-height: 100dvh;
}

.sidebar {
  flex: 0 0 var(--sidebar-w);
  display: flex;
  flex-direction: column;
  border-right: 1px solid var(--border-default);
  background: var(--surface-card);
  padding: var(--space-5) var(--space-3);
}

.sidebar-brand {
  padding: var(--space-2) var(--space-3) var(--space-5);
  font-size: var(--text-md);
  font-weight: var(--weight-semibold);
  color: var(--text-primary);
}

.sidebar-nav {
  display: flex;
  flex-direction: column;
  gap: var(--space-05);
}

.nav-group {
  display: flex;
  flex-direction: column;
  gap: 1px;
  margin-bottom: var(--space-4);
}

.nav-group-title {
  padding: var(--space-1) var(--space-3);
  font-size: var(--label-size);
  font-weight: var(--label-weight);
  color: var(--label-color);
}

/* 링크(활성 화면)와 비활성 항목(준비 중) 둘 다 이 클래스를 쓴다 — 위치가 흔들리면 안 된다 */
.nav-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  border-radius: var(--radius-md);
  padding: var(--space-2) var(--space-3);
  font-size: var(--text-base);
  line-height: var(--leading-snug);
  color: var(--text-body);
  text-decoration: none;
  transition: background var(--duration-fast) var(--ease-default);
}

a.nav-item:hover {
  background: var(--surface-hover);
}

a.nav-item[aria-current='page'] {
  background: var(--brand-50);
  color: var(--brand-hover);
  font-weight: var(--weight-semibold);
}

.main {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  border-bottom: 1px solid var(--border-default);
  background: var(--surface-card);
  padding: 0.875rem var(--space-6);
}

.topbar h1 {
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
}

.content {
  flex: 1 1 auto;
  padding: var(--space-6);
  max-width: var(--content-max);
}

/* ------------------------------------------------------------------ */
/* Auth shell — 첫 방문자 로그인 랜딩(`data-state="anon"`)             */
/*                                                                      */
/* `.shell`(사이드바·topbar)은 `[data-state]` 축 밖이라 show()가 지우지 */
/* 못한다 — port-mailroom과 달리 이 화면은 상시 셸이 있는 SPA라, anon */
/* 카드가 화면 전체를 덮어써 셸을 가린다(`position: fixed`). 시각적으로만 */
/* 덮으면 키보드 포커스가 뒤로 새므로 console-core.js의 show()가 셸에   */
/* `inert`도 같이 건다.                                                */
/* ------------------------------------------------------------------ */
.auth-shell {
  position: fixed;
  inset: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow-y: auto;
  min-height: 100dvh;
  padding: 3rem 1.5rem;
  background: var(--surface-app);
}

.auth-glow {
  pointer-events: none;
  position: fixed;
  inset: 0;
  background: var(--brand-glow);
}

.auth-card {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.5rem;
  width: 100%;
  max-width: 26rem;
  border-radius: var(--radius-xl);
  background: var(--surface-card);
  padding: 2rem;
  box-shadow: var(--shadow-2);
}

.auth-card > * {
  width: 100%;
}

.brand-lockup {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.75rem;
}

.brand-lockup svg {
  color: var(--brand);
}

.brand-lockup h1 {
  font-size: 1.25rem;
  line-height: 1.4;
  font-weight: 600;
  letter-spacing: -0.01em;
}

.auth-copy {
  font-size: 0.875rem;
  line-height: 1.6;
  color: var(--text-secondary);
  text-align: center;
}

.auth-footer {
  margin-top: 0.75rem;
  font-size: 0.75rem;
  line-height: 1.5;
  color: var(--text-secondary);
  text-align: center;
}

/* ------------------------------------------------------------------ */
/* Card                                                               */
/* ------------------------------------------------------------------ */
.card {
  margin-bottom: var(--space-6);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg);
  background: var(--surface-card);
  box-shadow: var(--shadow-1);
  padding: var(--space-6);
}

.card:last-child {
  margin-bottom: 0;
}

.card-header {
  margin-bottom: var(--space-5);
}

.card-header h2 {
  margin-bottom: var(--space-15);
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
}

.card-header p {
  max-width: 48rem;
  font-size: var(--text-base);
  line-height: var(--leading-normal);
  color: var(--text-secondary);
}

/* 접을 수 있는 카드 — 제목 줄 오른쪽에 접기 버튼. 접히면 머리 아래 여백도 줄인다. */
.card-header--toggle {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
}

.card-header--toggle[data-collapsed] {
  margin-bottom: var(--space-3);
}

/* 접힌 조회 결과의 요약 한 줄 — 누구를 보고 있는지만 남긴다. 칸은 고정 열이고 긴 값은
   말줄임 + title(ui.md §10) — 상호가 길어도 옆 칸이 밀리지 않는다. */
.result-summary {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.6fr) minmax(0, 1fr) minmax(0, 1fr) minmax(
      0,
      1.2fr
    );
  gap: var(--space-5);
  margin: 0;
  font-size: var(--text-sm);
}

/* 이름을 값 위에 둔다 — 옆에 두면 좁은 폭에서 이름이 값 자리를 먹는다. */
.result-summary div {
  display: grid;
  gap: var(--space-1);
  min-width: 0;
}

.result-summary dt {
  font-size: var(--text-xs);
  color: var(--text-secondary);
}

.result-summary dd {
  margin: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: var(--weight-medium);
  color: var(--text-primary);
}

/* ------------------------------------------------------------------ */
/* Buttons                                                            */
/* ------------------------------------------------------------------ */
.btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  border: 0;
  border-radius: var(--radius-md);
  padding: var(--space-2) var(--space-4);
  font-family: inherit;
  font-size: var(--text-base);
  line-height: var(--leading-snug);
  font-weight: var(--weight-medium);
  white-space: nowrap;
  cursor: pointer;
  transition:
    background var(--duration-fast) var(--ease-default),
    transform var(--duration-fast) var(--ease-default);
}

.btn-sm {
  padding: var(--space-15) var(--space-3);
  font-size: var(--text-xs);
}

.btn-block {
  width: 100%;
}

.btn-primary {
  background: var(--brand-hover);
  color: #ffffff;
}

.btn-primary:hover {
  background: var(--brand-active);
}

.btn-primary:active {
  background: var(--brand-press);
  transform: scale(0.98);
}

.btn-secondary {
  border: 1.5px solid var(--border-default);
  background: var(--surface-card);
  color: var(--text-body);
}

.btn-secondary:hover {
  background: var(--surface-subtle);
}

.btn-danger {
  background: var(--danger-solid);
  color: #ffffff;
}

.btn-danger:hover {
  background: var(--danger-solid-hover);
}

.btn-danger:active {
  background: var(--danger-solid-active);
  transform: scale(0.98);
}

/*
 * 흰 아웃라인(#ffffff)이 --surface-card(#ffffff) 배경 위에서 안 보이던 반전 버그 수정.
 * 브랜드색 아웃라인 + 포커스 링으로 통일 — .input·.select·사이드바 링크도 같은 규칙을 쓴다.
 */
.btn-primary:focus-visible,
.btn-danger:focus-visible,
.input:focus-visible,
.select:focus-visible,
a.nav-item:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
  box-shadow: 0 0 0 4px var(--brand-focus-ring);
}

.btn:disabled,
.btn[aria-disabled='true'] {
  opacity: 0.4;
  cursor: not-allowed;
  pointer-events: none;
}

/* 줄바꿈 없음(ui.md §10) — 버튼 그룹이 두 줄로 갈라지면 칸 폭이 내용에 흔들린다.
   다 안 들어가면 가로 스크롤로(넘칠 만큼 버튼이 쌓이는 화면은 없다 — 방어적 처리) */
.actions {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: var(--space-2);
  overflow-x: auto;
}

/* 조회 폼의 실행 버튼 줄 — 폼 우측에 붙인다(입력 격자의 오른쪽 끝과 시선을 맞춘다) */
.actions--end {
  justify-content: flex-end;
}

/* ------------------------------------------------------------------ */
/* Tabstrip — 한 결과 안에서 대상을 바꿔 가며 보는 가로 탭            */
/* (사이드바 .nav-item 은 화면 이동, 이쪽은 같은 화면 안의 대상 전환) */
/* ------------------------------------------------------------------ */
.tabstrip {
  display: flex;
  flex-wrap: nowrap;
  gap: var(--space-1);
  overflow-x: auto;
  border-bottom: 1px solid var(--border-default);
  margin-bottom: var(--space-4);
}

.tabstrip-item {
  flex: 0 0 auto;
  border: 0;
  border-bottom: 2px solid transparent;
  background: none;
  padding: var(--space-2) var(--space-3);
  font-family: inherit;
  font-size: var(--text-base);
  line-height: var(--leading-snug);
  color: var(--text-secondary);
  white-space: nowrap;
  cursor: pointer;
}

.tabstrip-item:hover {
  color: var(--text-body);
}

.tabstrip-item[aria-selected='true'] {
  border-bottom-color: var(--brand);
  color: var(--brand-hover);
  font-weight: var(--weight-semibold);
}

.tabstrip-item[aria-busy='true'] {
  color: var(--text-disabled);
  cursor: progress;
}

.tabstrip-item:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: -2px;
}

/* 격자 페이지 넘김 — id 규약(-prev·-next·-range)은 console-core.js의
   renderPagingControls()와의 계약이라 바꾸지 않는다. 감싸는 마크업만 grid로 정리 */
.pager {
  display: grid;
  grid-template-columns: auto auto 1fr;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-4);
}

.pager-range {
  font-size: var(--text-xs);
  color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
  text-align: right;
}

/* ------------------------------------------------------------------ */
/* Inline text primitives                                             */
/* ------------------------------------------------------------------ */
.num {
  font-variant-numeric: tabular-nums;
}

/*
 * 주요경영지표만 숫자를 오른쪽에 붙인다 — 결산 회차를 가로로 훑으며 자릿수를 비교하는
 * 표라 소수점이 세로로 맞아야 읽힌다. `.num`은 시각·소요처럼 비교하지 않는 칸에도 쓰여
 * 전역으로 올리면 이력 표의 정렬까지 바뀐다.
 */
#detail-panel-indicators .table th.num,
#detail-panel-indicators .table td.num {
  text-align: right;
}

/* 운임지수·시황 보고서 표 — 값을 세로로 훑으며 비교하는 표라 숫자를 오른쪽에 붙인다
   (#detail-panel-indicators 와 같은 근거). 머리글도 같이 움직여야 열이 안 어긋난다. */
[data-tab-panel='indices'] .table th.num,
[data-tab-panel='indices'] .table td.num,
[data-tab-panel='reports'] .table th.num,
[data-tab-panel='reports'] .table td.num {
  text-align: right;
}

/* 회계기준·재무구분 필터 블록과 표 사이 — 필터 아래 힌트(.hint)가 위쪽 여백은 이미 갖고
   있어서 표 쪽만 띄운다. */
#detail-panel-indicators .table-scroll,
#detail-panel-financial-statements .table-scroll {
  margin-top: var(--space-4);
}

/* 단위 줄이 표 바로 위에 붙으면 위 여백은 단위 줄이 이미 갖고 있다 */
#detail-panel-indicators .table-unit + .table-scroll,
#detail-panel-financial-statements .table-meta + .table-scroll {
  margin-top: var(--space-2);
}

/* 표 단위 — 모든 표가 상단 우측에 같은 모양(`(단위: 천원)`)으로 적는다. 라벨·값에 단위를
   섞지 않는다. 왼쪽 캡션(회계기준 등)이 있으면 `.table-meta`가 한 줄에 나눠 세운다. */
.table-unit {
  margin-top: var(--space-3);
  margin-left: auto;
  font-size: var(--text-sm);
  color: var(--text-secondary);
  text-align: right;
  white-space: nowrap;
}

.table-meta {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
}

.table-unit + .report-table {
  margin-top: var(--space-1);
}

.hint {
  margin-top: var(--space-3);
  font-size: var(--text-base);
  line-height: var(--leading-normal);
  color: var(--text-secondary);
}

/* ------------------------------------------------------------------ */
/* Callout — 인라인 알림 배너                                          */
/* ------------------------------------------------------------------ */
.callout {
  display: flex;
  gap: var(--space-3);
  margin-bottom: var(--space-6);
  border: 1.5px solid var(--border-default);
  border-radius: var(--radius-lg);
  padding: var(--space-4) 1.125rem;
  font-size: var(--text-md);
  line-height: var(--leading-normal);
}

.callout strong {
  display: block;
  margin-bottom: 0.15rem;
  color: inherit;
}

.callout[data-tone='info'] {
  background: var(--callout-info-bg);
  border-color: var(--callout-info-border);
  color: var(--callout-info-text);
}

.callout[data-tone='success'] {
  background: var(--callout-success-bg);
  border-color: var(--callout-success-border);
  color: var(--callout-success-text);
}

.callout[data-tone='warning'] {
  background: var(--callout-warning-bg);
  border-color: var(--callout-warning-border);
  color: var(--callout-warning-text);
}

.callout[data-tone='danger'] {
  background: var(--callout-danger-bg);
  border-color: var(--callout-danger-border);
  color: var(--callout-danger-text);
}

/*
 * Toast — `#banner`를 화면 우상단에 고정한 콜아웃. 스크롤을 내린 채로도 조치 결과가 보여야 한다.
 * `popover`의 UA 기본값(inset 0 · margin auto · 가운데 정렬)을 걷어내고 자리를 다시 잡는다.
 * `.callout`의 `display: flex`가 UA의 닫힘 상태 `display: none`을 이기므로 닫힘을 다시 적는다.
 */
.toast {
  position: fixed;
  inset: var(--space-4) var(--space-4) auto auto;
  align-items: center;
  width: max-content;
  max-width: min(28rem, calc(100vw - 2 * var(--space-4)));
  margin: 0;
  box-shadow: var(--shadow-1);
}

.toast:not(:popover-open) {
  display: none;
}

.toast p {
  flex: 1;
  margin: 0;
  overflow-wrap: anywhere;
}

@media (prefers-reduced-motion: no-preference) {
  .toast:popover-open {
    animation: modal-in var(--duration-fast) var(--ease-default);
  }
}

/* ------------------------------------------------------------------ */
/* Badge — 상태 표시. 색은 보조(색약 접근성) — 텍스트가 항상 의미를 진다  */
/* ------------------------------------------------------------------ */
.badge {
  display: inline-flex;
  align-items: center;
  border-radius: var(--radius-pill);
  padding: var(--space-05) 0.625rem;
  font-size: var(--text-xs);
  line-height: var(--leading-tight);
  font-weight: var(--weight-medium);
  white-space: nowrap;
  background: var(--badge-neutral-bg);
  color: var(--badge-neutral-text);
}

.badge[data-status='ACTIVE'],
.badge[data-status='ACCEPTED'] {
  background: var(--badge-success-bg);
  color: var(--badge-success-text);
}

.badge[data-status='PENDING'],
.badge[data-status='OPEN'] {
  background: var(--badge-warning-bg);
  color: var(--badge-warning-text);
}

.badge[data-status='DISABLED'],
.badge[data-status='REVOKED'] {
  background: var(--badge-danger-bg);
  color: var(--badge-danger-text);
}

/* 만료는 별도 상태값이 아니라 화면이 계산한 파생 표시다(ui.md — derived, not a status) */
.badge[data-status='EXPIRED'] {
  background: var(--badge-neutral-bg);
  color: var(--badge-neutral-text);
}

.badge[data-role='VIEWER'] {
  background: var(--badge-neutral-bg);
  color: var(--badge-neutral-text);
}

.badge[data-role='ADMIN'] {
  background: var(--badge-brand-bg);
  color: var(--badge-brand-text);
}

/* ------------------------------------------------------------------ */
/* Empty / loading                                                    */
/* ------------------------------------------------------------------ */
.empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-4);
  max-width: 480px;
  margin-inline: auto;
  padding: var(--space-8) 0;
  text-align: center;
}

.empty-title {
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
  color: var(--text-body);
}

.empty-desc {
  font-size: var(--text-base);
  line-height: var(--leading-normal);
  color: var(--text-secondary);
}

.loading {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  padding: var(--space-4) 0;
  font-size: var(--text-base);
  color: var(--text-secondary);
}

.spinner {
  width: 1.5rem;
  height: 1.5rem;
  flex-shrink: 0;
  border: 2px solid var(--border-default);
  border-top-color: var(--brand);
  border-radius: 50%;
  animation: spin 750ms linear infinite;
}

@keyframes spin {
  to {
    rotate: 360deg;
  }
}

/* ------------------------------------------------------------------ */
/* Table                                                              */
/* ------------------------------------------------------------------ */
/*
 * 열 폭 고정 — table-layout: fixed + <colgroup>(ui.md §4·§10). CSS Grid로 재작성하지 않는다:
 * <th scope="col"> 스크린리더 관계와 인쇄 display: table-header-group을 그대로 쓰면서
 * 같은 목표(열 위치가 내용에 안 흔들림)를 더 적은 변경으로 만족한다.
 */
.table-scroll {
  max-height: 34rem;
  overflow: auto;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg);
}

.table {
  table-layout: fixed;
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);
  font-variant-numeric: tabular-nums;
}

.table th,
.table td {
  height: var(--row-h);
  padding: var(--space-2) var(--space-3);
  text-align: left;
  vertical-align: middle;
  border-bottom: 1px solid var(--border-default);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.table th {
  background: var(--surface-subtle);
  font-size: var(--label-size);
  font-weight: var(--label-weight);
  color: var(--label-color);
}

.table thead th {
  position: sticky;
  top: 0;
  z-index: 1;
}

.table tbody tr:last-child td {
  border-bottom: 0;
}

.table tbody tr:hover {
  background: var(--surface-hover);
}

/* <colgroup><col class="col-*"> 폭 유틸리티 — table-layout: fixed와 짝. 폭을 안 준 열은
   남는 폭을 나눠 갖는다(가변 텍스트 열) */
.col-time {
  width: 9.5rem;
}

.col-brn {
  width: 7rem;
}

/* B/L 번호(ADR-0008) — BRN보다 자릿수가 가변적이라 폭을 조금 더 준다 */
.col-bl {
  width: 8.5rem;
}

.col-badge {
  width: 6rem;
}

.col-badge-lg {
  width: 7rem;
}

.col-ms {
  width: 5.5rem;
}

.col-short {
  width: 4rem;
}

/* 시각 없는 날짜(YYYY-MM-DD) 전용 — col-time(9.5rem)은 시:분까지 담는 폭이라 과하다 */
.col-date {
  width: 6.75rem;
}

/* 지표·항목 이름 열 — 가장 긴 라벨(매출액영업이익률, 8자)이 잘리지 않는 폭 */
.col-metric {
  width: 9.5rem;
}

/* NICE 기본정보 항목명 열 — 라벨 대부분이 들어가는 폭. 가장 긴 라벨
   ((구)우편번호(6자리), 12자)은 말줄임되고 전체값은 title로 남는다(ui.md §10) */
.col-field {
  width: 11rem;
}

/* 시황 보고서(ADR-0016)의 게시판 이름 열 — 가장 긴 라벨(닝보 컨테이너선 보고서, 12자)이
   들어가는 폭. col-field(NICE 항목명)와 값이 같아도 열의 뜻이 달라 따로 둔다 */
.col-board {
  width: 11.5rem;
}

.col-mid {
  width: 5rem;
}

/* 운임지수 표(ADR-0010) 전용 폭. 이름 열(시리즈)만 폭을 안 주면 남는 폭을 전부 먹고
   값 열이 col-short(4rem)로 눌린다 — `54,962`가 `54,9…`로 잘리고 `-12.34%`도 못 읽는다.
   값·변화율·항로 구분은 가장 긴 실측값이 들어가는 폭으로 먼저 떼어 둔다. */
.col-value {
  width: 7rem;
}

.col-rate {
  width: 5.5rem;
}

/* KCCI 항로 구분(`Non-Mainlane` · `Intra Asia` · `Mainlane`) — 원천 원문이라 번역이 없다 */
.col-lane {
  width: 8rem;
}

/* 시리즈 이름 열. 폭을 안 주면 남는 폭을 혼자 다 먹어 이름과 값이 화면 양 끝으로 갈라지고
   한 행을 읽는 데 눈이 500px을 건넌다. 가장 긴 이름(`Australia & New Zealand`)이 들어가는
   폭만 잡고, 남는 폭은 모든 열이 비율대로 나눠 갖는다. */
.col-series {
  width: 16rem;
}

.col-actions-sm {
  width: 8rem;
}

.col-actions-md {
  width: 10rem;
}

.col-actions-lg {
  width: 14rem;
}

/* ------------------------------------------------------------------ */
/* Forms                                                              */
/* ------------------------------------------------------------------ */
.form-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--space-3);
  align-items: end;
}

.form-grid--2 {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.field {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  min-width: 0;
}

.field--span2 {
  grid-column: span 2;
}

/* 입력 격자의 남는 칸에 서는 실행 버튼. 별도 줄(`.actions--end`)로 내리면 입력에서 멀어지고
   바로 아래 표와의 사이에 끼어 어느 쪽 것인지 안 읽힌다. `.form-grid`가 align-items: end라
   버튼 바닥선이 입력 바닥선과 맞고, `flex-start`로 칸 폭만큼 늘어나지 않게 잡는다. */
.field--action {
  align-items: flex-start;
}

/* 실행 버튼이 격자 안으로 들어오면 폼과 결과 표가 맞붙는다 — 버튼 줄이 주던 간격을
   표 쪽에서 되돌려 받는다. 시황 보고서 탭에만 건다: `.form-grid + .table-scroll`을 전역으로
   두면 같은 모양인 관리자 초대 목록까지 같이 벌어진다(이번 변경 밖이다). */
[data-tab-panel='reports'] .form-grid + .table-scroll {
  margin-top: var(--space-5);
}

/* 관세청환율 목록은 통화가 50개 안팎이라 기본 높이(34rem)로는 스크롤이 길다. 헤더·필터 줄을 뺀
   나머지를 쓰되, 낮은 창에서도 몇 줄은 보이게 하한을 둔다. 상세 창의 표는 대상이 아니다. */
[data-tab-panel='customs-fx'] .card > .table-scroll {
  max-height: max(20rem, calc(100dvh - 25rem));
}

.field label {
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  color: var(--text-secondary);
}

.field-error {
  font-size: var(--text-xs);
  color: var(--text-error);
}

/*
 * 라벨·값 글꼴 분리(ui.md §9) — 같은 칸에 라벨과 값이 붙을 때 <span>을 갈라 이 두 클래스를
 * 쓴다. 라벨은 작고(11px) 굵고 흐리게, 값은 본문 크기·색으로 — 붙어 있어도 한 단어로
 * 안 읽힌다. `.stat dt`·`.detail-grid dt`도 같은 라벨 규칙으로 통합한다.
 */
.label,
.stat dt,
.detail-grid dt {
  font-size: var(--label-size);
  font-weight: var(--label-weight);
  color: var(--label-color);
}

.value {
  font-size: var(--value-size);
  color: var(--value-color);
}

.input,
.select {
  min-height: var(--control-h);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  background: var(--surface-card);
  font: inherit;
  font-size: var(--text-base);
  color: var(--text-body);
}

.select-sm,
.input-sm {
  min-height: var(--control-h-sm);
  padding: var(--space-1) var(--space-2);
  font-size: var(--text-sm);
}

/* TTL 입력은 격자 열 폭을 흔들지 않게 고정 폭 */
.input-sm[type='number'] {
  width: 7rem;
}

.input:disabled,
.select:disabled {
  opacity: 0.4;
  cursor: not-allowed;
  pointer-events: none;
}

.checkbox-group {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));
  gap: var(--space-1) 0.875rem;
  min-height: var(--control-h);
  align-items: center;
}

.checkbox-group label {
  display: inline-flex;
  align-items: center;
  gap: var(--space-15);
  font-size: var(--text-base);
  font-weight: var(--weight-normal);
  color: var(--text-body);
}

.checkbox-group input[type='checkbox']:disabled + span {
  opacity: 0.4;
}

/*
 * 토글 — 값이 켜짐/꺼짐 두 갈래뿐인 설정 하나. 두 갈래를 select로 두면 고르기 전에 현재
 * 값을 읽을 수 없다. 네이티브 checkbox + role="switch"를 쓴다(클릭 가능한 div는 키보드·
 * 스크린리더에서 상태가 없다) — 라벨은 명사구 고정이고 상태는 스위치가 말한다(ui.md §1·§5).
 */
.switch {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: var(--control-h);
  font-size: var(--text-base);
  color: var(--text-body);
  cursor: pointer;
}

.switch input[type='checkbox'] {
  appearance: none;
  position: relative;
  flex: none;
  margin: 0;
  width: 2.25rem;
  height: 1.25rem;
  border-radius: 999px;
  background: var(--p-neutral-300);
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease-default);
}

.switch input[type='checkbox']::after {
  content: '';
  position: absolute;
  top: 0.125rem;
  left: 0.125rem;
  width: 1rem;
  height: 1rem;
  border-radius: 50%;
  background: var(--surface-card);
  box-shadow: var(--shadow-1);
  transition: translate var(--duration-fast) var(--ease-default);
}

.switch input[type='checkbox']:checked {
  background: var(--brand-hover);
}

.switch input[type='checkbox']:checked::after {
  translate: 1rem 0;
}

.switch input[type='checkbox']:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
  box-shadow: 0 0 0 4px var(--brand-focus-ring);
}

@media (prefers-reduced-motion: reduce) {
  .switch input[type='checkbox'],
  .switch input[type='checkbox']::after {
    transition: none;
  }
}

/* 입력 한 칸 + 버튼이 같은 줄에 서는 폼. `.field`가 늘어나고 버튼은 바닥선에 맞춘다. */
.inline-form {
  display: flex;
  align-items: flex-end;
  gap: var(--space-2);
}

.inline-form .field {
  flex: 1 1 auto;
  max-width: 22rem;
}

/*
 * 서브탭 — 사이드바 탭(`data-tab-*`)과 **다른 축**이다. 한 화면 안에서 같은 주체(BRN)의
 * 다른 면을 번갈아 보는 자리라 사이드바와 같은 모양을 쓰면 어느 축이 움직였는지 안 보인다.
 * 밑줄 강조 하나로만 구분한다(ui.md §4 — 격자를 흔들지 않는다).
 */
.subtabs {
  display: flex;
  gap: var(--space-1);
  border-bottom: 1px solid var(--border-default);
  margin-bottom: var(--space-4);
  overflow-x: auto;
}

.subtab {
  appearance: none;
  flex: none;
  border: 0;
  border-bottom: 2px solid transparent;
  border-radius: 0;
  background: none;
  padding: var(--space-2) var(--space-3);
  font: inherit;
  font-size: var(--text-base);
  font-weight: var(--weight-medium);
  color: var(--text-secondary);
  white-space: nowrap;
  cursor: pointer;
}

.subtab:hover {
  color: var(--text-body);
}

.subtab[aria-selected='true'] {
  color: var(--brand-hover);
  border-bottom-color: var(--brand-hover);
}

.subtab:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: -2px;
}

/*
 * 상세 미조회 자리 — 기본 조회 직후 서브탭 아래가 비면 "조회가 안 됐다"로 읽힌다. 유료 원천은
 * 탭을 눌러야 부르므로, 빈 자리를 다음 행동(위 탭)으로 채운다. 점선 테두리는 "아직 채워지지
 * 않은 자리"의 관용 표현이고, 화살표 아이콘이 탭 쪽을 가리킨다.
 */
.pending-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-1);
  border: 1.5px dashed var(--callout-info-border);
  border-radius: var(--radius-lg);
  background: var(--callout-info-bg);
  padding: var(--space-6) var(--space-4);
  text-align: center;
  font-size: var(--text-base);
  line-height: var(--leading-normal);
  color: var(--text-secondary);
}

.pending-state[hidden] {
  display: none;
}

.pending-state strong {
  font-weight: var(--weight-medium);
  color: var(--callout-info-text);
}

.pending-state-icon {
  width: 1.25rem;
  height: 1.25rem;
  fill: none;
  stroke: var(--callout-info-border);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

@media (prefers-reduced-motion: no-preference) {
  .pending-state-icon {
    animation: pending-nudge 1.6s ease-in-out 3;
  }
}

@keyframes pending-nudge {
  50% {
    transform: translateY(-3px);
  }
}

/*
 * 원천 칩 줄 — 원천별 결과를 표로 펼치면 정작 읽어야 할 조회 결과보다 커진다. 원천 수는
 * 엔드포인트가 고정하므로(ADR-0011) 한 줄이면 충분하다. 칩 자체가 원문 보기 버튼이다.
 */
.chip-row {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-4);
  overflow-x: auto;
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-15);
  border: 1px solid var(--border-default);
  border-radius: 999px;
  background: var(--surface-card);
  padding: var(--space-1) var(--space-3);
  font: inherit;
  font-size: var(--text-sm);
  color: var(--text-body);
  white-space: nowrap;
  cursor: pointer;
}

/*
 * 최근 조회 칩 — 원천 칩 줄(위)과 달리 flex가 아니라 격자다. 개수가 사람의 조회 이력에
 * 달렸고 상호명 길이도 제각각이라, 한 줄 flex면 가로 스크롤 뒤로 칩이 숨고 `flex-wrap:
 * wrap`이면 칸 크기를 내용이 정하게 된다(둘 다 ui.md §10 위반). 열 폭을 먼저 못 박고
 * 칩이 그 안에서 줄어들게 한다 — 상호명이 길든 짧든 격자가 흔들리지 않는다.
 */
.chip-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
  gap: var(--space-2);
  margin-top: var(--space-2);
}

#recent-lookups {
  margin-top: var(--space-4);
}

/* 칩이 열 폭을 넘지 않는다 — 넘치는 상호명은 `.chip-label`이 말줄임으로 받는다. */
.chip-recent {
  min-width: 0;
  justify-content: space-between;
}

.chip-label {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

.chip-meta {
  flex: none;
  color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}

.chip:hover {
  background: var(--surface-hover);
}

.chip:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}

.chip:disabled {
  opacity: 0.55;
  cursor: default;
}

.chip .badge {
  margin-left: var(--space-1);
}

/* ------------------------------------------------------------------ */
/* 요약 지표 타일 — 라벨/값 폰트를 나눈다(ui.md 격자 규칙)             */
/* ------------------------------------------------------------------ */
.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
  gap: var(--space-4);
  margin: 0;
}

.stat {
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  background: var(--surface-subtle);
  padding: 0.875rem var(--space-4);
}

.stat dd {
  margin: var(--space-1) 0 0;
  color: var(--text-primary);
  font-size: var(--text-xl);
  font-variant-numeric: tabular-nums;
}

.stat-delta {
  margin: var(--space-1) 0 0;
  color: var(--text-secondary);
  font-size: var(--text-xs);
  font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------------------ */
/* 외부 통신 원문 카드 — 조회 이력 상세·외부 통신 이력 격자가 공유한다.   */
/* 접이식(<details>) — 기본은 표지(배지·제목·일자)만, 눌러서 펼친다     */
/* ------------------------------------------------------------------ */
.disclosure {
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  margin-bottom: var(--space-2);
}

.disclosure > summary {
  position: relative;
  display: grid;
  grid-template-columns: 6rem minmax(0, 1fr) 9.5rem;
  gap: var(--space-3);
  align-items: center;
  padding: var(--space-2) var(--space-6) var(--space-2) var(--space-3);
  cursor: pointer;
  list-style: none;
}

/* display: grid가 <summary>의 네이티브 펼침 마커(list-item 전용)를 지운다 — 대체 화살표 */
.disclosure > summary::after {
  content: '▸';
  position: absolute;
  right: var(--space-3);
  top: 50%;
  transform: translateY(-50%);
  color: var(--text-secondary);
}

.disclosure[open] > summary {
  border-bottom: 1px solid var(--border-default);
}

.disclosure[open] > summary::after {
  content: '▾';
}

.disclosure-body {
  padding: var(--space-3);
}

/* 라벨 열 고정 — 값이 길어도 라벨 열이 밀리지 않는다(ui.md 격자 규칙) */
.detail-grid {
  display: grid;
  grid-template-columns: 8rem minmax(0, 1fr);
  gap: var(--space-2) var(--space-4);
  margin: 0;
}

.detail-grid dd {
  margin: 0;
  min-width: 0;
  color: var(--text-body);
  font-size: var(--text-sm);
  overflow-wrap: anywhere;
}

.detail-grid pre,
/* 원문 카드(`#lookup-raw-payload`)도 같은 규칙 — 긴 JSON이 카드를 가로로 밀지 않는다(ui.md §10) */
#lookup-raw-payload,
#kodata-raw-payload {
  margin: 0;
  max-height: 16rem;
  overflow: auto;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  background: var(--surface-subtle);
  padding: var(--space-2) var(--space-3);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

@media print {
  .sidebar,
  #logout,
  #banner,
  #retry,
  .actions,
  .form-grid,
  .pager {
    display: none !important;
  }

  body {
    background: #ffffff;
    color: #000000;
  }

  .content {
    max-width: none;
    padding: 0;
  }

  .card {
    box-shadow: var(--shadow-0);
    border-color: #000000;
    break-inside: avoid;
  }

  .table-scroll,
  [data-tab-panel='customs-fx'] .card > .table-scroll {
    max-height: none;
    overflow: visible;
    border-color: #000000;
  }

  .table {
    table-layout: auto;
  }

  .table th,
  .table td {
    border-color: #000000;
    color: #000000;
    white-space: normal;
    overflow: visible;
  }

  .table thead {
    display: table-header-group;
  }

  .table tbody tr {
    break-inside: avoid;
  }

  .badge {
    background: none !important;
    color: #000000 !important;
    border: 1px solid #000000;
  }

  a[href]::after {
    content: '';
  }
}

/* NICE 기본정보 상세 — 공통 9필드 표와 붙지 않게 띄운다 */
#detail-profile-source {
  margin-top: var(--space-5);
}

#detail-profile-sites > section {
  margin-top: var(--space-5);
}

/* ------------------------------------------------------------------ */
/* 기업 리포트 (A4 인쇄)                                               */
/* 조회 뷰와 리포트 뷰는 같은 탭의 두 상태다 — 새 탭으로 넘기지 않는다  */
/* (exec-plan 2026-09-18 결정 3). 화면에서는 종이 모양 그대로 미리보기다 */
/* ------------------------------------------------------------------ */
:root {
  /* 계열 색 — 파랑 · 주황 · 청록. 서열이 아니라 구분이고, 의미는 항상 글자가 진다.
     validate_palette(dataviz) 통과: 인접 쌍 CVD ΔE 12 이상 · 표면 대비 3:1 이상.
     흑백 인쇄에서는 세 색의 명도가 가까워 막대에 무늬를 겹친다(report-chart.js `texture`). */
  --chart-1: var(--p-primary-600);
  --chart-2: #d26c28;
  --chart-3: #008f89;
  --chart-grid: var(--border-default);
  --chart-axis-text: var(--text-secondary);

  /* A4 세로 실측 — 인쇄 여백을 뺀 본문 폭 */
  --page-w: 210mm;
  --page-pad: 14mm 12mm;
}

[data-view='lookup'] #report {
  display: none;
}

[data-view='report'] > .card {
  display: none;
}

.report-toolbar {
  margin-bottom: var(--space-4);
}

.report-doc {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-6);
}

/* 한 쪽 = 한 장. 화면에서도 종이 폭으로 고정한다 — 미리보기와 인쇄물이 갈리면 미리보기가
   거짓말을 한다. 높이는 내용이 정한다(빈 종이 아래쪽을 억지로 만들지 않는다). */
.report-page {
  box-sizing: border-box;
  width: var(--page-w);
  max-width: 100%;
  padding: var(--page-pad);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg);
  background: var(--surface-card);
  box-shadow: var(--shadow-1);
  break-after: page;
}

.report-page:last-child {
  break-after: auto;
}

/* 문서 머리 — 종류(왼쪽)와 기준 시각(오른쪽)이 한 줄이다. 상호는 여기 오지 않는다:
   문서 종류보다 크게, 식별 블록의 제목으로 선다. */
.report-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  padding-bottom: var(--space-2);
  border-bottom: 2px solid var(--text-primary);
}

.report-asof {
  font-size: var(--text-xs);
  color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}

/* 문서 종류를 먼저 말하는 작은 머리글 — 제목(상호)과 같은 크기면 한 덩어리로 읽힌다(ui.md §9) */
.report-kicker {
  font-size: var(--label-size);
  font-weight: var(--label-weight);
  letter-spacing: 0.06em;
  color: var(--brand);
}

.report-head h2 {
  margin-top: var(--space-1);
  font-size: var(--text-xl);
  font-weight: var(--weight-bold);
  line-height: var(--leading-tight);
  color: var(--text-primary);
}

/* 식별 블록 — 왼쪽은 사실 목록, 오른쪽은 등급 상자. 신용의견서의 1쪽 머리다.
   등급 상자는 폭을 고정한다(등급 문자열 길이에 따라 사실 목록 폭이 흔들리면 안 된다). */
.report-identity {
  display: grid;
  grid-template-columns: 1fr 34mm;
  align-items: start;
  gap: var(--space-5);
  margin-top: var(--space-4);
}

.report-company-en {
  margin-top: var(--space-05);
  font-size: var(--text-sm);
  color: var(--text-secondary);
}

/* `라벨  값` 목록. 라벨 폭을 고정해 값의 왼쪽 끝이 한 줄로 선다 — 이게 표 없이도
   표처럼 읽히게 하는 유일한 장치다. */
.report-facts {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-1) var(--space-5);
  margin-top: var(--space-3);
}

.report-facts--wide {
  grid-template-columns: 1fr 1fr;
}

.report-facts > div {
  display: grid;
  grid-template-columns: 7rem 1fr;
  gap: var(--space-2);
  align-items: baseline;
  break-inside: avoid;
}

.report-facts dt {
  font-size: var(--label-size);
  font-weight: var(--label-weight);
  color: var(--label-color);
}

.report-facts dd {
  font-size: var(--text-base);
  color: var(--text-body);
  word-break: keep-all;
  overflow-wrap: break-word;
}

/* 등급 상자 — 이 문서에서 제일 먼저 보여야 하는 값 하나 */
.report-grade {
  border: 2px solid var(--text-primary);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-2);
  text-align: center;
}

.report-grade-value {
  font-size: var(--text-2xl);
  font-weight: var(--weight-bold);
  line-height: var(--leading-tight);
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}

.report-grade-caption {
  margin-top: var(--space-1);
  font-size: var(--label-size);
  font-weight: var(--label-weight);
  letter-spacing: 0.04em;
  color: var(--label-color);
}

.report-grade-since {
  margin-top: var(--space-05);
  font-size: var(--text-xs);
  color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}

/* 쪽 안의 절 제목 — 쪽 제목(2px)보다 한 단 약한 선으로 위계를 만든다.
   종이에서 제목만 앞 장에 남는 걸 막는다(한 쪽에 절이 여럿인 리포트가 있다). */
.report-section-head {
  break-after: avoid;
  margin-top: var(--space-5);
  padding-bottom: var(--space-1);
  border-bottom: 1px solid var(--text-primary);
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
  color: var(--text-primary);
}

.report-site {
  margin-top: var(--space-2);
  break-inside: avoid;
}

/* 출처 한 줄 — 값마다 원천 열을 다는 대신 쪽 끝에서 한 번 밝힌다 */
.report-source {
  margin-top: var(--space-5);
  padding-top: var(--space-2);
  border-top: 1px solid var(--border-default);
  font-size: var(--text-xs);
  color: var(--text-secondary);
}

.report-page-title {
  padding-bottom: var(--space-2);
  border-bottom: 2px solid var(--text-primary);
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
  color: var(--text-primary);
}

.report-section-title {
  margin-top: var(--space-5);
}

/* 리포트 표는 스크롤하지 않는다 — 종이에는 스크롤이 없다(`.table-scroll`과 다른 점) */
/* 쪽 자체에는 break-inside를 걸지 않는다 — 등급 이력이 길면 한 장을 넘겨야 하고, 넘기지
   못하게 막으면 넘친 행이 종이 밖으로 잘린다. 잘리면 안 되는 건 행과 차트다. */
.report-table {
  margin-top: var(--space-2);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  overflow: hidden;
}

/* 종이에는 가로 스크롤이 없다 — 잘라내는 대신 접는다. 한글은 어절째 넘긴다
   (`break-word`만 두면 "부가가치세 일반과/세자"처럼 단어 중간에서 끊긴다). */
.report-table .table th,
.report-table .table td {
  white-space: normal;
  overflow: visible;
  text-overflow: clip;
  word-break: keep-all;
  overflow-wrap: break-word;
}

.report-table .table thead th {
  position: static;
}

.report-table .table tbody tr {
  break-inside: avoid;
}

#report-page-indicators .report-table .table th.num,
#report-page-indicators .report-table .table td.num {
  text-align: right;
}

/* 쪽 머리의 한 줄 요약(범위·회차) — 제목 바로 밑에 붙고 표와는 떨어진다 */
.report-lead {
  margin-top: var(--space-2);
  margin-bottom: var(--space-3);
}

/* 오늘 이후까지 유효한 구간 — 오른쪽 끝이 실제 끝이 아니라 축의 끝이다 */
.report-chart-band--open {
  stroke-dasharray: 5 3;
}

.report-missing {
  margin-top: var(--space-4);
  display: inline-flex;
  align-items: center;
  border-radius: var(--radius-pill);
  padding: var(--space-05) 0.625rem;
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  background: var(--badge-neutral-bg);
  color: var(--badge-neutral-text);
}

/* ------------------------------------------------------------------ */
/* 리포트 차트 (report-chart.js가 그리는 인라인 SVG)                    */
/* ------------------------------------------------------------------ */
.report-chart-box {
  margin-top: var(--space-2);
  break-inside: avoid;
}

.report-chart {
  display: block;
  width: 100%;
  height: auto;
}

.report-chart-grid {
  stroke: var(--chart-grid);
  stroke-width: 1;
}

/* 0선은 눈금선이 아니라 부호의 기준이다 — 굵기로 가른다 */
.report-chart-zero {
  stroke: var(--text-secondary);
  stroke-width: 1.5;
}

.report-chart-tick,
.report-chart-axis,
.report-chart-note {
  font-size: 11px;
  fill: var(--chart-axis-text);
  font-variant-numeric: tabular-nums;
}

.report-chart-legend,
.report-chart-point-label {
  font-size: 11px;
  font-weight: var(--weight-medium);
  fill: var(--text-body);
}

.report-chart-bar {
  fill: var(--chart-1);
}

.report-chart-line {
  fill: none;
  stroke: var(--chart-1);
  stroke-width: 2;
  stroke-linejoin: round;
}

.report-chart-dot {
  fill: var(--chart-1);
}

.report-chart-series-2 {
  fill: var(--chart-2);
  stroke: var(--chart-2);
}

.report-chart-series-3 {
  fill: var(--chart-3);
  stroke: var(--chart-3);
}

/* 계열을 색으로만 가르지 않는다 — 꺾은선은 선 모양이 1차 구분이다(흑백 인쇄·색각 이상) */
/* 점·라벨용 `.report-chart-series-N { fill }`과 명시도가 같아 뒤에 오면 선 아래가 칠해진다 — 선은 다시 비운다. */
.report-chart-line.report-chart-series-2 {
  fill: none;
  stroke-dasharray: 7 4;
}

.report-chart-line.report-chart-series-3 {
  fill: none;
  stroke-dasharray: 2 3;
}

/* 막대 위에 겹치는 무늬 — 색을 못 보는 상황(흑백 인쇄·색각 이상)의 보조 구분이다 */
.report-chart-texture {
  pointer-events: none;
}

.report-chart-texture-line {
  stroke: #ffffff;
  stroke-width: 1.5;
  stroke-opacity: 0.7;
}

.report-chart-texture-dot {
  fill: #ffffff;
  fill-opacity: 0.8;
}

.report-chart-band {
  fill: var(--brand-100);
  stroke: var(--chart-1);
  stroke-width: 1;
}

.report-chart-band-label {
  font-size: 12px;
  font-weight: var(--weight-semibold);
  fill: var(--text-primary);
}

/* ------------------------------------------------------------------ */
/* 인쇄 — A4 세로. 리포트 뷰가 켜져 있으면 조회 카드는 이미 display:none  */
/* 이라 인쇄물에는 리포트만 남는다.                                     */
/* ------------------------------------------------------------------ */
@page {
  size: A4 portrait;
  margin: 14mm 12mm;
}

@media print {
  .report-toolbar {
    display: none !important;
  }

  /* 리포트를 인쇄할 때만 화면 제목을 뺀다 — 리포트 표지가 이미 제목을 갖고 있어
     그대로 두면 인쇄물 맨 위에 제목이 둘이다. 조회 화면 인쇄는 예전 그대로다. */
  body[data-view='report'] .topbar {
    display: none;
  }

  /* 회색 글자는 종이에서 거의 안 나온다 */
  .report-asof,
  .report-company-en,
  .report-grade-since,
  .report-source {
    color: #000000;
  }

  /* 종이가 이미 여백을 주므로 쪽 자체는 테두리 없이 폭만 채운다 */
  .report-page {
    width: auto;
    max-width: none;
    padding: 0;
    border: 0;
    border-radius: 0;
    box-shadow: none;
  }

  /* 화면에선 종이 폭으로 고정해 가운데 세우지만, 인쇄물의 폭은 종이가 정한다 —
     center로 두면 width:auto인 쪽이 내용 폭까지 줄어 쪽마다 폭이 달라진다. */
  .report-doc {
    gap: 0;
    align-items: stretch;
  }

  .report-table {
    border-color: #000000;
  }

  /* 화면 색은 종이에서 옅게 나온다 — 선·글자를 검정 계열로 내린다 */
  .report-chart-grid {
    stroke: #666666;
  }

  /* 계열 색은 그대로 둔다(색 인쇄) — 흑백으로 나가도 막대는 무늬, 선은 파선 모양이 구분을 진다.
     막대·선·점의 색까지 검정·회색으로 내리면 계열 구분이 전부 사라진다. */
  .report-chart {
    print-color-adjust: exact;
    -webkit-print-color-adjust: exact;
  }

  .report-chart-zero,
  .report-chart-band {
    stroke: #000000;
  }

  .report-chart-band {
    fill: #ffffff;
  }

  .report-chart-tick,
  .report-chart-axis,
  .report-chart-note,
  .report-chart-legend,
  .report-chart-point-label,
  .report-chart-band-label {
    fill: #000000;
  }

  .report-kicker {
    color: #000000;
  }
}

/* ------------------------------------------------------------------ */
/* 연동 가이드 (`GET /guide`)                                          */
/* 콘솔이 아니라 읽는 문서다 — 격자·상태 규칙 대신 본문 조판이 필요하다.  */
/* 전역 리셋이 목록 들여쓰기와 문단 간격을 지웠으므로 이 화면 안에서만    */
/* 되살린다. 토큰은 그대로 쓴다 — 새 색·새 치수를 만들지 않는다.         */
/* ------------------------------------------------------------------ */
[data-page='guide'] .content {
  max-width: 64rem;
}

[data-page='guide'] .sidebar-nav {
  position: sticky;
  top: var(--space-5);
}

[data-page='guide'] .card p {
  font-size: var(--text-base);
  line-height: var(--leading-normal);
}

[data-page='guide'] .card > p + p,
[data-page='guide'] .card > ul,
[data-page='guide'] .card > ol,
[data-page='guide'] .card .table-scroll {
  margin-top: var(--space-4);
}

[data-page='guide'] .card h3 {
  margin-top: var(--space-6);
  margin-bottom: var(--space-3);
  font-size: var(--text-md);
  font-weight: var(--weight-semibold);
  color: var(--text-primary);
}

[data-page='guide'] .card-header + h3 {
  margin-top: 0;
}

[data-page='guide'] ul,
[data-page='guide'] ol {
  padding-left: 1.25rem;
  font-size: var(--text-base);
  line-height: var(--leading-normal);
}

[data-page='guide'] li + li {
  margin-top: var(--space-2);
}

[data-page='guide'] li strong {
  font-weight: var(--weight-semibold);
  color: var(--text-primary);
}

[data-page='guide'] code {
  border-radius: var(--radius-sm);
  background: var(--surface-subtle);
  padding: 0.05rem 0.3rem;
  font-family: var(--font-mono);
  font-size: 0.9em;
  color: var(--text-primary);
  overflow-wrap: anywhere;
}

[data-page='guide'] a {
  color: var(--brand-hover);
}

[data-page='guide'] a:hover {
  color: var(--brand-active);
}

/* 목차 링크는 본문 링크와 달리 밑줄 없이 콘솔 내비와 같은 모양을 유지한다 */
[data-page='guide'] .sidebar-nav a,
[data-page='guide'] .topbar a {
  color: var(--text-body);
  text-decoration: none;
}

[data-page='guide'] .callout p {
  margin-top: 0.15rem;
}

/* 문서의 표는 데이터 격자가 아니라 본문이다 — 콘솔의 한 줄 고정·말줄임(ui.md §10)은
   설명을 잘라 먹는다. 이 화면 안에서만 줄바꿈을 허용하고 위 정렬로 되돌린다 */
[data-page='guide'] .table th,
[data-page='guide'] .table td {
  height: auto;
  white-space: normal;
  overflow: visible;
  text-overflow: clip;
  vertical-align: top;
  line-height: var(--leading-snug);
}

[data-page='guide'] .table {
  table-layout: auto;
}

/* 표 안의 경로·파라미터는 쪼개지면 못 읽는다 — 한 덩어리로 두고 열 폭을 늘린다 */
[data-page='guide'] .table code {
  white-space: nowrap;
}

/* 콜아웃의 `strong`은 제목 줄이라 블록이다(위 `.callout strong`) — 본문 안에서 강조로 쓴
   것까지 줄을 끊으면 문장이 두 동강 난다 */
[data-page='guide'] .callout p strong {
  display: inline;
  margin-bottom: 0;
}

/* ------------------------------------------------------------------ */
/* 운임지수 탭 (ADR-0010) — 원천별 표 묶음 + 시리즈 선택                */
/* ------------------------------------------------------------------ */

/* 원천이 셋이라 표도 셋이다 — 한 표에 몰면 단위가 다른 값이 한 격자에 섞인다.
   셋을 세로로 쌓지 않고 서브탭으로 갈라 한 번에 하나만 띄운다(`data-subtab-panel`) —
   그래서 블록 사이 간격 규칙도, 블록마다 붙이던 제목(`.index-source-title`)도 없다.
   이름은 탭이 진다. */

/* 표 셀 안의 선택 버튼 — 링크처럼 보이되 이동이 아니라 아래 상세를 바꾼다 */
.link-button {
  padding: 0;
  border: 0;
  background: none;
  color: var(--brand-hover);
  font: inherit;
  text-align: left;
  cursor: pointer;
  /* 버튼은 <td>의 ellipsis를 물려받지 않는다 — 보고서 제목처럼 긴 값이 칸 밖으로 삐져
     나가 옆 열을 덮는다. 전문은 cell()이 단 title로 남는다(ui.md §10). */
  max-width: 100%;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.link-button:hover {
  text-decoration: underline;
}

/* 선택된 시리즈 — 색 하나로만 가르지 않는다(ui.md §5의 근거와 같다) */
.link-button[aria-current='true'] {
  font-weight: var(--weight-semibold);
  text-decoration: underline;
}

/* 선택된 구간 프리셋. 사이드바 탭은 `aria-current="page"`라 선택자가 겹치지 않는다 */
.btn[aria-current='true'] {
  border-color: var(--brand);
  background: var(--brand-50);
  color: var(--brand-hover);
  font-weight: var(--weight-semibold);
}

/* ------------------------------------------------------------------ */
/* 모달 — 목록에서 고른 한 건의 상세                                  */
/* ------------------------------------------------------------------ */

/*
 * 목록 아래에 카드를 펼치던 자리를 대신한다. 목록이 20~25행이면 그 카드는 화면 두 개 아래에
 * 열려서, 누른 사람에게는 아무 일도 안 일어난 것과 같다(운임지수 딥링크 신고의 원인).
 *
 * 네이티브 `<dialog>` 라 포커스 트랩·Esc·배경 inert 는 우리가 쓰지 않는다. `.card` 를 상속하지
 * 않는 이유는 `.card` 가 `margin-bottom` 과 문서 흐름을 전제하기 때문이다 — 여기선 배치를
 * 브라우저가 한다.
 */
.modal {
  width: min(880px, 92vw);
  max-height: 86vh;
  /* dialog 기본 여백·테두리를 걷어내고 우리 격자를 세운다 */
  margin: auto;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg);
  background: var(--surface-card);
  box-shadow: var(--shadow-1);
  padding: 0;
  color: var(--text-body);
  overflow: hidden;
}

/*
 * 머리줄을 고정하고 본문만 구르게 — 긴 첨부 목록에서 제목이 사라지지 않는다.
 * `[open]` 을 반드시 붙인다: `dialog` 를 닫아 두는 건 브라우저 기본 규칙
 * `dialog:not([open]) { display: none }` 하나뿐이라, 조건 없이 `display` 를 주면
 * 닫힌 창이 목록 아래에 그대로 펼쳐진다(실측).
 */
.modal[open] {
  display: flex;
  flex-direction: column;
}

.modal::backdrop {
  background: oklch(0.16 0.006 260.5 / 0.45);
}

/* 열릴 때만 움직인다. 위치·크기가 아니라 합성 속성만 건드려 레이아웃을 다시 계산하지 않는다 */
@media (prefers-reduced-motion: no-preference) {
  .modal[open] {
    animation: modal-in var(--duration-fast) var(--ease-default);
  }
}

@keyframes modal-in {
  from {
    opacity: 0;
    transform: translateY(var(--space-2));
  }
}

.modal-head {
  display: flex;
  align-items: start;
  gap: var(--space-4);
  border-bottom: 1px solid var(--border-default);
  padding: var(--space-5) var(--space-6);
}

.modal-title {
  flex: 1;
  min-width: 0;
}

.modal-title h2 {
  margin-bottom: var(--space-15);
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
  color: var(--text-primary);
}

/* 부제는 라벨 줄이다 — 제목과 같은 크기·색이면 한 덩이로 읽힌다(ui.md §9) */
.modal-subtitle {
  font-size: var(--text-sm);
  color: var(--text-secondary);
}

/*
 * 닫기 버튼. 글리프(×)가 아니라 글자를 쓰는 이유는 ui.md §11 과 같다 — 기호 하나는 읽는 쪽의
 * 말이 아니다. 44×44 는 손가락 최소 크기라 보조 버튼이라도 줄이지 않는다.
 */
.modal-close {
  flex: none;
  min-width: 2.75rem;
  min-height: 2.75rem;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  background: var(--surface-card);
  padding: 0 var(--space-3);
  font: inherit;
  font-size: var(--text-sm);
  color: var(--text-secondary);
  cursor: pointer;
}

.modal-close:hover {
  background: var(--surface-hover);
  color: var(--text-body);
}

.modal-close:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}

.modal-body {
  overflow-y: auto;
  padding: var(--space-6);
}

/*
 * 게시글 본문. 원천은 `<p>` 한 줄이 요약 한 줄인 불릿 목록이고 우리는 그걸 개행만 남긴
 * 평문으로 받는다 — 그래서 `pre-wrap` 이다. 태그를 안 쓰니 `innerHTML` 도 필요 없다.
 * 등폭 글꼴은 쓰지 않는다: 코드가 아니라 문장이다.
 */
.report-body {
  margin-bottom: var(--space-6);
  border-radius: var(--radius-md);
  background: var(--surface-subtle);
  padding: var(--space-4) var(--space-5);
  font-size: var(--text-base);
  line-height: 1.7;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* --- 하이픈 조회 --------------------------------------------------------- */

/* 기업 조회 리포트와 같은 규칙을 그대로 탄다 — 쪽·인쇄 CSS를 복제하지 않는다. */
[data-view='lookup'] #hyphen-report {
  display: none;
}

/* 항목이 아홉이라 한 줄로 늘어놓지 않고 성격별로 묶는다 — 묶음 제목이 곧 찾는 단서다. */
/* wrap 대신 격자다 — 줄바꿈을 폭이 정하면 묶음 경계가 화면마다 달라진다(ui.md §10). */
.subtab-groups {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
  gap: var(--space-4);
  margin-bottom: var(--space-4);
}

.subtab-group {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.hyphen-params {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
  align-items: end;
  gap: var(--space-3);
  margin-bottom: var(--space-3);
}

/* 계정명의 선행 공백이 계정 계층이다(출처 실측) — 접으면 표의 구조가 사라진다. */
.table td.pre {
  white-space: pre;
}

/* 숫자는 자릿수를 세로로 맞춘다 — 금액은 눈으로 자리를 비교한다. */
.table th.num,
.table td.num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/*
 * 열 수를 응답이 정하는 표. 고정 분할(`table-layout: fixed`)을 쓰면 열 열일곱짜리 축에서
 * 글자가 세로로 한 자씩 끊긴다 — 폭은 내용이 정하고 넘치면 가로로 스크롤한다(ui.md §4의
 * 예외이고, 근거는 열 수가 컴파일 타임에 없다는 것이다).
 */
.table--auto {
  table-layout: auto;
  width: max-content;
  min-width: 100%;
}

/* 금액·비율은 한 덩어리다 — 줄바꿈이 끼면 `500,000,00 0`처럼 읽힌다. */
.table--auto td.num,
.table--auto th.num,
.report-table .table--auto td.num,
.report-table .table--auto th.num {
  white-space: nowrap;
}

/* 종이에는 가로 스크롤이 없다 — 열이 많은 축은 글자를 줄여서라도 한 장에 담는다. */
@media print {
  #hyphen-report .table--auto {
    font-size: var(--text-xs);
  }
}

/*
 * 거래처 순위 — 비중은 순서가 핵심이라 막대를 붙인다. 색으로 뜻을 나르지 않는다(인쇄는
 * 흑백이다): 순서와 길이와 값 라벨이 전부이고, 같은 값이 아래 표에 그대로 다시 있다.
 */
.report-rank {
  display: grid;
  gap: var(--space-2);
  margin: var(--space-3) 0;
}

.report-rank > div {
  display: grid;
  grid-template-columns: minmax(6rem, 14rem) 1fr;
  align-items: center;
  gap: var(--space-3);
  break-inside: avoid;
}

.report-rank dt {
  font-size: var(--text-sm);
  color: var(--text-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.report-rank dd {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0;
}

.report-rank-bar {
  height: 0.75rem;
  min-width: 2px;
  border: 1px solid var(--text-primary);
  background: var(--surface-subtle);
}

.report-rank-value {
  flex: none;
  font-size: var(--text-xs);
  font-variant-numeric: tabular-nums;
  color: var(--text-secondary);
}

@media print {
  .report-rank-bar {
    background: #d9d9d9;
    print-color-adjust: exact;
  }

  .report-rank-value {
    color: #000;
  }
}

/*
 * 재무제표 — 결산일을 열로, 계정을 행으로 둔다. 계정 계층은 들여쓰기로 읽히고(`data-level`은
 * 응답의 `level`, 0~4로 자른다), 같은 보고서(`reportCode`) 안의 계정이 끝나는 자리는
 * 위쪽 구분선으로 가른다 — 코드에 이름이 없어 제목을 지어내지 않는다.
 * 숫자는 오른쪽 정렬이고(`.table th.num`) 음수는 부호에 더해 색을 입힌다 — 흑백 인쇄에서도
 * 부호가 뜻을 나른다.
 */
.fs-table th[scope='row'][data-level='1'] {
  padding-left: calc(var(--space-3) + 1rem);
}

.fs-table th[scope='row'][data-level='2'] {
  padding-left: calc(var(--space-3) + 2rem);
}

.fs-table th[scope='row'][data-level='3'] {
  padding-left: calc(var(--space-3) + 3rem);
}

.fs-table th[scope='row'][data-level='4'] {
  padding-left: calc(var(--space-3) + 4rem);
}

.fs-table tr[data-group-start] > * {
  border-top: 2px solid var(--border-default);
}

.fs-table td.neg {
  color: var(--p-danger);
}

/* 주주 표의 기준 묶음(회계기준·기준일) 머리줄 */
.table tr.group-row th {
  background: var(--surface-subtle);
  text-align: left;
}

/* 재무제표 쪽 — 출처 줄이 표와 갈라져 다음 쪽에 혼자 남지 않게 한다. */
#report-page-fs .report-table {
  break-after: avoid;
}

#report-page-fs .report-source {
  break-before: avoid;
}

/* 마지막 행 밑줄 — `.table tbody tr:last-child td`는 td만 지워서 행 머리(th)의 선이 첫 열에만 남는다. */
.fs-table tbody tr:last-child th {
  border-bottom: 0;
}

/* --- 검색 카드 압축 (NICE·하이픈·한국평가데이터) -------------------------- */

/*
 * 검색 카드는 번호 한 칸과 버튼이 전부라 큼직한 카드가 필요 없다 — 높이를 줄여 아래 자료
 * 영역이 화면을 차지하게 한다. 제목과 한 줄 설명은 가로로 두고, 캐시 스위치는 입력 줄
 * 끝으로 보낸다.
 */
.card--search {
  margin-bottom: var(--space-4);
  padding: var(--space-4);
}

.card--search .card-header {
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  margin-bottom: var(--space-3);
}

.card--search .card-header h2,
.card--search .card-header p {
  margin: 0;
}

.inline-form-aside {
  margin-left: auto;
}

/* --- 한국평가데이터 조회 --------------------------------------------------- */

[data-view='lookup'] #kodata-report {
  display: none;
}

/* 제목 줄 오른쪽에 카드 전체에 걸리는 동작(리포트)을 붙인다 — 버튼만 따로 한 줄을 쓰면 목록이 그만큼 내려간다. */
.card-header--split {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
}

/*
 * 항목 목록 + 결과. 열한 항목을 한눈에 두고 결과를 옆에 띄운다 — 목록을 위에 깔면 결과가
 * 목록 높이만큼 밀려 내려가고, 대분류를 탭으로 접으면 항목까지 두 번 눌러야 닿는다.
 * 벤더 메뉴의 대분류 > 중분류 > 항목은 들여쓰기로 옮긴다(격자 열로 나누면 라벨 열이 항목보다
 * 넓어져 항목이 오히려 묻힌다).
 */
.kodata-browser {
  display: grid;
  grid-template-columns: 14rem minmax(0, 1fr);
  gap: var(--space-6);
  border-top: 1px solid var(--border-default);
  padding-top: var(--space-5);
}

/* 재무표가 길어도 목록이 화면에 남는다 — 다른 항목으로 가려고 위로 되감지 않는다. */
.kodata-nav {
  position: sticky;
  top: var(--space-4);
  align-self: start;
  display: grid;
  gap: var(--space-4);
  border-right: 1px solid var(--border-default);
  padding-right: var(--space-4);
}

.kodata-nav-group,
.kodata-nav-minor {
  display: grid;
  gap: var(--space-05);
}

.kodata-nav-major {
  margin: 0 0 var(--space-1);
  padding: 0 var(--space-3);
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  letter-spacing: 0.02em;
  color: var(--text-secondary);
}

/* 중분류 — 항목 둘 이상을 묶을 때만 선다. 묶인 항목은 안내선 안쪽으로 들여 쓴다. */
.kodata-nav-minor-label {
  margin: var(--space-1) 0 0;
  padding: var(--space-1) var(--space-3);
  font-size: var(--text-xs);
  color: var(--text-secondary);
}

.kodata-nav-item {
  appearance: none;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--space-2);
  min-height: 2.25rem;
  border: 0;
  border-radius: var(--radius-md);
  background: none;
  padding: var(--space-15) var(--space-3);
  font: inherit;
  font-size: var(--text-base);
  line-height: var(--leading-snug);
  text-align: left;
  color: var(--text-body);
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease-default);
}

.kodata-nav-item:hover {
  background: var(--surface-hover);
}

.kodata-nav-item[aria-current='true'] {
  background: var(--brand-50);
  box-shadow: inset 2px 0 0 var(--brand);
  color: var(--brand-hover);
  font-weight: var(--weight-semibold);
}

.kodata-nav-item:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: -2px;
}

/* 조회 중에는 같은 항목을 다시 누를 수 없다(`mutate`) — 눌리지 않는 이유가 커서로 보인다. */
.kodata-nav-item:disabled {
  cursor: progress;
}

.kodata-nav-minor .kodata-nav-item {
  margin-left: var(--space-3);
  border-left: 1px solid var(--border-default);
  border-radius: 0 var(--radius-md) var(--radius-md) 0;
}

.kodata-nav-minor .kodata-nav-item[aria-current='true'] {
  border-left-color: var(--brand);
  box-shadow: inset 1px 0 0 var(--brand);
}

/*
 * 받아 둔 항목 표시 — 다시 눌러도 과금되지 않는 항목이 어디인지 목록에서 바로 보인다.
 * 색 점은 보조 표시이고 뜻은 `aria-label`·`title`이 나른다(ui.md §5 — 이모지 대신 색 점).
 */
.kodata-nav-state {
  width: 0.5rem;
  height: 0.5rem;
  border-radius: var(--radius-pill);
  background: var(--p-success);
}

.kodata-nav-state[data-state='error'] {
  background: var(--p-danger);
}

.kodata-nav-state[data-state='loading'] {
  background: var(--brand);
}

@media (prefers-reduced-motion: no-preference) {
  .kodata-nav-state[data-state='loading'] {
    animation: kodata-pulse 1s ease-in-out infinite;
  }
}

@keyframes kodata-pulse {
  50% {
    opacity: 0.3;
  }
}

.kodata-view {
  min-width: 0;
}

/* 미선택 안내의 화살표는 왼쪽 목록을 가리킨다. */
@media (prefers-reduced-motion: no-preference) {
  #kodata-pending .pending-state-icon {
    animation-name: pending-nudge-left;
  }
}

@keyframes pending-nudge-left {
  50% {
    transform: translateX(-3px);
  }
}

/* 결과 머리 — 위치(대분류 › 중분류)와 항목 이름, 그 항목에만 걸리는 입력·원문을 한 줄에. */
.kodata-view-head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: end;
  gap: var(--space-4);
}

.kodata-crumbs {
  margin: 0 0 var(--space-05);
  font-size: var(--text-xs);
  color: var(--text-secondary);
}

.kodata-view-title h3 {
  margin: 0;
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
  color: var(--text-primary);
}

.kodata-view-tools {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

/* 기준연도 — 라벨을 입력 옆에 붙여 머리 줄 한 줄에 담는다. */
.field--inline {
  flex-direction: row;
  align-items: center;
  gap: var(--space-2);
}

.field--inline .input {
  width: 6.5rem;
}

.kodata-view-meta {
  margin: var(--space-1) 0 var(--space-4);
}

/* 조회 중·실패·자료 없음 — 결과 자리에서 바로 알린다. 옛 항목의 표를 남겨 두면 그 표를 새 결과로 읽는다. */
.kodata-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-1);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg);
  background: var(--surface-subtle);
  padding: var(--space-6) var(--space-4);
  text-align: center;
  font-size: var(--text-base);
  line-height: var(--leading-normal);
  color: var(--text-secondary);
}

.kodata-state strong {
  font-weight: var(--weight-medium);
  color: var(--text-body);
}

.kodata-state[data-tone='danger'] {
  border-color: var(--callout-danger-border);
  background: var(--callout-danger-bg);
  color: var(--callout-danger-text);
}

.kodata-state[data-tone='danger'] strong {
  color: inherit;
}

.kodata-state .btn {
  margin-top: var(--space-2);
}

/*
 * 이름·값 쌍 격자. 단일형(기업개요는 필드가 서른 개)은 두 줄 표로 세우면 화면 세 장이라,
 * 쌍을 여러 열로 접어 높이를 줄인다. 라벨 열은 고정이다(ui.md §4) — 값이 길면 줄을 바꾼다.
 */
.kodata-facts {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(20rem, 1fr));
  column-gap: var(--space-6);
  margin: 0;
}

.kodata-fact {
  display: grid;
  grid-template-columns: 8.5rem minmax(0, 1fr);
  align-items: baseline;
  gap: var(--space-3);
  border-bottom: 1px solid var(--border-default);
  padding: var(--space-2) 0;
}

.kodata-fact dt {
  font-size: var(--label-size);
  font-weight: var(--label-weight);
  color: var(--label-color);
}

.kodata-fact dd {
  margin: 0;
  min-width: 0;
  font-size: var(--text-base);
  color: var(--text-body);
  font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
}

/* 모든 행이 같은 값인 열 — 표 위 한 덩어리로 올린다. 표 머리와 헷갈리지 않게 바탕을 깐다. */
.kodata-facts--common {
  grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr));
  margin-bottom: var(--space-3);
  border-radius: var(--radius-md);
  background: var(--surface-subtle);
  padding: var(--space-1) var(--space-4);
}

.kodata-facts--common .kodata-fact {
  grid-template-columns: 7.5rem minmax(0, 1fr);
  border-bottom: 0;
  padding: var(--space-15) 0;
}

.kodata-raw {
  margin-top: var(--space-4);
}

.kodata-raw .label {
  margin-bottom: var(--space-1);
}

@media (max-width: 48rem) {
  .kodata-browser {
    grid-template-columns: 1fr;
  }

  /* 목록이 위로 올라가면 대분류 묶음을 옆으로 늘어놓는다 — 한 줄로 쌓으면 결과가 한 화면 밑으로 밀린다. */
  .kodata-nav {
    position: static;
    grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr));
    align-items: start;
    border-right: 0;
    border-bottom: 1px solid var(--border-default);
    padding: 0 0 var(--space-4);
  }

  /* 목록이 위로 올라가면 화살표도 위를 가리킨다. */
  #kodata-pending .pending-state-icon {
    rotate: 90deg;
  }
}

@media print {
  #kodata-report .table--auto {
    font-size: var(--text-xs);
  }
}
