/* ============================================================
   layout.css — 고정 레이아웃 프레임
   SNB · 글로벌 탑바 · 페이지 헤더/툴바/탭 · 모듈 그리드 · DatePicker.
   여기 있는 규칙은 "어떤 요청이 들어와도 고정"인 뼈대다.
   모듈(차트·데이터 컨테이너) 스타일은 styles.css 담당.
   값은 design-system/styles.css 토큰만 사용. 최소 폰트 15px.
   ============================================================ */

:root {
  /* ---- 레이아웃 ---- */
  --snb-w: 240px;
  --topbar-h: 48px;
  /* 툴 밴드 — 탭·필터가 들어가는 줄. 컨트롤(32px) 위아래로 --band-pad-y 만큼 여백을 둔다. */
  --band-pad-y: var(--spacing-8);
  --tabs-pad-y: var(--spacing-20);   /* 본문 탭 줄 위아래 여백 (위·아래 같은 값) */
  --chart-label-size: 13px;          /* 차트 안 보조 텍스트 — 축 라벨·범례가 공유 */
  --chart-h: 280px;                  /* 시각화 영역 기본 높이 — 차트든 아니든 나란히 두면 키가 맞아야 한다 */
  --band-inner-h: calc(var(--control-h) + var(--band-pad-y) * 2);
  --band-h: calc(var(--band-inner-h) + 1px);   /* 내용 + 하단 보더 1 */
  --page-max: 1440px;
  --page-gutter: 32px;   /* 헤더 · 툴바 · 본문이 공유하는 좌우 라인 */
  --module-gap: var(--spacing-12);   /* 모듈 사이 간격 — 가로·세로 모두 이 값 */
  --section-gap: var(--spacing-32);  /* 제목이 붙은 덩어리 사이 간격 — 모듈 사이보다 넓어야 제목이 제 덩어리에 붙는다 */
  --modal-h: 640px;      /* 설정 모달 고정 높이 (탭 전환해도 안 흔들리게) */
  --snb-toggle-size: var(--control-h);   /* 접기/펼치기 버튼 클릭영역 — 탑바 icon-btn 과 동일 */
  --motion: .12s ease-out;         /* 기본 — 제자리에서 색·테두리·그림자만 바뀔 때 */
  --motion-layout: .2s ease-out;   /* 예외 — 이동 거리가 큰 레이아웃 전환 (SNB 접기 등) */
  --motion-focus: .2s ease-out;    /* 범례 호버 강조 — 그림 전체가 한꺼번에 물러나서 --motion 으로는 번쩍인다.
                                      chart-setup.js 의 FOCUS_ANIM_MS 와 같은 값 */
  --shadow-inset: inset 0 1px 2px rgba(36, 40, 45, .07);  /* 눌린 면 (세그먼트 트랙 등) */
  --scrim: rgba(36, 40, 45, .48);    /* 모달 뒤 딤 (DS --dimmed 0.30 보다 진하게) */
  --scrim-blur: 6px;     /* 모달 뒤 배경 블러 */
  --tip-bg: rgba(36, 40, 45, .95);   /* 툴팁 배경 (grey-900 + 투명도) — 가이드·데이터 툴팁 공용 */
  /* 화면 위에 확실히 떠 있어야 하는 흰 면 — 가까운 그림자와 먼 그림자를 겹쳐 깊이를 만든다 */
  --shadow-float: 0 2px 6px rgba(36, 40, 45, .10), 0 12px 32px rgba(36, 40, 45, .18);
  /* 스크롤할 때 고정 영역 아래에 지는 그림자 — 넓게 퍼지고 연하게 */
  --shadow-sticky: 0 6px 24px rgba(36, 40, 45, .06);
  --tip-delay: .12s;               /* 스쳐 지나갈 때 안 깜빡일 만큼만 — .3s 는 구역 폴리곤처럼 짚어 보는 자리에서 느렸다(10/2) */
  --letter-spacing: -0.01em;
  --font-base: 16px;                 /* 본문·라벨 기본 크기 — 15px 였던 자리를 전부 이 토큰으로 */
  --font-nav: 15px;                  /* 내비 글자(SNB 메뉴 · 브레드크럼) — 본문보다 한 단계 작게 */
  --font-sub: 14px;                  /* 보조 정보(주 텍스트 옆 부가 줄) — 읽는 글자의 하한은 15, 보조 줄만 14 까지 */

  /* ---- 아이콘 ----
     12px 이 최소 단위. 버튼 안에 들어가는 아이콘(닫기 X, 내보내기, 캘린더 등)만 16px. */
  --icon-size: 12px;
  --icon-size-btn: 16px;
  --icon-stroke: 2;      /* Lucide 기본 굵기. 작은 아이콘은 아래에서 올려 쓴다 */

  /* ---- 컨트롤 공통 ----
     여기 값을 바꾸면 SNB 메뉴 · 층 버튼그룹 · 드롭다운 · 모달 메뉴 · 기간 프리셋이
     한꺼번에 따라온다. 개별 컴포넌트에 색을 직접 쓰지 말 것. */
  --control-h: 32px;                           /* 버튼·필터 컨트롤 기본 높이 */
  --control-h-lg: 40px;                        /* 화면의 주 동작이 하나뿐인 자리(로그인) */
  --control-border-active: var(--primary);     /* 텍스트 인풋 포커스 테두리 — DS 기본(.input:focus)과 같은 파랑. 버튼류는 쓰지 않는다 (9/24 슬기님) */
  /* 버튼류 상태는 전부 같은 값을 쓴다 — 호버 · 열림(active) · 선택 모두 아래 세 값.
     테두리는 상태와 무관하게 --border 유지. 개별 컴포넌트에서 따로 색을 쓰지 말 것. */
  /* 넓은 면(표·목록 행)의 호버는 작은 컨트롤보다 연하게 — 같은 농도를 쓰면
     면이 넓은 만큼 훨씬 진해 보여서 "선택됨"으로 읽힌다 */
  --row-hover: rgba(142, 148, 157, .05);
  --disabled-opacity: .4;            /* 비활성 상태는 색을 갈아끼우지 않고 통째로 흐리게 — 글자·아이콘·배경이 같은 비율로 물러난다 */
  --focus-dim: .22;                  /* 범례로 하나를 짚었을 때 물러나는 쪽의 불투명도 — chart-setup.js 의 FOCUS_DIM 과 같은 값 */
  --selected-bg: var(--grey-50);               /* 호버 · 활성 · 선택 배경 */
  --selected-fg: var(--text-primary);          /* 선택됨 글자 */
  --selected-border: var(--border);            /* 선택됨 테두리 (버튼그룹처럼 테두리 있는 경우) */
  --selected-bg-on-soft: var(--grey-50);       /* SNB 처럼 배경이 이미 bg-soft 인 면 위에서 */
  --control-fill: var(--grey-900);             /* 체크박스·토글·라디오 등 켜짐 상태 채움 */
  /* 파랑은 차트 전용. 컴포넌트의 강조는 뉴트럴로 간다. */
  --accent-fill: var(--grey-900);              /* 주요 버튼 · 선택된 날짜 등 강조 채움 */
  --accent-fill-hover: var(--grey-800);
  --accent-soft: var(--grey-50);

  /* 증감 방향 색 — 상승 초록 / 하락 빨강. 숫자 증감을 쓰는 모든 자리가 공유 */
  --trend-up: var(--green-600);
  --trend-down: var(--red-500);               /* 강조의 약한 버전 (기간 범위 배경 등) */
}

/* 폼 요소는 font-family 를 상속하지 않는다 (UA 기본값 = Arial).
   버튼·인풋 안 텍스트까지 Pretendard 가 먹도록 되돌린다. */
button, input, select, textarea { font-family: inherit; letter-spacing: inherit; }

/* ---- 아이콘 ----
   Lucide(ISC) 를 쓰고 굵기는 여기서만 관리한다. 12px 로 줄여 쓰는 자리는 조금 굵게. */
svg[stroke="currentColor"] { stroke-width: var(--icon-stroke); }
.snb-group-chev, .dd-chev, .dp-chev { stroke-width: 2.5; }
.checkrow-box svg { stroke-width: 3.5; }

/* ---- 상태 전환 기본값 ----
   모든 인터랙티브 컴포넌트는 --motion(ease-out) 으로 부드럽게 바뀐다.
   개별 컴포넌트에 transition 을 따로 쓰지 말 것 — 여기서 한 번에 관리한다.
   레이아웃이 움직이는 것(SNB 접기, 탑바, 밴드 그림자, 툴팁)만 각자 선언한다. */
/* :is(.app, .modal-scrim) 프리픽스로 특정도를 (0,1,1) 로 올려서
   DS 의 .btn 같은 단일 클래스 규칙(0,1,0)까지 덮는다. */
:is(.app, .modal-scrim) :is(a, button, input, select, textarea, label, svg),
.snb-link, .list-row, .module, .checkrow-box, .toggle-track, .toggle-thumb, .radio-dot,
.snb-group-chev, .dd-chev, .dp-chev {
  transition:
    background-color var(--motion),
    border-color var(--motion),
    color var(--motion),
    box-shadow var(--motion),
    opacity var(--motion),
    transform var(--motion);
  /* 폼 요소는 자간도 상속하지 않고, DS 의 .btn 등은 letter-spacing:0 을 박아둬서
     같은 특정도 규칙으로 여기서 되돌린다. */
  letter-spacing: var(--letter-spacing);
}

/* ============================================================
   1. App shell — SNB(고정 열) + 본문 열(탑바 + 페이지)
   ============================================================ */
body { letter-spacing: var(--letter-spacing); }

.app { display: flex; min-height: 100vh; background: var(--white); }

.app-body {
  flex: 1; min-width: 0;
  display: flex; flex-direction: column;
  /* SNB 가 fixed 라 흐름에서 빠져 있다. 그만큼 본문을 오른쪽으로 민다. */
  margin-left: var(--snb-w);
  transition: margin-left var(--motion-layout);
}
.app.is-snb-hidden .app-body { margin-left: 0; }

.app-main { flex: 1; min-width: 0; padding-top: var(--topbar-h); }
.app-main:has(.page-band) { padding-top: calc(var(--topbar-h) + var(--band-h)); }

.page {
  width: 100%; max-width: var(--page-max); margin: 0 auto;
  padding: 0 var(--page-gutter) var(--spacing-64);
  display: flex; flex-direction: column; gap: var(--module-gap);
}
/* 밴드가 있으면 그 밑으로 16px, 없으면 헤더 밑으로 24px
   (밴드와 본문은 슬롯이 달라서 형제 선택자가 아니라 :has 로 판단한다) */
.page { padding-top: var(--spacing-24); }
.app-main:has(.page-band) .page { padding-top: var(--spacing-16); }

/* 본문 안 탭 줄(요약·방문객 분석·…) — 위아래 여백을 같은 값으로 맞춘다.
   .page 의 위쪽 padding 과 모듈 사이 gap 을 걷어내고, 탭 줄이 자기 여백만 갖게 한다. */
.app-main:has(.page-band) .page:has(> .page-tabs) { padding-top: 0; }
.page > .page-tabs {
  padding: var(--tabs-pad-y) 0;
  margin-bottom: calc(var(--module-gap) * -1);
}

/* ============================================================
   2. SNB (좌측 내비게이션) — 브랜드 / 내비 / 푸터
   ============================================================ */
/* 접힌 상태 — 폭을 0 으로 줄여 왼쪽으로 닫히고, 탑바가 그만큼 넓어진다.
   display:none 이 아니라 폭 애니메이션이라 부드럽게 열리고 닫힌다. */
.app.is-snb-hidden .snb {
  width: 0; padding-left: 0; padding-right: 0;
  border-right-color: transparent;
}
.app.is-snb-hidden .topbar { left: 0; }
/* 줄어드는 동안 내용이 우그러들지 않게 원래 폭을 유지하고 잘려나가게 한다 */
.snb > * { min-width: calc(var(--snb-w) - var(--spacing-24)); }

.snb {
  /* 헤더·툴 밴드와 같이 fixed. z-index 는 가장 높게(50) 둬서
     고정 요소들의 그림자가 SNB 위로 번지지 않게 한다. */
  position: fixed; top: 0; left: 0; z-index: 50;
  width: var(--snb-w); height: 100vh;
  overflow: hidden;   /* 스크롤은 메뉴(.snb-nav)만 — 로고 줄과 하단 계정은 자리를 지킨다 */
  transition: width var(--motion-layout), padding var(--motion-layout), border-right-color var(--motion-layout);
  display: flex; flex-direction: column; gap: var(--spacing-20);
  padding: 0 var(--spacing-12) var(--spacing-12);
  background: var(--bg-soft);
  border-right: 1px solid var(--border);
}

.snb-brand {
  display: flex; align-items: center; justify-content: space-between; gap: var(--spacing-8);
  padding: var(--spacing-12) var(--spacing-8) 0;
}
.snb-logo {
  height: 18px; width: auto; max-width: 100%; display: block;
  object-fit: contain; object-position: left center;
}

/* ---- 브랜드 줄 ----
   로고 하나뿐이다 — 누르면 첫 화면으로 간다. */
.snb-logo-link { display: inline-flex; align-items: center; min-width: 0; border-radius: var(--radius-6); }
.snb-logo-link:focus-visible { outline: none; box-shadow: var(--focus-ring); }

.snb-toggle {
  /* 클릭영역은 34px 유지. 아이콘 우측선을 셰브론과 맞추려고 버튼을 그만큼 바깥으로 뺀다. */
  margin-right: calc((var(--snb-toggle-size) - var(--icon-size-btn)) / -2);
  display: inline-flex; align-items: center; justify-content: center;
  width: var(--snb-toggle-size); height: var(--snb-toggle-size); flex-shrink: 0;
  border-radius: var(--radius-6);
  background: none; border: none; color: var(--text-caption); cursor: pointer;
}
.snb-toggle:hover { background: var(--transparent-hover); color: var(--text-primary); }
.snb-toggle:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.snb-toggle svg { width: var(--icon-size-btn); height: var(--icon-size-btn); }

.snb-nav {
  flex: 1; min-height: 0;   /* flex 자식은 min-height:auto 라 내용만큼 늘어난다 — 0 으로 눌러야 스크롤이 생긴다 */
  display: flex; flex-direction: column; gap: var(--spacing-8);
  overflow-y: auto; overflow-x: hidden;
  margin: 0 calc(var(--spacing-12) * -1); padding: 0 var(--spacing-12);   /* 스크롤바가 메뉴 글자를 밀지 않게 거터를 안쪽으로 */
}
.snb-brand, .snb-footnav { flex-shrink: 0; }
.snb-group { display: flex; flex-direction: column; gap: var(--spacing-2); }

.snb-group-label {
  display: flex; align-items: center; gap: var(--spacing-6);
  height: 36px; padding: 0 var(--spacing-8);
  border-radius: var(--radius-6);
  font-size: var(--font-nav); font-weight: 500; line-height: 1.4; color: var(--text-caption);
  background: none; border: none; cursor: pointer; text-align: left;
}
.snb-group-label:hover { background: var(--transparent-hover); color: var(--text-sub); }
.snb-group-label:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.snb-group-count {
  margin-left: auto; font-size: var(--font-nav); font-weight: 400;
  color: var(--text-caption); font-variant-numeric: tabular-nums;
}
/* 접기 셰브론은 상시 노출. 라벨 오른쪽 끝에 바로 붙는다. */
.snb-group-chev {
  width: var(--icon-size); height: var(--icon-size); flex-shrink: 0; margin-left: auto;
  color: var(--text-caption);
}
.snb-group-label:hover .snb-group-chev { color: var(--text-sub); }
.snb-group-label.is-collapsed .snb-group-chev { transform: rotate(-90deg); }

.snb-group-items { display: flex; flex-direction: column; gap: var(--spacing-2); }
.snb-group-items[hidden] { display: none; }
/* 묶음 안 항목의 글자 시작선 = 점포 줄 왼쪽 여백(16) + 셰브론 + 간격. 셰브론 없는 항목(준비 중)도 같은 선에 맞춘다 */
.snb-group-items .snb-link { padding-left: calc(var(--spacing-16) + var(--icon-size) + var(--spacing-8)); }

.snb-link {
  display: flex; align-items: center; gap: var(--spacing-8);
  min-height: 36px; padding: var(--spacing-8);
  border-radius: var(--radius-6);
  font-size: var(--font-nav); font-weight: 500; line-height: 1.4; color: var(--text-body);
}
.snb-link svg { width: var(--icon-size); height: var(--icon-size); color: var(--text-caption); flex-shrink: 0; }
.snb-link:hover:not(.is-disabled) { background: var(--transparent-hover); }
.snb-link.is-active {
  background: var(--selected-bg-on-soft); color: var(--selected-fg);
}
.snb-link.is-active svg { color: var(--text-primary); }
.snb-link.is-disabled { opacity: var(--disabled-opacity); cursor: default; }
/* 준비 중 거점의 셰브론 — 줄 여백 · 글자는 그대로 두고, 트리 노드 셰브론과 같은 왼쪽 홈(16px)에 절대 위치로 겹친다 */
.snb-link.has-gutter-chev { position: relative; }
.snb-link-chev-gutter {
  position: absolute; left: var(--spacing-16); top: 50%; transform: translateY(-50%);
  width: var(--icon-size); height: var(--icon-size); stroke-width: 2.5; color: var(--text-caption);
}
.snb-link-sub { margin-left: auto; font-size: var(--font-nav); font-weight: 400; color: var(--text-caption); }

/* 트리 노드(점포 › 관점) — 줄 전체가 토글 버튼, 셰브론은 왼쪽. 부모는 선택색을 쓰지 않는다(선택은 잎 하나). */
.snb-node { display: flex; flex-direction: column; gap: var(--spacing-2); }
/* 점포 줄은 폴더다 — 이동하는 메뉴(자식)보다 한 단계 낮은 위계. 가는 글자 · 보조색 · 낮은 높이.
   보고 있는 점포는 본문색으로만 올린다(선택색은 잎 하나만 쓴다). */
.snb-group-items .snb-node-toggle, .snb-node-toggle {
  padding: var(--spacing-6) var(--spacing-8) var(--spacing-6) var(--spacing-16);   /* 셰브론이 왼쪽 여백 자리를 대신 쓴다 */
  min-height: 32px;
  width: 100%; border: none; background: none; cursor: pointer; text-align: left; font: inherit;
  font-size: var(--font-nav); font-weight: 400; line-height: 1.4; color: var(--text-sub);
}
.snb-node-toggle:hover { color: var(--text-body); }
.snb-node-toggle:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.snb-node-toggle.is-current { color: var(--text-body); }
.snb-node-toggle .snb-node-chev {
  width: var(--icon-size); height: var(--icon-size); flex-shrink: 0; stroke-width: 2.5;
  color: var(--text-caption); transition: transform var(--motion-layout);
}
.snb-node-toggle.is-open .snb-node-chev { transform: rotate(90deg); }
/* 자식 묶음 왼쪽에 안내선 하나 — 셰브론 가운데에서 내려와 "이 점포의 메뉴"임을 잇는다.
   가로 꺾임(ㄴ)은 안 그린다 — 선 하나면 소속이 읽히고 더 그리면 소음. 점포 줄이 가벼워진 뒤 자식이 떠 보이는 걸 잡는다. */
.snb-children { display: flex; flex-direction: column; gap: var(--spacing-2); position: relative; }
.snb-children::before {
  content: ""; position: absolute; top: var(--spacing-4); bottom: var(--spacing-4);
  left: calc(var(--spacing-16) + var(--icon-size) / 2 - 0.5px); width: 1px;   /* 선 두께의 절반을 빼야 선의 중심이 셰브론 중심 */
  background: var(--border);
}
.snb-children[hidden] { display: none; }
/* 자식 글자는 부모 이름 글자와 같은 세로선 — 어디에 놓이든 16 + 셰브론 + 간격 */
.snb-children .snb-link { padding-left: calc(var(--spacing-16) + var(--icon-size) + var(--spacing-8)); }

/* 하단 로그인 정보 — SNB 좌우 패딩을 상쇄해 열 전체 너비를 쓰는 별도 컨테이너 */
.snb-footnav {
  margin: 0 calc(var(--spacing-12) * -1) calc(var(--spacing-12) * -1);
  border-top: 1px solid var(--border);
}
.snb-user {
  display: flex; align-items: center; gap: var(--spacing-12); width: 100%;
  padding: var(--spacing-12);
  background: none; border: none; border-radius: 0; cursor: pointer; text-align: left;
}
.snb-user:hover { background: var(--transparent-hover); }
.snb-user:focus-visible { outline: none; box-shadow: var(--focus-ring); }
/* 고객사 로고 칸은 1:1 고정(44px) — 로고 비율에 따라 칸이 늘어나지 않는다. 가로로 긴 마크는 칸 안에서 작아진다.
   (9/23 슬기님 확정) 안쪽 여백으로 테두리에 붙지 않게. 이름 · 고객사 두 줄(38.4px)은 이 안에 들어온다. */
.snb-user-logo {
  width: 44px; height: 44px; flex-shrink: 0;
  padding: var(--spacing-4); box-sizing: border-box;
  border-radius: var(--radius-6); object-fit: contain; background: var(--white);
  border: 1px solid var(--border);
}
.snb-user-logo.is-mono {
  padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--grey-900); border-color: var(--grey-900); color: var(--white);
  font-size: 17px; font-weight: 700; line-height: 1;
}
.snb-user-text { flex: 1; min-width: 0; display: flex; flex-direction: column; }
/* 두 줄 합이 로고 칸(44px) 안에 들어와야 한다 — 16px * 1.2 * 2 = 38.4 */
.snb-user-name {
  font-size: var(--font-base); font-weight: 600; line-height: 1.2; color: var(--text-primary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.snb-user-sub {
  font-size: var(--font-sub); line-height: 1.2; color: var(--text-caption);   /* 보조 정보 — 주 텍스트 옆에 딸린 줄은 14px 까지 */
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ---- 가이드 툴팁 ----
   위치는 layout.js 가 계산한다. data-tip-pos 로 bottom(기본)/top/right/left 지정.
   폰트 13px — 최소 15px 규칙의 예외(툴팁 한정). */
/* 툴팁은 .app 바깥(body 직속)에 그려진다 — 앱 안쪽에만 걸어둔 자간 규칙이 닿지 않으므로
   폰트와 자간을 여기서 직접 지정한다. */
.tip {
  position: fixed; top: 0; left: 0; z-index: 110;   /* 모달 스크림(100)보다 위 — 전체 화면 팝업 안 구역 툴팁이 가려졌다 */
  font-family: var(--font-sans); letter-spacing: var(--letter-spacing);
  width: max-content; max-width: 260px;   /* 놓인 자리와 무관하게 글자 길이로만 폭이 정해지도록 */
  padding: var(--spacing-6) var(--spacing-8);
  border-radius: var(--radius-10);
  background: var(--tip-bg); color: var(--white);
  backdrop-filter: blur(2px); -webkit-backdrop-filter: blur(2px);
  font-size: 13px; font-weight: 500; line-height: 1.4;   /* 어두운 바탕에 흰 13px 은 400 이 가늘어 보여 500 */
  box-shadow: var(--shadow-md);
  opacity: 0; pointer-events: none;
  transform: translateY(4px);
  transition: opacity var(--motion), transform var(--motion);
}
.tip.is-on { opacity: 1; transform: translateY(0); transition-delay: var(--tip-delay); }
/* 구역 폴리곤 툴팁 — 지연 없이 페이드만(120ms, 기본 모션과 같은 길이). 60ms 는 있으나 마나였다 */
.tip-main { display: block; color: var(--white); }
.tip-sub { display: block; color: var(--grey-200); font-weight: 400; }   /* 어두운 바탕에서 300 은 가라앉아 200 */
.tip.is-instant { transition: opacity 120ms ease-out; transform: none; }
.tip.is-instant.is-on { transition-delay: 0s; }

/* 데이터 툴팁 — 가이드 툴팁과 같은 재질, 내용만 다르다.
   값을 읽는 용도라 지연 없이 바로 뜨고, 글자는 가이드보다 한 단계 크다. */
/* 데이터 툴팁은 흰 면 — 값을 정확히 읽는 자리라 드롭다운·데이트피커와 같은 재질을 쓴다.
   (가이드 툴팁은 잠깐 떴다 사라지는 안내라 어두운 면을 그대로 둔다) */
.tip-data {
  padding: var(--spacing-12) var(--spacing-16);
  background: var(--white); color: var(--text-primary);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-float);
  backdrop-filter: none; -webkit-backdrop-filter: none;
  font-size: var(--font-base); font-weight: 500;
  font-variant-numeric: proportional-nums;
}
.tip-data.is-on { transition-delay: 0s; }
/* 날짜는 값보다 한 단계 작고 연하게 — 주인공은 숫자다 */
.tip-date { font-size: 13px; color: var(--text-caption); margin-bottom: var(--spacing-6); }
/* 값이 하나뿐일 때 */
.tip-solo { font-size: 28px; font-weight: 600; line-height: 1.2; color: var(--grey-800); }
/* 단위는 숫자보다 작게 — KPI 카드와 같은 규칙 */
.tip-unit { font-size: 20px; font-weight: 500; margin-left: 1px; letter-spacing: 0; color: var(--text-sub); }
/* 값이 여럿일 때 — 라벨 칸과 값 칸을 나눠 여러 줄이 세로로 맞아떨어지게 한다.
   값은 오른쪽 정렬(끝자리가 맞아야 자릿수가 비교된다), 라벨과는 24px 띄운다 —
   붙어 있으면 어느 값이 어느 줄 것인지 훑기 어렵다. */
.tip-rows {
  display: grid; grid-template-columns: auto 1fr;
  gap: var(--spacing-2) var(--spacing-24);
  line-height: 1.5;
  justify-items: end;
}
.tip-rows .tip-row-label {
  justify-self: start;
  display: inline-flex; align-items: center; gap: var(--spacing-6);
}
/* 두 번째 묶음은 계열이 아니라 합계다 — 빈 칩으로 줄을 맞추는 대신 선으로 떼어 낸다.
   값은 오른쪽 정렬이라 두 묶음의 끝자리가 그대로 맞는다.
   선은 툴팁 끝까지 닿는다(풀블리드) — 좌우 여백만큼 밖으로 빼고 그 여백을 안쪽으로
   옮겨서, 선만 넓어지고 글자 자리는 그대로다. */
.tip-rows + .tip-rows {
  margin: var(--spacing-8) calc(var(--spacing-16) * -1) 0;
  /* 위 여백은 툴팁 아래 여백(--spacing-12)과 같은 값 —
     그래야 합계 줄이 선과 툴팁 바닥 사이 가운데에 선다 */
  padding: var(--spacing-12) var(--spacing-16) 0;
  border-top: 1px solid var(--border);
}
.tip-row { display: contents; }
.tip-solo + .tip-rows { margin-top: var(--spacing-8); }
.tip-row-label, .tip-row-value { white-space: nowrap; }
/* 색 칩 — 툴팁이 막대·선의 어느 색을 말하는지 잇는다 */
.tip-chip {
  display: inline-block; width: 10px; height: 10px; flex-shrink: 0;
  /* 10px 에 r4 라야 둥근 사각형 — 8px 에 r4 는 정확히 원이 된다.
     다른 범례 칩(.legend-dot · .fn-chip)과 같은 모양을 유지한다. */
  border-radius: var(--radius-4);
}
/* 제목 줄의 칩은 flex 가 아니라 글자 흐름 안에 있다 — 자기 여백을 따로 갖는다 */
.tip-date .tip-chip { margin-right: var(--spacing-6); vertical-align: middle; position: relative; top: -1px; }
.tip-row-label { color: var(--text-sub); }
.tip-row-value { color: var(--grey-800); font-weight: 600; }

/* ============================================================
   3. 글로벌 탑바 — 좌: 검색 / 우: 알림 · 계정
   ============================================================ */
/* 스크롤해도 항상 같은 자리 — SNB 열 오른쪽에 고정. 본문은 --topbar-h 만큼 내려 시작한다. */
.topbar {
  position: fixed; top: 0; left: var(--snb-w); right: 0; z-index: 40;
  display: flex; height: var(--topbar-h); flex-shrink: 0;
  transition: left var(--motion-layout);
  background: var(--white); border-bottom: 1px solid var(--border);
}
/* 내용은 본문과 같은 폭·같은 거터로 중앙 정렬 — 배경과 보더만 전폭 */
.topbar-inner {
  width: 100%; max-width: var(--page-max); margin: 0 auto;
  display: flex; align-items: center; gap: var(--spacing-12);
  padding: 0 var(--page-gutter);
}
/* 펼치기 버튼은 SNB 가 접혔을 때만 */
.topbar .topbar-snb-toggle { display: none; flex-shrink: 0; margin-left: calc(var(--spacing-8) * -1); }
.app.is-snb-hidden .topbar .topbar-snb-toggle { display: inline-flex; }

.topbar-title {
  flex: 1; min-width: 0;
  display: flex; align-items: center; gap: var(--spacing-6);
  white-space: nowrap;   /* overflow:hidden 을 두면 경로 칸 드롭다운 메뉴가 잘려 안 보인다 — 말줄임은 칸(.topbar-crumb)이 맡는다 */
}
.topbar-crumb {
  font-size: var(--font-nav); font-weight: 500; line-height: 1.5;
  color: var(--text-sub);
  overflow: hidden; text-overflow: ellipsis;
}
a.topbar-crumb:hover { color: var(--grey-900); }
.topbar-crumb.is-current { font-weight: 600; color: var(--text-primary); }
/* 경로 칸 드롭다운 — 버튼이 아니라 경로여야 한다. 테두리·배경 없이 글자 + 셰브론, 호버에만 배경 */
.dd-crumb .dd-trigger {
  height: auto; padding: var(--spacing-2) var(--spacing-6); margin: 0 calc(var(--spacing-6) * -1);
  border: none; background: none; gap: var(--spacing-4);
  font-size: var(--font-nav); line-height: 1.5;
}
.dd-crumb .dd-trigger:hover { background: var(--transparent-hover); }
.dd-crumb.is-open .dd-trigger { background: var(--transparent-hover); color: var(--text-primary); }
.dd-crumb .dd-chev { width: 14px; height: 14px; }
/* 메뉴 상자 왼쪽을 경로 버튼(호버 배경) 왼쪽에 맞춘다 — 버튼이 음수 여백(6)만큼 왼쪽으로 나가 있다 */
.dd-crumb .dd-menu { left: calc(-1 * var(--spacing-6)); }
/* 구분자는 텍스트 글리프(›) 대신 아이콘 — 글꼴마다 높이가 달라 미묘하게 어긋난다 */
.topbar-crumb-sep {
  display: inline-flex; align-items: center; flex-shrink: 0;
  color: var(--text-caption);
}
.topbar-crumb-sep svg { width: 14px; height: 14px; stroke-width: 2.5; margin-top: -2px; }

.topbar-tools {
  margin-left: auto; min-width: 0;
  display: flex; align-items: center; gap: var(--spacing-8);
}

/* 아이콘 버튼 — 모달 닫기 등 */
.icon-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: var(--control-h); height: var(--control-h); border-radius: var(--radius-8);
  background: none; border: none; color: var(--text-sub); cursor: pointer;
}
.icon-btn:hover { background: var(--bg-soft); color: var(--text-primary); }
.icon-btn:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.icon-btn svg { width: var(--icon-size-btn); height: var(--icon-size-btn); }


/* ============================================================
   4. 페이지 헤더 · 툴바 · 탭 — 모든 페이지 공통 규격
   ============================================================ */
.page-head { display: flex; flex-direction: column; gap: var(--spacing-16); }

.breadcrumb {
  display: flex; align-items: center; gap: var(--spacing-6);
  font-size: var(--font-base); line-height: 1.5; color: var(--text-sub);
}
.breadcrumb a:hover { color: var(--grey-900); }
.breadcrumb-sep { color: var(--text-caption); }
.breadcrumb-current { color: var(--text-primary); font-weight: 600; }

.page-head-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--spacing-16); flex-wrap: wrap;
}
.page-head-text { display: flex; flex-direction: column; gap: var(--spacing-4); min-width: 0; }
.page-head-actions { display: flex; align-items: center; gap: var(--spacing-8); flex-wrap: wrap; }

.page-meta {
  display: flex; align-items: center; gap: var(--spacing-8); flex-wrap: wrap;
  font-size: var(--font-base); line-height: 1.5; color: var(--text-sub);
}
.page-meta-dot {
  width: 3px; height: 3px; flex-shrink: 0;
  border-radius: var(--radius-pill); background: var(--text-caption);
}

/* 헤더 밑에 붙는 고정 밴드 — 배경·그림자는 전폭, 내용은 본문과 같은 폭으로 중앙 정렬 */
/* 헤더와 같은 방식으로 고정한다. sticky 는 붙기 직전까지 같이 움직여서 덜렁거린다. */
.page-band {
  position: fixed; top: var(--topbar-h); left: var(--snb-w); right: 0; z-index: 30;
  background: var(--white);
  border-bottom: 1px solid var(--border);
  transition: left var(--motion-layout), box-shadow var(--motion-layout);
}
.app.is-snb-hidden .page-band { left: 0; }
.page-band-inner {
  width: 100%; max-width: var(--page-max); margin: 0 auto;
  height: var(--band-inner-h);
  display: flex; align-items: center;
  padding: 0 var(--page-gutter);
}
.page-band-inner { gap: var(--spacing-24); }
.page-band-inner > * { flex: 1; min-width: 0; }
.page-band-inner > .page-toolbar { align-items: center; }
/* 단층 매장 — 탭이 밴드 왼쪽에 들어올 때는 폭을 내용만큼만 */
.page-band-inner > .page-tabs { flex: 0 0 auto; }
.page-band-inner > .page-tabs:only-child { flex: 1; }

.page-toolbar {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--spacing-12); flex-wrap: wrap;
}
.page-toolbar-left,
.page-toolbar-right { display: flex; align-items: center; gap: var(--spacing-8); flex-wrap: wrap; }

/* 헤더에 붙어 있는 동안만 하단 그림자. 붙고 떨어질 때 부드럽게. */
.page-band.is-stuck,
.topbar.is-stuck { box-shadow: var(--shadow-sticky); }

.page-tabs {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--spacing-16);
}
.page-tabs-list { display: flex; gap: var(--spacing-8); }
.page-tabs-actions { display: flex; align-items: center; gap: var(--spacing-8); }
/* 페이지의 주 내비게이션 — 선택된 탭은 굵기와 색으로만 구분한다.
   굵어질 때 폭이 변하면 옆 탭들이 밀리므로, ::before 로 굵은 상태의 폭을
   미리 깔아두고 같은 그리드 칸에 겹쳐 놓는다. 폭은 항상 굵은 기준으로 고정. */
.tab-btn {
  display: inline-grid; place-items: center;
  height: 32px; padding: 0 var(--spacing-8);
  border: none; border-radius: var(--radius-6);
  font-size: var(--font-base); font-weight: 500; line-height: 1.5; color: var(--text-sub);
  background: none; cursor: pointer;
}
.tab-btn > span { grid-area: 1 / 1; }
.tab-btn::before {
  content: attr(data-label);
  grid-area: 1 / 1;
  font-weight: 700; visibility: hidden; pointer-events: none;
}
.tab-btn:hover { background: var(--selected-bg); color: var(--text-primary); }
.tab-btn.is-active { color: var(--text-primary); font-weight: 700; }
.tab-btn:focus-visible { outline: none; box-shadow: var(--focus-ring); }

/* 탭별 보조 필터 — 탭 바로 아래, 지표 기준값을 바꾸는 줄 */
.page-subfilter { display: flex; flex-direction: column; gap: var(--spacing-8); }
.page-subfilter-row { display: flex; align-items: center; gap: var(--spacing-12); flex-wrap: wrap; }
.page-subfilter-label {
  font-size: var(--font-base); font-weight: 500; line-height: 1.4; color: var(--text-caption);
}
.page-subfilter-note { font-size: var(--font-base); line-height: 1.5; color: var(--text-caption); }

/* ---- 버튼 ----
   디자인 시스템 파일의 .btn 은 참고만 하고, 이 정의가 기준이다.
   상태 색은 전부 공통 토큰(--selected-*)을 쓴다. */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--spacing-6);
  height: var(--control-h); padding: 0 var(--spacing-12);
  border: 1px solid transparent; border-radius: var(--radius-8);
  background: none; cursor: pointer; white-space: nowrap; text-decoration: none;
  font-size: var(--font-base); font-weight: 500; line-height: 1.4;
}
.btn svg { width: var(--icon-size-btn); height: var(--icon-size-btn); flex-shrink: 0; }
.btn:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.btn:disabled { cursor: not-allowed; }

.btn.secondary { background: var(--white); border-color: var(--border); color: var(--text-primary); }
.btn.secondary:hover:not(:disabled) { background: var(--selected-bg); }
.btn.secondary:active:not(:disabled) { background: var(--grey-50); }
.btn.secondary:disabled { background: var(--white); color: var(--text-disabled); border-color: var(--border); }

.btn.fill { background: var(--accent-fill); border-color: var(--accent-fill); color: var(--white); }
.btn.fill:hover:not(:disabled) { background: var(--accent-fill-hover); border-color: var(--accent-fill-hover); }
.btn.fill:active:not(:disabled) { background: var(--grey-700); border-color: var(--grey-700); }
.btn.fill:disabled { background: var(--grey-100); color: var(--grey-300); border-color: var(--grey-100); }

/* 파랑 채움 — 디자인 시스템 .btn.fill 의 원래 값. 대시보드 안 컴포넌트는 뉴트럴(.fill = grey-900)이고, 로그인처럼 화면에 동작이 하나뿐인 자리에만 */
.btn.primary { background: var(--primary); border-color: var(--primary); color: var(--white); }
.btn.primary:hover:not(:disabled) { background: var(--blue-500-hover); border-color: var(--blue-500-hover); }
.btn.primary:active:not(:disabled) { background: var(--blue-600); border-color: var(--blue-600); }
.btn.primary:disabled { background: var(--grey-100); color: var(--grey-300); border-color: var(--grey-100); }

/* 되돌릴 수 없는 동작(삭제 확정)만 빨강 — 디자인 시스템 .btn.danger 와 같은 값 */
.btn.danger { background: var(--red-500); border-color: var(--red-500); color: var(--white); }
.btn.danger:hover:not(:disabled) { background: var(--red-500-hover); border-color: var(--red-500-hover); }
.btn.danger:active:not(:disabled) { background: var(--red-600); border-color: var(--red-600); }
.btn.danger:focus-visible { box-shadow: var(--focus-ring-danger); }

/* ============================================================
   5. 필터 컨트롤 — 세그먼트 · 드롭다운
   ============================================================ */
/* 버튼 그룹 — 서로 붙은 outline 버튼. 인접 테두리는 겹쳐서 1px 로 보이게 한다. */
.seg { display: inline-flex; }
.seg-btn {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center;
  height: var(--control-h); padding: 0 var(--spacing-12);
  margin-left: -1px;
  border: 1px solid var(--border); border-radius: 0;
  background: var(--white); cursor: pointer;
  font-size: var(--font-base); font-weight: 500; line-height: 1.4; color: var(--text-sub);
}
.seg-btn:first-child { margin-left: 0; border-top-left-radius: var(--radius-8); border-bottom-left-radius: var(--radius-8); }
.seg-btn:last-child { border-top-right-radius: var(--radius-8); border-bottom-right-radius: var(--radius-8); }
.seg-btn:hover:not(.is-disabled) { z-index: 1; background: var(--selected-bg); color: var(--selected-fg); }
.seg-btn:focus-visible { z-index: 2; outline: none; box-shadow: var(--focus-ring); }
/* 쓸 수 없는 선택지 — 눌리지 않지만 자리는 지킨다. 이유는 툴팁으로. */
.seg-btn.is-disabled { opacity: var(--disabled-opacity); cursor: not-allowed; }
.seg-btn.is-active {
  z-index: 1;
  background: var(--selected-bg); border-color: var(--selected-border);
  color: var(--selected-fg);
}
.seg-btn.is-active:hover { background: var(--selected-bg); color: var(--selected-fg); }

/* 세그먼트 컨트롤 — 버튼그룹과 다른 컴포넌트.
   눌린 트랙(bg-soft) 위에 선택된 칩이 떠 있는 형태. 보조 필터처럼 한 단계 낮은 자리에 쓴다. */
.seg.is-segmented {
  gap: var(--spacing-2); padding: var(--spacing-4);
  background: var(--grey-50); border-radius: var(--radius-8);   /* 버튼그룹과 같은 스케일 */
  box-shadow: var(--shadow-inset);           /* 트랙은 살짝 눌린 면 */
}
/* 필터 이름을 트랙 안에 넣는 변형 */
.seg.is-segmented.has-label { padding-left: var(--spacing-8); }
.seg-label {
  display: inline-flex; align-items: center; height: 24px;
  padding-right: var(--spacing-8);
  font-size: var(--font-base); line-height: 1.4; color: var(--text-caption); white-space: nowrap;
}

.seg.is-segmented .seg-btn {
  height: 24px; margin-left: 0; padding: 0 var(--spacing-12);
  border: none; border-radius: var(--radius-6); background: none;
  color: var(--text-sub); font-weight: 500;
}
/* 호버하면 반투명 칩이 깔린다. 선택된 흰 칩에는 적용 안 함. */
.seg.is-segmented .seg-btn:hover:not(.is-active):not(.is-disabled) {
  background: var(--transparent-hover); color: var(--text-primary);
}
/* 선택된 칩은 버튼 배경이 아니라 따로 얹은 .seg-thumb 가 그린다.
   버튼이 직접 칠하면 선택이 바뀔 때 한쪽은 꺼지고 다른 쪽은 켜질 뿐 옮겨가지 않는다. */
.seg.is-segmented { position: relative; }
.seg.is-segmented .seg-btn.is-active { background: none; color: var(--text-primary); }
.seg.is-segmented .seg-btn { position: relative; z-index: 1; }   /* 칩 위로 */
.seg-thumb {
  position: absolute; left: 0; top: var(--spacing-4); bottom: var(--spacing-4);
  z-index: 0; pointer-events: none;
  border-radius: var(--radius-6);
  background: var(--white);
  /* 테두리는 inset ring 으로 — 칩 크기가 변하지 않는다 */
  box-shadow: 0 0 0 1px var(--border), var(--shadow-sm);
  transition: transform var(--motion-layout), width var(--motion-layout);
}

.dd { position: relative; display: inline-flex; }
.dd-trigger {
  display: inline-flex; align-items: center; gap: var(--spacing-6);
  height: var(--control-h); padding: 0 var(--spacing-12);
  border: 1px solid var(--border); border-radius: var(--radius-8);
  background: var(--white); cursor: pointer;
  font-size: var(--font-base); font-weight: 500; line-height: 1.4; color: var(--text-primary);
}
.dd-trigger:hover { background: var(--bg-soft); }
.dd-trigger:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.dd.is-open .dd-trigger { background: var(--selected-bg); color: var(--selected-fg); }
.dd-chev { width: var(--icon-size); height: var(--icon-size); color: var(--text-caption); }
.dd-icon { width: var(--icon-size); height: var(--icon-size); color: var(--text-sub); flex: none; }
/* 메뉴 안 두 번째 화면 — 첫 화면(목록)을 감추고 헤더(‹ 제목) + 내용으로 갈아끼운다 */
.dd-page-main { display: flex; flex-direction: column; gap: var(--spacing-2); }
.dd-page-main[hidden] { display: none; }
.dd-opt-drill { display: flex; align-items: center; justify-content: space-between; gap: var(--spacing-8); width: 100%; background: none; border: 0; text-align: left; font: inherit; cursor: pointer; }
.dd-opt-chev { width: var(--icon-size); height: var(--icon-size); color: var(--text-caption); flex: none; }
.dd-sub { min-width: 240px; }
.dd-sub[hidden] { display: none; }
/* 헤더 구분선은 메뉴 끝까지 — 메뉴 안쪽 여백만큼 바깥으로 빼고 그만큼 다시 채운다 */
.dd-sub-head {
  display: flex; align-items: center; gap: var(--spacing-4);
  margin: calc(var(--spacing-4) * -1) calc(var(--spacing-4) * -1) var(--spacing-4);
  padding: var(--spacing-6) var(--spacing-8);
  border-bottom: 1px solid var(--grey-50);
}
.dd-sub-back { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; border: 0; border-radius: var(--radius-6); background: none; color: var(--text-sub); cursor: pointer; }
.dd-sub-back svg { width: var(--icon-size); height: var(--icon-size); }
.dd-sub-back:hover { background: var(--bg-soft); color: var(--text-primary); }
.dd-sub-back:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.dd-sub-title { font-size: var(--font-base); font-weight: 600; line-height: 1.4; color: var(--text-primary); }
.dd.is-right .dd-menu { left: auto; right: 0; }   /* 오른쪽 끝 컨트롤은 안쪽으로 펼친다 */
.dd.is-open .dd-chev { transform: rotate(180deg); }
/* 떠 있는 요소 공통 규칙 — width: max-content
   absolute/fixed 요소는 "놓인 자리에서 남은 가로 공간"만큼만 넓어진다.
   그래서 화면 오른쪽에 붙으면 글자가 멋대로 줄바꿈된다.
   폭이 글자 길이로만 정해지도록 max-content 를 박고, 한계는 max-width 로 준다. */
.dd-menu {
  position: absolute; top: calc(100% + var(--spacing-4)); left: 0; z-index: 30;
  width: max-content; min-width: 100%; max-width: 320px; padding: var(--spacing-4);
  display: flex; flex-direction: column; gap: var(--spacing-2);
  background: var(--white); border: 1px solid var(--border);
  border-radius: var(--radius-8); box-shadow: var(--shadow-md);
}
.dd-menu[hidden] { display: none; }
.dd-menu.is-up { top: auto; bottom: calc(100% + var(--spacing-4)); }   /* 아래 공간이 모자랄 때 */
.dd-opt {
  padding: var(--spacing-6) var(--spacing-12); border-radius: var(--radius-6);
  font-size: var(--font-base); line-height: 1.4; color: var(--text-body); white-space: nowrap;
}
.dd-opt:hover:not(.is-disabled) { background: var(--bg-soft); }
.dd-opt.is-active { background: var(--selected-bg); color: var(--selected-fg); }
/* 쓸 수 없는 선택지 — 눌리지 않지만 자리는 지킨다. 이유는 툴팁으로. (.seg-btn.is-disabled 와 같은 규칙) */
.dd-opt.is-disabled { opacity: var(--disabled-opacity); cursor: not-allowed; }
/* 트리거 안 이름표 */
.dd-label { color: var(--text-caption); font-weight: 400; }

/* ============================================================
   6. DatePicker — 프리셋 + 2개월 캘린더 범위 선택
   ============================================================ */
.dp { position: relative; display: inline-flex; }

.dp-trigger {
  display: inline-flex; align-items: center; gap: var(--spacing-8);
  height: var(--control-h); padding: 0 var(--spacing-12);
  border: 1px solid var(--border); border-radius: var(--radius-8);
  background: var(--white); cursor: pointer;
  font-size: var(--font-base); font-weight: 500; line-height: 1.4; color: var(--text-primary);
  font-variant-numeric: proportional-nums;
}
/* 개별 버튼·버튼그룹은 흰 면, 회색 면은 세그먼트 트랙만 — 툴 밴드 안에서 면이 갈리지 않게 */
.dp-trigger:hover { background: var(--selected-bg); }
.dp-trigger:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.dp.is-open .dp-trigger { background: var(--selected-bg); color: var(--selected-fg); }
.dp-trigger-preset { color: var(--text-caption); font-weight: 400; }
.dp-chev { width: var(--icon-size); height: var(--icon-size); color: var(--text-caption); }
.dp.is-open .dp-chev { transform: rotate(180deg); }

.dp-pop {
  position: absolute; top: calc(100% + var(--spacing-6)); right: 0; z-index: 50;
  width: max-content;   /* 위 .dd-menu 의 "떠 있는 요소 공통 규칙" 참고 */
  display: flex; flex-direction: column;
  background: var(--white); border: 1px solid var(--border);
  border-radius: var(--radius-12); box-shadow: var(--shadow-lg); overflow: hidden;
}
.dp-pop[hidden] { display: none; }
.dp-body { display: flex; align-items: stretch; }

.dp-presets {
  width: 152px; flex-shrink: 0; padding: var(--spacing-8);
  display: flex; flex-direction: column; gap: var(--spacing-2);
  border-right: 1px solid var(--border); background: var(--bg-soft);
}
.dp-preset {
  padding: var(--spacing-8) var(--spacing-12); border-radius: var(--radius-6);
  background: none; border: none; cursor: pointer; text-align: left;
  font-size: var(--font-base); font-weight: 500; line-height: 1.4; color: var(--text-body);
}
.dp-preset:hover { background: var(--transparent-hover); color: var(--text-primary); }
.dp-preset:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.dp-preset.is-active { background: var(--selected-bg); color: var(--selected-fg); }

.dp-cals { display: flex; gap: var(--spacing-24); padding: var(--spacing-16); }
.dp-cal { width: 252px; display: flex; flex-direction: column; gap: var(--spacing-8); }
.dp-cal-head {
  display: flex; align-items: center; justify-content: space-between; gap: var(--spacing-8);
  min-height: var(--control-h);
}
.dp-cal-title {
  font-size: var(--font-base); font-weight: 600; line-height: 1.4; color: var(--text-primary);
  font-variant-numeric: proportional-nums;
}
.dp-nav {
  display: inline-flex; align-items: center; justify-content: center;
  width: var(--control-h); height: var(--control-h); border-radius: var(--radius-6);
  background: none; border: none; cursor: pointer; color: var(--text-sub);
}
.dp-nav:hover:not(:disabled) { background: var(--bg-soft); color: var(--text-primary); }
.dp-nav:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.dp-nav:disabled { color: var(--text-disabled); cursor: not-allowed; }
.dp-nav svg { width: var(--icon-size-btn); height: var(--icon-size-btn); }
.dp-nav.is-prev svg { transform: rotate(90deg); }
.dp-nav.is-next svg { transform: rotate(-90deg); }

.dp-grid { display: grid; grid-template-columns: repeat(7, 1fr); }
.dp-dow {
  height: 28px; display: flex; align-items: center; justify-content: center;
  font-size: var(--font-base); line-height: 1.4; color: var(--text-caption);
}
.dp-dow.is-sun { color: var(--red-400); }

.dp-cell { position: relative; padding: var(--spacing-1) 0; }
.dp-cell.is-in-range::before {
  content: ""; position: absolute; inset: var(--spacing-1) 0;
  background: var(--accent-soft);
}
.dp-cell.is-range-start::before { left: 50%; border-radius: var(--radius-pill) 0 0 var(--radius-pill); }
.dp-cell.is-range-end::before { right: 50%; border-radius: 0 var(--radius-pill) var(--radius-pill) 0; }
.dp-cell.is-range-start.is-range-end::before { display: none; }
/* 종료일을 고르는 중 — 커서가 지나는 구간을 미리 보여준다. 확정된 구간보다 연하게. */
.dp-cell.is-preview::before {
  content: ""; position: absolute; inset: var(--spacing-1) 0;
  background: var(--grey-25);
}
.dp-cell.is-preview-end::before { border-radius: 0 var(--radius-pill) var(--radius-pill) 0; }

.dp-day {
  position: relative; width: 100%; height: 34px;
  display: flex; align-items: center; justify-content: center;
  border-radius: var(--radius-8); background: none; border: none; cursor: pointer;
  font-size: var(--font-base); line-height: 1.4; color: var(--text-body);
  /* 달력 격자는 세로로 자리가 맞아야 하므로 고정폭 유지 */
  font-variant-numeric: tabular-nums;
}
.dp-day:hover:not(:disabled) { background: var(--transparent-hover); color: var(--text-primary); }
.dp-day:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.dp-day:disabled { color: var(--text-disabled); cursor: not-allowed; }
.dp-day.is-outside { color: var(--text-disabled); }
.dp-day.is-edge {
  background: var(--accent-fill); color: var(--white);
  box-shadow: none;
}
.dp-day.is-edge:hover:not(:disabled) { background: var(--accent-fill-hover); color: var(--white); }

.dp-foot {
  display: flex; align-items: center; justify-content: space-between; gap: var(--spacing-16);
  padding: var(--spacing-12) var(--spacing-16);
  border-top: 1px solid var(--border); background: var(--white);
}
.dp-foot-summary {
  display: flex; align-items: center; gap: var(--spacing-8);
  font-size: var(--font-base); line-height: 1.4; color: var(--text-sub);
  font-variant-numeric: proportional-nums;
}
/* 시작일 · 종료일 직접 입력 — 컨트롤 높이의 좁은 칸, 숫자가 가운데 */
.dp-input {
  width: 128px; height: 32px; padding: 0 var(--spacing-8); text-align: center;
  border: 1px solid var(--border); border-radius: var(--radius-8); background: var(--white);
  font: inherit; font-size: var(--font-base); color: var(--text-primary); font-variant-numeric: tabular-nums;
}
.dp-input::placeholder { color: var(--text-caption); }
.dp-input:focus { outline: none; border-color: var(--control-border-active); box-shadow: var(--focus-ring); }
.dp-foot-dash { color: var(--text-caption); }
.dp-foot-days { color: var(--text-sub); }
.dp-foot-summary strong { color: var(--text-primary); font-weight: 600; }
.dp-foot-actions { display: flex; align-items: center; gap: var(--spacing-8); }

/* ============================================================
   7. 모듈 그리드 & placeholder 컨테이너
   모듈 내부(차트·표)는 후순위. 프레임은 자리/간격만 책임진다.
   ============================================================ */
.page-section { display: flex; flex-direction: column; gap: var(--module-gap); }
/* 제목이 붙은 섹션만 앞뒤로 더 띄운다.
   .page 의 gap 은 모듈 사이 간격(12)이라 그대로 두면 제목이 앞 덩어리 꼬리로 읽힌다.
   모든 섹션을 넓히면 모듈 줄 사이까지 벌어지므로, 제목 있는 섹션만 차액을 margin 으로 더한다. */
.page-section:has(> .page-section-head) {
  gap: var(--spacing-16);   /* 제목과 카드 사이도 모듈 사이보다 한 단계 넓게 */
  margin: calc(var(--section-gap) - var(--module-gap)) 0;
}
.page-section:has(> .page-section-head):first-child { margin-top: 0; }
.page-section:has(> .page-section-head):last-child { margin-bottom: 0; }
.page-section-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--spacing-16); flex-wrap: wrap;
}
.page-section-title { font-size: 17px; font-weight: 600; line-height: 1.45; color: var(--text-primary); }
.page-section-note { font-size: var(--font-base); line-height: 1.5; color: var(--text-caption); }

.module-grid {
  display: grid; grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: var(--module-gap); align-items: stretch;
}
.module { grid-column: span 12; }
.module.is-3 { grid-column: span 3; }
.module.is-4 { grid-column: span 4; }
.module.is-6 { grid-column: span 6; }
.module.is-8 { grid-column: span 8; }
.module.is-12 { grid-column: span 12; }

.module {
  display: flex; flex-direction: column; gap: var(--module-gap);
  padding: var(--spacing-20);
  background: var(--white); border: 1px solid var(--border); border-radius: var(--radius-12);
}
/* 카드 전체가 링크인 모듈 — 눌러서 갈 곳이 있다는 걸 그림자가 든 만큼으로 알린다.
   테두리 색은 그대로 둔다 (버튼 state 규칙: 상태가 바뀌어도 --border 유지). */
.module.is-link { cursor: pointer; transition: box-shadow var(--motion); }
.module.is-link:hover { box-shadow: var(--shadow-lg); }
/* 모듈은 두 덩어리다 — 제목 줄과 내용.
   제목 줄 아래에 구분선은 두지 않는다. 제목의 굵기와 아래 여백만으로 이미 갈리고,
   카드가 여러 개면 가로선이 그만큼 반복돼 화면이 시끄러워진다.
   제목 줄에 컨트롤이 들어가도 마찬가지다 — 예외를 두지 않는다. */
.module-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--spacing-12); min-height: 24px;
  /* 제목과 내용 사이는 모듈 사이 간격보다 넓게 — 선 없이 여백만으로 갈라야 해서 */
  margin-bottom: calc(var(--spacing-20) - var(--module-gap));
}
/* 제목 줄 오른쪽(module-head-actions)은 만질 것(세그먼트 컨트롤·필터) 자리다.
   범례는 읽는 것이라 본문 아래 중앙에 둔다 — .legend 기본값 그대로. */
/* 모듈 제목은 KPI·차트·표 구분 없이 하나로 통일한다 */
.module-title { font-size: var(--font-base); font-weight: 600; line-height: 1.45; color: var(--text-primary); }
.module-title-row { display: inline-flex; align-items: center; gap: var(--spacing-4); }
.module-info { display: inline-flex; color: var(--text-caption); cursor: help; }
.module-info svg { width: 16px; height: 16px; }
.module-info:hover, .module-info:focus-visible { color: var(--text-sub); outline: none; }
/* 지표 이름 옆 ⓘ — 글자 줄 안에 붙는다. 제목 옆 ⓘ 보다 한 단계 작게 */
.metric-info { display: inline-flex; vertical-align: -2px; margin-left: 3px; color: var(--text-caption); cursor: help; }
.metric-info svg { width: 14px; height: 14px; }
.metric-info:hover, .metric-info:focus-visible { color: var(--text-sub); outline: none; }
.module-desc { font-size: var(--font-base); line-height: 1.4; color: var(--text-caption); }
.module-head-text { display: flex; flex-direction: column; gap: var(--spacing-2); }
.module-head-actions { display: flex; align-items: center; gap: var(--spacing-8); flex-shrink: 0; }
.module-body { flex: 1; display: flex; flex-direction: column; }

.module-ph {
  flex: 1; min-height: var(--ph-h, 180px);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--spacing-4); padding: var(--spacing-24);
  border: 1px dashed var(--grey-100); border-radius: var(--radius-8);
  background: var(--bg-soft);
}
.module-ph-label { font-size: var(--font-base); font-weight: 600; line-height: 1.4; color: var(--text-sub); }
.module-ph-note { font-size: var(--font-base); line-height: 1.4; color: var(--text-caption); }
.module.is-ph-sm { --ph-h: 108px; }
.module.is-ph-lg { --ph-h: 280px; }

/* ============================================================
   7-1. 프레임 밖 화면 — 로그인 · 관리자 설정. .app 대신 화면 전체를 쓴다
   ============================================================ */
body.is-standalone .app { display: none; }
/* 연회색 바탕 가운데 흰 카드 — 심볼 · 제목은 가운데, 칸과 버튼은 카드 폭 가득. 오류 띠는 카드 위, 안내는 카드 아래 */
.login {
  min-height: 100vh; display: flex; align-items: center; justify-content: center;
  padding: var(--spacing-24) var(--spacing-16); background: var(--bg-soft);
}
.login-wrap {
  width: 100%; max-width: 440px;
  display: flex; flex-direction: column; gap: var(--spacing-20);
  padding-bottom: var(--spacing-48);   /* 시각적 가운데를 살짝 위로 */
}
.login-error { margin: 0; font-size: var(--font-sub); line-height: 1.5; color: var(--red-500); }   /* 칸 아래 한 줄 */
.login-card {
  display: flex; flex-direction: column; gap: var(--spacing-24);
  padding: var(--spacing-40) var(--spacing-40) var(--spacing-32);
  background: var(--white); border: 1px solid var(--border); border-radius: var(--radius-12);
}
.login-logo { align-self: center; height: 28px; width: auto; margin-bottom: var(--spacing-12); }
.login-head { display: flex; flex-direction: column; align-items: flex-start; gap: var(--spacing-6); margin-bottom: var(--spacing-4); text-align: left; }
.login-title { margin: 0; font-size: 22px; font-weight: 700; line-height: 1.3; color: var(--text-primary); letter-spacing: -0.02em; }
.login-fields { display: flex; flex-direction: column; gap: var(--spacing-16); }
.login-field { display: flex; flex-direction: column; gap: var(--spacing-6); }
.login-label { font-size: var(--font-sub); font-weight: 400; line-height: 1.4; color: var(--text-sub); }   /* 보조 글 크기(14) — 칸이 말하므로 라벨은 약하게 */
/* 화면에 할 일이 이것 하나라 설정 모달 인풋(32)보다 크게 */
.login-card .field-input { max-width: none; height: var(--control-h-lg); }   /* 공통 .field-input 의 최대 폭(320)을 이긴다 — 뒤에 적힌 공통 규칙이 같은 세기면 이겨서 */
.login-submit { width: 100%; height: var(--control-h-lg); margin-top: var(--spacing-8); }
.login-help { margin: 0; text-align: center; font-size: var(--font-base); line-height: 1.5; color: var(--text-sub); }
.login-intro { margin: 0; font-size: var(--font-base); line-height: 1.5; color: var(--text-sub); }

/* ---- 관리자 설정 페이지 — 왼쪽 섹션 메뉴는 설정 모달 메뉴(.modal-nav-item)와 같은 모양 ---- */
/* 머리 줄 · 왼쪽 메뉴는 고정, 본문만 스크롤 — 대시보드의 SNB · 탑바와 같은 규칙 */
.admin { height: 100vh; display: flex; flex-direction: column; overflow: hidden; background: var(--white); }
.admin-head {
  display: flex; align-items: center; gap: var(--spacing-16); flex-shrink: 0;
  height: 56px; padding: 0 var(--spacing-24); border-bottom: 1px solid var(--border);
}
/* 돌아가기 — 아이콘만, 이름은 가이드 툴팁. 탑바 아이콘 버튼(.icon-btn)과 같은 크기 */
.admin-back {
  display: inline-flex; align-items: center; justify-content: center;
  width: var(--control-h); height: var(--control-h); border-radius: var(--radius-6);
  color: var(--text-sub); text-decoration: none;
}
.admin-back:hover { background: var(--bg-soft); color: var(--text-primary); }
.admin-back:focus-visible { outline: none; box-shadow: var(--focus-ring); }
/* 한글 글자는 줄 상자 가운데보다 위에 앉아 셰브론이 처져 보인다 — 탑바 경로 구분자(.topbar-crumb-sep)와 같은 만큼 올린다 */
.admin-back svg { width: var(--icon-size-btn); height: var(--icon-size-btn); margin-top: -2px; }
.admin-title { margin: 0; font-size: var(--font-base); font-weight: 600; line-height: 1.4; color: var(--text-primary); }
.admin-client { margin-left: auto; }
.admin-client-name { font-size: var(--font-base); font-weight: 500; line-height: 1.4; color: var(--text-sub); }
.admin-body { flex: 1; min-height: 0; display: flex; align-items: stretch; }
.admin-nav {
  flex: 0 0 220px; width: 220px; overflow-y: auto;
  display: flex; flex-direction: column; gap: var(--spacing-2);
  padding: var(--spacing-16) var(--spacing-12); border-right: 1px solid var(--border); background: var(--bg-soft);
}
.admin-nav .modal-nav-item { text-decoration: none; justify-content: space-between; gap: var(--spacing-8); }
/* 로그아웃은 설정 모달과 같은 동작 항목 — 맨 아래 고정(is-action), 아이콘 · 글자는 왼쪽에 붙인다 */
.admin-nav .modal-nav-item.is-action { justify-content: flex-start; }
.admin-nav-dot { width: 8px; height: 8px; flex: none; border-radius: var(--radius-pill); background: var(--grey-300); }
.admin-nav-dot.is-error { background: var(--red-500); }
.admin-nav-dot[hidden] { display: none; }
.admin-panel {
  flex: 1; min-width: 0; overflow-y: auto;
  padding: 0 var(--spacing-32) 120px;   /* 위 여백은 제목 블록이 갖는다 — 붙는 도구 줄이 스크롤 영역 맨 위에 딱 닿게. 아래 여백은 떠 있는 저장 줄 몫 */
  display: flex; flex-direction: column; gap: var(--spacing-32);   /* 제목 덩어리와 표 사이 */
}
.admin-panel-title { margin: 0; font-size: 19px; font-weight: 700; line-height: 1.5; color: var(--text-primary); }
/* 저장하지 않은 변경이 있을 때만 뜨는 줄 — 긴 표에서도 버튼이 늘 보인다 */
.admin-bar {
  position: fixed; left: 50%; bottom: var(--spacing-24); transform: translateX(-50%); z-index: 40;
  display: flex; align-items: center; gap: var(--spacing-32);   /* 글과 버튼 묶음 사이 */
  padding: var(--spacing-12) var(--spacing-12) var(--spacing-12) var(--spacing-20);
  background: var(--white); border: 1px solid var(--border); border-radius: var(--radius-12); box-shadow: var(--shadow-float);
}
.admin-bar-actions { display: flex; align-items: center; gap: var(--spacing-8); }
.admin-bar[hidden] { display: none; }
/* 저장 알림 — 올라오며 나타나고, 2초 뒤 내려가며 사라진다. 모달 위에서도 보이게 모달(100) · 툴팁(110)보다 위 */
.admin-toast { z-index: 120; gap: var(--spacing-8); padding-right: var(--spacing-20); animation: admin-bar-in var(--motion-layout) both; }   /* 아이콘과 글은 붙여서 — 저장 줄의 32 는 버튼 묶음용 */
.admin-toast.is-leaving { animation: admin-bar-out var(--motion-layout) both; }   /* 토큰에 easing 이 들어 있다 — 뒤에 또 쓰면 선언이 무효 */
.admin-toast-icon { width: var(--icon-size-btn); height: var(--icon-size-btn); color: var(--text-primary); flex: none; }
@keyframes admin-bar-in { from { transform: translate(-50%, var(--spacing-16)); opacity: 0; } to { transform: translate(-50%, 0); opacity: 1; } }
@keyframes admin-bar-out { from { transform: translate(-50%, 0); opacity: 1; } to { transform: translate(-50%, var(--spacing-16)); opacity: 0; } }
/* 저장 중 버튼 — 돌아가는 원은 디자인 시스템(.btn.is-loading::before). 비활성이어도 회색이 아니라 채운 색 그대로 */
.btn.fill.is-loading:disabled { background: var(--accent-fill); border-color: var(--accent-fill); color: var(--white); cursor: progress; }
.admin-bar-text { font-size: var(--font-base); font-weight: 500; line-height: 1.4; color: var(--text-primary); }

/* ============================================================
   8. 모달 — 설정 등 공통 다이얼로그
   ============================================================ */
body.is-modal-open { overflow: hidden; }

.modal-scrim {
  position: fixed; inset: 0; z-index: 100;
  display: flex; align-items: center; justify-content: center;
  padding: var(--spacing-24);
  background: var(--scrim);
  backdrop-filter: blur(var(--scrim-blur));
  -webkit-backdrop-filter: blur(var(--scrim-blur));
}
.modal {
  display: flex; flex-direction: column;
  width: 100%; max-width: 880px;
  height: var(--modal-h); max-height: calc(100vh - var(--spacing-48));
  background: var(--white); border: 1px solid var(--border);
  border-radius: var(--radius-12); box-shadow: var(--shadow-lg); overflow: hidden;
}

/* ---- 알림 대화상자(.alert-modal) — 내용만큼만 높은 작은 변형(삭제 확인 · 임시 비밀번호).
   머리 · 바닥에 선과 면이 없고 여백이 촘촘하다. 설정 같은 큰 모달과 따로 관리한다 ---- */
.alert-modal { max-width: 480px; height: auto; }
.alert-modal .modal-head { padding: var(--spacing-20) var(--spacing-24) var(--spacing-8); border-bottom: none; }
.alert-modal .modal-title { font-size: var(--font-base); font-weight: 600; line-height: 1.4; }
.alert-modal .modal-panel { padding: var(--spacing-24); gap: var(--spacing-8); }
.alert-modal .modal-text { font-weight: 600; }   /* 머리 줄이 없으니 첫 문장이 제목 노릇 */
.alert-modal .pw-list { margin-top: var(--spacing-8); }
.alert-modal .modal-foot { padding: 0 var(--spacing-24) var(--spacing-24); border-top: none; background: none; }
/* 전체화면 변형 — 도면 크게 보기. 화면을 다 쓰고 본문은 한가운데 */
.modal.is-zoom { max-width: none; height: 100%; max-height: 100%; }
.modal.is-zoom .modal-panel { align-items: center; justify-content: center; }

/* 가로로 늘어놓는 줄은 세로 가운데 정렬이 기본이다.
   flex-start 로 두면 그 줄에서 제일 높은 요소(보통 버튼)가 높이를 정하고
   글자만 위에 붙어 떠 보인다. 위 맞춤은 여러 줄 덩어리끼리 나란히 놓을 때만 쓴다. */
.modal-head {
  display: flex; align-items: center; justify-content: space-between; gap: var(--spacing-16);
  padding: var(--spacing-16) var(--spacing-24);
  border-bottom: 1px solid var(--border);
}
.modal-head-text { display: flex; flex-direction: column; gap: var(--spacing-2); min-width: 0; }
.modal-title { font-size: 19px; font-weight: 700; line-height: 1.5; color: var(--text-primary); }
.modal-desc { font-size: var(--font-base); line-height: 1.5; color: var(--text-caption); }

.modal-body { flex: 1; min-height: 0; display: flex; align-items: stretch; }

.modal-nav {
  flex: 0 0 180px; width: 180px;
  display: flex; flex-direction: column; gap: var(--spacing-2);
  padding: var(--spacing-12); border-right: 1px solid var(--border);
  background: var(--bg-soft); overflow-y: auto;
}
.modal-nav-item {
  display: flex; align-items: center; min-height: 36px;
  padding: var(--spacing-8) var(--spacing-12); border-radius: var(--radius-6);
  font-size: var(--font-base); font-weight: 500; line-height: 1.4; color: var(--text-body);
  background: none; border: none; cursor: pointer; text-align: left;
}
.modal-nav-item:hover { background: var(--transparent-hover); }
.modal-nav-item:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.modal-nav-item.is-active {
  background: var(--selected-bg-on-soft); color: var(--selected-fg);
}
/* 다른 화면으로 나가는 항목 — 탭들 아래 선으로 떼고 셰브론으로 "여기서 열리지 않는다"를 말한다 */
/* 링크 항목(관리자 페이지로 이동)은 탭 묶음 아래 선 하나로 떼어 둔다 — 탭이 아니라 다른 화면으로 나가는 길 */
.modal-nav-item.is-link { position: relative; justify-content: space-between; margin-top: var(--spacing-24); text-decoration: none; }
.modal-nav-item.is-link::before {
  content: ""; position: absolute; top: calc(var(--spacing-12) * -1); left: calc(var(--spacing-12) * -1); right: calc(var(--spacing-12) * -1);
  border-top: 1px solid var(--grey-50);
}
/* 동작 항목(로그아웃)만 맨 아래에 고정 */
.modal-nav-item.is-action { gap: var(--spacing-8); margin-top: auto; color: var(--text-sub); }
.modal-nav-icon { width: var(--icon-size-btn); height: var(--icon-size-btn); color: var(--text-caption); }
.modal-nav-chev { width: var(--icon-size); height: var(--icon-size); color: var(--text-caption); }

.modal-panel {
  flex: 1; min-width: 0; overflow-y: auto;
  padding: var(--spacing-24);
  display: flex; flex-direction: column; gap: var(--spacing-16);
}
.modal-panel-note { font-size: var(--font-base); line-height: 1.5; color: var(--text-caption); }
.modal-text { margin: 0; font-size: var(--font-base); line-height: 1.5; color: var(--text-primary); }
.modal-foot-left { margin-right: auto; }   /* 바닥 줄 왼쪽에 두는 버튼(전체 복사) */

.modal-foot {
  display: flex; align-items: center; justify-content: flex-end; gap: var(--spacing-8);
  padding: var(--spacing-16) var(--spacing-24);
  border-top: 1px solid var(--border); background: var(--bg-soft);
}

/* ---- 모달 안 폼 조각 ---- */
.field-list { display: flex; flex-direction: column; }
.field-row {
  display: flex; align-items: center; gap: var(--spacing-16);
  padding: var(--spacing-12) 0; border-bottom: 1px solid var(--grey-50);
}
.field-row:last-of-type { border-bottom: none; }   /* 뒤에 안내문(p)이 붙어도 마지막 줄의 선은 뺀다 */
.field-label {
  flex: 0 0 160px; width: 160px;
  display: flex; flex-direction: column; gap: var(--spacing-2);
  font-size: var(--font-base); font-weight: 500; line-height: 1.4; color: var(--text-primary);
}
.field-note { font-size: var(--font-base); font-weight: 400; line-height: 1.4; color: var(--text-caption); }
.field-control { flex: 1; min-width: 0; display: flex; align-items: center; gap: var(--spacing-8); flex-wrap: wrap; }
.field-value { font-size: var(--font-base); line-height: 1.5; color: var(--text-body); }
.field-input {
  width: 100%; max-width: 320px; height: var(--control-h);
  padding: 0 var(--spacing-12);
  border: 1px solid var(--border); border-radius: var(--radius-8);
  background: var(--white); font-size: var(--font-base); line-height: 1.4; color: var(--text-primary);
}
.field-input:focus { outline: none; border-color: var(--control-border-active); box-shadow: var(--focus-ring); }
.field-input::placeholder { color: var(--grey-200); }
.field-input[readonly] { background: var(--bg-soft); color: var(--text-sub); cursor: default; }
.field-input[readonly]:focus { border-color: var(--border); box-shadow: none; }
.field-error { margin: 0; font-size: var(--font-sub); line-height: 1.5; color: var(--red-500); }   /* 칸 아래 한 줄 — 로그인과 같은 꼴 */
.field-control .field-error { flex-basis: 100%; }
/* 라벨은 늘 위에 붙이고 첫 줄만 입력칸(32) 가운데에 맞춘다 — 오류 줄 · 보조 줄로 줄이 높아져도 아무것도 안 움직인다 */
.field-row { align-items: flex-start; }
.field-row .field-label { padding-top: calc((var(--control-h) - var(--font-base) * 1.4) / 2); }
.field-row .field-control { min-height: var(--control-h); }
/* 비밀번호 칸 — 눈 아이콘은 칸 안 오른쪽, 글자는 아이콘을 피해 끝난다 */
.pw-field { position: relative; display: block; width: 100%; max-width: 320px; }
.pw-field .field-input { max-width: none; width: 100%; padding-right: calc(var(--spacing-12) + var(--icon-size-btn) + var(--spacing-8)); }
.pw-toggle {
  position: absolute; right: var(--spacing-4); top: 50%; transform: translateY(-50%);
  display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px;
  border: 0; border-radius: var(--radius-6); background: none; color: var(--text-caption); cursor: pointer;
}
.pw-toggle:hover { background: var(--bg-soft); color: var(--text-primary); }
.pw-toggle:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.pw-toggle svg { width: var(--icon-size-btn); height: var(--icon-size-btn); }
.login-card .pw-field { max-width: none; }
/* 첫 로그인 계정 설정 — 이름 아래 비밀번호 변경 체크 하나와 한 줄 안내. 체크하면 그 아래 새 비밀번호 칸 */
.login-section { display: flex; flex-direction: column; gap: var(--spacing-8); }
/* 카드 안 글자는 세 가지뿐 — 제목(22 굵게) · 설명(16 연하게) · 라벨(14 연하게) */
.login-card .login-check .checkrow-label { font-weight: 400; }   /* 체크 글자는 입력칸 글자와 같은 굵기 */
/* 체크 줄은 다른 줄과 같은 왼쪽 선에서 시작한다 — 들여쓰기 · 호버 면 없이 */
.login-card .login-check { padding: 0; margin: 0; border-radius: 0; gap: var(--spacing-8); }   /* 상자와 글 사이는 좁게 */
.login-optional { font-weight: 400; color: var(--text-sub); }
.login-card .login-check:hover { background: none; }
.login-section [data-login-pw-fields] { margin-top: var(--spacing-8); }
.login-section [data-login-pw-fields][hidden] { display: none; }
.field-input.is-error, .dd-trigger.is-error { border-color: var(--red-500); }
.field-input.is-error:focus { box-shadow: var(--focus-ring-danger); }

/* 폼용 드롭다운 — 칸을 꽉 채우고 고른 값은 한 줄로 */
.dd-field { width: 100%; }
.dd-field .dd-trigger { width: 100%; justify-content: space-between; font-weight: 400; }
.dd-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dd-text.is-empty { color: var(--text-caption); }
.dd-kind { color: var(--grey-200); margin-right: var(--spacing-6); }   /* 두 단계 드롭다운의 종류 이름(그룹 · 지점) */
.dd-opt-btn { width: 100%; background: none; border: 0; text-align: left; font: inherit; cursor: pointer; }
.dd-head { padding: var(--spacing-8) var(--spacing-12) var(--spacing-2); font-size: var(--font-base); font-weight: 500; line-height: 1.4; color: var(--text-caption); }
.dd-empty { padding: var(--spacing-8) var(--spacing-12); font-size: var(--font-base); line-height: 1.4; color: var(--text-caption); white-space: nowrap; }
.dd-menu .checkrow.is-compact { padding: var(--spacing-6) var(--spacing-8); }
/* 고르는 메뉴 — 목록이 길면 메뉴 안에서 스크롤, 검색 칸은 위에 고정 */
.dd-menu-pick { max-height: 320px; }
.dd-menu.dd-menu-pick { max-width: 420px; }   /* 둘째 화면 안에서는 메뉴 폭을 그대로 채운다 */
/* 메뉴 줄은 한 줄 — 보조 글(어디에 연결됐는지)은 아래가 아니라 오른쪽 끝에 */
.checkrow-text.is-row { flex: 1; flex-direction: row; align-items: center; justify-content: space-between; gap: var(--spacing-12); }
.checkrow-text.is-row .checkrow-note { white-space: nowrap; }
.dd-menu-pick .check-list { overflow-y: auto; min-height: 0; }
.dd-menu-pick .checkrow[hidden], .dd-list .dd-opt[hidden] { display: none; }
.dd-sub-body.dd-menu-pick { display: flex; flex-direction: column; min-height: 0; }
.dd-list { display: flex; flex-direction: column; gap: var(--spacing-2); overflow-y: auto; min-height: 0; }
.dd-opt-drill.is-active { background: var(--selected-bg); color: var(--selected-fg); }
.dd-search-box { flex-shrink: 0; padding: var(--spacing-6) var(--spacing-6) var(--spacing-8); }
.checkrow.is-disabled { opacity: var(--disabled-opacity); cursor: not-allowed; }
.toggle.is-disabled { opacity: var(--disabled-opacity); cursor: not-allowed; }
.icon-btn.is-disabled { opacity: var(--disabled-opacity); cursor: not-allowed; }

/* 관리 표(거점 · 그룹 · 계정) — 줄마다 입력칸이 있는 표. 열 폭은 탭이 --adm-cols 로 준다 */
.adm { display: flex; flex-direction: column; }
.adm-row {
  display: grid; grid-template-columns: var(--adm-cols); gap: var(--spacing-12); align-items: center;
  padding: var(--spacing-8) 0; border-bottom: 1px solid var(--grey-50);
}
.adm-row:last-child { border-bottom: none; }
/* 머리글은 상자 — 열 폭은 본문 줄과 같게 두고(좌우 여백을 줄이 아니라 첫 · 끝 칸에), 글자 시작선은 입력칸 글자와 같은 12px */
.adm-row.is-head {
  padding: var(--spacing-8) 0; margin-bottom: var(--spacing-8);
  background: var(--grey-25); border: 1px solid var(--border); border-radius: var(--radius-8);
  font-size: var(--font-base); font-weight: 500; line-height: 1.4; color: var(--text-caption);
}
/* 머리글 글자는 첫 열만 상자 안쪽 여백(12)을 두고, 나머지 열은 열 시작선에 둔다 — 전부 입력칸 글자선에 맞추면 오히려 어긋나 보였다(경위: CLAUDE.md 결정 기록) */
.adm-row.is-head > :first-child { padding-left: var(--spacing-12); }
.adm-row.is-head > :not(:first-child):not(.is-center) { padding-left: 2px; }   /* 둘째 열부터는 열 시작선에서 2px 만 */
.adm-row.is-head .module-info { margin-left: var(--spacing-4); vertical-align: -2px; }   /* 머리글 옆 ⓘ — 모듈 제목 옆과 같은 부품 */
.adm-row.is-head > :last-child { padding-right: var(--spacing-12); }
.adm-row.is-head > .is-center { padding-left: 0; text-align: center; }   /* 토글 · 버튼 칸 머리글은 내용처럼 가운데 */
.adm-row .field-input { max-width: none; }
/* 표 안 컨트롤은 공통 높이(32)보다 한 단계 높게 — 줄마다 입력칸이라 32 는 빽빽했다 */
.adm-row .field-input, .adm-row .dd-trigger, .adm-row .btn { height: 34px; }
.adm-cell-center { display: flex; justify-content: center; }
.adm-empty { padding: var(--spacing-16) 0; }
/* 고객사 설정 폼 — 표 대신 설정 모달의 필드 줄을 쓴다. 페이지는 넓으니 모달처럼 좁히지 않는다 */
.adm-form .field-label { flex-basis: 200px; width: 200px; flex-direction: row; align-items: baseline; gap: var(--spacing-8); }   /* 보조 글(SVG · PNG)은 라벨 옆에 나란히 */
.adm-form .field-input { max-width: 480px; height: 34px; }
.adm-form .field-row { padding: var(--spacing-16) 0; }
.logo-slot { display: flex; align-items: center; gap: var(--spacing-12); }
.adm-cell-pw { display: flex; align-items: center; gap: var(--spacing-8); min-width: 0; }

/* 임시 비밀번호 대화상자 — 아이디 · 비밀번호 · 복사 한 줄씩 */
.pw-list { display: flex; flex-direction: column; }
.pw-row { display: flex; align-items: center; gap: var(--spacing-12); padding: var(--spacing-8) 0; border-bottom: 1px solid var(--grey-50); }
.pw-row:last-child { border-bottom: none; }
.pw-id { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--font-base); font-weight: 500; color: var(--text-primary); }
.pw-code { font-family: ui-monospace, Menlo, monospace; font-size: var(--font-base); letter-spacing: .04em; color: var(--text-primary); }
.icon-btn.is-done { color: var(--text-primary); background: var(--selected-bg); }
.admin-panel-head { display: flex; flex-direction: column; gap: var(--spacing-6); padding-top: var(--spacing-24); }
.admin-panel-head .modal-panel-note { margin: 0; }
/* 표 위 검색 — 줄을 브라우저 안에서 거른다 */
.admin-table { display: flex; flex-direction: column; gap: var(--spacing-12); }
/* 도구 줄과 표 머리글은 스크롤해도 위에 붙는다 — 도구 줄(32)이 맨 위, 머리글이 그 바로 아래. 사이 여백은 도구 줄의 흰 면이 채운다 */
.admin-tools {
  position: sticky; top: 0; z-index: 20;
  display: flex; align-items: center; justify-content: space-between; gap: var(--spacing-12);
  padding: var(--spacing-12) 0; margin: calc(var(--spacing-12) * -1) 0;
  background: var(--white);
}
.admin-tools .field-input, .admin-tools .btn { height: 34px; }   /* 표 안 컨트롤과 같은 높이 */
.admin-tools { height: calc(34px + var(--spacing-12) * 2); box-sizing: border-box; }   /* 머리글이 붙는 기준과 같은 높이로 고정 */
.adm-row.is-head { position: sticky; top: calc(34px + var(--spacing-12) * 2); z-index: 19; }
/* 붙은 머리글 아래 여백도 흰 면으로 — 지나가는 줄이 틈으로 비치지 않게 */
.adm-row.is-head::after { content: ""; position: absolute; left: -1px; right: -1px; top: 100%; height: var(--spacing-8); background: var(--white); }
.admin-tools-right { display: flex; align-items: center; gap: var(--spacing-8); }
.admin-count { font-size: var(--font-base); font-weight: 500; line-height: 1.4; color: var(--text-sub); }
/* 검색 칸 — 왼쪽에 돋보기, 글자는 아이콘 뒤에서 시작 */
.search-field { position: relative; display: block; }
.search-field .field-input { display: block; }   /* 인라인이면 라벨 아래 글줄 여백이 붙어 높이가 어긋난다 */
.search-field > svg { position: absolute; left: var(--spacing-12); top: 50%; width: var(--icon-size-btn); height: var(--icon-size-btn); transform: translateY(-50%); color: var(--text-caption); pointer-events: none; }
.search-field .field-input { max-width: none; padding-left: calc(var(--spacing-12) + var(--icon-size-btn) + var(--spacing-8)); background: var(--grey-25); }
.admin-search { width: 360px; max-width: 100%; }
.adm-row[hidden] { display: none; }
.adm-nomatch { margin: 0; padding: var(--spacing-16) 0; }


.toggle { display: inline-flex; align-items: center; gap: var(--spacing-8); cursor: pointer; }
.toggle input { position: absolute; opacity: 0; width: 0; height: 0; }
.toggle-track {
  position: relative; width: 40px; height: 22px; flex-shrink: 0;
  border-radius: var(--radius-pill); background: var(--grey-200);
}
.toggle-thumb {
  position: absolute; top: 3px; left: 3px; width: 16px; height: 16px;   /* 트랙(22) 안에서 3px 띄움 — 원이 트랙을 꽉 채우면 무겁다 */
  border-radius: var(--radius-pill); background: var(--white); box-shadow: var(--shadow-sm);
}
.toggle input:checked + .toggle-track { background: var(--control-fill); }
.toggle input:checked + .toggle-track .toggle-thumb { transform: translateX(18px); }
.toggle input:focus-visible + .toggle-track { box-shadow: var(--focus-ring); }
.toggle-label { font-size: var(--font-base); line-height: 1.4; color: var(--text-body); }

.check-list { display: flex; flex-direction: column; gap: var(--spacing-2); }
.checkrow {
  /* 여기만 위 맞춤 — 오른쪽 설명이 여러 줄로 흐를 때 체크박스가 첫 줄에 붙어야 한다 */
  display: flex; align-items: flex-start; gap: var(--spacing-12);
  padding: var(--spacing-12); border-radius: var(--radius-8); cursor: pointer;
}
.checkrow:hover { background: var(--bg-soft); }
.checkrow input { position: absolute; opacity: 0; width: 0; height: 0; }
.checkrow-box {
  display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; flex-shrink: 0; margin-top: 1px;
  border: 1px solid var(--border); border-radius: var(--radius-6);
  background: var(--white); color: transparent;
}
.checkrow-box svg { width: var(--icon-size); height: var(--icon-size); }
.checkrow input:checked + .checkrow-box {
  background: var(--control-fill); border-color: var(--control-fill); color: var(--white);
}
.checkrow input:focus-visible + .checkrow-box { box-shadow: var(--focus-ring); }
.checkrow-text { display: flex; flex-direction: column; gap: var(--spacing-2); min-width: 0; }
.checkrow-label { font-size: var(--font-base); font-weight: 500; line-height: 1.4; color: var(--text-primary); }
.checkrow-note { font-size: var(--font-base); line-height: 1.4; color: var(--text-caption); }

.radio-row { display: flex; align-items: center; gap: var(--spacing-16); flex-wrap: wrap; }
.radio {
  display: inline-flex; align-items: center; gap: var(--spacing-6); cursor: pointer;
  font-size: var(--font-base); line-height: 1.4; color: var(--text-body);
}
.radio input { position: absolute; opacity: 0; width: 0; height: 0; }
.radio-dot {
  width: 18px; height: 18px; flex-shrink: 0;
  border: 1px solid var(--border); border-radius: var(--radius-pill); background: var(--white);
}
.radio input:checked + .radio-dot {
  border: 5px solid var(--control-fill); background: var(--white);
}
.radio input:focus-visible + .radio-dot { box-shadow: var(--focus-ring); }

/* ---- 모달 안 목록 ---- */
.list { display: flex; flex-direction: column; }
.list-row {
  display: flex; align-items: center; justify-content: space-between; gap: var(--spacing-16);
  width: 100%; padding: var(--spacing-12); border-bottom: 1px solid var(--grey-50);
  background: none; border-left: none; border-right: none; border-top: none; text-align: left;
}
.list-row:last-child { border-bottom: none; }
.list-row.is-clickable { cursor: pointer; border-radius: var(--radius-8); }
.list-row.is-clickable:hover { background: var(--bg-soft); }
.list-row.is-active { background: var(--selected-bg); }
.list-row-text { display: flex; flex-direction: column; gap: var(--spacing-2); min-width: 0; }
.list-row-name { font-size: var(--font-base); font-weight: 600; line-height: 1.4; color: var(--text-primary); }
.list-row-sub { font-size: var(--font-base); line-height: 1.4; color: var(--text-caption); }
.badge {
  display: inline-flex; align-items: center; height: 24px; padding: 0 var(--spacing-8);
  border-radius: var(--radius-pill); background: var(--grey-50); color: var(--text-sub);
  font-size: var(--font-base); font-weight: 500; line-height: 1;
}
.badge.is-muted { background: var(--grey-50); color: var(--text-caption); }

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

/* ============================================================
   9. 반응형 — lg 미만에서 SNB를 상단 바로 접음
   ============================================================ */
@media (max-width: 1279px) {
  :root { --page-gutter: 24px; }
}
/* 태블릿 미지원 — 좁아져도 데스크톱 레이아웃(고정 SNB + 헤더 + 밴드)을 그대로 유지한다.
   폭이 모자라면 본문이 가로 스크롤된다. 모듈 열 수만 줄인다. */
@media (max-width: 1023px) {
  .module.is-3 { grid-column: span 6; }
  .module.is-4 { grid-column: span 6; }
  .module.is-8 { grid-column: span 12; }
}

@media (max-width: 767px) {
  .modal { height: 100%; max-height: 100%; border-radius: 0; }
  .modal-body { flex-direction: column; }
  .modal-nav {
    width: auto; flex-direction: row; overflow-x: auto;
    border-right: none; border-bottom: 1px solid var(--border);
  }
  .modal-nav-item { white-space: nowrap; }
  .field-row { flex-direction: column; align-items: flex-start; gap: var(--spacing-6); }
  .field-label { width: auto; }
  .module.is-3, .module.is-4, .module.is-6 { grid-column: span 12; }
  .dp-pop { position: fixed; left: var(--spacing-12); right: var(--spacing-12); top: auto; width: auto; }
  .dp-body { flex-direction: column; }
  .dp-presets { width: auto; flex-direction: row; flex-wrap: wrap; border-right: none; border-bottom: 1px solid var(--border); }
  .dp-cals { flex-direction: column; overflow-x: auto; }
  .dp-cal { width: 100%; }
}

/* ==========================================================================
   로딩 뼈대 (스켈레톤)
   스피너 대신 뼈대를 쓴다 — 한 화면에 카드가 6~10 장이라 스피너가 그만큼 돌면
   시선이 흩어지고, 내용이 들어오는 순간 카드 높이가 튄다.
   뼈대는 자리를 미리 잡아 두므로 데이터가 와도 레이아웃이 안 흔들린다.
   ========================================================================== */
/* 흐르는 그라데이션 대신 밝기만 숨 쉬듯 오르내린다.
   좌우로 쓸고 가는 빛은 상자마다 따로 움직여서, 한 화면에 여덟 개면 방향이 제각각으로 읽힌다.
   밝기는 방향이 없어서 여러 개가 같이 있어도 한 덩어리로 보인다. */
.sk {
  display: block;
  background: var(--grey-50);
  border-radius: var(--radius-6);
  animation: sk-pulse 1.6s ease-in-out infinite;
}
@keyframes sk-pulse {
  from, to { opacity: 1; }
  50% { opacity: .45; }
}
/* 움직임을 줄여 달라고 설정한 사람에게는 흐르지 않고 가만히 있는 회색 면으로 */
@media (prefers-reduced-motion: reduce) { .sk { animation: none; } }

.sk-line { height: 20px; }
.sk-line.is-w25 { width: 25%; }
.sk-line.is-w40 { width: 40%; }
.sk-block { height: 96px; }
.sk-chart { height: var(--chart-h); }

/* 스크립트가 도착하기 전 본문 뼈대 — app.js 첫 그리기에서 통째로 사라진다 */
.page-boot { padding-top: var(--spacing-24); }

/* 차트 자리 뼈대 — 그려질 모양을 따라간다 (bars / circle / block).
   캔버스 위에 겹쳐 두고, mount 가 .is-loading 을 떼면 사라진다. */
.chart-sk { position: absolute; inset: 0; display: none; }
.chart.is-loading .chart-sk { display: flex; }
/* 로딩 중에는 캔버스 위에 겹친 것들(도넛 가운데 숫자 등)을 감춘다 */
.chart.is-loading > :not(.chart-sk):not(canvas) { display: none; }

.chart-sk.is-bars { align-items: flex-end; gap: var(--spacing-8); padding-top: var(--spacing-8); }
.chart-sk.is-bars > .sk { flex: 1; min-width: 0; border-radius: var(--radius-4) var(--radius-4) 0 0; }
.chart-sk.is-block { padding: var(--spacing-8) 0; }
.chart-sk.is-block > .sk { width: 100%; height: 100%; border-radius: var(--radius-8); }
.chart-sk.is-circle { align-items: center; justify-content: center; }
/* 도넛은 캔버스 짧은 변에 맞춰 커진다 — 뼈대도 같은 규칙으로 동그랗게 */
.chart-sk.is-circle > .sk { height: 78%; aspect-ratio: 1; border-radius: var(--radius-pill); }

/* ---- 차트가 아닌 모듈의 뼈대 ----
   실제 모듈과 같은 뼈대·같은 칸 수를 쓴다. 자리만 다르게 잡으면
   내용이 들어오는 순간 레이아웃이 튀어서 뼈대를 둔 뜻이 없어진다. */
.sk-line.is-w50 { width: 50%; }
.sk-line.is-w60 { width: 60%; }
.sk-line.is-w70 { width: 70%; }
.sk-line.is-w80 { width: 80%; }
.sk-num { height: 34px; width: 70%; }
.sk-num.is-sm { height: 26px; }

/* 표 — 머리글 한 줄 + 행 줄무늬. 실제 표와 같은 높이를 쓴다 */
.sk-table { display: flex; flex-direction: column; gap: var(--spacing-4); }
.sk-table-head { height: 37px; }
.sk-table-row { height: 37px; opacity: .6; }

/* KPI 묶음 — kpi-group 과 같은 칸 수·같은 여백 */
.sk-kpi { display: grid; grid-template-columns: repeat(var(--kpi-cols, 4), minmax(0, 1fr)); }
.sk-kpi-item {
  display: flex; flex-direction: column; gap: var(--spacing-8);
  min-width: 0; padding: var(--spacing-20);
}
.sk-kpi { margin: calc(var(--spacing-20) * -1); }

/* 퍼널 — 단계마다 줄어드는 막대 */
.sk-fn { display: flex; gap: var(--spacing-16); }
.sk-fn-col {
  flex: 1; min-width: 0;
  display: flex; flex-direction: column; gap: var(--spacing-8);
  padding: 0 var(--spacing-16);
}
.sk-fn-track { height: 200px; display: flex; align-items: flex-end; }
.sk-fn-bar { width: 100%; border-radius: var(--radius-4) var(--radius-4) 0 0; }

/* 순위 목록 — 거점 순위(1칸) · 주요 구역(3칸) */
.sk-rank { display: grid; grid-template-columns: repeat(var(--sk-rank-cols, 1), minmax(0, 1fr)); gap: var(--spacing-32); }
.sk-rank-col { display: flex; flex-direction: column; gap: var(--spacing-8); min-width: 0; }
.sk-rank-row { height: 28px; }

/* 거점 요약 카드 — 지표 셋 + 문장 두 줄 */
.sk-ins { flex: 1; display: flex; flex-direction: column; gap: var(--spacing-20); }
.sk-ins-stats { display: grid; grid-template-columns: repeat(var(--ins-cols, 3), minmax(0, 1fr)); gap: var(--spacing-8); }
.sk-ins-stats .sk-kpi-item { padding: 0; gap: var(--spacing-4); }
.sk-ins-text {
  flex: 1; display: flex; flex-direction: column; gap: var(--spacing-8);
  margin: 0 calc(var(--spacing-20) * -1) calc(var(--spacing-20) * -1);
  padding: var(--spacing-16) var(--spacing-20);
  border-top: 1px solid var(--border);
}

/* ---- SNB 메뉴 설정 — 거점 순서 끌어서 바꾸기 (설정 모달) ---- */
/* 설정 모달의 순서 목록 — 줄마다 테두리 상자(거점 하나 = 상자 하나). 전체를 감싸는 테두리는 해 보고 뺐다.
   호버 · 잡는 중에도 테두리는 그대로(컨트롤 공통 규칙), 바탕만 바뀐다 */
.order-box .order-list { gap: var(--spacing-6); }
.order-box .order-item { border: 1px solid var(--border); }
.order-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; position: relative; touch-action: none; user-select: none; }
.order-item {
  display: flex; align-items: center; gap: var(--spacing-4);
  padding: var(--spacing-6) var(--spacing-8) var(--spacing-6) var(--spacing-4);   /* 손잡이는 헤더 ‹ 보다 한 단계 바깥 — 잡는 자리가 줄 맨 왼쪽에 붙게 */
  border-radius: var(--radius-6); background: var(--white); cursor: grab;
  transition: transform 160ms ease;
}
.order-item:hover { background: var(--bg-soft); }
.order-item.is-dragging { position: relative; z-index: 2; cursor: grabbing; background: var(--bg-soft); box-shadow: var(--shadow-md); transition: none; }   /* 잡은 줄은 호버와 같은 색 */
/* 손잡이는 헤더의 ‹ 와 같은 28px 상자 — 아이콘 중심과 이름 시작선이 헤더와 맞는다 */
.order-handle { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; flex: none; color: var(--text-caption); }
.order-handle svg { width: var(--icon-size); height: var(--icon-size); }
.order-name { flex: 1; min-width: 0; font-size: var(--font-base); font-weight: 500; line-height: 1.4; color: var(--text-primary); white-space: nowrap; }
