/* ═══════════════════════════════════════════════════════════════════════════
   @marunex/board-core — 보드 공통 화면 규칙
   ───────────────────────────────────────────────────────────────────────────
   두 보드가 글자 단위로 같던 규칙만 담는다. 화면 고유 규칙은 소비 프로젝트가
   제 styles.css 에 두고 **이 파일 뒤에** 싣는다.

   ★ 색 리터럴을 쓰지 않는다. 전부 tokens.css 의 토큰 참조다 — 그래야 themes.css
     가 토큰만 덮어써도 전 화면 톤이 바뀐다.
   ★ 순서가 계약이다. 로드 순서는 index.js 의 THEME_LOAD_ORDER 를 볼 것.
   ═══════════════════════════════════════════════════════════════════════════ */
/* ═══════════════════════════════════════════════════════════════════
   화면 스타일 — 색 리터럴(#hex)이 이 파일에 단 하나도 없다.
   색·라운드·간격은 전부 tokens.css 의 토큰을 참조하고,
   톤 교체는 themes.css 가 그 토큰만 덮어써서 처리한다.
   ※ 로드 순서: tokens.css → styles.css → themes.css
   ※ 여기에 새 색을 쓸 일이 생기면 hex를 적지 말고 tokens.css 에 토큰을 먼저 만들 것.
═══════════════════════════════════════════════════════════════════ */
/* ── 기본 ──────────────────────────────────────────────────────── */
* {
  box-sizing: border-box;
  word-break: keep-all;
  overflow-wrap: break-word;
}

/* §3-A 전역 타이포 — Pretendard + 한글 자간 보정(-0.01em), 제목은 -0.02em */
html {
  /* 글꼴 이름은 tokens.css `--nu-font` 한 곳에만 적는다 - 여기 박으면 테마가 못 덮는다 */
  font-family: var(--nu-font);
  letter-spacing: -0.01em;
  text-rendering: optimizeLegibility;
  -webkit-text-size-adjust: 100%;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
h1, h2, h3 { letter-spacing: -0.02em; }

/* §4-D 얇은 스크롤바 · ::selection (전역) */
::-webkit-scrollbar { width: 5px; height: 5px; }
::-webkit-scrollbar-track { background: var(--nu-surface-3); }
::-webkit-scrollbar-thumb { background: var(--nu-surface-4); border-radius: var(--nu-r-small); }
::-webkit-scrollbar-thumb:hover { background: var(--jv-primary); }
::selection { background: var(--nu-primary-selection); color: var(--jv-txt1); }

html, body {
  height: 100%;
}

body {
  margin: 0;
  font-family: inherit;
  line-height: 1.5;
  color: var(--text);
  background: var(--nu-board, var(--bg));   /* 화면 바탕(틀) - 상자가 뜨게 한 단계 짙다(0.38.0) */
  overflow: hidden;
}

/* ── 앱 레이아웃 ────────────────────────────────────────────────── */
.app-shell {
  display: grid;
  grid-template-columns: 240px 1fr;
  height: 100vh;
}

.sidebar-backdrop {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.72);
  z-index: 250;
}
.sidebar-backdrop.show { display: block; }

/* ── 사이드바 ───────────────────────────────────────────────────── */
.sidebar {
  display: flex;
  flex-direction: column;
  padding: 24px;
  gap: 24px;
  background: var(--sidebar);
  border-right: 1px solid rgba(255,255,255,0.08);
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
}

.brand {
  display: flex;
  align-items: center;
  gap: 14px;
}

.logo {
  width: 46px;
  height: 46px;
  border-radius: var(--nu-r-large);
  background: linear-gradient(135deg, var(--brand-ci) 0%, var(--brand-ci-dark) 100%);
  box-shadow: 0 2px 8px rgba(237,28,36,0.35);
  flex-shrink: 0;
}

/* (주)오토젠 CI 마크 — 다크 사이드바 위 흰 칩에 배치 */
.brand-ci {
  height: 46px;
  width: auto;
  background: var(--nu-card);
  border-radius: var(--nu-r-large);
  padding: 6px 9px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.22);
  flex-shrink: 0;
}

.brand span {
  font-size: 1.15rem;
  font-weight: 800;
  color: var(--nu-on-accent);
  letter-spacing: -0.01em;
}

.nav {
  display: grid;
  gap: 6px;
}

.nav a {
  display: block;
  padding: 11px 16px;
  text-decoration: none;
  color: rgba(255,255,255,0.75);
  background: rgba(255,255,255,0.05);
  border: 1px solid rgba(255,255,255,0.07);
  border-radius: var(--nu-r-large);
  font-size: 0.92rem;
  font-weight: 500;
  transition: background 0.15s, color 0.15s;
}

.nav a:hover,
.nav a.active {
  background: rgba(255,255,255,0.15);
  color: var(--nu-on-accent);
  border-color: rgba(255,255,255,0.18);
}

/* ── 8분류 그룹 네비게이션 (오토젠_웹_화면설계_기초자료 §1~8) ── */
.nav-group { display: grid; gap: 6px; }
.nav-group > summary {
  list-style: none;
  cursor: pointer;
  padding: 8px 12px 6px;
  color: rgba(255,255,255,0.5);
  font-size: 0.76rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  display: flex;
  align-items: center;
  justify-content: space-between;
  user-select: none;
}
.nav-group > summary::-webkit-details-marker { display: none; }
.nav-group > summary::after {
  content: '▸';
  font-size: 0.68rem;
  opacity: 0.55;
  transition: transform 0.15s;
}
.nav-group[open] > summary::after { transform: rotate(90deg); }
.nav-group .nav-sub { display: grid; gap: 5px; }
.nav-group .nav-sub a { padding-left: 24px; font-size: 0.88rem; }

/* ── 반응형: 좁은 화면(태블릿/모바일 가로)에서는 사이드바를 드로어로 전환 ──── */
@media (max-width: 1200px) {
  .app-shell { grid-template-columns: 1fr; }

  .sidebar {
    position: fixed;
    top: 0;
    left: 0;
    width: 240px;
    height: 100vh;
    z-index: 300;
    transform: translateX(-100%);
    transition: transform 0.22s ease;
    box-shadow: 4px 0 24px rgba(0,0,0,0.3);
  }
  .sidebar.open { transform: translateX(0); }
}
@media (min-width: 1201px) {
  .sidebar-backdrop { display: none !important; }
}

/* ── 메인 콘텐츠 ────────────────────────────────────────────────── */
.main-content {
  display: flex;
  flex-direction: column;
  height: 100%;
  min-height: 0;
  min-width: 0;
}

/* ── 탑바 ───────────────────────────────────────────────────────── */
.topbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0 28px;
  height: 56px;
  background: var(--header);
  border-bottom: 1px solid rgba(255,255,255,0.08);
  position: sticky;
  top: 0;
  z-index: 10;
  flex-shrink: 0;
}

.topbar-left {
  display: flex;
  align-items: center;
  gap: 14px;
}

.menu-btn {
  width: 34px;
  height: 34px;
  border: none;
  border-radius: var(--nu-r-medium);
  background: rgba(255,255,255,0.1);
  color: var(--nu-on-accent);
  cursor: pointer;
  font-size: 1rem;
  display: flex;
  align-items: center;
  justify-content: center;
}

.page-title {
  font-size: 1rem;
  font-weight: 700;
  color: var(--nu-on-accent);
  letter-spacing: -0.01em;
}

.topbar-right {
  display: flex;
  align-items: center;
  gap: 14px;
  font-size: 0.85rem;
  font-weight: 600;
  color: rgba(245,245,245,0.8);
}

.user-chip {
  padding: 5px 12px;
  border: none;
  border-radius: var(--nu-r-pill);
  background: rgba(255,255,255,0.1);
  color: var(--nu-on-accent);
  font-family: inherit;
  font-size: 0.82rem;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s;
}
.user-chip:hover { background: rgba(255,255,255,0.2); }

.logout-btn {
  padding: 5px 14px;
  border: 1px solid rgba(255,255,255,0.18);
  border-radius: var(--nu-r-medium);
  background: rgba(255,255,255,0.05);
  color: rgba(255,255,255,0.85);
  font-size: 0.8rem;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}
.logout-btn:hover {
  background: rgba(255,255,255,0.15);
  color: var(--nu-on-accent);
}

/* ── 히어로 ─────────────────────────────────────────────────────── */
.hero {
  display: grid;
  gap: 2px;
  padding: 8px 28px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--nu-r-xl);
  box-shadow: var(--shadow);
}

.hero-title {
  font-size: 2.2rem;
  font-weight: 800;
  line-height: 1.15;
  text-align: center;
  color: var(--text);
  letter-spacing: -0.02em;
}

.hero-subtitle {
  text-align: center;
  color: var(--muted);
  font-size: 0.95rem;
  line-height: 1.2;
  min-height: 1.2em;
}

.hero-title,
.hero-subtitle,
.page-title {
  word-break: keep-all;
}

/* ── 공통 레이아웃 ─────────────────────────────────────────────── */
.layout-root {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 18px;
}

/* ── 반응형 공통 규칙 (기준 해상도 1920×1080) ──────────────────────
   그리드/플렉스 자식은 기본값이 min-width:auto 라서 "내용의 최소 폭" 아래로는 줄지 않는다.
   Chart.js 캔버스는 렌더 시점 폭이 인라인 style로 박히므로, 넓은 화면에서 열어둔 뒤 창을
   좁히면 그 캔버스 폭에 레이아웃이 잠겨 아무 반응이 없다(새로 열면 정상 → 재현 조건이 헷갈림).
   캔버스는 컨테이너가 줄어야 줄고 컨테이너는 캔버스 때문에 못 주는 교착이라, 아래 min-width:0
   으로 바닥을 풀어줘야 한다. 1920에서는 시각적 변화가 없다. */
/* ★ **`.content` 의 여백·간격은 여기 없다.** 그 기본 규칙을 보드가 들고 있어서다
   (cheil 12px/16px · simaps 24px/28px 로 서로 다르다). 미디어 질의는 명시도를 올리지
   않으므로, 덮개만 여기 두면 **나중에 실리는 보드의 기본 규칙에 져서 조용히 죽는다.**
   실제로 그랬다 — simaps 에서 880x760 여백이 12/18 대신 24/28 로 남아 표 열 폭까지
   수천 개가 어긋났고, 눈으로는 "좀 널널하네" 로만 보였다.

   같은 선택자의 규칙은 한 파일에 모은다. `.content` 는 전부 보드 쪽이다.
   아래 min-width 만 남긴 것은 그것이 값이 아니라 **바닥을 푸는 것**이라서다 —
   보드가 무엇으로 덮든 바뀌지 않는다. */
.content, .layout-root, .layout-root > * { min-width: 0; }
.home-kri-cards > *, .home-kpi-row > *, .home-mid > *, .home-bot > *,
.viz-grid > *, .inj-grid > *, .prod-layout > *, .ed-grid > *,
.layout-grid > *, .tables-grid > *, .dash-stat-row > *, .dash-mid-section > *,
.sh-factory-row > *, .sh-footer > *, .util-row > *, .ep-card-grid > * { min-width: 0; }
.panel, .viz-card, .home-card, .home-kpi, .home-kri-card { min-width: 0; }
canvas { max-width: 100%; }

/* 브라우저 한 화면 무스크롤: 페이지를 창 높이에 맞추고 넘치는 표만 내부 스크롤.
   표에 걸린 max-height(px·calc)는 창 높이마다 어긋나므로 "남은 공간을 채우는" 방식으로 대체한다.
   ※ 브라우저 실제 뷰포트는 주소창·탭바 때문에 모니터 해상도보다 100~150px 작다(1080 → 약 937). */
#layoutRoot.fit-page { display: flex; flex-direction: column; flex: 1; min-height: 0; }
#layoutRoot.fit-page > .panel,
#layoutRoot.fit-page > .inv-tab-content,
#layoutRoot.fit-page > .demand-panel { flex: 1; min-height: 0; display: flex; flex-direction: column; }
/* 남은 높이를 먹는 표는 "플렉스 열의 직계 자식"인 것만 대상으로 한다.
   더 깊이 중첩된 표(예: 생산실적의 좌우 2단 안쪽)는 부모가 높이를 제한하지 않아
   max-height를 풀면 표가 무한히 늘어난다 — 그런 화면은 기존 계산식을 그대로 둔다. */
#layoutRoot.fit-page > .panel > .inv-grid-wrap,
#layoutRoot.fit-page > .panel > .demand-grid-wrap,
#layoutRoot.fit-page > .panel > .sc-table-wrap,
#layoutRoot.fit-page > .panel > .ep-table-wrap,
#layoutRoot.fit-page > .panel > .simr-table-wrap,
#layoutRoot.fit-page > .panel > .wr-table-wrap,
#layoutRoot.fit-page > .panel > .ed-table-wrap,
#layoutRoot.fit-page > .panel > .table-wrapper,
#layoutRoot.fit-page > .panel > .home-card > .inv-grid-wrap,
#layoutRoot.fit-page > .inv-tab-content > .panel > .inv-grid-wrap,
#layoutRoot.fit-page > .demand-panel > .demand-grid-wrap { flex: 1 1 auto; min-height: 96px; max-height: none !important; overflow: auto; }
/* 재고현황은 탭 구조라 본문이 .inv-tab-content > .panel 로 한 단계 더 들어간다.
   그 .panel 이 남는 높이를 받아 안에서 다시 표에 넘겨준다. */
#layoutRoot.fit-page > .inv-tab-content > .panel { flex: 1; min-height: 0; display: flex; flex-direction: column; }
#layoutRoot.fit-page > .panel > .home-card { flex: 1 1 auto; }
/* 차트가 든 카드도 남은 높이에 맞춰 늘고 준다(고정 높이면 짧은 창에서 표를 밀어낸다) */
#layoutRoot.fit-page .home-card { display: flex; flex-direction: column; min-height: 0; }
/* 카드가 여러 줄인 블록은 남는 높이만큼만 쓰고, 모자라면 그 블록 안에서만 스크롤한다
   (페이지 전체가 스크롤되는 것보다 낫다 — 표·차트는 항상 화면에 남는다) */
/* 호기 카드 줄은 제 높이를 지킨다(눌리면 아래 차트와 겹친다) — 남는 높이는 아래 차트가 먹는다 */
#layoutRoot.fit-page > .panel > .util-row { flex: 0 0 auto; }
#layoutRoot.fit-page > .panel > .inj-grid { flex: 1 1 auto; min-height: 0; }
#layoutRoot.fit-page > .panel > .inj-grid > .viz-card { overflow: auto; min-height: 0; }
/* 표 위에 오는 요약·차트·필터 줄은 자기 높이 유지(표만 늘어나고 줄어든다) */
#layoutRoot.fit-page .inv-filter-bar,
#layoutRoot.fit-page .fr-banner,
#layoutRoot.fit-page .viz-grid,
#layoutRoot.fit-page .viz-card,
#layoutRoot.fit-page .ep-mach-row,
#layoutRoot.fit-page .inv-note { flex: 0 0 auto; }

/* ── 1100↓ 무스크롤 해제 (홈 외 전 화면) ────────────────────────────
   fit-page는 "창 높이에 맞추고 표만 내부 스크롤"이 전제다. 좁은 화면에서 차트 카드가
   1열로 접히면 같은 높이에 내용이 2배로 들어가 카드가 짓눌린다(홈 대시보드와 같은 원인).
   폭이 좁아지면 세로로 길어지는 게 정상이므로 페이지 스크롤을 허용한다.
   ※ .content 는 이미 overflow-y:auto 라 별도 처리가 필요 없다. */
@media (max-width: 1100px) {
  #layoutRoot.fit-page { flex: 0 0 auto; min-height: auto; }
  #layoutRoot.fit-page > .panel,
  #layoutRoot.fit-page > .inv-tab-content,
  #layoutRoot.fit-page > .inv-tab-content > .panel,
  #layoutRoot.fit-page > .demand-panel { flex: 0 0 auto; min-height: auto; }
  /* 표는 화면 높이 기준으로 되돌린다 — 안 그러면 수천 행이 그대로 늘어난다 */
  #layoutRoot.fit-page .inv-grid-wrap,
  #layoutRoot.fit-page .demand-grid-wrap { flex: 0 0 auto; max-height: 60vh !important; }
  /* 차트는 폭에 비례한 고정 높이 */
  #layoutRoot.fit-page .viz-wrap,
  #layoutRoot.fit-page .ep-viz-wrap { flex: 0 0 auto; height: clamp(180px, 40vw, 280px); }
  #layoutRoot.fit-page .viz-card { overflow: hidden; }
}

/* ── 창 높이가 짧을 때 단계 축소 (모든 화면 공통) ─────────────────── */
@media (max-height: 900px) {
  .hero { padding: 6px 24px; }
  .hero-title { font-size: 1.75rem; }
  .hero-subtitle { font-size: 0.86rem; }
  .util-card { padding: 9px 11px; }
}
@media (max-height: 780px) {
  .hero { padding: 4px 20px; }
  .hero-title { font-size: 1.4rem; }
  .hero-subtitle { display: none; }
  .util-row { gap: 9px; }
  .util-card { padding: 7px 9px; }
  .util-mn { font-size: 0.86rem; }
  .util-sub { font-size: 0.72rem; }
  .viz-card { padding: 8px 12px; }
  .fr-banner { padding: 6px 12px; font-size: 0.8rem; }
  .kri-totals .home-kri-card { padding: 6px 10px; }
  .kri-totals .home-kri-desc { display: none; }
  .inj-form { gap: 7px; }
  .inj-steps { margin: 2px 0 7px; }
  .inj-mon { margin-top: 9px; padding-top: 9px; }
  .inj-mon-num b { font-size: 1.25rem; }
}
@media (max-height: 700px) {
  .hero { display: none; }
  /* 가동현황 — 호기 카드를 더 낮게(한 줄 배치는 유지, 게이지는 vh로 자동 축소) */
  .util-row { gap: 7px; }
  .util-card { padding: 6px 7px; }
  .util-card .util-sub:last-child { display: none; }
  /* 사출기 연동 — 배너·카드 압축 */
  .fr-banner { font-size: 0.75rem; padding: 5px 10px; }
  .inj-machine-hdr { padding: 6px 12px; }
  .inj-precond { padding: 5px 9px; font-size: 0.74rem; }
  .inj-form { gap: 5px; }
  .inj-form label { font-size: 0.8rem; }
  .inj-step { font-size: 0.72rem; padding: 3px 8px; }
  .inj-badge { font-size: 0.84rem; padding: 4px 11px; }
  .inj-mon { margin-top: 7px; padding-top: 7px; }
  .inj-mon-num b { font-size: 1.1rem; }
  .inj-addr, .inj-mon-sub { font-size: 0.7rem; }
  .viz-card { padding: 7px 10px; }
}

.layout-grid {
  display: grid;
  gap: 18px;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
}

/* ── 위젯 패널 (공통 카드) ─────────────────────────────────────── */
.widget-panel {
  padding: 20px 22px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--nu-r-xl);
  box-shadow: var(--mx-lift);   /* 카드와 같은 떠 보이기(0.38.0) */
}

.widget-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 14px;
}

.widget-title {
  font-size: 1rem;
  font-weight: 700;
  color: var(--text);
}

/* 표를 담는 패널이 부모로부터 유한한 높이를 받으면, 헤더는 고정하고
   표 영역만 내부 스크롤되게 함 (페이지 전체는 스크롤되지 않도록) */
.table-widget-panel {
  display: flex;
  flex-direction: column;
  min-height: 0;
}
.table-widget-panel .widget-header { flex: 0 0 auto; }
.table-scroll-wrap {
  flex: 1;
  min-height: 0;
  overflow: auto;
}
.table-scroll-wrap th {
  position: sticky;
  top: 0;
  z-index: 1;
}

/* ── 기본 테이블 ─────────────────────────────────────────────────── */
table {
  width: 100%;
  border-collapse: collapse;
  color: var(--text);
}

th, td {
  padding: 10px 12px;
  border-bottom: 1px solid var(--border);
}

th {
  text-align: left;
  background: var(--th-bg);
  color: var(--th-text);
  font-size: 0.88rem;
  font-weight: 600;
}

tbody tr:hover {
  background: var(--row-hover);
}

tbody tr:nth-child(even) {
  background: var(--row-alt);
}

/* ── 필터 ────────────────────────────────────────────────────────── */
.filters {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 14px;
  padding: 18px 0;
}

.filter-group {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.filter-group label {
  font-size: 0.88rem;
  color: var(--muted);
}

.filter-group select {
  width: 100%;
  padding: 10px 12px;
  border-radius: var(--nu-r-large);
  border: 1px solid var(--border);
  background: var(--panel);
  color: var(--text);
  font-size: 0.88rem;
}

.filter-group select option {
  background: var(--nu-card);
  color: var(--text);
}

.filter-group select:focus {
  outline: none;
  border-color: var(--nu-primary);
  box-shadow: 0 0 0 3px rgba(130,10,209,0.12);
}

/* ── 카드 그리드 ─────────────────────────────────────────────────── */
.cards-row {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 16px;
}

.info-card {
  padding: 20px;
  border-radius: var(--nu-r-xl);
  background: var(--panel);
  border: 1px solid var(--border);
  box-shadow: var(--shadow);
}

.info-label {
  font-size: 0.88rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  margin-bottom: 10px;
  color: var(--muted);
  word-break: keep-all;
}

.info-value {
  font-size: 1.9rem;
  font-weight: 700;
  color: var(--text);
}

.info-detail {
  margin-top: 8px;
  color: var(--muted);
  font-size: 0.85rem;
}

.red-card    { border-left: 5px solid var(--nu-alert); }
.yellow-card { border-left: 5px solid var(--nu-warning); }
.green-card  { border-left: 5px solid var(--nu-success); }
.blue-card   { border-left: 5px solid var(--nu-primary); }

/* ── 차트 ────────────────────────────────────────────────────────── */
.charts-grid {
  display: grid;
  grid-template-columns: 2fr 1.2fr;
  gap: 18px;
}

.chart-box,
.table-card {
  padding: 20px 22px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--nu-r-xl);
  box-shadow: var(--shadow);
}

.chart-title,
.card-title {
  margin-bottom: 14px;
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--text);
}
/* 한 패널 안에서 두 번째부터 오는 제목 — 앞 블록과 붙어 보이지 않게 띄운다. */
.chart-title.is-gap { margin-top: 8px; }
.chart-title.is-gap-lg { margin-top: 12px; }

.chart-box canvas {
  width: 100% !important;
  height: 300px !important;
}

/* ── 대시보드 Stat Cards ─────────────────────────────────────────── */
.dash-stat-row {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16px;
}

.dash-stat-card {
  padding: 3px 16px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-left: 5px solid transparent;
  border-radius: var(--nu-r-large);
  display: flex;
  flex-direction: column;
  gap: 2px;
  box-shadow: var(--shadow);
}

.dash-stat-title {
  font-size: 0.92rem;
  font-weight: 800;
  letter-spacing: 0.03em;
  color: var(--text);
}

.dash-stat-body {
  display: grid;
  grid-template-columns: 1fr 52px;
  gap: 10px;
  align-items: center;
}

.dash-stat-info {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.dash-stat-line {
  display: flex;
  align-items: baseline;
  gap: 4px;
  font-size: 0.9rem;
}

.dash-stat-lbl {
  color: var(--muted);
  white-space: nowrap;
}

.dash-stat-num {
  color: var(--text);
  font-weight: 700;
}

.dash-stat-gauge {
  position: relative;
  width: 52px;
  height: 52px;
  flex-shrink: 0;
}

.dash-stat-gauge canvas {
  width: 100% !important;
  height: 100% !important;
}

.dash-stat-ring-label {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0;
  pointer-events: none;
}

.ring-lbl {
  font-size: 0.5rem;
  color: var(--muted);
}

.ring-pct {
  font-size: 0.82rem;
  font-weight: 800;
  color: var(--text);
}

/* ── 대시보드: 홈 화면을 뷰포트 높이에 맞춰 스크롤 없이 채움 ──────────── */
.layout-root.dash-fill {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
}
.layout-root.dash-fill .dash-stat-row  { flex: 0 0 auto; }
.layout-root.dash-fill .dash-equip-section { flex: 0 0 auto; }
.layout-root.dash-fill .dash-mid-section {
  flex: 1 1 0;
  min-height: 120px;
  height: auto;
}

/* ── 대시보드 Middle Section ─────────────────────────────────────── */
.dash-mid-section {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-auto-rows: 1fr;
  height: 370px;
  gap: 16px;
  align-items: stretch;
}

.dash-mid-left {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-height: 0;
  overflow-y: auto;
}

.dash-mid-right {
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.dash-line-panel {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.dash-line-wrap {
  flex: 1;
  min-height: 0;
  position: relative;
}

.dash-line-wrap canvas {
  width: 100% !important;
  height: 100% !important;
}

/* ── Progress Panel: 월/일 계획을 좌우로 배치해 높이를 절반으로 줄임 ──── */
.dash-progress-panel {
  display: flex;
  flex-direction: column;
  flex: 0 0 auto;
  padding: 8px 22px;
}

.dash-progress-panel .widget-header { margin-bottom: 2px; }

.prog-row {
  display: flex;
  flex-direction: row;
  gap: 22px;
}

.prog-item {
  display: flex;
  flex-direction: column;
  gap: 6px;
  flex: 1;
  min-width: 0;
}

.prog-meta {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 0.88rem;
  color: var(--muted);
  line-height: 1.6;
}

.prog-num {
  color: var(--text);
  font-weight: 700;
  font-size: 0.95rem;
  margin-left: 4px;
}

.prog-track {
  height: 28px;
  background: var(--nu-surface-3);
  border-radius: var(--nu-r-medium);
  overflow: hidden;
}

.prog-fill {
  height: 100%;
  border-radius: var(--nu-r-medium);
  display: flex;
  align-items: center;
  justify-content: flex-end;
  min-width: 60px;
  transition: width 0.7s ease;
}

.prog-pct {
  padding-right: 14px;
  font-weight: 800;
  font-size: 1rem;
  color: var(--nu-on-accent);
  text-shadow: 0 1px 3px rgba(0,0,0,0.3);
}

.grad-red-yellow   { background: linear-gradient(90deg, var(--nu-alert) 0%, var(--nu-warning) 100%); }
.grad-orange-green { background: linear-gradient(90deg, var(--nu-warning) 0%, var(--nu-success) 100%); }
.grad-blue-cyan     { background: linear-gradient(90deg, var(--nu-primary) 0%, var(--nu-primary-light) 100%); }

/* ── Distribution Panel: 남는 공간을 채워 오른쪽 차트 박스 하단과 맞춤 ── */
.dash-dist-panel {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
  padding: 8px 22px;
}

.dash-dist-panel .widget-header {
  flex: 0 0 auto;
  margin-bottom: 8px;
}

/* 제목 아래 남은 공간 안에서 도넛+리스트를 세로 중앙 정렬 (제목과 절대 겹치지 않음) */
.dash-dist-body {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: 1fr 110px;
  gap: 14px;
  align-items: center;
  align-content: center;
}

.dash-dist-list {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px 12px;
}

.dash-dist-item {
  font-size: 0.88rem;
  color: var(--muted);
  display: flex;
  align-items: center;
  gap: 3px;
}

.dash-dist-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  flex-shrink: 0;
  margin-right: 3px;
}

.dash-dist-name { font-weight: 700; }
.dash-dist-val  { color: var(--text); font-weight: 700; }

.dash-dist-total {
  grid-column: 1 / -1;
  margin-top: 6px;
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--text);
  border-top: 1px solid var(--border);
  padding-top: 6px;
}

.dash-dist-donut { width: 110px; height: 110px; flex-shrink: 0; }
.dash-dist-donut canvas { width: 100% !important; height: 100% !important; }

/* ═══════════════════════════════════════════════════════════════════
   생산실적 (production) — 한 화면에 맞춰 3개 패널이 세로로 채워짐
═══════════════════════════════════════════════════════════════════ */
.layout-root.prod-fill {
  flex: 1;
  min-height: 0;
  grid-template-rows: auto 1fr;
}

.prod-target-panel { padding: 12px 22px; }
.prod-target-panel .widget-header { margin-bottom: 8px; }

.prod-target-row {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
}

.prod-target-item {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.prod-target-label {
  font-size: 0.92rem;
  color: var(--muted);
}

.prod-target-num {
  color: var(--text);
  font-weight: 700;
  margin-left: 4px;
}

.prod-chart-panel {
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.prod-chart-wrap {
  flex: 1;
  min-height: 0;
  position: relative;
}

.prod-chart-wrap canvas {
  width: 100% !important;
  height: 100% !important;
}

/* ── Equipment Bars ─────────────────────────────────────────────── */
.dash-equip-section { overflow: hidden; }

.equip-bars-wrap {
  display: flex;
  gap: 6px;
  align-items: flex-end;
  overflow-x: auto;
  height: 160px;
  padding-bottom: 2px;
  scrollbar-width: thin;
  scrollbar-color: var(--nu-txt4) transparent;
}

.equip-bars-wrap::-webkit-scrollbar { height: 4px; }
.equip-bars-wrap::-webkit-scrollbar-thumb { background: var(--nu-surface-4); border-radius: var(--nu-r-small); }

.equip-bar-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  min-width: 46px;
  flex: 1;
  height: 100%;
}

.equip-status {
  display: flex;
  flex-direction: column;
  align-items: center;
  min-height: 34px;
  font-size: 0.62rem;
  color: var(--nu-alert-text);
  line-height: 1.3;
  text-align: center;
  font-weight: 600;
}

.equip-track {
  flex: 1;
  width: 100%;
  background: var(--nu-surface-3);
  border-radius: 4px 4px 0 0;
  overflow: hidden;
  display: flex;
  align-items: flex-end;
}

.equip-fill {
  width: 100%;
  border-radius: 4px 4px 0 0;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  min-height: 4px;
  transition: height 0.6s ease;
}

.equip-pct {
  font-size: 0.7rem;
  font-weight: 700;
  color: var(--nu-on-accent);
  padding-top: 4px;
  text-shadow: 0 1px 2px rgba(0,0,0,0.4);
}

.equip-name {
  font-size: 0.62rem;
  color: var(--muted);
  text-align: center;
  margin-top: 5px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}

/* ── 공통 Stat Card (다른 페이지용) ──────────────────────────────── */
.dashboard-stat-card {
  padding: 8px 14px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--nu-r-xl);
  display: flex;
  flex-direction: column;
  gap: 4px;
  box-shadow: var(--shadow);
}

.dashboard-stat-header {
  color: var(--muted);
  font-size: 0.88rem;
  font-weight: 600;
}

.dashboard-stat-value {
  color: var(--text);
  font-size: 1.6rem;
  font-weight: 700;
}

.dashboard-top-row {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 16px;
}

.dashboard-summary-section {
  display: grid;
  grid-template-columns: 1.8fr 1.2fr;
  gap: 18px;
  margin-bottom: 18px;
}

.dashboard-summary-left,
.dashboard-summary-right { display: grid; gap: 18px; }

.progress-row {
  padding: 18px 20px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--nu-r-large);
  box-shadow: var(--shadow);
}

.progress-label {
  display: flex;
  justify-content: space-between;
  color: var(--muted);
  margin-bottom: 8px;
  font-size: 0.88rem;
}

.progress-values {
  display: flex;
  justify-content: space-between;
  color: var(--text);
  font-weight: 700;
  margin-bottom: 8px;
}

.progress-bar {
  height: 10px;
  background: var(--nu-surface-3);
  border-radius: var(--nu-r-pill);
  overflow: hidden;
}

.progress-fill {
  height: 100%;
  background: linear-gradient(90deg, var(--nu-alert), var(--nu-warning));
}

.distribution-list { display: grid; gap: 10px; }

.distribution-item {
  display: flex;
  justify-content: space-between;
  color: var(--text);
  font-size: 0.92rem;
}

.utilization-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
  gap: 14px;
  margin-top: 18px;
}

.utilization-bar-card {
  padding: 16px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--nu-r-large);
  box-shadow: var(--shadow);
}

.utilization-name {
  color: var(--muted);
  margin-bottom: 8px;
  font-size: 0.88rem;
}

.utilization-value {
  color: var(--text);
  font-size: 1.05rem;
  font-weight: 700;
  margin-bottom: 8px;
}

.utilization-bar-track {
  width: 100%;
  height: 10px;
  background: var(--nu-surface-3);
  border-radius: var(--nu-r-pill);
  overflow: hidden;
}

.utilization-bar-fill {
  height: 100%;
  background: linear-gradient(90deg, var(--nu-success), var(--nu-primary));
}

.stat-card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 16px;
}

.stat-card {
  padding: 20px 22px;
  border-radius: var(--nu-r-large);
  background: var(--panel);
  border: 1px solid var(--border);
  box-shadow: var(--shadow);
}

.stat-card .info-label  { margin-bottom: 10px; }
.stat-card .info-value  { font-size: 1.9rem; font-weight: 700; }
.stat-card .info-detail { margin-top: 8px; color: var(--muted); }

.table-wrapper { overflow-x: auto; }

.tables-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 18px;
}

.error-msg {
  padding: 24px;
  color: var(--muted);
  text-align: center;
}

/* ── 시뮬레이션 Form ──────────────────────────────────────────────── */
.simulation-form {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 12px;
  margin-bottom: 16px;
}

.simulation-form label {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 0.92rem;
  color: var(--muted);
}

.simulation-form input {
  width: 100%;
  padding: 9px 12px;
  border-radius: var(--nu-r-large);
  border: 1px solid var(--border);
  background: var(--panel);
  color: var(--text);
  font-size: 0.88rem;
}

.primary-btn {
  padding: 10px 16px;
  border: none;
  border-radius: var(--nu-r-large);
  background: var(--accent4);
  color: var(--nu-on-accent);
  font-weight: 700;
  cursor: pointer;
  font-size: 0.9rem;
}

.primary-btn:hover { background: var(--nu-primary-dark); }

/* ── 가동현황 필터 ────────────────────────────────────────────────── */
/* 브라우저 창 높이가 얼마든 한 화면에 맞추고, 넘치면 표 내부만 스크롤되게 함 */
#layoutRoot.util-page {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
  gap: 8px;
}
#layoutRoot.util-page > .util-filter-bar { flex: 0 0 auto; }

.util-filter-bar {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 0;
}

.util-content {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
  gap: 14px;
}
.util-content > .dashboard-top-row   { flex: 0 0 auto; }
.util-content > .dash-equip-section  { flex: 0 0 auto; }
.util-content > .table-widget-panel  { flex: 1 1 auto; min-height: 0; }

.util-filter-label {
  font-size: 0.9rem;
  color: var(--muted);
  white-space: nowrap;
}

.util-plant-select {
  padding: 8px 14px;
  border-radius: var(--nu-r-large);
  border: 1px solid var(--border);
  background: var(--panel);
  color: var(--text);
  font-size: 0.88rem;
  cursor: pointer;
  min-width: 140px;
}

.util-plant-select option { background: var(--nu-card); color: var(--text); }
.util-plant-select:focus  { outline: none; border-color: var(--accent4); }

/* ── 재고현황 ─────────────────────────────────────────────────────── */
#layoutRoot.inv-page { gap: 8px; }

/* ── 재고 3분류 탭 (원단/제품/부자재) ── */
.inv-tab-bar {
  display: flex;
  gap: 4px;
  border-bottom: 2px solid var(--border);
}
.inv-tab {
  padding: 6px 22px;
  border: none;
  background: transparent;
  color: var(--muted);
  font-size: 0.95rem;
  font-weight: 600;
  cursor: pointer;
  border-bottom: 3px solid transparent;
  margin-bottom: -2px;
}
.inv-tab:hover { color: var(--text); }
.inv-tab.active { color: var(--accent4); border-bottom-color: var(--accent4); }
.inv-tab-content { display: flex; flex-direction: column; gap: 8px; }
/* 총계 박스 → 그래프 → 검색줄 → 표 순. 사이 간격은 다른 화면과 같은 기준(8px)으로 통일하고,
   검색줄 자체 마진은 없앤다 — 회수한 높이는 표가 가져간다. */
#layoutRoot.inv-page .inv-filter-bar { margin: 0; }
#layoutRoot.inv-page .inv-note { margin: 0; }
#layoutRoot.inv-page .viz-card { padding: 9px 12px; }
#layoutRoot.inv-page .viz-title { margin-bottom: 6px; }
/* 그래프는 3장 한 줄 — 구성(도넛) + 보조 2종(막대). 3장이 안 들어가는 폭에서만 접힌다. */
.inv-viz-grid { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
#layoutRoot.inv-page .viz-wrap { height: clamp(130px, 18vh, 210px); }

.inv-pending-badge {
  margin-left: 6px;
  padding: 2px 10px;
  border-radius: var(--nu-r-pill);
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--accent2);
  background: rgba(229,163,10,0.15);
  border: 1px solid var(--accent2);
  vertical-align: middle;
}
.inv-placeholder {
  padding: 60px 24px;
  text-align: center;
  background: var(--panel);
  border: 1px dashed var(--border);
  border-radius: var(--nu-r-large);
  margin-top: 8px;
}
.inv-placeholder-title { font-size: 1.1rem; font-weight: 700; color: var(--accent2); margin-bottom: 8px; }
.inv-placeholder-desc { color: var(--muted); font-size: 0.9rem; }

/* .inv-section-header / .inv-section-title / .inv-unit 은 재고 탭 상단이
   공통 총계 박스(.kri-totals)로 전환되면서 제거됨 */

.inv-layout {
  display: grid;
  grid-template-columns: 1fr 1.2fr;
  gap: 20px;
  align-items: start;
}

.inv-table-col { overflow-x: auto; }

.inv-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.85rem;
}

.inv-table thead th {
  background: var(--th-bg);
  color: var(--th-text);
  padding: 10px 10px;
  text-align: center;
  border: 1px solid var(--jv-border);
  font-weight: 600;
  white-space: nowrap;
}

.inv-table td {
  padding: 8px 10px;
  border: 1px solid var(--border);
  color: var(--text);
  vertical-align: middle;
}

.inv-td-plant {
  text-align: center;
  background: var(--row-alt);
  font-weight: 600;
  white-space: nowrap;
}

.inv-td-name  { color: var(--accent4); font-weight: 600; }
.inv-td-num   { text-align: right; font-variant-numeric: tabular-nums; }
.inv-td-center { text-align: center; }

.inv-row-subtotal td {
  background: var(--nu-page);
  font-weight: 600;
  color: var(--text);
}

.inv-row-total td {
  background: var(--nu-surface-3);
  font-weight: 700;
  color: var(--text);
}

.inv-charts-col {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.inv-plant-section {
  padding: 14px 16px 18px;
}

.inv-plant-title {
  font-size: 0.88rem;
  font-weight: 700;
  color: var(--muted);
  margin-bottom: 10px;
}

.inv-chart-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}

.inv-chart-box {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.inv-chart-title {
  font-size: 0.95rem;
  font-weight: 700;
  margin-bottom: 8px;
  color: var(--text);
}

.inv-chart-box canvas { width: 100% !important; height: 200px !important; }

/* ─── Scheduling / Simulation ─────────────────────────────────────── */
.sched-top-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 0;
}

.sched-settings-right {
  display: flex;
  align-items: center;
  gap: 10px;
}

.sched-plant-tabs { display: flex; gap: 8px; }

.sched-tab {
  padding: 6px 18px;
  border-radius: var(--nu-r-xxl);
  border: 1px solid var(--border);
  background: var(--panel);
  color: var(--muted);
  cursor: pointer;
  font-size: 0.83rem;
  font-weight: 600;
  transition: background 0.15s;
}

.sched-tab.active {
  background: var(--th-bg);
  color: var(--nu-on-accent);
  border-color: var(--th-bg);
}

.sched-req-btn {
  padding: 7px 20px;
  background: var(--accent4);
  color: var(--nu-on-accent);
  border: none;
  border-radius: var(--nu-r-medium);
  cursor: pointer;
  font-size: 0.88rem;
  font-weight: 600;
}

.sched-section {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--nu-r-medium);
  padding: 14px 16px;
  margin-bottom: 14px;
  box-shadow: var(--shadow);
}

.sched-section-title {
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--text);
  margin-bottom: 10px;
}

.sched-section-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
  flex-wrap: wrap;
  gap: 8px;
}

.sched-hist-filter {
  display: flex;
  align-items: center;
  gap: 6px;
}
/* 같은 줄에 조회 대신 '이 화면이 보는 자료' 를 적을 때. */
.sched-hist-filter.is-note { color: var(--nu-txt3); font-size: 0.78rem; }
/* 날짜 두 칸 사이의 물결표. 값이 아니라 잇는 기호라 흐리게 둔다. */
.sched-range-sep { color: var(--nu-txt-disabled); }

.sched-table-wrap { overflow-x: auto; }

.sched-hist-wrap {
  max-height: 388px; /* 헤더 1줄 + 데이터 10줄 높이 */
  overflow-y: auto;
}

.sched-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.82rem;
  min-width: 600px;
}

.sched-table th {
  background: var(--th-bg);
  color: var(--th-text);
  padding: 8px 10px;
  text-align: center;
  border-bottom: 1px solid var(--jv-border);
  white-space: nowrap;
  position: sticky;
  top: 0;
  z-index: 1;
  font-size: 0.8rem;
}

.sched-table td {
  padding: 7px 10px;
  text-align: center;
  border-bottom: 1px solid var(--border);
  color: var(--text);
  white-space: nowrap;
}

.sched-table tr:hover td        { background: var(--row-hover); }
.sched-table tr:nth-child(even) td { background: var(--row-alt); }
.sched-table tr:nth-child(even):hover td { background: var(--row-hover); }

.sched-link      { color: var(--accent4) !important; cursor: pointer; }
.sched-link.is-underlined { text-decoration: underline; }
.sched-small     { font-size: 0.72rem; }
.sched-bold      { font-weight: 700; color: var(--text) !important; }
.sched-highlight { color: var(--nu-info-text) !important; font-weight: 600; }

.sched-empty {
  text-align: center;
  color: var(--muted);
  padding: 22px;
}

.sched-label     { color: var(--muted); font-size: 0.83rem; }

.sched-date-input {
  background: var(--panel);
  border: 1px solid var(--border);
  color: var(--text);
  padding: 5px 8px;
  border-radius: var(--nu-r-medium);
  font-size: 0.8rem;
}

.sched-green-date {
  background: var(--nu-success-light);
  border-color: var(--nu-success);
  color: var(--nu-success-text);
}

.sched-del-req {
  color: var(--accent) !important;
  cursor: pointer;
  font-weight: 700;
}

.sched-gray-btn {
  padding: 5px 14px;
  background: var(--nu-page);
  color: var(--muted);
  border: 1px solid var(--border);
  border-radius: var(--nu-r-medium);
  cursor: pointer;
  font-size: 0.8rem;
}

.sched-blue-btn {
  padding: 7px 20px;
  background: var(--accent4);
  color: var(--nu-on-accent);
  border: none;
  border-radius: var(--nu-r-medium);
  cursor: pointer;
  font-size: 0.85rem;
  font-weight: 600;
}

.sched-orders-wrapper {
  overflow-x: auto;
  overflow-y: auto;
  max-height: calc(100vh - 396px);
  border: 1px solid var(--border);
  border-radius: var(--nu-r-medium);
  margin-bottom: 8px;
}

.sched-orders-table { min-width: 900px; }

.sched-priority-cell { text-align: center; cursor: pointer; }
.sched-priority-marked {
  color: var(--nu-alert-text);
  font-weight: 700;
}

.sched-action-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  background: var(--nu-page);
  border: 1px solid var(--border);
  border-radius: var(--nu-r-medium);
  flex-wrap: wrap;
}

/* ── 금형교환 기준(C2) 설정 패널 ── */
.sched-mold-bar {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 8px 12px;
  margin-top: 6px;
  background: var(--nu-warning-light);
  border: 1px solid var(--accent2);
  border-radius: var(--nu-r-medium);
  flex-wrap: wrap;
  font-size: 0.88rem;
  color: var(--text);
}
.sched-mold-item { display: inline-flex; align-items: center; gap: 4px; }
.sched-mold-num {
  width: 56px;
  padding: 4px 6px;
  border: 1px solid var(--border);
  border-radius: var(--nu-r-small);
  text-align: center;
  font-size: 0.86rem;
}
.sched-mold-note { color: var(--muted); font-size: 0.78rem; margin-left: auto; }

.sched-select {
  background: var(--panel);
  border: 1px solid var(--border);
  color: var(--text);
  padding: 5px 8px;
  border-radius: var(--nu-r-medium);
  font-size: 0.82rem;
}

.sched-name-input {
  background: var(--panel);
  border: 1px solid var(--border);
  color: var(--text);
  padding: 5px 10px;
  border-radius: var(--nu-r-medium);
  font-size: 0.82rem;
  width: 180px;
}

#layoutRoot.sim-downtime-page { gap: 8px; }

.sched-plant-label {
  color: var(--nu-warning-text);
  font-weight: 800;
  font-size: 1rem;
  margin-bottom: 0;
}

.sched-downtime-filter {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 0;
  flex-wrap: wrap;
}

.sched-filter-right {
  margin-left: auto;
  display: flex;
  gap: 6px;
}

.sched-sel-bar { display: flex; gap: 5px; margin-bottom: -6px; }

.sched-downtime-wrap {
  max-height: calc(100vh - 360px);
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: var(--nu-r-medium);
  margin-bottom: 0;
}

.sched-bottom-bar { display: flex; justify-content: flex-end; }
.sched-start-btn  { min-width: 130px; }
.sched-elapsed    { color: var(--nu-warning-text) !important; font-weight: 800; font-size: 1.25rem; text-align: center; }
.simr-name-link   { cursor: pointer; text-decoration: underline; }

/* ── Simulation result ─────────────────────────────────────────── */
#layoutRoot.sim-result-page { gap: 8px; }

.simr-filter-bar {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 0;
  flex-wrap: wrap;
}

.simr-plant-lbl {
  color: var(--nu-warning-text);
  font-weight: 800;
  font-size: 1rem;
  min-width: 50px;
}

.simr-mode-lbl {
  color: var(--nu-warning-text);
  font-weight: 700;
  font-size: 0.9rem;
  flex: 1;
  text-align: center;
}

.simr-top-btn {
  padding: 7px 18px;
  background: var(--nu-page);
  color: var(--muted);
  border: 1px solid var(--border);
  border-radius: var(--nu-r-medium);
  cursor: pointer;
  font-size: 0.85rem;
  font-weight: 600;
}

.simr-top-btn:hover { background: var(--nu-surface-3); }

.simr-table-wrap {
  overflow-x: auto;
  overflow-y: auto;
  max-height: calc(100vh - 280px);
  border: 1px solid var(--border);
  border-radius: var(--nu-r-medium);
  margin-bottom: 0;
}

.simr-table    { min-width: 1100px; font-size: 0.78rem; }
.simr-table th { font-size: 0.76rem; padding: 7px 6px; }
.simr-table td { padding: 6px 6px; }

.simr-seq  { font-weight: 700; color: var(--accent4) !important; }
.simr-proj { text-align: left !important; max-width: 160px; white-space: normal; word-break: keep-all; }
.simr-zone { font-weight: 700; color: var(--text) !important; white-space: nowrap; }
.simr-dt   { font-size: 0.74rem; line-height: 1.5; white-space: nowrap; }
.simr-date { color: var(--muted) !important; }

.simr-overdue {
  color: var(--nu-on-accent) !important;
  background: var(--nu-alert);
  font-weight: 700;
  border-radius: var(--nu-r-small);
  padding: 2px 6px;
}

/* 금형교환(C2) 표시 */
.simr-mold-change {
  color: var(--accent2) !important;
  font-weight: 700;
}
.simr-mold-none { color: var(--muted) !important; }
.simr-mold-info {
  margin-left: auto;
  padding: 4px 12px;
  border-radius: var(--nu-r-pill);
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--accent2);
  background: rgba(229,163,10,0.13);
  border: 1px solid var(--accent2);
}

.simr-special {
  background: var(--nu-warning);
  color: var(--nu-on-accent) !important;
  font-weight: 700;
  border-radius: var(--nu-r-small);
}

.simr-order-cell { white-space: nowrap; }

.simr-bottom-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 0;
  flex-wrap: wrap;
  gap: 10px;
}

.simr-sched-name { color: var(--text); font-size: 1rem; font-weight: 600; }

.simr-confirm-btn {
  padding: 7px 20px;
  background: var(--accent4);
  color: var(--nu-on-accent);
  border: none;
  border-radius: var(--nu-r-medium);
  cursor: pointer;
  font-size: 0.85rem;
  font-weight: 600;
}

.simr-confirm-btn:disabled { cursor: default; background: var(--nu-primary-lightest); }

/* ═══════════════════════════════════════════════════════════════════
   설비 그룹별 생산현황 (equip-production)
═══════════════════════════════════════════════════════════════════ */
.ep-filter-wrap {
  display: flex;
  flex-direction: row;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px;
  padding: 10px 16px;
  background: var(--nu-page);
  border: 1px solid var(--border);
  border-radius: var(--nu-r-medium);
  margin-bottom: 10px;
}

.ep-product-lbl {
  font-size: 1.1rem;
  font-weight: 800;
  color: var(--nu-warning-text);
  white-space: nowrap;
}

.ep-select {
  padding: 6px 12px;
  background: var(--panel);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: var(--nu-r-medium);
  font-size: 0.85rem;
  min-width: 160px;
}

.ep-select-sm { min-width: 140px; }

.ep-cb-wrap {
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--text);
  font-size: 0.9rem;
  cursor: pointer;
}

.ep-cb-wrap input { width: 16px; height: 16px; cursor: pointer; accent-color: var(--th-bg); }

.ep-table-wrap {
  overflow-x: auto;
  overflow-y: auto;
  max-height: calc(100vh - 340px);
  border: 1px solid var(--border);
  border-radius: var(--nu-r-medium);
  margin-bottom: 14px;
}

.ep-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.83rem;
  min-width: 700px;
}

.ep-table thead th {
  background: var(--th-bg);
  color: var(--th-text);
  padding: 8px 10px;
  text-align: center;
  border-bottom: 1px solid var(--jv-border);
  white-space: nowrap;
  position: sticky;
  top: 0;
  z-index: 1;
}

.ep-table td {
  padding: 7px 10px;
  text-align: center;
  border-bottom: 1px solid var(--border);
  color: var(--text);
  vertical-align: middle;
}

.ep-table tr:hover td        { background: var(--row-hover); }
.ep-table tr:nth-child(even) td { background: var(--row-alt); }
.ep-table tr:nth-child(even):hover td { background: var(--row-hover); }
.ep-table tr.ep-row-done td        { background: rgba(26,174,92,0.10) !important; }
.ep-table tr.ep-row-done:hover td  { background: rgba(26,174,92,0.18) !important; }
.ep-table tr.ep-row-overdue td     { background: rgba(229,34,45,0.09) !important; }
.ep-table tr.ep-row-overdue:hover td { background: rgba(229,34,45,0.16) !important; }

.ep-td-proj    { text-align: left !important; max-width: 180px; white-space: normal; word-break: keep-all; }
.ep-td-product { white-space: nowrap; }
.ep-td-num     { text-align: right !important; font-variant-numeric: tabular-nums; }

.ep-overdue {
  background: var(--nu-alert) !important;
  color: var(--nu-on-accent) !important;
  font-weight: 700;
  border-radius: var(--nu-r-small);
  padding: 2px 6px;
}

/* ═══════════════════════════════════════════════════════════════════
   생산 스케줄 확정 (schedule-confirm)
═══════════════════════════════════════════════════════════════════ */
#layoutRoot.sc-page { gap: 8px; }

.sc-filter-bar {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  padding: 10px 14px;
  background: var(--nu-page);
  border: 1px solid var(--border);
  border-radius: var(--nu-r-medium);
  margin-bottom: 0;
}

.sc-cb-lbl {
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--text);
  font-size: 0.88rem;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
}

.sc-cb-lbl input { width: 16px; height: 16px; accent-color: var(--th-bg); }

.sc-filters {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  flex: 1;
}

.sc-sel {
  padding: 5px 10px;
  background: var(--panel);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: var(--nu-r-medium);
  font-size: 0.82rem;
  min-width: 100px;
}

.sc-date {
  padding: 5px 8px;
  background: var(--panel);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: var(--nu-r-medium);
  font-size: 0.82rem;
}

.sc-table-wrap {
  overflow-x: auto;
  overflow-y: auto;
  max-height: calc(100vh - 320px);
  border: 1px solid var(--border);
  border-radius: var(--nu-r-medium);
  margin-bottom: 0;
}

.sc-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.78rem;
  min-width: 1100px;
}

.sc-table thead th {
  background: var(--th-bg);
  color: var(--th-text);
  padding: 8px 8px;
  text-align: center;
  border-bottom: 1px solid var(--jv-border);
  white-space: nowrap;
  position: sticky;
  top: 0;
  z-index: 1;
}

.sc-table td {
  padding: 6px 8px;
  text-align: center;
  border-bottom: 1px solid var(--border);
  color: var(--text);
  white-space: nowrap;
}

.sc-table tr:hover td        { background: var(--row-hover); }
.sc-table tr:nth-child(even) td { background: var(--row-alt); }
.sc-table tr:nth-child(even):hover td { background: var(--row-hover); }

.sc-seq   { font-weight: 700; color: var(--accent4) !important; }
.sc-link  { color: var(--accent4) !important; cursor: pointer; }
.sc-equip { color: var(--nu-warning-text) !important; font-weight: 700; }
.sc-proj  { text-align: left !important; max-width: 160px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sc-zone  { font-weight: 700; color: var(--text) !important; max-width: 90px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sc-dt    { font-size: 0.72rem; line-height: 1.5; }
.sc-num   { text-align: right !important; font-variant-numeric: tabular-nums; }

.sc-overdue {
  background: var(--nu-alert) !important;
  color: var(--nu-on-accent) !important;
  font-weight: 700;
  border-radius: var(--nu-r-small);
  padding: 2px 4px;
}

.sc-footer {
  display: flex;
  align-items: center;
  gap: 28px;
  padding: 12px 18px;
  background: var(--nu-page);
  border: 1px solid var(--border);
  border-radius: var(--nu-r-medium);
  flex-wrap: wrap;
  margin-bottom: 12px;
}

.sc-footer-stat { color: var(--muted); font-size: 0.92rem; }
.sc-footer-stat strong { color: var(--text); font-size: 1.05rem; margin-left: 4px; }

/* ═══════════════════════════════════════════════════════════════════
   설비 상세현황 (equip-detail)
═══════════════════════════════════════════════════════════════════ */
.ed-shell {
  display: grid;
  grid-template-columns: 360px 1fr;
  gap: 16px;
  align-items: start;
  min-height: calc(100vh - 220px);
}

.ed-left {
  display: flex;
  flex-direction: column;
  gap: 14px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--nu-r-large);
  padding: 18px 16px;
  box-shadow: var(--shadow);
}

.ed-top-row { display: flex; align-items: center; gap: 12px; }

.ed-product-lbl {
  font-size: 1.15rem;
  font-weight: 800;
  color: var(--nu-warning-text);
  min-width: 60px;
}

.ed-equip-sel {
  flex: 1;
  padding: 7px 12px;
  background: var(--panel);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: var(--nu-r-medium);
  font-size: 0.9rem;
  font-weight: 700;
}

.ed-doc-box {
  background: var(--nu-row-alt);
  border: 1px solid var(--border);
  border-radius: var(--nu-r-medium);
  padding: 10px 12px;
}

.ed-doc-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 8px;
}

.ed-doc-lbl    { color: var(--muted); font-size: 0.82rem; }
.ed-doc-num    { color: var(--accent4); font-size: 1.1rem; font-weight: 700; flex: 1; }
.ed-doc-status { color: var(--muted); font-size: 0.82rem; }

.ed-prog-track {
  height: 28px;
  background: var(--nu-surface-3);
  border-radius: var(--nu-r-medium);
  overflow: hidden;
}

.ed-prog-fill {
  height: 100%;
  background: linear-gradient(90deg, var(--nu-success), var(--nu-success-soft));
  border-radius: var(--nu-r-medium);
  display: flex;
  align-items: center;
  justify-content: flex-end;
  min-width: 40px;
  transition: width 0.6s ease;
}

.ed-prog-pct { padding-right: 10px; font-size: 0.85rem; font-weight: 700; color: var(--nu-on-accent); }

.ed-nav-row { display: flex; align-items: stretch; gap: 8px; }

.ed-info-card {
  flex: 1;
  background: var(--nu-row-alt);
  border: 1px solid var(--border);
  border-radius: var(--nu-r-medium);
  padding: 14px 12px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.ed-info-row { display: flex; align-items: flex-start; gap: 8px; font-size: 0.9rem; }

.ed-info-row-split { display: flex; gap: 12px; align-items: flex-start; }

.ed-info-lbl { color: var(--muted); white-space: nowrap; }
.ed-info-val { color: var(--text); font-weight: 600; word-break: keep-all; }

.ed-photo {
  flex-shrink: 0;
  width: 80px;
  height: 90px;
  border-radius: var(--nu-r-medium);
  overflow: hidden;
  border: 1px solid var(--border);
}

.ed-photo-placeholder {
  width: 100%;
  height: 100%;
  background: var(--nu-gradient);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 2rem;
  font-weight: 800;
  color: var(--nu-on-accent);
}

.ed-status-row { display: flex; align-items: center; gap: 14px; padding-top: 4px; }
.ed-status-lbl { color: var(--muted); font-size: 0.92rem; }

.ed-active   { background: var(--nu-success); color: var(--nu-on-accent); }
.ed-inactive { background: var(--nu-alert); color: var(--nu-on-accent); }

.ed-right {
  display: flex;
  flex-direction: column;
  gap: 12px;
  min-width: 0;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--nu-r-large);
  padding: 18px 16px;
  min-height: calc(100vh - 220px);
  box-shadow: var(--shadow);
}

.ed-right-header {
  font-size: 1rem;
  font-weight: 700;
  color: var(--text);
  padding-bottom: 8px;
  border-bottom: 2px solid var(--border);
}

.ed-daily-prog-wrap { padding: 4px 0 6px; }

.ed-daily-prog-track {
  position: relative;
  height: 32px;
  background: var(--nu-surface-3);
  border-radius: var(--nu-r-medium);
  overflow: hidden;
}

.ed-daily-prog-fill {
  height: 100%;
  background: linear-gradient(90deg, var(--nu-success), var(--nu-success-soft));
  border-radius: var(--nu-r-medium);
  min-width: 4px;
  transition: width 0.6s ease;
}

.ed-daily-prog-pct {
  position: absolute;
  right: 12px;
  top: 50%;
  transform: translateY(-50%);
  font-size: 0.9rem;
  font-weight: 700;
  color: var(--text);
}

.ed-right-table-wrap {
  flex: 1;
  min-width: 0;
  min-height: 0;
  overflow-x: auto;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: var(--nu-r-medium);
}

.ed-right-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.78rem;
  table-layout: fixed;
}

.ed-right-table thead th {
  background: var(--th-bg);
  color: var(--th-text);
  padding: 7px 4px;
  text-align: center;
  border-bottom: 1px solid var(--jv-border);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  position: sticky;
  top: 0;
  z-index: 1;
}

.ed-right-table td {
  padding: 6px 4px;
  text-align: center;
  border-bottom: 1px solid var(--border);
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.ed-right-table tr:hover td        { background: var(--row-hover); }
.ed-right-table tr:nth-child(even) td { background: var(--row-alt); }
.ed-right-table tr.ed-row-done td        { background: rgba(26,174,92,0.10) !important; }
.ed-right-table tr.ed-row-done:hover td  { background: rgba(26,174,92,0.18) !important; }
.ed-right-table tr.ed-row-overdue td     { background: rgba(229,34,45,0.09) !important; }
.ed-right-table tr.ed-row-overdue:hover td { background: rgba(229,34,45,0.16) !important; }

.ed-proj    { text-align: left !important; white-space: normal; word-break: break-all; overflow-wrap: break-word; max-width: 180px; overflow: hidden; }
.ed-num     { text-align: right !important; font-variant-numeric: tabular-nums; }
.ed-dt      { font-size: 0.72rem; }
.ed-overdue { background: var(--nu-alert) !important; color: var(--nu-on-accent) !important; font-weight: 700; border-radius: var(--nu-r-small); padding: 2px 4px; }

@media (max-width: 900px) { .ed-shell { grid-template-columns: 1fr; } }

/* ═══════════════════════════════════════════════════════════════════
   철선소요예정량 (wire-req)
═══════════════════════════════════════════════════════════════════ */
.wr-section {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--nu-r-large);
  padding: 16px 18px;
  box-shadow: var(--shadow);
}

.wr-section-title {
  font-size: 1rem;
  font-weight: 700;
  color: var(--text);
  margin-bottom: 12px;
}

.wr-table-wrap { overflow-x: auto; overflow-y: auto; }

.wr-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.83rem;
  min-width: 600px;
}

.wr-orange-row th {
  background: var(--nu-warning);
  color: var(--nu-on-accent);
  padding: 10px 12px;
  text-align: center;
  border: 1px solid var(--nu-warning-text-2);
  font-weight: 700;
  white-space: nowrap;
  position: sticky;
  top: 0;
  z-index: 1;
}

.wr-table td {
  padding: 9px 12px;
  text-align: center;
  border-bottom: 1px solid var(--border);
  border-right: 1px solid var(--border);
  color: var(--text);
}

.wr-table tr:nth-child(even) td { background: var(--row-alt); }
.wr-table tr:hover td           { background: var(--row-hover); }

.wr-center { text-align: center !important; }
.wr-num    { text-align: right !important; font-variant-numeric: tabular-nums; }

/* ═══════════════════════════════════════════════════════════════════
   계획대비 출하현황 (shipment)
═══════════════════════════════════════════════════════════════════ */
#layoutRoot.sh-page { gap: 10px; }

.sh-section-title {
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--text);
  margin-bottom: 0;
  padding-bottom: 8px;
  border-bottom: 2px solid var(--border);
}

.sh-pending-badge {
  margin-left: 10px;
  padding: 2px 10px;
  border-radius: var(--nu-r-pill);
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--accent2);
  background: rgba(229,163,10, 0.15);
  border: 1px solid var(--accent2);
  vertical-align: middle;
}

.sh-factory-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 18px;
}

.sh-factory-col {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--nu-r-large);
  padding: 14px 16px;
  box-shadow: var(--shadow);
}

.sh-factory-header {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 10px;
}

.sh-factory-name { font-size: 1rem; font-weight: 700; color: var(--text); }
.sh-unit         { font-size: 0.78rem; color: var(--muted); }

.sh-table-wrap { overflow-x: auto; margin-bottom: 12px; }

.sh-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.82rem;
}

.sh-table thead th {
  background: var(--th-bg);
  color: var(--th-text);
  padding: 7px 10px;
  text-align: center;
  border: 1px solid var(--jv-border);
  white-space: nowrap;
}

.sh-table td {
  padding: 7px 10px;
  border: 1px solid var(--border);
  color: var(--text);
  text-align: center;
}

.sh-table tr:hover td { background: var(--row-hover); }

.sh-name { text-align: left !important; font-weight: 600; }
.sh-num  { text-align: right !important; font-variant-numeric: tabular-nums; }

.sh-subtotal td {
  background: var(--nu-page);
  font-weight: 700;
  color: var(--text);
}

.sh-charts-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}

.sh-chart-box {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.sh-chart-title {
  font-size: 0.9rem;
  font-weight: 700;
  color: var(--text);
  margin-bottom: 8px;
  text-align: center;
}

.sh-chart-box canvas { width: 100% !important; height: 200px !important; }

.sh-footer {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
  padding: 10px 18px;
  background: var(--nu-page);
  border: 1px solid var(--border);
  border-radius: var(--nu-r-large);
}

.sh-footer-item { display: flex; align-items: baseline; gap: 12px; }
.sh-footer-lbl  { color: var(--muted); font-size: 0.92rem; }
.sh-footer-val  { color: var(--text); font-size: 1.3rem; font-weight: 800; }

/* ═══════════════════════════════════════════════════════════════════
   공통 팝업 모달
═══════════════════════════════════════════════════════════════════ */
.popup-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.55);
  z-index: 3000;
  display: flex;
  align-items: center;
  justify-content: center;
}

.popup-box {
  background: var(--panel);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--nu-r-large);
  min-width: 460px;
  max-width: 660px;
  max-height: 90vh;
  overflow-y: auto;
  padding: 28px 32px 24px;
  position: relative;
  box-shadow: 0 8px 40px var(--shadow-lg);
}

.popup-box-wide { min-width: 540px; }

.popup-title {
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--text);
  margin-bottom: 22px;
}

.popup-close-btn {
  position: absolute;
  top: 16px;
  right: 18px;
  background: none;
  border: none;
  color: var(--muted);
  font-size: 1.25rem;
  cursor: pointer;
  line-height: 1;
  padding: 2px 6px;
  border-radius: var(--nu-r-small);
  transition: color 0.15s, background 0.15s;
}
.popup-close-btn:hover { color: var(--text); background: var(--row-hover); }

.popup-section-label {
  font-size: 0.8rem;
  color: var(--muted);
  margin-bottom: 8px;
  margin-top: 4px;
}

.popup-reqno {
  font-size: 1.25rem;
  font-weight: 800;
  color: var(--accent4);
  margin-bottom: 16px;
}

.popup-info-box {
  background: var(--row-alt);
  border: 1px solid var(--border);
  border-radius: var(--nu-r-medium);
  padding: 16px 20px;
  margin-bottom: 16px;
}

.popup-priority-row {
  display: flex;
  align-items: center;
  gap: 12px;
  font-size: 0.92rem;
  color: var(--text);
}

.popup-priority-input {
  width: 88px;
  padding: 6px 10px;
  background: var(--nu-card);
  border: 1px solid var(--border);
  border-radius: var(--nu-r-small);
  color: var(--text);
  font-size: 0.92rem;
  text-align: center;
}

.popup-detail-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px 24px;
  margin-bottom: 6px;
  font-size: 0.86rem;
  color: var(--text);
}
.popup-detail-row-full {
  margin-bottom: 6px;
  font-size: 0.86rem;
  color: var(--text);
}

.popup-lbl {
  color: var(--muted);
  display: inline-block;
  min-width: 56px;
}

.popup-bottom {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 20px;
}

/* 팝업 폼 공통 */
.popup-form-row {
  display: flex;
  align-items: center;
  margin-bottom: 13px;
  gap: 10px;
  font-size: 0.9rem;
}

.popup-form-lbl {
  min-width: 86px;
  color: var(--muted);
  text-align: right;
  flex-shrink: 0;
}
/* 값 자리가 여러 줄일 때. 가운데 맞춤이면 이름표가 덩어리 한가운데로 내려간다. */
.popup-form-row.is-top { align-items: flex-start; }
.popup-form-lbl.is-top { padding-top: 6px; }
/* 남는 폭을 다 먹는 값 자리 — 목록·격자처럼 스스로 접는 것이 들어온다. */
.popup-form-field { flex: 1; }

.popup-form-val {
  color: var(--text);
  font-weight: 600;
}

/* 팝업 폼 칸 - 치수는 입력 칸 한 벌 토큰(--mx-ctl-*)을 읽는다(0.33.0). 사이트 설정 「입력 칸 모양」을 팝업도 따른다.
   클래스 이름은 그대로 둔다 - 세 보드의 팝업이 화면 코드를 안 고치고 한꺼번에 맞춰진다. */
.popup-form-sel,
.popup-form-input,
.popup-form-date,
.popup-form-input-sm {
  box-sizing: border-box;
  height: var(--mx-ctl-h);
  padding: 0 var(--mx-ctl-pad-x);
  background-color: var(--nu-card);
  border: 1px solid var(--mx-ctl-border);
  border-radius: var(--mx-ctl-radius);
  color: var(--text);
  font: inherit;
  font-size: var(--mx-ctl-font-size);
  min-width: 0;
}
.popup-form-sel,
.popup-form-input,
.popup-form-date { flex: 1; }
.popup-form-input-sm { width: 110px; }
textarea.popup-form-input { height: auto; min-height: calc(var(--mx-ctl-h) * 2); padding-top: 5px; padding-bottom: 5px; }
select.popup-form-sel {
  appearance: none; -webkit-appearance: none; cursor: pointer;
  padding-right: calc(var(--mx-ctl-pad-x) + var(--mx-ctl-icon-gap));
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%236B7280' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right var(--mx-ctl-pad-x) center; background-size: 12px 12px;
}
.popup-form-sel:hover, .popup-form-input:hover, .popup-form-input-sm:hover { border-color: var(--mx-ctl-border-hover); }
.popup-form-sel:focus-visible, .popup-form-input:focus, .popup-form-input-sm:focus {
  outline: none; border-color: var(--jv-primary-mid); box-shadow: 0 0 0 3px var(--jv-primary-light);
}

.popup-form-date {
  flex: none;
  width: auto;
  padding: 6px 10px;
  background: var(--nu-success);
  border-color: var(--nu-success);
  color: var(--nu-on-accent);
  cursor: pointer;
}
.popup-form-date::-webkit-calendar-picker-indicator { filter: invert(1); cursor: pointer; }

.popup-check-row {
  display: flex;
  align-items: center;
  gap: 20px;
  font-size: 0.9rem;
  color: var(--text);
}
.popup-check-row label { display: flex; align-items: center; gap: 6px; cursor: pointer; }
.popup-check-row input[type="checkbox"] { width: 15px; height: 15px; accent-color: var(--nu-primary); cursor: pointer; }

/* 복수 추가 설비 테이블 */
.popup-equip-ctrl {
  display: flex;
  gap: 8px;
  margin-bottom: 8px;
}

.popup-equip-table-wrap {
  max-height: 180px;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: var(--nu-r-small);
  margin-bottom: 12px;
}

.popup-equip-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.85rem;
}

.popup-equip-table th {
  background: var(--header);
  color: var(--th-text);
  padding: 7px 10px;
  text-align: center;
  position: sticky;
  top: 0;
}

.popup-equip-table td {
  padding: 6px 10px;
  border-bottom: 1px solid var(--border);
  color: var(--text);
  text-align: center;
}

.popup-equip-table tr:hover td { background: var(--row-hover); }
.popup-equip-table tr.equip-selected td { background: rgba(130,10,209,0.12); }

.popup-date-range {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1;
}

.popup-date-sep { color: var(--muted); }

/* 팝업 버튼 공통 */
.popup-btn-apply  { padding: 8px 26px; background: var(--nu-primary); color: var(--nu-on-accent); border: none; border-radius: var(--nu-r-medium); font-size: 0.9rem; font-weight: 600; cursor: pointer; }
.popup-btn-cancel { padding: 8px 20px; background: var(--nu-txt2); color: var(--nu-on-accent); border: none; border-radius: var(--nu-r-medium); font-size: 0.9rem; font-weight: 600; cursor: pointer; }
.popup-btn-del    { padding: 8px 20px; background: var(--nu-alert); color: var(--nu-on-accent); border: none; border-radius: var(--nu-r-medium); font-size: 0.9rem; font-weight: 600; cursor: pointer; }
.popup-btn-xs     { padding: 4px 10px; background: var(--nu-txt2); color: var(--nu-on-accent); border: none; border-radius: var(--nu-r-small); font-size: 0.8rem; cursor: pointer; }
.popup-btn-xs:hover { background: var(--nu-primary); color: var(--nu-on-accent); }
.popup-btn-xs-red { padding: 4px 10px; background: var(--nu-alert-text-2); color: var(--nu-alert-border); border: none; border-radius: var(--nu-r-small); font-size: 0.8rem; cursor: pointer; }
.popup-btn-xs-red:hover { background: var(--nu-alert); color: var(--nu-on-accent); }

/* ── 반응형 ─────────────────────────────────────────────────────── */
@media (max-width: 1200px) {
  .cards-row,
  .charts-grid,
  .tables-grid { grid-template-columns: 1fr; }
}

@media (max-width: 1100px) {
  .dash-stat-row   { grid-template-columns: repeat(2, 1fr); }
  .dash-mid-section { grid-template-columns: 1fr; }
}

@media (max-width: 900px) {
  .sh-factory-row { grid-template-columns: 1fr; }
  .sh-footer      { grid-template-columns: 1fr; }
}

/* ═══════════════════════════════════════════════════════════════════
   콤팩트 모드 — 4:3 비율 등 세로 공간이 좁은 화면에서 한 화면에 맞춤
   (타이틀/여백을 줄여 스크롤 없이 최대한 표시)
═══════════════════════════════════════════════════════════════════ */
@media (max-height: 820px) {
  /* 사이드바 */
  .sidebar   { padding: 14px; gap: 14px; }
  .brand     { gap: 10px; }
  .logo      { width: 36px; height: 36px; border-radius: var(--nu-r-large); }
  .brand span{ font-size: 1rem; }
  .nav a     { padding: 8px 12px; font-size: 0.85rem; }

  /* 탑바 */
  .topbar     { height: 42px; padding: 0 18px; }
  .page-title { font-size: 0.86rem; }

  /* 콘텐츠 여백 — .content 는 보드 것이라 여기 없다(파일 머리 참고) */
  .layout-root { gap: 10px; }
  .layout-grid { gap: 10px; }

  /* 히어로(페이지 타이틀) */
  .hero          { padding: 10px 18px; gap: 3px; border-radius: var(--nu-r-large); }
  .hero-title    { font-size: 1.3rem; }
  .hero-subtitle { font-size: 0.76rem; }

  /* 위젯 패널 공통 */
  .widget-panel  { padding: 12px 14px; border-radius: var(--nu-r-large); }
  .widget-header { margin-bottom: 8px; }
  .widget-title  { font-size: 0.88rem; }
  .card-title    { margin-bottom: 8px; font-size: 0.86rem; }

  /* 표 공통 (기본 + 페이지별 테이블) */
  th, td,
  .inv-table th, .inv-table td,
  .sched-table th, .sched-table td,
  .ep-table th, .ep-table td,
  .sc-table th, .sc-table td,
  .ed-right-table th, .ed-right-table td,
  .wr-table th, .wr-table td,
  .sh-table th, .sh-table td {
    padding: 5px 8px;
  }
  .inv-table, .sched-table, .ep-table, .sc-table,
  .ed-right-table, .wr-table, .sh-table {
    font-size: 0.74rem;
  }
  .sched-hist-wrap { max-height: 200px; }
  .sched-section   { padding: 10px 12px; margin-bottom: 10px; }

  /* 대시보드 차트/카드 */
  .chart-box canvas      { height: 210px !important; }
  .dash-stat-card  { padding: 12px 14px; gap: 8px; }
  .dash-stat-body  { grid-template-columns: 1fr 80px; }
  .dash-stat-gauge { width: 80px; height: 80px; }
  .dash-mid-section{ gap: 10px; }
  .dash-mid-left   { gap: 10px; }
  .dash-progress-panel { gap: 12px; }
  .dash-dist-donut { width: 96px; height: 96px; }
  .equip-bars-wrap { height: 140px; }

  /* 재고/출하 차트 */
  .inv-chart-box canvas { height: 140px !important; }
  .sh-chart-box canvas  { height: 140px !important; }

  /* 설비상세 */
  .ed-right { min-height: calc(100vh - 150px); }
}

/* ── 사용자 관리(관리자) ────────────────────────────────────────────── */
.admin-page .content { overflow-y: auto; }

.admin-btn-primary {
  padding: 10px 16px;
  background: var(--accent4);
  color: var(--nu-on-accent);
  border: none;
  border-radius: var(--nu-r-large);
  font-size: 0.85rem;
  font-weight: 700;
  cursor: pointer;
  transition: background 0.18s;
}
.admin-btn-primary:hover { background: var(--nu-primary-dark); }

.admin-btn-ghost {
  padding: 10px 16px;
  background: transparent;
  color: var(--muted);
  border: 1px solid var(--border);
  border-radius: var(--nu-r-large);
  font-size: 0.85rem;
  font-weight: 600;
  cursor: pointer;
}
.admin-btn-ghost:hover { background: var(--row-hover); }

.admin-btn-small {
  padding: 5px 12px;
  border-radius: var(--nu-r-medium);
  border: 1px solid var(--border);
  background: var(--nu-card);
  color: var(--text);
  font-size: 0.78rem;
  font-weight: 600;
  cursor: pointer;
  margin-right: 6px;
}
.admin-btn-small:hover { background: var(--row-hover); }
.admin-btn-danger { color: var(--nu-alert-text); border-color: rgba(229,34,45,0.35); }
.admin-btn-danger:hover { background: rgba(229,34,45,0.09); }

.admin-row-actions { white-space: nowrap; }

.admin-form {
  margin-top: 18px;
  padding: 16px 18px;
  border: 1px solid var(--border);
  border-radius: var(--nu-r-large);
  background: var(--row-alt);
  display: grid;
  gap: 10px;
  max-width: 360px;
}

.admin-form-title { font-size: 0.95rem; font-weight: 700; color: var(--text); }

.admin-form-row { display: grid; gap: 4px; }
.admin-form-row label { font-size: 0.82rem; font-weight: 600; color: var(--muted); }
.admin-form-row input,
.admin-form-row select {
  padding: 9px 11px;
  border-radius: var(--nu-r-medium);
  border: 1px solid var(--border);
  background: var(--nu-card);
  color: var(--text);
  font-size: 0.88rem;
  font-family: inherit;
}
.admin-form-row input:disabled { background: var(--row-alt); color: var(--muted); }

.admin-form-error { font-size: 0.8rem; font-weight: 600; color: var(--nu-alert-text); min-height: 1em; }
.admin-form-error.admin-form-success { color: var(--accent3); }

.admin-form-actions { display: flex; gap: 8px; }

.admin-perm-body { display: grid; gap: 12px; }
.admin-perm-hint { font-size: 0.85rem; color: var(--muted); line-height: 1.6; }

/* ── 역할 × 메뉴 권한 매트릭스 ──
   행 = 역할, 열 = 메뉴(12종).
   ※ 열 제목을 세로쓰기(writing-mode: vertical-rl)로 세우지 않는다 — 그 기법은 알파벳용이고,
     한글은 글자가 선 채로 쌓여 rotate(180deg)까지 걸면 아래에서 위로 읽히게 된다.
     12열 × 66px + 역할열 = 약 1,000px라 가로로 그냥 들어간다. 단어 단위로만 줄바꿈한다. */
.admin-perm-wrap { overflow: auto; border: 1px solid var(--border); border-radius: var(--nu-r-large); }
.admin-perm-table { border-collapse: collapse; width: 100%; font-size: 0.85rem; }
.admin-perm-table thead th {
  position: sticky; top: 0; z-index: 2; background: var(--sidebar); color: var(--nu-on-accent);
  padding: 7px 6px; font-weight: 600; vertical-align: bottom;
  font-size: 0.74rem; line-height: 1.32; white-space: normal; word-break: keep-all; min-width: 62px;
}
.admin-perm-table th.apm-role {
  position: sticky; left: 0; z-index: 3; text-align: left; min-width: 132px;
  padding: 8px 12px; background: var(--sidebar); color: var(--nu-on-accent);
}
.admin-perm-table tbody th.apm-role { background: var(--row-alt); color: var(--text); font-weight: 700; }
.admin-perm-table tbody th.apm-role small { display: block; font-weight: 500; font-size: 0.72rem; color: var(--muted); margin-top: 2px; }
.admin-perm-table tbody td { padding: 7px 4px; text-align: center; border-top: 1px solid var(--border); }
.admin-perm-table tbody tr:hover td { background: var(--row-hover); }
.admin-perm-table input[type=checkbox] { width: 16px; height: 16px; accent-color: var(--th-bg); cursor: pointer; }
.admin-perm-table td.apm-act, .admin-perm-table th.apm-act { white-space: nowrap; padding-right: 12px; }
.apm-msg { margin-left: 8px; font-size: 0.76rem; font-weight: 600; }
.apm-msg.apm-ok { color: var(--nu-success-text); }
.apm-msg.apm-fail { color: var(--nu-alert-text); }

/* ── 비밀번호 변경 모달 ──────────────────────────────────────────────── */
.pwd-modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.72);
  z-index: 400;
  display: flex;
  align-items: center;
  justify-content: center;
}
.pwd-modal-card {
  width: 320px;
  max-width: calc(100vw - 40px);
  padding: 28px 26px;
  background: var(--panel);
  border-radius: var(--nu-r-xl);
  box-shadow: var(--shadow-lg);
  display: grid;
  gap: 10px;
}

/* 임시 비밀번호로 처음 들어왔을 때 왜 이 창이 떠 있는지 적는 줄 */
.pwd-modal-note {
  margin: 0;
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--muted);
}

/* ── 서열계획(HMC 수요) §3-1 피벗 그리드 ── */
.demand-panel { padding: 18px 20px; display: flex; flex-direction: column; gap: 12px; }
.demand-toolbar { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; font-size: 0.85rem; }
.demand-toolbar label { display: flex; align-items: center; gap: 6px; color: var(--muted); font-weight: 500; }
.demand-toolbar select, .demand-toolbar input[type="text"] {
  padding: 6px 10px; border: 1px solid var(--border); border-radius: var(--nu-r-medium);
  background: var(--nu-card); color: var(--text); font-size: 0.85rem;
}
.demand-toolbar input[type="text"] { min-width: 220px; }
.demand-toolbar .dm-check { cursor: pointer; }
/* .dm-freshness(스냅샷 출처)는 총계 박스 '총 수요' 카드 설명줄로 이동 */
.demand-grid-wrap { overflow: auto; max-height: calc(100vh - 210px); border: 1px solid var(--border); border-radius: var(--nu-r-large); }
.demand-grid { border-collapse: collapse; width: 100%; font-size: 0.82rem; white-space: nowrap; }
/* ── 열 폭 고정은 서열계획(.demand-panel) 표에만 적용한다 ──
   ※ .demand-grid 는 원단소요예정량 표와 공용이다. 여기에 table-layout:fixed 를 걸면
     colgroup이 없는 그 표까지 전 열이 균등폭이 되어 재질명·공급사가 잘린다(2026-08 회귀).
   서열계획은 좌측 5개 열을 실제 값 최대 길이에 맞춰 못 박고, 남는 폭은 폭 미지정 열
   (D+n 일자)이 균등하게 나눠 갖는다 → D+14(15열)까지 가로 스크롤 없이 들어온다.
   값 최대 길이 실측(2026-08, 오토젠 생산품): BD_KEY 15자 · 차종 6 · 부위 6 · ALC 4 · 컬러 6 */
.demand-panel .demand-grid { table-layout: fixed; }
.demand-panel .demand-grid col.dm-w-veh   { width: 66px; }
.demand-panel .demand-grid col.dm-w-bd    { width: 146px; }
.demand-panel .demand-grid col.dm-w-part  { width: 76px; }
.demand-panel .demand-grid col.dm-w-alc   { width: 60px; }
.demand-panel .demand-grid col.dm-w-color { width: 72px; }
.demand-panel .demand-grid col.dm-w-total { width: 78px; }
/* 폭을 고정했으니 넘치는 값은 잘라서 표시(전체 값은 title 툴팁) */
.demand-panel .demand-grid th, .demand-panel .demand-grid td { overflow: hidden; text-overflow: ellipsis; }
/* 차종·부위·ALC·컬러는 값 길이가 짧고 일정해 가운데 정렬이 읽기 좋다(품번은 좌측 유지) */
.demand-grid .dm-c { text-align: center; }
.demand-grid thead th {
  position: sticky; top: 0; z-index: 2; background: var(--sidebar); color: var(--nu-on-accent);
  padding: 7px 8px; text-align: center; font-weight: 600; border-bottom: 1px solid var(--border);
}
.demand-grid thead th .dm-date { font-weight: 400; opacity: 0.75; font-size: 0.72rem; }
.demand-grid tbody td { padding: 6px 8px; border-bottom: 1px solid var(--border); }
.demand-grid tbody tr:nth-child(even) { background: var(--row-alt); }
.demand-grid tbody tr:hover { background: var(--row-hover); }
.demand-grid .dm-num { text-align: right; font-variant-numeric: tabular-nums; }
.demand-grid .dm-bd { font-family: 'Consolas', monospace; font-size: 0.78rem; }
.demand-grid .dm-zero { color: var(--nu-txt-disabled); }
.demand-grid .dm-total { font-weight: 700; background: rgba(229,163,10,0.06); }
/* 합계 열 헤더: 배경이 밝은 베이지라 흰 글씨가 안 보임 → 검은색으로 */
.demand-grid thead th.dm-total { color: var(--nu-ink); background: rgba(229,163,10,0.18); }
.demand-grid .dm-weekend { background: rgba(83,7,137,0.05); }
.demand-grid thead th.dm-weekend { background: var(--nu-txt1); }
.demand-grid tfoot td {
  position: sticky; bottom: 0; background: var(--nu-page); font-weight: 700; color: var(--nu-ink);
  padding: 8px 10px; border-top: 2px solid var(--border);
}
.demand-grid .dm-empty { text-align: center; color: var(--muted); padding: 28px; }

/* ── 재고현황 (오토젠 실 재고 레이어: 원단롤/재단품/완제품) ── */
.inv-note { margin: 8px 0 4px; padding: 9px 14px; border-radius: var(--nu-r-medium);
  background: var(--nu-warning-light); border: 1px solid var(--nu-warning-border); color: var(--nu-warning-text); font-size: 0.84rem; }
.inv-filter-bar { display: flex; align-items: center; gap: 12px; margin: 10px 0; flex-wrap: wrap; font-size: 0.85rem; }
.inv-filter-bar label { display: flex; align-items: center; gap: 6px; color: var(--muted); }
.inv-filter-bar select, .inv-filter-bar input[type="text"] {
  padding: 6px 10px; border: 1px solid var(--border); border-radius: var(--nu-r-medium); background: var(--nu-card); color: var(--text); font-size: 0.85rem; }
.inv-filter-bar input[type="text"] { min-width: 240px; }
.inv-filter-bar .inv-count { margin-left: auto; color: var(--muted); font-weight: 600; }
.inv-grid-wrap { overflow: auto; max-height: calc(100vh - 250px); border: 1px solid var(--border); border-radius: var(--nu-r-large); }
.inv-grid { border-collapse: collapse; width: 100%; font-size: 0.83rem; white-space: nowrap; }
.inv-grid thead th { position: sticky; top: 0; z-index: 2; background: var(--sidebar); color: var(--nu-on-accent);
  padding: 8px 12px; text-align: left; font-weight: 600; }
.inv-grid thead th.inv-num { text-align: right; }
.inv-grid tbody td { padding: 6px 12px; border-bottom: 1px solid var(--border); }
.inv-grid tbody tr:nth-child(even) { background: var(--row-alt); }
.inv-grid tbody tr:hover { background: var(--row-hover); }
.inv-grid .inv-num { text-align: right; font-variant-numeric: tabular-nums; }
.inv-grid .inv-empty { text-align: center; color: var(--muted); padding: 28px; }
.inv-color-chip { display: inline-block; padding: 1px 8px; border-radius: var(--nu-r-large); font-size: 0.76rem;
  background: var(--nu-page); border: 1px solid var(--border); color: var(--text); }

/* ── 출하현황 (SHIPPING_INVENTORY_TRAJECTORY 실데이터) ──
   .sh-kpi* / .sh-period 는 전 화면 공통 총계 박스(.kri-totals)로 대체되어 제거됨 */
/* 표 위(차트 2장 + 검색줄) 여백은 다른 화면과 같은 기준으로 압축하되, 차트 높이는 확보한다.
   좌측 카드에 요약 줄(.sh-viz-foot)이 붙어 카드가 더 높아지는데, 두 카드는 그리드에서 같은
   높이로 늘어나므로 우측 막대 차트가 그 차이만큼 더 높아진다(막대 가독성 확보). */
.sh-panel .inv-filter-bar { margin: 0; }
.sh-panel .viz-card { padding: 9px 12px; display: flex; flex-direction: column; }
.sh-panel .viz-title { margin-bottom: 6px; }
.sh-panel .viz-wrap { height: clamp(140px, 20vh, 230px); flex: 1 1 auto; min-height: 130px; }
.sh-panel .viz-grid { gap: 10px; }
/* 도넛 아래 요약 3종 — 달성율·부족분·불량 */
.sh-viz-foot { display: flex; gap: 12px; margin-top: 8px; padding-top: 8px; border-top: 1px dashed var(--border); }
.sh-viz-foot span { flex: 1 1 0; min-width: 0; font-size: 0.72rem; color: var(--muted); }
.sh-viz-foot em { display: block; font-style: normal; font-size: 0.7rem; font-weight: 600; color: var(--muted); }
.sh-viz-foot b { font-size: 1.05rem; font-weight: 800; color: var(--text); font-variant-numeric: tabular-nums; }

/* ── 원단 발주현황 리드타임 칩 ──
   전용 줄(.wr-lead-row)을 없애고 표 위 검색줄 왼쪽에 얹었다 — 한 줄 절약하면서
   리드타임은 표(발주일·입고예정) 바로 옆에 남아 맥락이 유지된다. */
.wr-lead-lbl { font-weight: 700; color: var(--text); font-size: 0.82rem; }
.wr-lead-chip { display: inline-block; padding: 2px 9px; border-radius: var(--nu-r-large); font-size: 0.78rem;
  background: rgba(229,163,10,0.1); border: 1px solid var(--accent2); color: var(--accent2); }
.wr-bar { gap: 8px; }
.wr-bar .wr-spacer { flex: 1 1 auto; }
.wr-bar label, .wr-bar .inv-count { margin-left: 0; }
.wr-panel .inv-filter-bar { margin: 0; }
.wr-panel .viz-card { padding: 9px 12px; }
.wr-panel .viz-title { margin-bottom: 6px; }

/* ── 생산실적 (MES 양품 미러) ── */
.prod-layout { display: grid; grid-template-columns: 340px minmax(0, 1fr); gap: 14px; align-items: stretch; }
.prod-chart-card { background: var(--panel); border: 1px solid var(--border); border-radius: var(--nu-r-large); padding: 12px; display: flex; flex-direction: column; }
.prod-chart-fill { position: relative; flex: 1 1 auto; min-height: 240px; }
.prod-chart-title { font-weight: 700; font-size: 0.9rem; margin-bottom: 8px; color: var(--text); }
.prod-table-col { min-width: 0; }
/* 필터줄 상하 마진 제거 — 좌측 '차종별 양품' 그래프 박스 상단과 '차종' 검색조건 줄 상단을 맞춘다
   (두 열은 같은 y에서 시작하므로, 마진만 없으면 위쪽 선이 정확히 일치한다) */
.prod-layout .inv-filter-bar { margin: 0 0 10px; }
@media (max-width: 1200px) { .prod-layout { grid-template-columns: 1fr; } }

/* ── 스케줄확정 호기 카드(칩) ── */
.ep-mach-row { display: flex; gap: 8px; flex-wrap: wrap; }
.ep-mach-card { flex: 1 1 130px; min-width: 120px; text-align: left; cursor: pointer;
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--nu-r-large); padding: 6px 11px; }
.ep-mach-card.active { border-color: var(--accent2); box-shadow: 0 0 0 2px rgba(229,163,10,0.18); }
.ep-mach-name { font-weight: 700; font-size: 0.9rem; color: var(--text); }
.ep-mach-good { font-size: 1.25rem; font-weight: 800; color: var(--accent2); font-variant-numeric: tabular-nums; }
.ep-mach-good span { font-size: 0.72rem; color: var(--muted); font-weight: 500; margin-left: 3px; }
.ep-mach-bar { height: 6px; background: var(--nu-page); border-radius: var(--nu-r-small); overflow: hidden; margin: 4px 0; }
.ep-mach-bar > div { height: 100%; background: var(--accent2); }
.ep-mach-items { font-size: 0.76rem; color: var(--muted); }
/* 검색조건 한 줄(계획일·호기·건수·작업지시서) — 상하 여백을 없애 남는 높이를 표에 준다.
   건수의 margin-left:auto 가 자기 뒤 요소(작업지시서 버튼)까지 함께 오른쪽 끝으로 민다. */
.sc-panel .inv-filter-bar { margin: 0; }
.sc-panel .ep-mach-good { font-size: 1.1rem; }

/* ── 설비별 생산현황: 호기별 계획 대비 실적 카드(반원 게이지) ──
   1920 폭에서 호기 7대가 한 줄에 균등 배치되고, 아래 비교 차트가 남은 높이를 채운다. */
/* 좁은 화면은 auto-fit으로 접히고, 넓은 화면(1360↑)에서는 호기 대수(--ep-cols, JS가 카드 수를 넣음)
   만큼 한 줄에 균등 배치한다 — 마지막 호기 한 대만 다음 줄로 떨어지는 일이 없게. */
.ep-card-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 10px; }
@media (min-width: 1360px) { .ep-card-grid { grid-template-columns: repeat(var(--ep-cols, 7), minmax(0, 1fr)); } }
.ep-card { display: flex; flex-direction: column; background: var(--panel); border: 1px solid var(--border);
  border-top-width: 4px; border-radius: var(--nu-r-large); padding: 10px 12px 11px; box-shadow: 0 1px 3px rgba(0,0,0,0.05); }
.ep-card-top { display: flex; justify-content: space-between; align-items: center; gap: 6px; }
.ep-card-name { font-weight: 700; font-size: 0.95rem; color: var(--text); }
/* 호기 정체성 색 점 — 게이지 호·하단 도넛 조각과 같은 색(달성률이 낮아 호가 짧아도 색을 읽을 수 있게) */
.ep-dot { display: inline-block; width: 9px; height: 9px; border-radius: var(--nu-r-small); margin-right: 6px; vertical-align: baseline; }
.ep-card-badge { font-size: 0.68rem; font-weight: 700; padding: 2px 8px; border-radius: var(--nu-r-pill); white-space: nowrap; }
/* 반원 게이지 — 캔버스 아래 중앙(호의 안쪽)에 달성률 수치를 겹쳐 놓는다 */
.ep-gauge { position: relative; height: clamp(72px, 9.5vh, 108px); margin: 4px 0 2px; }
.ep-gauge-txt { position: absolute; left: 0; right: 0; bottom: 4px; text-align: center; line-height: 1.12; pointer-events: none; }
.ep-gauge-txt em { display: block; font-style: normal; font-size: 0.66rem; font-weight: 600; color: var(--muted); }
.ep-gauge-txt b { font-size: 1.32rem; font-weight: 800; font-variant-numeric: tabular-nums; }
.ep-card-nums { display: flex; gap: 8px; margin-top: 6px; padding-top: 7px; border-top: 1px dashed var(--border); }
.ep-num { flex: 1 1 0; min-width: 0; }
.ep-num em { display: block; font-style: normal; font-size: 0.68rem; font-weight: 600; color: var(--muted); }
.ep-num b { font-size: 1.02rem; font-weight: 800; color: var(--text); font-variant-numeric: tabular-nums; }
.ep-num-plan b { color: var(--muted); }
.ep-card-sub { margin-top: 6px; font-size: 0.71rem; color: var(--muted); }
/* 진행 막대 — 사출기 연동 화면(injFill)이 함께 쓴다 */
.ep-card-track { position: relative; height: 10px; background: var(--nu-page); border-radius: var(--nu-r-medium); overflow: hidden; }
.ep-card-fill { height: 100%; border-radius: var(--nu-r-medium); transition: width .3s ease; }
/* 달성 상태 색상 — 상단 보더·게이지 수치·배지 */
.ep-good  { border-top-color: var(--nu-success); } .ep-good  .ep-gauge-txt b { color: var(--nu-success-text); } .ep-good  .ep-card-badge { background: var(--nu-success-light); color: var(--nu-success-text); }
.ep-warn  { border-top-color: var(--nu-warning); } .ep-warn  .ep-gauge-txt b { color: var(--nu-warning-text); } .ep-warn  .ep-card-badge { background: var(--nu-warning-light); color: var(--nu-warning-text); }
.ep-low   { border-top-color: var(--nu-alert); } .ep-low   .ep-gauge-txt b { color: var(--nu-alert-text); } .ep-low   .ep-card-badge { background: var(--nu-alert-light); color: var(--nu-alert-text); }
.ep-noplan{ border-top-color: var(--nu-border-strong); } .ep-noplan .ep-gauge-txt b { color: var(--nu-txt4); } .ep-noplan .ep-card-badge { background: var(--nu-page); color: var(--nu-txt3); }

/* 카드 아래 비교 차트 2단 — 좌: 계획대비실적 혼합차트, 우: 실적 구성 도넛.
   위 호기 카드 그리드와 '같은 트랙'(--ep-cols 열 · 같은 gap)을 쓰고 4열 / 3열로 나눠 span 시킨다.
   → 두 박스의 경계가 INJT04 오른쪽 끝 · INJT05 왼쪽 끝 선과 정확히 일치한다(7대 기준 4:3).
   fr 비율(4fr:3fr)로 나누면 gap 때문에 1~2px 어긋나므로 트랙을 공유하는 이 방식을 쓴다. */
.ep-viz-grid { display: grid; grid-template-columns: repeat(var(--ep-cols, 7), minmax(0, 1fr)); gap: 10px; }
.ep-viz-grid > :first-child { grid-column: 1 / span 4; }
.ep-viz-grid > :last-child  { grid-column: span 3 / -1; }
/* 카드가 auto-fit으로 접히기 시작하는 구간부터는 열 맞춤이 의미 없다 — 4:3 비율만 유지 */
@media (max-width: 1359px) {
  .ep-viz-grid { grid-template-columns: minmax(0, 4fr) minmax(0, 3fr); }
  .ep-viz-grid > :first-child, .ep-viz-grid > :last-child { grid-column: auto; }
}
@media (max-width: 1000px) { .ep-viz-grid { grid-template-columns: 1fr; } }

/* ── 시각화 카드 그리드(출하/재고/원단 발주현황 공통) ── */
.viz-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 12px; }
.viz-card { background: var(--panel); border: 1px solid var(--border); border-radius: var(--nu-r-large); padding: 12px 14px; }
.viz-title { font-weight: 700; font-size: 0.9rem; color: var(--text); margin-bottom: 8px; }
.viz-title span { font-weight: 400; font-size: 0.76rem; color: var(--muted); margin-left: 6px; }
/* 차트 높이는 화면(창) 높이에 비례 — 노트북에서도 한 화면에 들어가도록 */
.viz-wrap { position: relative; height: clamp(140px, 20vh, 240px); }
.viz-wrap.viz-wrap-lg { height: clamp(150px, 24vh, 280px); }
.viz-empty { display: flex; align-items: center; justify-content: center; height: 100%; color: var(--muted); font-size: 0.85rem; }

/* ── 원단소요예정량 ──
   ※ 원단소요예정량 화면에서는 .fr-banner(노란 안내 박스)를 걷어냈다 — 예시 데이터 고지는
     총계 박스의 '예시' 배지와 차트 제목 부제가 대신한다(표기는 유지, 높이는 표에 돌려줌).
     아래 .fr-banner 스타일은 원단 발주현황·사출기 연동 화면이 계속 쓰므로 남긴다. */
.fr-banner { background: var(--nu-warning-light); border: 1px solid var(--nu-warning-border); color: var(--nu-warning-text); font-size: 0.85rem; font-weight: 600; padding: 9px 14px; border-radius: var(--nu-r-medium); }
.fr-mat-dot { display: inline-block; width: 10px; height: 10px; border-radius: var(--nu-r-small); margin-right: 7px; vertical-align: middle; }
.fr-panel .inv-filter-bar { margin: 0; }
.fr-panel .viz-card { padding: 9px 12px; }
.fr-panel .viz-title { margin-bottom: 6px; }
/* 표 행 수가 재질 수(5종)로 고정이라 표를 늘려도 빈 줄만 생긴다.
   → 표는 제 높이만 쓰고(0 1 auto), 남는 높이는 위 차트가 전부 가져간다.
     패널은 다른 화면과 같이 화면 아래까지 차므로 박스 아래 끝선도 그대로 맞는다. */
#layoutRoot.fit-page > .fr-panel > .viz-card { flex: 1 1 auto; min-height: 170px; display: flex; flex-direction: column; }
#layoutRoot.fit-page > .fr-panel > .viz-card > .viz-wrap { height: auto; flex: 1 1 auto; min-height: 140px; }
/* 0 0 auto — 절대 눌리지 않는다. 재질 5행은 항상 전부 보여야 한다(줄어들면 표 안이 스크롤된다). */
#layoutRoot.fit-page > .fr-panel > .demand-grid-wrap { flex: 0 0 auto; min-height: 0; }
#layoutRoot.fit-page > .fr-panel { overflow-y: auto; }
.nav-ext-ico { margin-left: 6px; font-size: 0.8em; opacity: 0.7; }

/* ── 사출기 연동 화면 ── */
.inj-machine-hdr { display: flex; align-items: center; justify-content: space-between; gap: 12px;
  background: var(--panel); border: 1px solid var(--border); border-left: 5px solid var(--accent2); border-radius: var(--nu-r-large); padding: 12px 16px; flex-wrap: wrap; }
.inj-mh-name { font-size: 1.15rem; font-weight: 800; color: var(--text); }
.inj-mh-sub { margin-left: 10px; font-size: 0.8rem; color: var(--muted); }
.inj-mh-right { display: flex; align-items: center; gap: 12px; }
.inj-mh-mold { font-size: 0.9rem; color: var(--muted); }
.inj-mh-mold b { color: var(--text); }
.inj-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
@media (max-width: 1100px) { .inj-grid { grid-template-columns: 1fr; } }
.inj-mc.sel { border-color: var(--accent2); box-shadow: 0 0 0 2px rgba(229,163,10,0.18); }
.inj-mode { font-size: 0.72rem; font-weight: 700; padding: 1px 8px; border-radius: var(--nu-r-large); }
.inj-mode-수동 { background: var(--nu-success-light); color: var(--nu-success-text); }
.inj-mode-자동 { background: var(--nu-alert-light); color: var(--nu-alert-text); }
.inj-mode-정지 { background: var(--nu-surface-2); color: var(--nu-txt3); }
.inj-mc-st { font-size: 1.05rem; font-weight: 800; margin: 4px 0 2px; }
.inj-st-대기 { color: var(--nu-success-text); } .inj-st-작업중 { color: var(--nu-primary); } .inj-st-정지 { color: var(--nu-txt4); }
.inj-form { display: flex; flex-direction: column; gap: 10px; padding: 4px 2px; }
.inj-form label { font-size: 0.86rem; color: var(--text); display: flex; align-items: center; gap: 8px; }
.inj-form select, .inj-form input[type="number"] { padding: 6px 9px; border: 1px solid var(--border); border-radius: var(--nu-r-medium); font-family: inherit; }
.inj-check { cursor: pointer; }
.inj-check small { color: var(--muted); font-weight: 400; }
.inj-precond { font-size: 0.8rem; padding: 8px 10px; border-radius: var(--nu-r-medium); }
.inj-precond.ok { background: var(--nu-success-light); color: var(--nu-success-text); }
.inj-precond.no { background: var(--nu-warning-light); color: var(--nu-warning-text); border: 1px solid var(--nu-warning-border); }
.inj-steps { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin: 4px 0 10px; }
.inj-step { font-size: 0.78rem; font-weight: 600; padding: 5px 10px; border-radius: var(--nu-r-medium); background: var(--nu-page); color: var(--nu-txt4); }
.inj-step.active { background: var(--nu-warning-light-2); color: var(--nu-warning-text); box-shadow: 0 0 0 1px var(--nu-warning-border); }
.inj-step.done { background: var(--nu-success-light); color: var(--nu-success-text); }
.inj-badge { display: inline-block; font-weight: 800; font-size: 0.95rem; padding: 6px 14px; border-radius: var(--nu-r-medium); }
.inj-badge small { font-weight: 500; opacity: 0.8; }
.inj-b-idle { background: var(--nu-surface-2); color: var(--nu-txt2); }
.inj-b-busy { background: var(--nu-warning-light-2); color: var(--nu-warning-text); }
.inj-b-good { background: var(--nu-success-light); color: var(--nu-success-text); }
.inj-b-warn { background: var(--nu-warning-light); color: var(--nu-warning-text); }
.inj-b-fail { background: var(--nu-alert-light); color: var(--nu-alert-text); }
/* ── 작업지시 목록 (사출기 연동의 출발점) ────────────────────────────────── */
/* 순서 셀 — 클릭하면 숫자 ↔ X 토글. 삭제 버튼이 X 표시된 건들을 일괄 처리한다. */
.inj-wo-grid .inj-seq {
  text-align: center; font-weight: 700; font-variant-numeric: tabular-nums;
  cursor: pointer; user-select: none; border-radius: var(--nu-r-medium); transition: background 0.12s, color 0.12s;
}
.inj-wo-grid .inj-seq:hover { background: var(--row-hover); }
.inj-wo-grid .inj-seq.x { color: var(--nu-alert-text); font-weight: 800; background: var(--nu-alert-light); }
.inj-wo-grid tr.inj-r-mark > td { background: var(--nu-alert-light-2) !important; }
/* 작업상태별 라인 색상 (엑셀 확인표: 완료 시 해당 라인 색상 변경) */
.inj-wo-grid tr.inj-r-done > td { background: var(--nu-success-light); color: var(--nu-success-text); }
.inj-wo-grid tr.inj-r-run  > td { background: var(--nu-primary-tint); }
.inj-wo-grid tr.inj-r-fail > td { background: var(--nu-alert-light); }
.inj-wo-grid td { vertical-align: middle; }
.inj-td-mold select {
  width: 100%; max-width: 148px; padding: 3px 6px; font-size: 0.78rem;
  border: 1px solid var(--border); border-radius: var(--nu-r-medium); background: var(--nu-card); color: var(--text);
}
.inj-td-move { white-space: nowrap; text-align: center; }
.inj-mv {
  border: 1px solid var(--border); background: var(--nu-card); color: var(--muted);
  border-radius: var(--nu-r-small); cursor: pointer; font-size: 0.62rem; line-height: 1; padding: 3px 4px; margin: 0 1px;
}
.inj-mv:hover { border-color: var(--jv-primary); color: var(--jv-primary); }
/* 상태 배지 — 표 안이라 작게 */
.inj-st-badge { display: inline-block; font-size: 0.72rem; font-weight: 700; padding: 2px 8px; border-radius: var(--nu-r-pill); }
.inj-sb-대기   { background: var(--nu-surface-2); color: var(--nu-txt2); }
.inj-sb-진행중 { background: var(--nu-info-light); color: var(--nu-info-text); }
.inj-sb-완료   { background: var(--nu-success-light); color: var(--nu-success-text); }
.inj-sb-실패   { background: var(--nu-alert-light); color: var(--nu-alert-text); }
/* 삭제 버튼 — 파괴적 동작이라 다른 버튼과 색을 구분한다 */
.inj-del-btn {
  border: 1px solid var(--nu-alert-border); background: var(--nu-card); color: var(--nu-alert-text);
  font-size: 0.82rem; font-weight: 700; border-radius: var(--nu-r-medium); padding: 5px 14px; cursor: pointer;
}
.inj-del-btn:hover:not(:disabled) { background: var(--nu-alert-light); border-color: var(--nu-alert); }
.inj-del-btn:disabled { opacity: 0.45; cursor: default; }
/* 조작 결과 안내 줄 */
.inj-msg { font-size: 0.82rem; padding: 7px 11px; border-radius: var(--nu-r-medium); }
.inj-m-good { background: var(--nu-success-light); color: var(--nu-success-text); }
.inj-m-warn { background: var(--nu-warning-light); color: var(--nu-warning-text); }
.inj-m-busy { background: var(--nu-warning-light-2); color: var(--nu-warning-text); }
.inj-m-fail { background: var(--nu-alert-light); color: var(--nu-alert-text); }

.inj-mon { margin-top: 14px; border-top: 1px solid var(--border); padding-top: 12px; }
.inj-mon-t { font-weight: 700; font-size: 0.86rem; color: var(--text); }
.inj-mon-t span { font-weight: 400; font-size: 0.76rem; color: var(--muted); margin-left: 6px; }
.inj-mon-num { margin: 6px 0; font-size: 0.9rem; color: var(--muted); }
.inj-mon-num b { font-size: 1.5rem; color: var(--text); font-variant-numeric: tabular-nums; }
.inj-mon-pct { float: right; font-weight: 800; color: var(--accent2); }
.inj-mon-dim { color: var(--muted); }
/* 모드 램프 4종(1000~1003) + 알람(1004) — LS 확정 주소 그대로 표시 */
.inj-lamps { display: inline-flex; gap: 4px; }
.inj-lamp { display: inline-flex; flex-direction: column; align-items: center; line-height: 1.15;
  font-size: 0.74rem; font-weight: 700; padding: 3px 9px; border-radius: var(--nu-r-medium); background: var(--nu-page); color: var(--nu-txt4); border: 1px solid transparent; }
.inj-lamp small { font-size: 0.62rem; font-weight: 500; opacity: 0.75; }
.inj-lamp.on { background: var(--nu-success-light); color: var(--nu-success-text); border-color: var(--nu-success-border); }
.inj-lamp-alarm.on { background: var(--nu-alert-light); color: var(--nu-alert-text); border-color: var(--nu-alert-border); }
.inj-st-알람 { color: var(--nu-alert-text); }
.inj-wait { font-size: 0.82rem; padding: 9px 11px; border-radius: var(--nu-r-medium); background: var(--nu-info-light); color: var(--nu-info-text); border: 1px solid var(--nu-info-border); }
.inj-mon-sub { margin-top: 8px; font-size: 0.8rem; color: var(--muted); }
.inj-mon-sub b { color: var(--text); font-variant-numeric: tabular-nums; }
.inj-mon-sub small { color: var(--muted); }
.inj-addr { margin-top: 6px; font-size: 0.74rem; color: var(--muted); }
.fr-banner.inj-ok { background: var(--nu-success-light); border-color: var(--nu-success-border); color: var(--nu-success-text); }
.fr-banner code { background: rgba(0,0,0,0.06); padding: 1px 6px; border-radius: var(--nu-r-small); }

/* ── 홈 대시보드 (Oracle 통합 실 KPI) ── */
.home-kpi-row { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 14px; margin-bottom: 14px; }
.home-kpi { background: var(--panel); border: 1px solid var(--border); border-radius: var(--nu-r-large); padding: 16px 18px; }
.home-kpi-l { font-size: 0.85rem; color: var(--muted); margin-bottom: 6px; }
.home-kpi-v { font-size: 1.9rem; font-weight: 800; font-variant-numeric: tabular-nums; line-height: 1.1; }
.home-kpi-s { font-size: 0.78rem; color: var(--muted); margin-top: 4px; }
.home-mid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; margin-bottom: 14px; }
.home-bot { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
.home-card { padding: 14px 16px; border: 1px solid var(--border); border-radius: var(--nu-r-large); background: var(--panel); }
.home-card-t { font-weight: 700; font-size: 0.92rem; color: var(--text); margin-bottom: 10px; }
.home-card-hint { font-weight: 400; font-size: 0.72rem; color: var(--muted, var(--nu-txt4)); margin-left: 6px; }
.home-inv-row { display: flex; gap: 12px; }
.home-inv { flex: 1; text-align: center; background: var(--row-alt); border: 1px solid var(--border); border-radius: var(--nu-r-large); padding: 14px 8px; }
.home-inv-l { font-size: 0.82rem; color: var(--muted); margin-bottom: 6px; }
.home-inv-v { font-size: 1.4rem; font-weight: 800; color: var(--text); font-variant-numeric: tabular-nums; }
.home-inv-v span { font-size: 0.72rem; color: var(--muted); font-weight: 500; margin-left: 3px; }
.home-note { font-size: 0.76rem; color: var(--muted); margin-top: 10px; }
/* 차트 높이는 1920×1080 한 화면을 채우도록 화면 높이에 비례(clamp). 1080에서 상단 291 / 하단 194px.
   ※ 홈 대시보드(.home-fill)에서는 아래 무스크롤 규칙이 이 값을 덮어쓰고 남은 공간을 채운다. */
.home-chart-wrap { position: relative; height: clamp(190px, 27vh, 320px); }
.home-chart-wrap.sm { height: clamp(140px, 18vh, 220px); }

/* ── 홈 대시보드 전용: 브라우저 한 화면 무스크롤 ────────────────────
   브라우저는 주소창·탭바 때문에 실제 뷰포트가 화면 해상도보다 100~150px 작다(1080 모니터 →
   보통 937px). 그래서 고정 높이(px/vh)로 맞추면 어떤 PC에서는 넘치고 어떤 PC에서는 빈다.
   KRI·KPI는 내용 높이대로 두고, 차트 2줄이 "남은 높이"를 나눠 갖게 해 항상 정확히 한 화면에 맞춘다. */
.content:has(> #layoutRoot.home-fill) { overflow: hidden; }
#layoutRoot.home-fill { display: flex; flex-direction: column; flex: 1; min-height: 0; gap: 12px; }
#layoutRoot.home-fill > .home-kri,
#layoutRoot.home-fill > .home-kpi-row { flex: 0 0 auto; margin-bottom: 0; }
/* 차트 2줄은 남은 높이를 균등 분할 — 가운데(차종별 양품)와 하단(설비 가동) 높이를 같게 */
#layoutRoot.home-fill > .home-mid { flex: 1 1 0; min-height: 0; margin-bottom: 0; }
#layoutRoot.home-fill > .home-bot { flex: 1 1 0; min-height: 0; }
#layoutRoot.home-fill .home-card { display: flex; flex-direction: column; min-height: 0; }
#layoutRoot.home-fill .home-card-t { flex: 0 0 auto; }
#layoutRoot.home-fill .home-chart-wrap { height: auto; flex: 1 1 auto; min-height: 0; }
#layoutRoot.home-fill .home-inv-row { flex: 1 1 auto; align-items: center; }
#layoutRoot.home-fill .home-note { flex: 0 0 auto; }
@media (max-height: 720px) {
  #layoutRoot.home-fill .home-kri-desc { display: none; }
  #layoutRoot.home-fill .home-kpi-v { font-size: 1.4rem; }
  #layoutRoot.home-fill .home-kpi-s { display: none; }
}
@media (max-height: 660px) {
  .content:has(> #layoutRoot.home-fill) { padding: 12px 20px; gap: 10px; }
  #layoutRoot.home-fill { gap: 8px; }
  #layoutRoot.home-fill .home-card { padding: 10px 12px; }
}

/* ── 설비 상세현황 (호기 스펙·금형매핑·최근실적) ── */
/* 검색조건 2줄 — ① 호기 버튼 줄 ② 작업일·교대 + 건수 줄.
   두 줄 모두 패널의 직계 자식이라 좌·우 끝이 아래 표(.inv-grid-wrap)의 양 끝과 정확히 맞는다.
   (건수는 .inv-filter-bar .inv-count 의 margin-left:auto 로 표 오른쪽 끝에 붙는다) */
#layoutRoot.ed-page .inv-filter-bar { margin: 0; }
.ed-mbtn-row { display: flex; gap: 6px; flex-wrap: wrap; }
.ed-mbtn { padding: 6px 13px; border: 1px solid var(--border); border-radius: var(--nu-r-medium); background: var(--panel);
  cursor: pointer; font-weight: 700; color: var(--text); display: flex; align-items: baseline; gap: 6px; }
.ed-mbtn span { font-size: 0.72rem; color: var(--muted); font-weight: 500; }
.ed-mbtn.active { background: var(--sidebar); color: var(--nu-on-accent); border-color: var(--sidebar); }
.ed-mbtn.active span { color: rgba(255,255,255,0.7); }
/* .ed-spec-row(스펙 카드 4장)는 상단 총계 박스(.kri-totals)로 승격되어 제거됨 */
.ed-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.3fr); gap: 14px; }
@media (max-width: 1200px) { .ed-grid { grid-template-columns: 1fr; } }

/* ── 설비 가동현황 (호기별 가동율 ≈추정) ── */
/* 호기 카드 — 설비별 생산현황과 같이 넓은 화면에서 호기 대수(--ep-cols)만큼 한 줄에 균등 배치 */
.util-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 10px; }
@media (min-width: 1360px) { .util-row { grid-template-columns: repeat(var(--ep-cols, 7), minmax(0, 1fr)); } }
.util-card { background: var(--panel); border: 1px solid var(--border); border-radius: var(--nu-r-large); padding: 10px 12px 11px; text-align: center; }
.util-mn { font-weight: 700; font-size: 0.95rem; color: var(--text); }
/* 가동율 게이지 — .ep-gauge(설비별 생산현황과 공용)를 240° 속도계형으로 키워 쓴다.
   도형 높이 = 반지름×1.5 라서 아래 height를 키운 만큼 호가 실제로 커진다(반원이면 카드 폭이
   반지름을 제한해 높이를 줘도 빈 공간만 늘어난다). 수치는 원 안쪽 가운데에 놓는다. */
.util-card .ep-gauge { height: clamp(104px, 14vh, 158px); margin: 6px 0 4px; }
.util-card .ep-gauge-txt { top: 0; bottom: 0; display: flex; flex-direction: column;
  align-items: center; justify-content: center; }
.util-card .ep-gauge-txt em { font-size: 0.7rem; }
.util-card .ep-gauge-txt b { font-size: 1.6rem; }
.util-card .ep-gauge-txt b.sm { font-size: 1.15rem; }
.util-sub { font-size: 0.74rem; color: var(--muted); }

/* ── 설비 가동현황 비가동 표시 ── */
.util-card-non { border-color: var(--accent); background: rgba(229,34,45,0.04); }
.util-badge { display: inline-block; padding: 1px 8px; border-radius: var(--nu-r-large); font-size: 0.7rem; font-weight: 700;
  background: var(--accent); color: var(--nu-on-accent); vertical-align: middle; }

/* ── 홈 대시보드 프로젝트 KRI 배너 ── */
.home-kri { background: var(--nu-gradient); border-radius: var(--nu-r-large); padding: 12px 18px; margin-bottom: 14px; }
.home-kri-title { color: var(--nu-on-accent); font-weight: 800; font-size: 0.95rem; margin-bottom: 8px; }
.home-kri-title span { font-weight: 500; font-size: 0.76rem; color: rgba(255,255,255,0.6); margin-left: 6px; }
.home-kri-cards { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }

/* ── 홈 대시보드 반응형 사다리 (1920 기준 → 좁아질 때 단계적으로 접힘) ──
   1200↓ 사이드바 드로어(위 §반응형) · 1100↓ 2열 → 1열 · 900↓ KPI 4열 → 2열 */
@media (max-width: 1100px) {
  .home-mid, .home-bot, .home-kri-cards { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 900px) {
  .home-kpi-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .home-kpi-v { font-size: 1.6rem; }
  .home-inv-row { flex-wrap: wrap; }
}

/* ── 1100↓ 무스크롤 해제 ─────────────────────────────────────────────
   홈은 1920 기준 '한 화면 무스크롤'(.home-fill)로 짜여 있다. 2열이 1열로 접히면
   같은 세로 공간에 카드가 2배로 들어가는데, .home-mid/.home-bot 이 여전히 남은 높이를
   반씩 나눠 갖고 .content가 overflow:hidden 이라 카드가 짓눌려 차트가 아래 제목 위로
   넘쳐 보였다. 좁은 화면에서 무스크롤은 지킬 수도 없고 지킬 이유도 없다 → 스크롤 허용.
   ※ 데스크톱(1100↑) 무스크롤 규약은 그대로다. */
@media (max-width: 1100px) {
  .content:has(> #layoutRoot.home-fill) { overflow: auto; }
  #layoutRoot.home-fill { flex: 0 0 auto; min-height: auto; }
  #layoutRoot.home-fill > .home-mid,
  #layoutRoot.home-fill > .home-bot { flex: 0 0 auto; min-height: auto; }
  /* 세로로 늘어나도 되니 차트는 화면 폭에 비례한 고정 높이를 다시 갖는다 */
  #layoutRoot.home-fill .home-chart-wrap { flex: 0 0 auto; height: clamp(190px, 42vw, 300px); }
  #layoutRoot.home-fill .home-chart-wrap.sm { height: clamp(160px, 34vw, 240px); }
  #layoutRoot.home-fill .home-inv-row { flex: 0 0 auto; }
  /* 차트가 카드 밖으로 새어나가지 않게 하는 마지막 방어선(리사이즈 중 한 프레임 대비) */
  #layoutRoot.home-fill .home-card { overflow: hidden; }
}
.home-kri-card { background: rgba(255,255,255,0.08); border: 1px solid rgba(255,255,255,0.14); border-radius: var(--nu-r-large); padding: 10px 14px; }
.home-kri-goal { color: var(--nu-on-accent); font-size: 1.02rem; font-weight: 700; }
.home-kri-goal b { color: var(--nu-warning-soft); font-size: 1.3rem; }
.home-kri-badge { display: inline-block; padding: 1px 8px; border-radius: var(--nu-r-large); font-size: 0.7rem; font-weight: 700; background: var(--nu-warning); color: var(--nu-on-accent); vertical-align: middle; margin-left: 4px; }
.home-kri-desc { color: rgba(255,255,255,0.72); font-size: 0.77rem; margin-top: 4px; line-height: 1.5; }

/* ═══════════════════════════════════════════════════════════════════════════
   홈 대시보드 전용 레이아웃 (DESIGN.md · Nubank NuDS)
   퍼플 프라이머리 + 중성 그레이 배경의 업무용 밀집형 대시보드.
   ★ 모든 선택자를 #layoutRoot.home-fill 안으로 한정한다. 홈 대시보드는 이 클래스를
     renderDashboardPage()에서만 부여하므로, 다른 화면에는 절대 영향이 없다.
   ※ 색 토큰은 :root(NuDS)에서 그대로 상속받는다 — 여기서 값을 재정의하지 않는다
     (DESIGN.md Don'ts "hex 직접 사용 금지 / 토큰은 한 곳에서만 관리").
   ═══════════════════════════════════════════════════════════════════════════ */
#layoutRoot.home-fill {
  /* §3-A 타이포 — 글꼴은 `html` 에서 물려받는다(tokens.css `--nu-font`). 자간만 여기서 */
  letter-spacing: -0.01em;
  color: var(--jv-txt1);
}
/* §2-B 페이지 배경 — 쿨그레이 (홈 대시보드일 때의 콘텐츠 영역에만).
   ※ --jv-* 는 #layoutRoot에 정의돼 있어 부모인 .content에서는 참조 불가 → 리터럴 값 사용 */
.content:has(> #layoutRoot.home-fill) { background: var(--nu-board, var(--nu-page)); }   /* body 와 같은 틀 바탕(0.38.0) */

/* ── §6-D KPI 카드: 아이콘 박스 좌 + 26px 수치 우 ───────────────────────── */
#layoutRoot.home-fill .home-kpi-row { gap: 12px; }
#layoutRoot.home-fill .jv-kpi {
  display: flex; align-items: center; gap: 14px;
  background: var(--jv-card); border: 1px solid var(--jv-border); border-radius: var(--nu-r-large);
  box-shadow: var(--jv-shadow); padding: 14px 16px;
  transition: box-shadow 0.15s, border-color 0.15s, transform 0.15s;   /* §6-C card-hover */
}
#layoutRoot.home-fill .jv-kpi:hover {
  box-shadow: 0 4px 16px rgba(130,10,209,0.12); border-color: var(--jv-primary-mid);
  transform: translateY(-1px);
}
#layoutRoot.home-fill .jv-kpi-ico {
  flex-shrink: 0; width: 46px; height: 46px; border-radius: var(--nu-r-large);
  display: flex; align-items: center; justify-content: center;
}
#layoutRoot.home-fill .jv-kpi-ico svg { width: 22px; height: 22px; }
#layoutRoot.home-fill .jv-t-primary { background: var(--jv-primary-light); color: var(--jv-primary); }
#layoutRoot.home-fill .jv-t-success { background: var(--jv-success-light); color: var(--jv-success); }
#layoutRoot.home-fill .jv-t-violet  { background: var(--jv-violet-light);  color: var(--jv-violet); }
#layoutRoot.home-fill .jv-t-warning { background: var(--jv-warning-light); color: var(--jv-warning); }
#layoutRoot.home-fill .jv-kpi-body { min-width: 0; }                    /* §10-B ③ truncate 대비 */
#layoutRoot.home-fill .home-kpi-l {
  margin: 0; font-size: 12px; font-weight: 500; color: var(--jv-txt3);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
#layoutRoot.home-fill .home-kpi-v {                                      /* §3-B 26px KPI 수치 */
  margin-top: 3px; font-size: 26px; font-weight: 700; line-height: 1;
  color: var(--jv-txt1); font-variant-numeric: tabular-nums; letter-spacing: -0.02em;
}
#layoutRoot.home-fill .jv-kpi-u { font-size: 13px; font-weight: 600; color: var(--jv-txt3); margin-left: 3px; }
#layoutRoot.home-fill .home-kpi-s { margin-top: 4px; font-size: 10px; color: var(--jv-txt4); }

/* ── §6-D 강조 카드(프라이머리 채움) — KRI 목표 배너 ─────────────────────
   ★ 홈 대시보드의 KRI 배너 + 총계 박스(.kri-totals)가 이 스타일을 공유한다.
     .kri-totals 를 붙인 화면(설비별 생산현황·출하계획·생산실적)은 본문 최상단에
     같은 파란 박스로 페이지 총계를 표시한다. 값은 여기 한 곳에서만 관리 —
     화면을 늘릴 때 선택자만 덧붙이고 수치는 절대 복제하지 않는다. */
#layoutRoot.home-fill .home-kri,
#layoutRoot .home-kri.kri-totals {
  /* 배경·그림자는 아래 §Colors 블록이 최종적으로 --nu-gradient / --nu-elev-low 로 덮어쓴다.
     여기 남은 값은 그 블록이 없을 때의 안전값 — 톤 고정 리터럴을 두면 다크에서 보라 그림자가
     남으므로 토큰으로만 적는다. */
  background: var(--jv-primary); border-radius: var(--nu-r-large); padding: 12px 16px;
  box-shadow: var(--nu-elev-low);
}
#layoutRoot.home-fill .home-kri-title,
#layoutRoot .kri-totals .home-kri-title { font-size: 13px; font-weight: 700; color: var(--nu-on-accent); margin-bottom: 8px; }
#layoutRoot.home-fill .home-kri-title span,
#layoutRoot .kri-totals .home-kri-title span { font-size: 11px; font-weight: 500; color: rgba(255,255,255,0.72); }
#layoutRoot.home-fill .home-kri-card,
#layoutRoot .kri-totals .home-kri-card {
  background: rgba(255,255,255,0.12); border: 1px solid rgba(255,255,255,0.18); border-radius: var(--nu-r-large); padding: 9px 13px;
}
#layoutRoot.home-fill .home-kri-goal,
#layoutRoot .kri-totals .home-kri-goal { font-size: 13px; font-weight: 700; color: var(--nu-on-accent); }
#layoutRoot.home-fill .home-kri-goal b,
#layoutRoot .kri-totals .home-kri-goal b { font-size: 16px; color: var(--nu-on-accent); }
#layoutRoot.home-fill .home-kri-badge,                                   /* §6-E 배지 10px pill */
#layoutRoot .kri-totals .home-kri-badge {
  font-size: 10px; font-weight: 700; padding: 1px 8px; border-radius: var(--nu-r-pill);
  background: rgba(255,255,255,0.22); color: var(--nu-on-accent); border: 1px solid rgba(255,255,255,0.28);
}
#layoutRoot.home-fill .home-kri-desc,
#layoutRoot .kri-totals .home-kri-desc { font-size: 11px; color: rgba(255,255,255,0.78); line-height: 1.45; margin-top: 4px; }

/* 총계 박스 공통 — 본문 최상단 고정 높이. 카드 수(3~4장)는 auto-fit이 알아서 나눈다.
   재고처럼 탭 안쪽(.inv-tab-content)에 놓이는 경우가 있어 직계 제한을 두지 않는다. */
#layoutRoot .home-kri.kri-totals { flex: 0 0 auto; margin-bottom: 0; }
#layoutRoot .kri-totals .home-kri-cards { grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }
#layoutRoot .kri-totals .home-kri-goal b { font-variant-numeric: tabular-nums; }
/* 예시(미연동) 데이터 화면용 회색 변형 — 현재 붙은 화면 없음(원단소요예정량이 쓰다가
   2026-08 전 화면 색 통일로 뗐다. 예시 고지는 카드의 '예시' 배지·설명줄이 담당).
   미연동 화면을 새로 만들 때 다시 쓸 수 있게 스타일만 남겨 둔다. */
#layoutRoot .home-kri.kri-mock { background: var(--nu-txt3); box-shadow: none; }
#layoutRoot .kri-mock .home-kri-badge { background: rgba(255,255,255,0.18); border-color: rgba(255,255,255,0.30); }

/* 총계 박스가 차지한 높이만큼 아래 본문이 줄어드니, 넘치는 영역만 내부 스크롤 ── */
/* 설비별 생산현황 — 호기 카드 줄은 제 높이를 지키고(0 1 auto), 남는 높이는 아래 비교 차트가 먹는다.
   기준일 필터 줄은 상하 여백을 없애 카드가 화면 위쪽에 바짝 붙게 한다. */
#layoutRoot.ep-page .inv-filter-bar { margin: 0; }
/* flex: 0 0 auto — 카드 줄이 두 줄이 돼도 절대 눌리지 않는다(눌리면 아래 차트와 겹친다) */
#layoutRoot.ep-page > .panel { overflow-y: auto; }
#layoutRoot.ep-page > .panel > .ep-card-grid { flex: 0 0 auto; align-content: start; }
/* 아래 4:3 차트 2단은 설비별 생산현황·설비 가동현황이 공유한다 — 화면이 아니라 클래스로 스코프 */
#layoutRoot.fit-page > .panel > .ep-viz-grid { flex: 1 1 auto; min-height: 180px; }
#layoutRoot.fit-page .ep-viz-grid > .viz-card { display: flex; flex-direction: column; min-height: 0; flex: 1 1 auto; }
#layoutRoot.fit-page .ep-viz-wrap { height: auto; flex: 1 1 auto; min-height: 130px; }
#layoutRoot.fit-page .ep-viz-grid > .viz-card > .inv-grid-wrap {
  flex: 1 1 auto; min-height: 96px; max-height: none !important; overflow: auto;
}
/* 생산실적 — 표가 .panel 직계가 아니라(prod-layout > prod-table-col) 공통 fit 규칙이
   닿지 않는다. 매직넘버 calc() 대신 여기서도 "남은 공간 채우기"로 맞춘다. */
#layoutRoot.fit-page > .panel > .prod-layout { flex: 1 1 auto; min-height: 0; }
#layoutRoot.fit-page .prod-table-col { display: flex; flex-direction: column; min-height: 0; }
#layoutRoot.fit-page .prod-table-col > .inv-grid-wrap {
  flex: 1 1 auto; min-height: 96px; max-height: none !important; overflow: auto;
}

/* ── §6-C 카드 + 차트 패널 ─────────────────────────────────────────────── */
#layoutRoot.home-fill .home-mid, #layoutRoot.home-fill .home-bot { gap: 12px; }
#layoutRoot.home-fill .home-card {
  background: var(--jv-card); border: 1px solid var(--jv-border); border-radius: var(--nu-r-large);
  box-shadow: var(--jv-shadow); padding: 12px 16px;
}
#layoutRoot.home-fill .home-card-t {                                     /* §3-B 13px 섹션 제목 */
  font-size: 13px; font-weight: 700; color: var(--jv-txt1);
  letter-spacing: -0.02em; margin-bottom: 8px;
}
#layoutRoot.home-fill .home-card-hint { font-size: 10px; font-weight: 400; color: var(--jv-txt4); margin-left: 6px; }
#layoutRoot.home-fill .home-inv-trend-t span { font-weight: 400; font-size: 10px; color: var(--jv-txt4); margin-left: 6px; }
#layoutRoot.home-fill .home-inv-trend-empty {
  flex: 1 1 auto; display: flex; align-items: center; justify-content: center;
  margin-top: 12px; border: 1px dashed var(--jv-border); border-radius: var(--nu-r-large);
  font-size: 11px; color: var(--jv-txt4);
}

/* ── §8 모션: 진입 애니메이션 ──────────────────────────────────────────── */
@keyframes jvSlideIn { from { transform: translateY(6px); opacity: 0; } to { transform: none; opacity: 1; } }
#layoutRoot.home-fill > * { animation: jvSlideIn 0.18s ease-out; }

/* ── §4-D 얇은 스크롤바 (홈 대시보드 내부 한정) ────────────────────────── */
#layoutRoot.home-fill ::-webkit-scrollbar { width: 5px; height: 5px; }
#layoutRoot.home-fill ::-webkit-scrollbar-track { background: var(--nu-surface-3); }
#layoutRoot.home-fill ::-webkit-scrollbar-thumb { background: var(--nu-surface-4); border-radius: var(--nu-r-small); }
#layoutRoot.home-fill ::-webkit-scrollbar-thumb:hover { background: var(--jv-primary); }

/* ═══════════════════════════════════════════════════════════════════════════
   사이드바 — 8분류 그룹 네비게이션
   ───────────────────────────────────────────────────────────────────────────
   설계 의도(고쳐 쓸 때 이 전제를 깨지 말 것):
   ① 위계는 "크기"가 아니라 "역할"로 만든다.
      그룹 헤더 = 작지만 자간 넓은 라벨(txt4) · 메뉴 항목 = 본문 크기(13px, txt2).
      예전엔 그룹 헤더가 항목보다 작고 진해서 위계가 뒤집혀 읽혔다.
   ② 그룹 경계는 "선"이 아니라 "여백"으로. 그룹 사이만 넓히면 8개 그룹이
      한 덩어리로 뭉치지 않는다(얇은 가이드선은 흰 배경에서 어차피 안 보였다).
   ③ 활성 표시는 진한 채움 대신 [연한 tint + 좌측 3px 바 + 프라이머리 글자].
      밀집형 목록에서 진한 알약 하나가 떠 있으면 오히려 산만하고, 이 조합이
      어떤 톤(다크 포함)에서도 대비가 유지된다.
   ④ 지금 보고 있는 화면이 속한 그룹의 헤더도 함께 강조한다(:has) — 8그룹에서
      "내가 어디 있는지"가 한눈에 보인다.
   ⑤ 1920×1080 무스크롤 유지 — 항목을 키우되 총 높이는 뷰포트 안에 들어와야 한다.
   ═══════════════════════════════════════════════════════════════════════════ */
.sidebar {
  background: var(--jv-card);
  border-right: 1px solid var(--jv-border);
  box-shadow: 2px 0 8px rgba(0,0,0,0.04);
  letter-spacing: -0.01em;
}
.brand span { color: var(--jv-txt1); font-weight: 800; }
.nav-ico {
  width: var(--nav-ico);
  height: var(--nav-ico);
  flex-shrink: 0;
  /* stroke는 currentColor — 비활성·hover·현재그룹 강조 색을 그대로 따라간다 */
}

/* ── 메뉴 항목 ─────────────────────────────────────────────────────────── */
.nav a {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--nav-ico-gap);
  background: transparent;
  border: none;
  border-radius: var(--nu-r-medium);
  padding: 7px 10px;
  font-size: 13px;
  font-weight: 500;
  line-height: 1.35;
  color: var(--jv-txt2);
  transition: background 0.12s, color 0.12s;
}
.nav a:hover {
  background: var(--jv-hover);
  color: var(--jv-txt1);
}
/* 활성 — tint 배경 + 좌측 바. 채움(흰 글자)이 아니라서 톤이 바뀌어도 안전하다 */
.nav a.active {
  background: var(--nu-primary-tint);
  color: var(--nu-brand-text);
  font-weight: 700;
}
.nav a.active::before {
  content: '';
  position: absolute;
  left: 0; top: 50%;
  width: 3px; height: 16px;
  transform: translateY(-50%);
  border-radius: 0 var(--nu-r-small) var(--nu-r-small) 0;
  background: var(--nu-primary);
}

/* ── 그룹 헤더 — "제목"이 아니라 "라벨". 작게, 자간 넓게, 연하게 ────────── */
.nav-group > summary {
  color: var(--jv-txt3);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  border-radius: var(--nu-r-medium);
  padding: 6px 10px;
  /* 아이콘 + 그룹명은 왼쪽에 붙이고 접기 화살표만 오른쪽 끝으로 민다
     (기본 space-between이면 아이콘·글자·화살표가 3등분으로 흩어진다) */
  justify-content: flex-start;
  gap: var(--nav-ico-gap);
  transition: color 0.12s, background 0.12s;
}
.nav-group > summary:hover { background: var(--jv-hover); color: var(--jv-txt2); }
.nav-group > summary::after {
  content: '›';
  margin-left: auto;
  font-size: 15px;
  line-height: 1;
  color: var(--jv-txt4);
  opacity: 0.9;
  transition: transform 0.15s, color 0.12s;
}
.nav-group[open] > summary::after { transform: rotate(90deg); }
.nav-group > summary:hover::after { color: var(--jv-txt2); }
/* 지금 보고 있는 화면이 속한 그룹은 헤더도 프라이머리로 — 현재 위치가 한눈에 */
.nav-group:has(a.active) > summary { color: var(--nu-brand-text); }
.nav-group:has(a.active) > summary::after { color: var(--nu-brand-text); }

/* ── 하위 항목 — 세로 가이드선으로 묶는다 ──────────────────────────────────
   그룹을 여러 개 열어 두면 어느 항목이 어느 그룹 소속인지 여백만으로는 흐려진다.
   → 열린 그룹의 하위 목록 왼쪽에 세로선을 세워 한 묶음으로 읽히게 한다.
   선 위치·글자 위치는 --nav-sub-line / --nav-sub-indent 가 정한다(위 :root 참고).
   ★ 하위 항목을 그룹명 글자(33px)에 맞춰 정렬하지 않는다 — 그렇게 하면 가장 긴 항목
     ("설비별 생산현황")이 사이드바 폭을 33px 만큼 밀어올린다. 가이드선이 소속을 이미
     말해 주므로 정렬은 선에 맡기고 들여쓰기는 25px 로 줄여 그만큼 본문에 돌려준다.
   (닫힌 그룹은 <details> 가 하위 목록을 렌더하지 않으므로 선도 함께 사라진다) */
.nav-group .nav-sub {
  margin-left: var(--nav-sub-line);
  padding-left: 0;
  border-left: 1px solid var(--jv-border);
}
/* 글자 x = --nav-sub-indent 가 되도록, 선까지의 거리(margin + 선 1px)를 뺀 만큼만 padding */
.nav-group .nav-sub a {
  padding-left: calc(var(--nav-sub-indent) - var(--nav-sub-line) - 1px);
  font-size: 13px;
}
/* 활성 항목은 가이드선 그 자리를 프라이머리로 덮어 "줄기 위에서 여기가 켜졌다"로 읽히게 한다 */
.nav-group .nav-sub a.active::before {
  left: -1px; width: 2px; height: 20px; border-radius: 0;
}

/* 외부 링크 아이콘은 오른쪽 끝으로 밀어 정렬을 맞춘다 */
.nav-ext-ico { color: var(--jv-txt4); opacity: 1; margin-left: auto; padding-left: 6px; }
.nav a.active .nav-ext-ico { color: var(--nu-brand-text); }

/* 내 메뉴 - 즐겨찾기 묶음 · 화면 제목 옆 별(0.36.0, board-shell.js MarunexMyMenu).
   ★ 별은 글자(☆ ★)다 - 색이 지워지는 고대비에서도 빈 별 · 찬 별로 갈린다. 눌림은 aria-pressed */
.nav-fav-ico::before { content: "★"; font-size: 13px; line-height: 1; color: var(--jv-warning); }
.nav-fav-ico { display: inline-flex; align-items: center; justify-content: center; }
.nav-fav-edit {
  /* 묶음 머리 「즐겨찾기」 글자 바로 오른쪽(0.39.1) - 머리의 굵기 · 자간을 물려받지 않게 되돌린다 */
  display: inline-block; flex: none; margin: 0 0 0 2px;
  padding: 1px 7px; font-size: 11px; font-weight: 400; letter-spacing: 0; line-height: 1.4; color: var(--jv-txt3);
  background: transparent; border: 1px solid var(--jv-border); border-radius: var(--nu-r-small); cursor: pointer;
}
.nav-fav-edit:hover { color: var(--jv-txt1); background: var(--jv-hover); }
/* 목록 줄은 글자 폭만 - 하위 목록이 grid 라 늘어나 사이드바 밖까지 뻗었다 */
.nav-group .nav-sub.nav-fav-list { justify-items: start; }
.nav-group .nav-sub.nav-fav-list > a, .nav-fav-row { justify-self: stretch; }
.nav-fav-edit[aria-pressed="true"] { color: var(--jv-primary); border-color: var(--jv-primary); font-weight: 700; }
.nav-fav-row {
  display: flex; align-items: center; gap: 2px; min-height: 28px;
  padding: 0 4px 0 6px;
  font-size: 13px; color: var(--jv-txt2); cursor: grab;
}
.nav-fav-row.is-drag { opacity: 0.45; }
/* 이름 폭을 묶는다 - 사이드바 목록은 가장 넓은 글자만큼 늘어나고 사이드바가 그 끝을 가린다.
   이름을 다 적으면 끝 단추(✕)가 가려진 쪽으로 밀렸다(2026-09-29 실측). 다 못 적은 이름은 title 로 */
.nav-fav-name { flex: 0 1 auto; width: 74px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nav-fav-btn {
  width: 20px; height: 22px; padding: 0; font-size: 10px; flex: none; line-height: 1; color: var(--jv-txt3);
  background: transparent; border: 1px solid transparent; border-radius: var(--nu-r-small); cursor: pointer;
}
.nav-fav-btn:hover:not(:disabled) { border-color: var(--jv-border); color: var(--jv-txt1); background: var(--jv-hover); }
.nav-fav-btn:disabled { opacity: 0.3; cursor: default; }
.pt-fav {
  margin-left: 6px; width: 26px; height: 26px; padding: 0; font-size: 17px; line-height: 1;
  color: var(--jv-txt4); background: transparent; border: 0; border-radius: var(--nu-r-medium); cursor: pointer;
}
.pt-fav:hover { color: var(--jv-warning); background: var(--jv-hover); }
.pt-fav[aria-pressed="true"] { color: var(--jv-warning); }
/* 화면 새 소식 종(0.41.0) - ☆ 바로 오른쪽. 숫자는 그 화면에서 아직 안 본 줄 수, 누르면 그 화면 소식을 날짜별로 편다 */
.pt-news {
  position: relative; display: inline-flex; align-items: center; justify-content: center;
  margin-left: 2px; width: 26px; height: 26px; padding: 0; color: var(--jv-txt3);
  background: transparent; border: 0; border-radius: var(--nu-r-medium); cursor: pointer;
}
.pt-news svg { width: 17px; height: 17px; }
.pt-news:hover, .pt-news[aria-expanded="true"] { color: var(--jv-txt1); background: var(--jv-hover); }
.pt-news-badge {
  position: absolute; top: -3px; right: -6px; min-width: 16px; height: 16px; padding: 0 4px; box-sizing: border-box;
  border-radius: 8px; background: var(--nu-alert); color: #fff; font-size: 10.5px; font-weight: 700; line-height: 16px;
  text-align: center; font-variant-numeric: tabular-nums; pointer-events: none;
}
.mx-news-panel {
  position: fixed; z-index: 2900; width: min(430px, calc(100vw - 24px)); max-height: min(70vh, 520px);
  display: flex; flex-direction: column; background: var(--jv-card); color: var(--jv-txt1);
  border: 1px solid var(--jv-border); border-radius: var(--nu-r-large); box-shadow: 0 8px 24px rgba(17, 24, 39, .18), 0 1px 3px rgba(17, 24, 39, .12);
}
.mx-news-h { display: flex; align-items: baseline; gap: 8px; padding: 11px 14px 9px; border-bottom: 1px solid var(--jv-border); }
.mx-news-h b { font-size: 14.5px; }
.mx-news-h span { font-size: 12.5px; color: var(--jv-txt3); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mx-news-b { overflow-y: auto; padding: 2px 14px 8px; }
.mx-news-day { padding: 9px 0 6px; border-bottom: 1px dashed var(--jv-border); }
.mx-news-day:last-child { border-bottom: 0; }
.mx-news-day h4 { display: flex; align-items: center; gap: 6px; margin: 0 0 4px; font-size: 13px; font-weight: 700; font-variant-numeric: tabular-nums; }
.mx-news-new {
  display: inline-block; padding: 0 5px; border-radius: 3px; background: var(--nu-alert); color: #fff;
  font-size: 10px; font-weight: 800; line-height: 15px; letter-spacing: .04em;
}
.mx-news-name { margin: 4px 0 2px; font-size: 12.5px; color: var(--jv-txt3); }
.mx-news-req {
  margin: 3px 0 4px; padding: 5px 9px; border-left: 3px solid var(--jv-primary); border-radius: 0 5px 5px 0;
  background: var(--jv-primary-light, var(--jv-hover)); font-size: 12.5px;
}
.mx-news-req b { margin-right: 6px; color: var(--jv-primary); }
.mx-news-req em { margin-left: 4px; font-style: normal; color: var(--jv-txt3); font-size: 12px; }
.mx-news-b ul { margin: 0; padding-left: 18px; font-size: 13.5px; line-height: 1.55; }
.mx-news-empty { padding: 18px 0; color: var(--jv-txt3); font-size: 13.5px; }
.mx-news-f { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 8px 14px; border-top: 1px solid var(--jv-border); }
.mx-news-all { padding: 0; background: none; border: 0; color: var(--jv-primary); font: inherit; font-size: 13px; cursor: pointer; }
.mx-news-all:hover { text-decoration: underline; }
@media (forced-colors: active) {
  .pt-news, .pt-news[aria-expanded="true"] { color: CanvasText; }
  /* 시스템이 바탕을 지운다 - 숫자 · NEW 는 테두리로 묶는다 */
  .pt-news-badge, .mx-news-new { forced-color-adjust: none; background: Canvas; color: CanvasText; border: 1px solid CanvasText; line-height: 14px; }
  .mx-news-panel { border: 2px solid CanvasText; }
  .mx-news-req { border-left-color: CanvasText; }
}
@media (forced-colors: active) {
  .nav-fav-ico::before, .pt-fav, .pt-fav[aria-pressed="true"] { color: CanvasText; }
  .nav-fav-edit, .nav-fav-btn { border-color: GrayText; }
  .nav-fav-edit[aria-pressed="true"] { border: 2px solid CanvasText; }
  .nav-fav-btn:disabled { color: GrayText; }
}
/* §4-D 얇은 스크롤바 */
.sidebar::-webkit-scrollbar { width: 5px; }
.sidebar::-webkit-scrollbar-track { background: transparent; }
.sidebar::-webkit-scrollbar-thumb { background: var(--nu-surface-4); border-radius: var(--nu-r-small); }
.sidebar::-webkit-scrollbar-thumb:hover { background: var(--jv-primary); }

/* §5-D 헤더 — 흰 배경 + 하단 경계선, 15px 볼드 타이틀
   슬림 헤더: 전 화면 공통 44px(본문 무스크롤 영역 확보). */
.topbar {
  background: var(--jv-card);
  border-bottom: 1px solid var(--jv-border);
  height: 44px;
  padding: 0 20px;
  letter-spacing: -0.01em;
}
.page-title {
  font-size: 15px; font-weight: 700; color: var(--jv-txt1); letter-spacing: -0.02em;
}
.topbar-right { color: var(--jv-txt3); font-size: 12px; font-weight: 500; }
#currentTime { color: var(--jv-txt3); font-variant-numeric: tabular-nums; }
/* §6-A 단추 글꼴 — 단추는 부모 글꼴을 **안 물려받는다**(브라우저 기본이 시스템 글꼴이라
   본문이 Pretendard 여도 단추만 Arial 로 뜬다). §6-B 「입력」이 input · select · textarea 만
   담고 button 을 안 담아, 이 규칙이 생기기 전에는 단추가 통째로 예외였다.
   ★ 클래스마다 한 줄씩 붙이지 말 것 — 실제로 `.mx-grid-btn` · `.user-chip` · `.mx-tabs button`
     셋이 그렇게 따로 붙어 있었고, 나머지 단추(`.admin-btn-*` · `.logout-btn` · `.menu-btn` …)는
     그대로 Arial 이었다. 여기 한 곳에서 잡으면 새 단추도 저절로 따라온다 */
button, input[type="button"], input[type="submit"], input[type="reset"] {
  font-family: inherit;
}

/* 아이콘 버튼 §6-A BTN_ICON */
.menu-btn {
  background: transparent; color: var(--jv-txt3); border-radius: var(--nu-r-medium); transition: background 0.12s, color 0.12s;
  width: 30px; height: 30px;
}
.menu-btn:hover { background: var(--jv-hover); color: var(--jv-txt1); }
/* 사용자 칩 — primary-light pill */
.user-chip {
  background: var(--jv-primary-light); color: var(--jv-primary);
  font-size: 12px; font-weight: 700; padding: 4px 10px;
}
.user-chip:hover { background: var(--nu-primary-tint-2); }
/* 이 보드가 보는 DB - 공급사 관리자에게만(admin-screens.js wireDataSourceBadge, 0.25.0).
   업무 표시와 섞이지 않게 점선 테두리 · 흐린 글자. 배경색에 기대지 않아 고대비에서도 테두리가 선다 */
.ds-badge {
  display: inline-block; max-width: 34vw; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: middle;
  font-size: 11px; font-weight: 600; font-variant-numeric: tabular-nums; color: var(--jv-txt2);
  background: var(--jv-card); border: 1px dashed var(--jv-border); border-radius: var(--nu-r-medium);
  padding: 2px 8px; margin-right: 8px; cursor: help;
}
/* 운영 · 개발 표시(admin-screens.js wireStageNotice, 0.35.7).
   운영 띠 - 머리줄 아래 한 줄. 판이 세로로 쌓는 판(.main-content)이라 줄어들지 않게만 하면 아래 화면이 남은 높이를 나눠 쓴다.
   ★ 고대비는 배경색을 지우므로 이 띠만 강제 색에서 빼서 빨강 · 흰 글자를 지킨다(글자 대비 5.9:1) */
.stage-band {
  flex: none; display: flex; align-items: center; gap: 10px;
  padding: 5px 20px; background: #B3141F; color: #FFFFFF;
  font-size: 13px; font-weight: 600; line-height: 1.4; border-bottom: 1px solid #7A0D15;
}
.stage-band b { font-size: 12px; font-weight: 800; letter-spacing: .08em; padding: 1px 8px; border: 1px solid #FFFFFF; border-radius: 4px; }
/* 개발 칩 - 머리줄 오른쪽 작게. 테두리로 서므로 고대비에서도 보인다 */
.stage-chip {
  display: inline-block; vertical-align: middle; margin-right: 8px; padding: 1px 8px;
  font-size: 11px; font-weight: 700; color: var(--nu-primary); border: 1px solid var(--nu-primary); border-radius: var(--nu-r-medium);
}
@media (forced-colors: active) {
  .stage-band, .stage-band b { forced-color-adjust: none; background: #B3141F; color: #FFFFFF; border-color: #FFFFFF; }
  .stage-chip { border-color: CanvasText; color: CanvasText; }
}
/* 로그아웃 — §6-A BTN_SECONDARY */
.logout-btn {
  background: var(--jv-card); border: 1px solid var(--jv-border); color: var(--jv-txt2);
  font-size: 12px; font-weight: 600; border-radius: var(--nu-r-medium); padding: 4px 10px;
  transition: border-color 0.12s, background 0.12s, color 0.12s;
}
.logout-btn:hover {
  background: var(--jv-card); border-color: var(--nu-primary-lightest); color: var(--jv-primary);
}

/* ═══════════════════════════════════════════════════════════════════════════
   공통 컴포넌트 정합 — 전 화면 (DESIGN.md §Shapes · §Components)
   토큰 매핑만으로 색은 이미 전환된다. 여기서는 라운드·그림자·버튼·인풋·탭처럼
   "레시피"가 정해진 요소를 지침 값으로 맞춘다.
   ═══════════════════════════════════════════════════════════════════════════ */
/* §4-A 라운드 / §4-B 그림자 — 카드는 테두리 + 얕은 그림자를 항상 함께 */
.panel, .viz-card, .home-card, .util-card, .ep-card, .inv-card, .sh-card {
  border-radius: var(--nu-r-large);
}
.panel { border: 1px solid var(--jv-border); box-shadow: var(--jv-shadow); }
/* 자료를 부르는 동안 세우는 빈 패널. .panel 자체는 안쪽 여백이 없어서, 글자가
   테두리에 붙지 않게 이 상태일 때만 준다. */
.panel.is-loading { padding: 20px; }

/* ── 표면 3단 — 페이지 > 큰 박스 > 개별 박스 ──────────────────────────────
   설비별 생산현황처럼 패널(.panel) 안에 카드가 또 들어가는 화면은 2·3단계가 같은
   --nu-card 라 층이 안 보였다. 안쪽 카드만 한 단계 위 표면(--nu-card-2)으로 올린다.
   · 라이트 톤: --nu-card-2 = --nu-card 라 값이 같다 → 보이는 변화 없음
   · 다크 톤  : themes.css 가 한 단계 밝은 값을 주므로 3단 깊이가 생긴다
   ※ .panel 안에 있을 때만 적용한다 — .home-card 처럼 자기가 곧 큰 박스(.panel.home-card)인
     경우까지 밝히면 2단계가 통째로 올라가 층 구분이 도로 사라진다. */
.panel .viz-card, .panel .ep-card, .panel .util-card,
.panel .inv-card, .panel .sh-card, .panel .home-card {
  background: var(--nu-card-2);
}

/* ═══════════════════════════════════════════════════════════════════════════
   §6-A 단추 한 벌 — `.mx-btn` + 변형
   ───────────────────────────────────────────────────────────────────────────
   치수는 tokens.css 의 `--mx-btn-*` 한 곳에 있고 여기는 그것을 읽기만 한다.
   그래서 벌을 갈아 끼워도(`[data-btn]`) 이 규칙들은 그대로다.

   종류는 변형으로 얹는다 - 아무것도 안 붙이면 「보통」(흰 바탕 + 테두리)이다.
     .mx-btn                     보통 — 가장 많이 쓰는 것
     .mx-btn--primary            주요 — 화면마다 하나. 채움
     .mx-btn--danger             위험 — 되돌릴 수 없는 것
     .mx-btn--quiet              조용한 — 테두리 없이. 표 안 · 도구 줄
     .mx-btn--link               글자 — 안내문 안에서 한 낱말로
     .mx-btn--xs / --sm / --lg   크기
     .mx-btn--icon               아이콘 전용(정사각). aria-label 을 반드시 단다
     .mx-btn--block              전체 폭
   묶는 것 - `.mx-btn-group`(붙은 묶음) · `.mx-seg`(택일) · `.mx-chip`(켜고 끄는 것)

   ★ **모든 종류에 테두리가 하나 있다.** 고대비에서 채움이 시스템 색으로 덮여도 모양이 남는다.
     조용한 것은 투명 테두리라 자리를 차지하되 안 보인다 - 켜질 때 줄이 안 흔들린다.
   ★ 고른 것은 `aria-pressed` 로 말한다. 색만으로 말하면 화면 읽기 프로그램과 고대비에서 사라진다.
   ═══════════════════════════════════════════════════════════════════════════ */
.mx-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--mx-btn-gap);
  box-sizing: border-box; min-height: var(--mx-btn-min-h);
  padding: var(--mx-btn-pad-y) var(--mx-btn-pad-x);
  border: 1px solid var(--jv-border-strong); border-radius: var(--mx-btn-radius);
  background: var(--jv-card); color: var(--jv-txt2);
  font-family: inherit; font-size: var(--mx-btn-font-size); font-weight: var(--mx-btn-weight);
  line-height: 1.25; letter-spacing: -0.01em; white-space: nowrap; text-decoration: none;
  cursor: pointer; transition: background 0.12s, border-color 0.12s, color 0.12s;
}
.mx-btn:hover { background: var(--jv-hover); border-color: var(--jv-primary); color: var(--jv-txt1); }
.mx-btn:active { background: var(--jv-primary-light); }
.mx-btn:focus-visible { outline: 2px solid var(--jv-primary); outline-offset: 1px; }
.mx-btn:disabled, .mx-btn[aria-disabled="true"] {
  background: var(--jv-card); border-color: var(--jv-border); color: var(--jv-txt4); cursor: not-allowed;
}

.mx-btn--primary {
  background: var(--mx-btn-fill); border-color: var(--mx-btn-fill); color: var(--nu-on-accent);
}
.mx-btn--primary:hover {
  background: var(--mx-btn-fill-hover); border-color: var(--mx-btn-fill-hover); color: var(--nu-on-accent);
}
.mx-btn--primary:active { background: var(--mx-btn-fill-hover); }
.mx-btn--primary:disabled, .mx-btn--primary[aria-disabled="true"] {
  background: var(--mx-btn-fill); border-color: var(--mx-btn-fill); color: var(--nu-on-accent);
  opacity: var(--nu-op-disabled);
}

.mx-btn--danger { background: var(--jv-danger); border-color: var(--jv-danger); color: var(--nu-on-accent); }
.mx-btn--danger:hover {
  background: var(--jv-danger-text); border-color: var(--jv-danger-text); color: var(--nu-on-accent);
}
.mx-btn--danger:disabled, .mx-btn--danger[aria-disabled="true"] {
  background: var(--jv-danger); border-color: var(--jv-danger); color: var(--nu-on-accent);
  opacity: var(--nu-op-disabled);
}

/* 조용한 것 - 표 줄마다 서는 단추. 빨강이 스무 번 서면 아무것도 안 읽힌다 */
.mx-btn--quiet { background: transparent; border-color: transparent; }
.mx-btn--quiet:hover { background: var(--jv-hover); border-color: transparent; }
.mx-btn--quiet:disabled, .mx-btn--quiet[aria-disabled="true"] { background: transparent; border-color: transparent; }
.mx-btn--danger.mx-btn--quiet { background: transparent; border-color: transparent; color: var(--jv-danger-text); }
.mx-btn--danger.mx-btn--quiet:hover { background: var(--jv-danger-light); border-color: var(--jv-danger); }

.mx-btn--link {
  background: transparent; border-color: transparent; color: var(--jv-primary-hover);
  min-height: 0; padding-left: 4px; padding-right: 4px;
}
.mx-btn--link:hover { background: transparent; border-color: transparent; text-decoration: underline; }

.mx-btn--xs {
  min-height: var(--mx-btn-xs-min-h); padding: var(--mx-btn-xs-pad-y) var(--mx-btn-xs-pad-x);
  font-size: var(--mx-btn-xs-font-size); border-radius: var(--mx-btn-xs-radius);
}
.mx-btn--sm {
  min-height: var(--mx-btn-sm-min-h); padding: var(--mx-btn-sm-pad-y) var(--mx-btn-sm-pad-x);
  font-size: var(--mx-btn-sm-font-size); border-radius: var(--mx-btn-sm-radius);
}
.mx-btn--lg {
  min-height: var(--mx-btn-lg-min-h); padding: var(--mx-btn-lg-pad-y) var(--mx-btn-lg-pad-x);
  font-size: var(--mx-btn-lg-font-size);
}

/* 아이콘 전용 - 정사각. 폭을 높이에 맞춰 두 값이 따로 놀지 않게 한다 */
.mx-btn--icon { padding-left: 0; padding-right: 0; width: var(--mx-btn-min-h); }
.mx-btn--xs.mx-btn--icon { width: var(--mx-btn-xs-min-h); }
.mx-btn--sm.mx-btn--icon { width: var(--mx-btn-sm-min-h); }
.mx-btn--lg.mx-btn--icon { width: var(--mx-btn-lg-min-h); }
.mx-btn--block { width: 100%; }

/* 붙은 묶음 - 같은 갈래의 동작. 테두리가 겹치지 않게 한 칸씩 당긴다 */
.mx-btn-group { display: inline-flex; }
.mx-btn-group > .mx-btn { border-radius: 0; margin-left: -1px; }
.mx-btn-group > .mx-btn:first-child {
  margin-left: 0;
  border-top-left-radius: var(--mx-btn-radius); border-bottom-left-radius: var(--mx-btn-radius);
}
.mx-btn-group > .mx-btn:last-child {
  border-top-right-radius: var(--mx-btn-radius); border-bottom-right-radius: var(--mx-btn-radius);
}
.mx-btn-group > .mx-btn:hover, .mx-btn-group > .mx-btn[aria-pressed="true"] { position: relative; z-index: 1; }

/* 택일 - 보기를 고르는 것. 고른 것은 바닥에서 떠오른다 */
.mx-seg {
  display: inline-flex; gap: 3px; padding: 3px;
  background: var(--nu-surface-2); border-radius: var(--mx-btn-radius);
}
.mx-seg > .mx-btn { background: transparent; border-color: transparent; color: var(--jv-txt3); }
.mx-seg > .mx-btn:hover { background: transparent; border-color: transparent; color: var(--jv-txt1); }
.mx-seg > .mx-btn[aria-pressed="true"] {
  background: var(--jv-card); border-color: transparent; color: var(--jv-txt1); box-shadow: var(--nu-elev-low);
}

/* 칩 - 켜고 끄는 것. 단추와 갈래가 다르다는 것을 모양(알약)이 말한다 */
.mx-chip {
  display: inline-flex; align-items: center; gap: 5px; box-sizing: border-box;
  padding: 5px 13px; border: 1px solid var(--jv-border-strong); border-radius: var(--nu-r-pill);
  background: var(--jv-card); color: var(--jv-txt2);
  font-family: inherit; font-size: var(--mx-btn-sm-font-size); font-weight: var(--mx-btn-weight);
  line-height: 1.25; white-space: nowrap; cursor: pointer;
  transition: background 0.12s, border-color 0.12s, color 0.12s;
}
.mx-chip:hover { border-color: var(--jv-primary); color: var(--jv-txt1); }
.mx-chip:focus-visible { outline: 2px solid var(--jv-primary); outline-offset: 1px; }
.mx-chip[aria-pressed="true"] {
  border-color: var(--jv-primary); background: var(--jv-primary-light); color: var(--nu-brand-text);
}
.mx-chip:disabled, .mx-chip[aria-disabled="true"] { color: var(--jv-txt4); cursor: not-allowed; }

@media (forced-colors: active) {
  /* 채움 · 그림자가 시스템 색으로 덮인다 - 고른 것을 **테두리 두께**로 말한다 */
  .mx-btn--primary, .mx-btn--danger { border-width: 2px; }
  /* 고른 택일 · 칩 - 테두리 색만 바꾸면 강조색이 회색인 대비 테마에서 안 보인다(2026-09-28 사용자 PC).
     탭(.mx-tabs .on)처럼 강조색으로 칠하고, 색과 무관한 ✓ 글자를 앞에 둔다 */
  .mx-seg > .mx-btn[aria-pressed="true"], .mx-chip[aria-pressed="true"] {
    forced-color-adjust: none; background: Highlight; color: HighlightText; border: 2px solid CanvasText; font-weight: 700;
  }
  .mx-seg > .mx-btn[aria-pressed="true"]::before, .mx-chip[aria-pressed="true"]::before { content: "✓ "; }
  .mx-btn--quiet, .mx-seg > .mx-btn { border-color: GrayText; }
}

/* §6-A 버튼(옛 이름) — 주요(프라이머리) / 보조(흰 배경 + 테두리).
   ★ 새 화면은 위 `.mx-btn` 을 쓴다. 아래는 옛 화면이 쓰는 이름이라 남겨 둔 것이고,
     화면별로 `.mx-btn` 으로 옮긴 뒤 걷는다(옮기는 표: 단추 구성안 3번). */
.primary-btn, .admin-btn-primary, .sched-blue-btn {
  background: var(--jv-primary); color: var(--nu-on-accent); border: none; border-radius: var(--nu-r-medium);
  font-weight: 600; transition: background 0.12s;
}
.primary-btn:hover, .admin-btn-primary:hover, .sched-blue-btn:hover { background: var(--jv-primary-hover); }
.simr-top-btn, .admin-btn-ghost {
  background: var(--jv-card); color: var(--jv-txt2); border: 1px solid var(--jv-border);
  border-radius: var(--nu-r-medium); transition: border-color 0.12s, color 0.12s;
}
.simr-top-btn:hover, .admin-btn-ghost:hover {
  background: var(--jv-card); border-color: var(--jv-primary-mid); color: var(--jv-primary);
}
.simr-top-btn:disabled, .sched-blue-btn:disabled, .primary-btn:disabled { opacity: 0.5; cursor: default; }

/* §6-B 입력 — 포커스는 outline이 아니라 연한 블루 테두리로 통일 */
input[type="text"], input[type="number"], input[type="password"], input[type="date"],
input[type="search"], select, textarea {
  border-radius: var(--nu-r-medium); border: 1px solid var(--jv-border); color: var(--jv-txt1);
  font-family: inherit; letter-spacing: -0.01em;
}
input:focus, select:focus, textarea:focus { outline: none; border-color: var(--jv-primary-mid); }
::placeholder { color: var(--jv-txt4); }

/* §6-F 탭 — 활성은 프라이머리 */
.inv-tab.active { color: var(--jv-primary); border-bottom-color: var(--jv-primary); }
.inv-tab { transition: color 0.12s; }

/* 표 — 헤더는 밝은 배경 + 진한 글자(토큰), 행 hover는 hover 토큰 */
thead th { font-weight: 600; }
.inv-grid tbody tr:hover, .inv-table tbody tr:hover, .demand-grid tbody tr:hover { background: var(--jv-hover); }

/* 다크 테마 시절 잔재 정리 */
.ed-photo-placeholder { background: linear-gradient(135deg, var(--jv-primary), var(--nu-primary-light)); }

/* 다크 네이비를 "채움"으로 쓰던 요소들 — 밝은 테마에서 흰 글자가 사라지므로 프라이머리로 전환 */
.inv-grid thead th, .demand-grid thead th {
  background: var(--jv-page); color: var(--jv-txt2); border-bottom: 1px solid var(--jv-border);
}
.demand-grid thead th.dm-weekend { background: var(--nu-surface-3); color: var(--jv-txt3); }
.demand-grid thead th.dm-total { background: var(--jv-warning-light); color: var(--jv-warning-text); }
.demand-grid tfoot td { background: var(--jv-page); color: var(--jv-txt1); border-top: 1px solid var(--jv-border); }
.demand-grid .dm-total { background: rgba(229,163,10,0.06); }
.demand-grid .dm-weekend { background: rgba(0,0,0,0.035); }
.demand-grid .dm-zero { color: var(--jv-txt4); }
.inv-color-chip { background: var(--jv-page); }
.sched-tab.active { background: var(--jv-primary); color: var(--nu-on-accent); border-color: var(--jv-primary); }
.ed-mbtn.active { background: var(--jv-primary); color: var(--nu-on-accent); border-color: var(--jv-primary); }
.ed-mbtn.active span { color: rgba(255,255,255,0.75); }

/* 서열계획 합계 행(sticky tfoot) — 주말·합계 열의 반투명 배경이 그대로면 아래 데이터 행이
   비쳐 글자가 겹쳐 보인다. sticky로 떠 있는 셀은 불투명 배경이어야 한다. */
.demand-grid tfoot td.dm-weekend { background: var(--nu-surface-2); }
.demand-grid tfoot td.dm-total   { background: var(--nu-warning-light-3); }
.demand-grid tfoot td { background: var(--jv-page); }

/* 짧은 창에서 차트 높이 추가 축소 — .viz-wrap 기본 정의보다 뒤에 와야 적용된다(CSS 순서) */
@media (max-height: 700px) {
  .viz-wrap { height: clamp(112px, 17vh, 200px); }
  .viz-wrap.viz-wrap-lg { height: clamp(120px, 19vh, 220px); }
}

/* ── 좌측 메뉴 압축 (전 화면) ──────────────────────────────────────────────
   ① 좌우 폭 240 → 180px (콘텐츠 60px 확보)  ② 상하 여백·항목 높이를 줄여
   1920×1080은 물론 브라우저 실제 뷰포트(약 937px)에서도 메뉴가 스크롤되지 않게 한다.
   ※ min-width 1201px 안에 둔다 — 좁은 화면에서는 사이드바가 드로어로 바뀌므로 그대로 둔다.

   ▣ 폭 예산 — 180px 는 아래 두 최장 줄이 들어가는 최소치에 여유 약 32px 를 둔 값이다.
     하위 항목  여백10 + 들여쓰기25 + "설비별 생산현황"(12.5px, 약 91) + 우여백10 + 여백10 ≈ 147px
     그룹 헤더  여백10 + 패딩10 + 아이콘16 + 갭7 + "생산 모니터링"(10.5px, 약 66)
                + 화살표14 + 우여백10 + 여백10 ≈ 143px
     더 긴 메뉴명을 추가하면 이 예산을 다시 재고 폭이나 --nav-sub-indent 를 조정할 것. */
@media (min-width: 1201px) {
  .app-shell { grid-template-columns: 180px 1fr; }
  .sidebar { padding: 11px 10px; gap: 8px; }
  /* 로고 영역 */
  .brand { gap: 9px; padding-bottom: 10px; }
  .brand-ci { height: 32px; }
  .brand span { font-size: 0.98rem; }

  /* ★ 높이 예산 — 관리자 로그인(8그룹 + 14항목 전부 표시)에서도 사이드바가
     스크롤되지 않아야 한다. 실측 기준 약 780px / 뷰포트 약 800px.
     항목 여백을 여기서 더 키우면 메뉴가 스크롤되기 시작한다(항목 padding 1px = 전체 28px,
     그룹 margin 1px = 전체 8px). 메뉴를 추가할 때는 이 예산을 다시 재 볼 것. */

  /* 항목 사이는 좁게(2px), 그룹 사이는 넓게(8px) — 여백만으로 묶음이 생긴다.
     이 대비가 이 메뉴의 가독성을 좌우한다. 둘을 같은 값으로 되돌리지 말 것. */
  .nav { gap: 2px; }
  .nav-group { gap: 2px; margin-top: 7px; }
  .nav > a + .nav-group { margin-top: 8px; }

  .nav a { padding: 5px 10px; font-size: 12.5px; }
  .nav-group > summary { padding: 4px 10px; font-size: 10.5px; }
  .nav-group .nav-sub { gap: 2px; }
  /* 들여쓰기는 --nav-sub-* 가 이미 정했다 — 여기서 다시 계산식을 쓰지 말 것.
     (예전에 이 줄이 padding-left 를 재선언해 두는 바람에 기본 규칙과 어긋났었다) */
  .nav-group .nav-sub a { font-size: 12.5px; }
}

/* 상단 바 제목 — "메뉴명 - 화면명"(서브 화면이 있을 때). 본문 제목 박스(hero)는 제거됨 */
.page-title .pt-menu { font-weight: 700; color: var(--jv-txt1); }
.page-title .pt-sep  { margin: 0 7px; color: var(--jv-txt4); font-weight: 400; }
.page-title .pt-view { font-weight: 600; color: var(--jv-txt3); }

/* ── 설비 상세현황 전용: 표 헤더(타이틀 줄) 강조 ──────────────────────────
   흰 카드·쿨그레이 배경과 구분되도록 프라이머리 톤을 얹고, 헤더 문구는 가운데 정렬한다.
   #layoutRoot.ed-page 로 스코프 — 같은 .inv-grid를 쓰는 다른 화면에는 영향이 없다. */
#layoutRoot.ed-page .inv-grid thead th,
#layoutRoot.ed-page .inv-grid thead th.inv-num {
  text-align: center;
  background: var(--nu-primary-tint);
  color: var(--nu-brand-text);
  font-weight: 700;
  border-bottom: 2px solid var(--jv-primary-mid);
}

/* 설비 상세현황 표 — 세로 구분선 + 데이터 유형별 정렬
   · 교대(주간/야간)처럼 값 형식·길이가 일정한 열은 가운데
   · 품번·품목명·차종 등 텍스트는 왼쪽, 수량은 오른쪽
   · 좌/우 정렬 셀은 세로 구분선에 글자가 붙지 않도록 안쪽 여백을 준다 */
#layoutRoot.ed-page .inv-grid th,
#layoutRoot.ed-page .inv-grid td { border-right: 1px solid var(--jv-border); }
#layoutRoot.ed-page .inv-grid th:last-child,
#layoutRoot.ed-page .inv-grid td:last-child { border-right: none; }
#layoutRoot.ed-page .inv-grid td.ed-al-c { text-align: center; }
#layoutRoot.ed-page .inv-grid td.ed-al-l { text-align: left;  padding-left: 14px; }
#layoutRoot.ed-page .inv-grid td.ed-al-r,
#layoutRoot.ed-page .inv-grid td.inv-num { text-align: right; padding-right: 14px; }
#layoutRoot.ed-page .inv-grid td.inv-empty { border-right: none; text-align: center; }
/* 헤더 줄은 배경이 파란 톤이라 회색 세로선이 묻힌다 → 한 단계 진한 블루로 */
#layoutRoot.ed-page .inv-grid thead th { border-right-color: var(--nu-primary-lightest); }

/* 표 밀도 — 글자 크기는 그대로 두고 행 안쪽 여백만 줄여 한 화면에 더 많은 행을 보여준다
   (행 높이 약 30px → 26px, 같은 높이에서 4~5행 더). */
#layoutRoot.ed-page .inv-grid thead th { padding: 6px 12px; }
#layoutRoot.ed-page .inv-grid tbody td { padding: 4px 10px; }
#layoutRoot.ed-page .inv-grid td.ed-al-l { padding-left: 12px; }
#layoutRoot.ed-page .inv-grid td.ed-al-r,
#layoutRoot.ed-page .inv-grid td.inv-num { padding-right: 12px; }

/* ═══════════════════════════════════════════════════════════════════════════
   표 공통 스타일 (전 화면) — 설비 상세현황에서 정한 규칙을 표가 있는 모든 화면에 적용
   ① 헤더(타이틀 줄): 가운데 정렬 + 프라이머리 톤 배경으로 강조
   ② 세로 구분선: 셀마다 우측 1px(마지막 열 제외)
   ③ 정렬: 숫자=오른쪽 · 길이가 일정한 짧은 코드=가운데 · 텍스트=왼쪽 (app.js가 열별 자동 판정)
   ④ 좌/우 정렬 셀은 구분선에 글자가 붙지 않도록 안쪽 여백
   ═══════════════════════════════════════════════════════════════════════════ */
.layout-root thead th {
  text-align: center;
  background: var(--nu-primary-tint);
  color: var(--nu-brand-text);
  font-weight: 700;
  border-bottom: 2px solid var(--jv-primary-mid);
  border-right: 1px solid var(--nu-primary-lightest);
}
.layout-root thead th:last-child { border-right: none; }
.layout-root tbody td { border-right: 1px solid var(--mx-line-col, var(--jv-border)); }   /* 칸 사이 선 - 모든 표(0.38.0) */
.layout-root tbody td:last-child { border-right: none; }

/* 열별 자동 판정 결과 (board-shell 의 applyTableAlignment · README 「표 공통 규칙」) */
.layout-root tbody td.tb-al-c { text-align: center; }
.layout-root tbody td.tb-al-l { text-align: left;  padding-left: 14px; }
.layout-root tbody td.tb-al-r { text-align: right; padding-right: 14px; }
/* 머리글도 값과 같은 쪽에 붙인다 - 여백까지 같이 맞춰야 글자 시작점이 값과 한 줄로 선다.
   ★ 위 `.layout-root thead th` 의 가운데보다 명시도가 높아야 이긴다(클래스 하나 더). cheil 만 제 CSS 에
     들고 있어서 autogen 손 표는 머리글이 가운데로 남았다. */
.layout-root thead th.tb-al-c { text-align: center; }
.layout-root thead th.tb-al-l { text-align: left;  padding-left: 14px; }
.layout-root thead th.tb-al-r { text-align: right; padding-right: 14px; }
/* 빈 상태 안내 행은 구분선·정렬 예외 */
.layout-root tbody td.inv-empty, .layout-root tbody td.dm-empty,
.layout-root tbody td[colspan] { border-right: none; text-align: center; }

/* 서열계획 — 주말·합계 열은 고유 배경을 유지(위 공통 헤더 배경보다 뒤에 와야 이긴다) */
.layout-root .demand-grid thead th.dm-weekend { background: var(--nu-surface-3); color: var(--jv-txt3); border-right-color: var(--nu-border-strong); }
.layout-root .demand-grid thead th.dm-total   { background: var(--jv-warning-light); color: var(--jv-warning-text); border-right-color: var(--nu-warning-border-2); }

/* ═══════════════════════════════════════════════════════════════════════════
   NuDS 정합 레이어 (DESIGN.md) — 색 토큰만으로는 안 바뀌는 "형태·상태" 규칙
   ★ 이 블록이 스타일시트 맨 끝이다. 앞선 규칙을 이기도록 마지막에 둔다.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── §Shapes 오블롱 — 액션과 라벨은 pill ──────────────────────────────────
   "Formas oblongas… buttons e chips frequentemente usando pill"(DESIGN.md).
   표 안쪽 셀 요소는 밀도 때문에 medium(8px)을 유지하고,
화면 레벨 액션만 pill로 간다. */
.primary-btn,
.admin-btn-primary,
.admin-btn-ghost,
.admin-btn-danger,
.sched-blue-btn,
.simr-top-btn,
.simr-confirm-btn,
.logout-btn,
.ed-mbtn,
.popup-btn-apply,
.popup-btn-cancel,
.popup-btn-del,
.popup-btn-xs,
.popup-btn-xs-red {
  border-radius: var(--nu-r-pill);
}
/* 배지·태그·램프 — 상태 라벨은 전부 pill */
.home-kri-badge, .inj-badge, .inj-step, .inj-lamp, .inj-sb-대기, .inj-sb-진행중,
.inj-sb-완료, .inj-sb-실패, .ep-card-badge, .util-badge, .inj-mode-수동,
.inj-mode-자동, .inj-mode-정지 {
  border-radius: var(--nu-r-pill);
}

/* ── §Accessibility 포커스 가시성 ────────────────────────────────────────
   NuDS는 "screen readers · text resizing · 대비 4.5:1"을 컴포넌트마다 요구한다.
   테두리 색만 바꾸는 포커스는 키보드 사용자에게 약하다 → 프라이머리 링을 함께 준다. */
input:focus-visible, select:focus-visible, textarea:focus-visible,
button:focus-visible, a:focus-visible, summary:focus-visible {
  outline: 2px solid var(--nu-primary);
  outline-offset: 2px;
  border-radius: var(--nu-r-small);
}
input:focus, select:focus, textarea:focus { border-color: var(--nu-primary); }

/* ── §Elevation 떠 있는 요소만 그림자 ────────────────────────────────────
   라이트 모드는 flat 기조(흰색 vs #F5F5F5 색 분리)로 두고,
   콘텐츠 위로 "떠 있는" 것에만 elevation을 준다. */
.popup-overlay, .sidebar-backdrop { background: rgba(0,0,0,var(--nu-op-scrim)); }
.popup-box { box-shadow: var(--nu-elev-high); border-radius: var(--nu-r-xxl); }
.sidebar.open { box-shadow: var(--nu-elev-highest); }

/* ── §Colors 브랜드 그라디언트 — 강조 배너 1곳에만 ───────────────────────
   "Purple is Nubank… 로 유일한 강한 색". KRI 총계 배너를 브랜드 면으로 세운다. */
#layoutRoot.home-fill .home-kri,
#layoutRoot .home-kri.kri-totals {
  background: var(--nu-gradient);
  box-shadow: var(--nu-elev-low);
}
/* 미연동(예시) 배너는 중성 회색 — 브랜드 면과 구분 */
#layoutRoot .home-kri.kri-mock { background: var(--nu-txt3); box-shadow: none; }

/* ── §Colors 상태색은 상태에만 ───────────────────────────────────────────
   좌측 컬러바 카드(.red/.yellow/.green/.blue-card)의 '파랑'은 상태가 아니라
   중립 정보였다 → 브랜드 퍼플로 바꿔 상태 3색(위험·주의·정상)과 섞이지 않게 한다. */
.red-card    { border-left: 5px solid var(--nu-alert); }
.yellow-card { border-left: 5px solid var(--nu-warning); }
.green-card  { border-left: 5px solid var(--nu-success); }
.blue-card   { border-left: 5px solid var(--nu-primary); }

/* ── §Components 비활성 상태 ─────────────────────────────────────────────*/
button:disabled, .primary-btn:disabled, .simr-top-btn:disabled,
.sched-blue-btn:disabled, .simr-confirm-btn:disabled {
  opacity: var(--nu-op-disabled);
  cursor: default;
}

/* ── 선택·스크롤바 — 브랜드 톤 ──────────────────────────────────────────*/
::selection { background: var(--nu-primary-lightest); color: var(--nu-txt1); }
::-webkit-scrollbar-thumb:hover,
.sidebar::-webkit-scrollbar-thumb:hover { background: var(--nu-primary); }

/* ═══════════════════════════════════════════════════════════════════════════
   사이트 관리 > 화면 테마
   ═══════════════════════════════════════════════════════════════════════════ */
.theme-panel { display: flex; flex-direction: column; gap: 16px; }
.theme-help {
  margin: 0; padding: 10px 14px; font-size: 0.86rem; line-height: 1.6;
  color: var(--nu-txt2); background: var(--nu-primary-tint);
  border: 1px solid var(--nu-primary-lightest); border-radius: var(--nu-r-medium);
}
.theme-help b { color: var(--nu-brand-text); }

.theme-grid {
  display: grid; gap: 12px;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
}
.theme-card {
  display: flex; flex-direction: column; gap: 8px; align-items: flex-start;
  padding: 14px; text-align: left; cursor: pointer;
  font-family: inherit; letter-spacing: -0.01em;
  background: var(--nu-card); color: var(--nu-txt1);
  border: 1px solid var(--nu-border); border-radius: var(--nu-r-large);
  transition: border-color 0.12s, box-shadow 0.12s, transform 0.12s;
}
.theme-card:hover { border-color: var(--nu-primary-lightest); transform: translateY(-1px); box-shadow: var(--nu-elev-low); }
.theme-card.selected { border-color: var(--nu-primary); box-shadow: 0 0 0 2px var(--nu-primary-tint); }

/* 색 견본 — 배경 / 강조배경 / 주색 3단. 톤의 성격이 한눈에 보이게 겹쳐 놓는다 */
.theme-card-sw { display: flex; align-items: center; }
.theme-card-sw i {
  width: 30px; height: 30px; border-radius: 50%;
  border: 2px solid var(--nu-card); box-shadow: 0 0 0 1px var(--nu-border);
}
.theme-card-sw i + i { margin-left: -10px; }

/* 사이트명 입력칸 — 이름이 스무 자쯤 들어가야 잘리지 않는다.
   theme-actions 가 flex 라 폭을 안 주면 내용만큼 줄어든다. */
.site-name-input { min-width: 260px; }

/* 로고 고르기 입력칸은 늘 감춰 둔다 — 브라우저마다 다르게 생긴 기본 위젯 대신
   옆의 [이미지 선택…] 버튼이 대신 눌러 준다. */
.brand-file { display: none; }

.theme-card-name { display: flex; align-items: center; gap: 6px; font-size: 0.98rem; font-weight: 700; }
/* '현재 적용' 배지는 저장된 톤에만 — 미리보기만 한 카드에는 뜨지 않는다 */
.theme-card-cur {
  display: none; padding: 1px 8px; border-radius: var(--nu-r-pill);
  font-size: 0.68rem; font-weight: 700;
  background: var(--nu-success-light); color: var(--nu-success-text);
}
.theme-card.is-saved .theme-card-cur { display: inline-block; }
.theme-card-desc { font-size: 0.78rem; line-height: 1.5; color: var(--nu-txt3); }

/* ── 로고 관리 ────────────────────────────────────────────────────────────
   로고는 밝은 사이드바와 검은 사이드바 양쪽에 놓인다 → 두 배경을 나란히 보여 준다.
   두 칸의 배경색은 토큰이 아니라 고정값이 맞다. "라이트 톤에서 어떻게 보이나"를
   확인하는 칸이 지금 톤을 따라가 버리면 확인 자체가 안 된다. */
.brand-preview-row { display: flex; flex-wrap: wrap; align-items: stretch; gap: 12px; }
.brand-preview {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px;
  min-width: 190px; padding: 18px 22px;
  border: 1px solid var(--nu-border); border-radius: var(--nu-r-large);
}
.brand-preview img { height: 46px; width: auto; max-width: 150px; object-fit: contain; }
.brand-preview em {
  font-style: normal; font-size: 0.72rem; font-weight: 600; letter-spacing: -0.01em;
}
.brand-preview-light { background: #FFFFFF; }
.brand-preview-light em { color: #6B7280; }
.brand-preview-dark  { background: #14161A; }
.brand-preview-dark  em { color: #97A1B0; }
.brand-current {
  display: flex; flex-direction: column; justify-content: center; gap: 4px;
  padding: 0 4px; font-size: 0.84rem; color: var(--nu-txt2);
}
.brand-current b { color: var(--nu-txt1); }
.brand-current-sub { font-size: 0.76rem; color: var(--nu-txt3); }

.theme-actions { display: flex; align-items: center; gap: 10px; }
.theme-msg { font-size: 0.82rem; font-weight: 600; color: var(--nu-txt3); }
.theme-msg.ok { color: var(--nu-success-text); }
.theme-msg.fail { color: var(--nu-alert-text); }

/* 차트 색 패널(0.34.0) - 값마다 흰 바탕 · 검은 바탕 색. 칸 바탕을 실제 바탕색으로 칠해 그 색이 그 바탕에서 어떻게 보이는지 바로 보인다.
   ★ 강제 색상(윈도우 고대비)에서도 칠해 둔다 - 이 판은 색을 고르는 곳이라 시스템이 색을 지우면 쓸 수가 없다 */
.chart-color-tabs { margin: 0; }
.chart-color-table { border-collapse: collapse; width: 100%; max-width: 760px; font-size: 13px; }
.chart-color-table th, .chart-color-table td { border-bottom: 1px solid var(--jv-border); padding: 6px 8px; text-align: left; vertical-align: middle; }
.chart-color-table th { font-size: 12.5px; font-weight: 600; color: var(--jv-txt2); }
.chart-color-table .c { text-align: center; }
.chart-color-alias { display: block; font-size: 11.5px; color: var(--jv-txt3); }
.chart-color-cell { forced-color-adjust: none; display: inline-flex; align-items: center; gap: 8px; padding: 4px 10px 4px 4px; border-radius: 6px; }
.chart-color-cell.is-light { background: #FFFFFF; color: #16181A; border: 1px solid #D0D4D8; }
.chart-color-cell.is-dark { background: #000000; color: #FFFFFF; border: 1px solid #FFFFFF; }
.chart-color-cell input[type="color"] { width: 36px; height: 24px; padding: 0; border: 0; background: none; cursor: pointer; }
.chart-color-cell code { font-family: ui-monospace, Consolas, monospace; font-size: 12px; }

.topbar { height: var(--topbar-h); }

.sidebar {
  padding: 0;
  gap: 0;
  overflow: hidden;   /* 스크롤은 .nav 가 맡는다 → 메뉴가 길어져도 로고 밴드는 제자리 */
}
.brand {
  height: var(--topbar-h);
  flex-shrink: 0;
  padding: 0 10px;
  border-bottom: 1px solid var(--jv-border);
}
.nav::-webkit-scrollbar { width: 5px; }
.nav::-webkit-scrollbar-track { background: transparent; }
.nav::-webkit-scrollbar-thumb { background: var(--nu-surface-4); border-radius: var(--nu-r-small); }
.nav::-webkit-scrollbar-thumb:hover { background: var(--nu-primary); }
.app-shell.nav-off > .sidebar { display: none; }
.nav-toggle-all:hover { background: var(--jv-hover); color: var(--jv-txt1); }
.nav-toggle-all svg { width: 16px; height: 16px; }
/* 펼쳐진 상태에서는 '모두 접기'만, 전부 접힌 상태에서는 '모두 펴기'만 보인다 */
.nav-toggle-all .nav-ico-expand { display: none; }
.nav-toggle-all.all-closed .nav-ico-collapse { display: none; }
.nav-toggle-all.all-closed .nav-ico-expand { display: block; }
.sim-video-time b { font-weight: 800; }
.sim-video-x:hover { background: var(--nu-hover); color: var(--nu-txt1); }

.sim-video-player {
  display: block; width: 100%; aspect-ratio: 16 / 9;
  background: var(--nu-surface-3);   /* 로딩 중 흰 판이 번쩍이지 않게 */
  object-fit: cover;
}
.sim-video-foot {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 8px 6px 11px;
  border-top: 1px solid var(--nu-border-l);
}
.sim-video-btn:hover { background: var(--nu-hover); color: var(--nu-txt1); }

@media (max-width: 900px) {
  .sim-video-ov { padding: 10px; }
  .sim-video-box { width: 390px; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   두 보드가 같아진 셸 규칙
   ───────────────────────────────────────────────────────────────────────────
   화면 규칙을 가른 뒤 양쪽 프로젝트 파일에 **값까지 똑같이** 남아 있던 것들이다.
   규칙 단위로 견줘 확인하고 올렸다.

   ★ 홈 대시보드 높이 맞춤(#layoutRoot.home-fill 계열)은 양쪽에 같은 규칙이 있어도
     올리지 않았다. 형제 규칙들이 같은 명시도로 얽혀 있어서, 이 파일로 옮기면 순서가
     앞당겨져 프로젝트 파일에서 그 앞에 있던 규칙에 진다.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── 좌측 메뉴 접기 — 본문을 화면 전체로 ───────────────────────────────────
   상단 바의 메뉴 단추로 여닫는다. 격자 열과 사이드바를 한 클래스로 동시에 끈다.
   ★ 클래스 2개(0,2,0)라 @media 안의 .app-shell(0,1,0)보다 강하다 — 반응형 규칙이
     뒤에 오든 앞에 오든 이긴다. 그래서 미디어쿼리마다 복사할 필요가 없다.
   ※ 좁은 화면(1200px 이하)에서는 사이드바가 이미 드로어라 이 클래스를 쓰지 않는다.
   전환 애니메이션은 두지 않는다. 폭이 바뀌는 동안 차트가 매 프레임 리사이즈되면
   1920x1080 무스크롤 화면에서 눈에 보이게 버벅인다. */
.app-shell.nav-off { grid-template-columns: 1fr; }

/* ── 메뉴 그룹 일괄 접기/펴기 단추 ─────────────────────────────────────────
   로고 밴드 오른쪽 끝(margin-left: auto)에 붙는다. 44px 밴드 안에 들어가야 하므로
   단추 24px / 아이콘 16px. 아이콘은 둘을 넣어 두고 상태에 따라 하나만 보여준다 —
   innerHTML 을 갈아치우면 SVG 를 문자열로 들고 있어야 해서 HTML 쪽 아이콘 관리
   방식과 어긋난다. */
.nav-toggle-all {
  margin-left: auto;
  flex-shrink: 0;
  width: 24px;
  height: 24px;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: var(--nu-r-medium);
  background: transparent;
  color: var(--jv-txt3);
  cursor: pointer;
  transition: background 0.12s, color 0.12s;
}

/* ── 접어 둔 유의사항의 요약 줄 ────────────────────────────────────────────
   닫힘 상태는 알약 한 줄(약 26px)이다. 앞뒤 표식(::before ::after)은 화면마다 글자가
   달라 프로젝트 몫으로 둔다 — 여기 있는 것은 알약 자체와 hover 뿐이다. */
.data-note > summary { list-style: none; cursor: pointer; display: inline-flex;
  align-items: center; gap: 5px; padding: 2px 10px 2px 8px;
  font-size: 0.72rem; font-weight: 600; color: var(--nu-txt3);
  background: var(--nu-surface-2); border: 1px solid var(--nu-border-l);
  border-radius: var(--nu-r-pill); user-select: none; }
.data-note > summary::-webkit-details-marker { display: none; }
.data-note > summary:hover { color: var(--nu-txt2); border-color: var(--nu-border); }

/* 수행 중 표시 점. 깜빡임은 아래 keyframes 가 맡는다 — 그 이름을 쓰는 곳이 보드마다
   더 있으므로(진행 중 상태 글자 등) 규칙과 함께 여기 둔다. */
.sim-video-dot {
  width: 7px; height: 7px; border-radius: var(--nu-r-pill); flex: none;
  background: var(--nu-primary);
  animation: simVideoPulse 1.2s ease-in-out infinite;
}
@keyframes simVideoPulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.25; } }

/* 상단 바 화면 톤 선택기. 시계·사용자 칩과 같은 줄에 선다.
   상태는 theme-override.js 가 들고 있으므로 위젯 규칙도 여기가 맞다 — 다만 **고르는
   UI 를 어디에 어떻게 놓을지는 프로젝트가 정한다.**
   네이티브 <select> 라 강제 색상 모드에서는 시스템이 알아서 테두리를 그린다.
   그래서 forced-colors 블록에 따로 넣지 않았다. */
.theme-pick {
  height: 28px; padding: 0 6px; font-size: 0.78rem; font-family: inherit;
  color: var(--nu-txt2); background: var(--nu-card);
  border: 1px solid var(--nu-border-l); border-radius: var(--nu-r-medium);
  cursor: pointer; max-width: 168px;
}
.theme-pick:hover { border-color: var(--nu-border); }

/* 권한이 정해지기 전에는 관리 메뉴를 감춘다.

   /api/me 가 돌아오기 전 한 번 번쩍이는 것을 막는 장치다. 종전에는 마크업에
   style="display:none" 을 박아 두었는데, CSP 의 style-src 를 켜려면 style= 속성이
   없어야 해서 클래스로 옮겼다.

   ★ 감추는 일을 클래스가 계속 맡으면 안 된다. admin-screens.js 는 링크마다
     link.style.display = '' 로 여는데, 클래스 규칙이 남아 있으면 그 '' 가 아무것도
     못 연다(인라인이 비면 클래스가 다시 이긴다). 그래서 권한을 다 칠한 뒤
     body 에서 이 클래스를 뗀다 — 그 뒤로는 CSSOM 이 혼자 정한다. */
.nav-auth-pending .admin-only,
.nav-auth-pending .super-only { display: none; }

/* ── 공용 표 부품 (grid.js) ────────────────────────────────────────────────
   색을 직접 쓰지 않는다 — 전부 토큰이라 톤을 바꾸면 표도 따라간다.
   상태를 색으로만 알리지 않는 규칙이 여기도 걸린다: 정렬 방향은 화살표가 아니라
   글자('오름'·'내림')로 적고, 고정 컬럼은 체크박스를 끄는 것에 더해 (고정)이라 쓴다. */
.mx-grid { display: flex; flex-direction: column; min-height: 0; }
/* 떠 보이기 한 벌(0.38.0) - 화면 바탕 위에 바로 놓인 그리드는 흰 상자로 뜬다(목록 화면은 바깥 상자 없이 바탕 위에 그리드만 있다).
   ★ 상자(카드 · 사이트 판) 안에 든 그리드는 그 상자가 --mx-grid-lift: none · --mx-grid-edge: transparent 를 물려줘 두 번 뜨지 않는다 -
     상자 이름을 여기 적지 않는다(사이트 클래스와 겹치지 않게). 사이트 상자는 제 CSS 에서 두 값을 준다(.mx-surface 도 된다) */
.mx-grid { background: var(--jv-card, var(--nu-card)); border: 1px solid var(--mx-grid-edge, var(--nu-border));
  border-radius: var(--nu-r-small); box-shadow: var(--mx-grid-lift, var(--mx-lift)); }
.mx-card, .widget-panel, .mx-surface { --mx-grid-lift: none; --mx-grid-edge: transparent; --mx-grid-bar-pad: 0 0 6px 0; }
/* 사이트가 제 상자에 달아 쓰는 한 벌 - 흰 바탕 · 테두리 · 두 겹 그림자 */
.mx-surface { background: var(--jv-card, var(--nu-card)); border: 1px solid var(--nu-border); box-shadow: var(--mx-lift); }

/* 단추 줄 - 테두리를 두른 표는 테두리에서 위 · 오른쪽 6px 띄운다(0.43.0, 정호님 10-07 - 0px 로 붙어 있었다).
   상자 안에 든 표(테두리를 지운 표)는 상자가 안쪽 여백을 가지므로 그 상자가 --mx-grid-bar-pad 를 0 으로 물려준다 -
   사이트 상자도 --mx-grid-edge: transparent 와 같은 자리에서 준다 */
.mx-grid-bar {
  position: relative; display: flex; justify-content: flex-end; gap: 6px;
  padding: var(--mx-grid-bar-pad, 6px 6px 6px 0);
}
.mx-grid-btn {
  height: 28px; padding: 0 10px; font-size: 0.78rem; font-family: inherit;
  color: var(--nu-txt2); background: var(--nu-card);
  border: 1px solid var(--nu-border); border-radius: var(--nu-r-medium);
  cursor: pointer;
}
.mx-grid-btn:hover { border-color: var(--nu-border-strong); }

.mx-grid-wrap { overflow: auto; min-height: 0; }
.mx-grid-table { width: 100%; border-collapse: collapse; font-size: 0.82rem; }
.mx-grid-table th,
.mx-grid-table td {
  padding: 6px 8px; border-bottom: 1px solid var(--mx-line-row, var(--nu-border-l));   /* 표 선(0.38.0 - --mx-line-*) */
  white-space: nowrap;
}
.mx-grid-table thead th {
  position: sticky; top: 0; z-index: 1;
  background: var(--nu-primary-tint); color: var(--nu-txt1);
  font-weight: 600; text-align: center;
  border-bottom: 1px solid var(--mx-line-head, var(--nu-border));   /* 머리 아래는 본문 선보다 한 단계 더(0.38.0) */
}
/* 행 번호 — 몇 번째 줄인지 세지 않아도 되게. 좁게 두고 눈에 덜 띄게 한다 */
.mx-grid-no {
  width: 44px; text-align: right; color: var(--nu-txt3);
  font-variant-numeric: tabular-nums;
}
/* ★ 행 번호 머리글(#)도 값과 같은 오른쪽 - 위 `.mx-grid-table thead th` 의 가운데에 명시도로 밀리지 않게
     표 클래스를 앞에 붙인다(칸 정렬과 같은 까닭). */
.mx-grid-table th.mx-grid-no { text-align: right; }
/* 칸 정렬 - 컬럼 정의(kind · align)가 머리글과 값에 같은 클래스를 단다.
   ★ **머리글도 이 규칙을 따라야 한다.** 전에는 `.mx-grid-td-left, .mx-grid-th-left` 로 적어 명시도가
     클래스 하나였고, 위 `.mx-grid-table thead th`(클래스 하나 + 요소 둘)의 가운데에 밀려 **머리글이
     늘 가운데**였다 - 값만 오른쪽 · 왼쪽으로 가서 칸마다 제각각으로 보였다(0.14.0 ~ 0.23.2).
     표 클래스를 앞에 붙여 클래스 둘로 올린다. tests/table-align-css.test.js 가 명시도를 잰다. */
.mx-grid-table th.mx-grid-th-left,   .mx-grid-table td.mx-grid-td-left   { text-align: left; }
.mx-grid-table th.mx-grid-th-center, .mx-grid-table td.mx-grid-td-center { text-align: center; }
/* 숫자 칸은 자릿수가 흔들리지 않게 고정폭 숫자로 */
.mx-grid-table th.mx-grid-th-right,  .mx-grid-table td.mx-grid-td-right  { text-align: right; font-variant-numeric: tabular-nums; }

.mx-grid-sortable { cursor: pointer; user-select: none; }
.mx-grid-sortable:hover { background: var(--nu-primary-tint-2); }
.mx-grid-sorted { background: var(--nu-primary-tint-2); }
.mx-grid-dir { margin-left: 4px; font-size: 0.72rem; color: var(--nu-brand-text); }
/* 칼럼 폭 손잡이(0.39.0, grid.js bindResize) - 머리글 오른쪽 가장자리. 손을 올리거나 들어가야 선이 보인다.
   머리글이 sticky 라 그 안에서 자리를 잡는다. 표 밖으로 안 내민다 - 마지막 칸에서 가로 스크롤이 생긴다 */
.mx-grid-resize { position: absolute; top: 0; right: 0; bottom: 0; width: 7px; cursor: col-resize; touch-action: none; z-index: 2; }
.mx-grid-resize::after { content: ""; position: absolute; top: 20%; bottom: 20%; right: 2px; width: 2px; border-radius: 1px; background: transparent; }
.mx-grid-table thead th:hover > .mx-grid-resize::after { background: var(--nu-border-strong); }
.mx-grid-resize:hover::after,
.mx-grid-resize:focus-visible::after,
.mx-grid-resizing > .mx-grid-resize::after { top: 0; bottom: 0; background: var(--nu-brand-text); }
.mx-grid-resize:focus-visible { outline: none; }
.mx-grid-resizing { user-select: none; }

.mx-grid-table tbody tr:hover { background: var(--nu-surface-2); }
.mx-grid-clickable { cursor: pointer; }

/* 묶음 머리 줄 (0.26.1) - 이름 칸과 묶음 값. 배경만으로 가르지 않는다(고대비에서 사라진다) -
   위아래 굵은 선과 굵은 글자가 「여기서 묶음이 바뀐다」를 말한다 */
.mx-grid-table tbody tr.mx-grid-group > td {
  background: var(--nu-surface-2); font-weight: 600;
  border-top: 2px solid var(--nu-border); border-bottom: 1px solid var(--nu-border);
}
.mx-grid-table tbody tr.mx-grid-group:hover { background: var(--nu-surface-2); }
/* ★ 선택자를 한 단 올린다 - 사이트 CSS 의 빈 표 안내 규칙(autogen `.layout-root tbody td[colspan]` 0,2,2)이 합친 칸을 가운데로 끌었다 */
.mx-grid-table tbody tr.mx-grid-group > td.mx-grid-group-label { text-align: left; color: var(--nu-txt1); }

/* 행 상세 줄 (0.28.5) - 펼친 줄 바로 아래 전체 폭. 배경이 아니라 왼쪽 굵은 선이 「위 줄의 풀이」를 말한다(고대비에서 남는다).
   ★ 선택자를 묶음 줄처럼 한 단 올린다 - 사이트의 `td[colspan]` 가운데 규칙이 합친 칸을 끌지 않게 */
.mx-grid-table tbody tr.mx-grid-detail > td.mx-grid-detail-td {
  text-align: left; padding: 8px 12px 10px; border-left: 3px solid var(--nu-primary); white-space: normal;
}
.mx-grid-table tbody tr.mx-grid-detail:hover { background: transparent; }

/* 줄 끌어 옮기기 — 놓일 자리를 **선으로** 그린다. 색만 바꾸면 고대비에서 사라지고,
   줄 하나가 통째로 물드는 것보다 경계선이 「여기 사이」를 정확히 말한다.
   선은 테두리로 그린다(바깥 요소가 아니라) — tbody 안에 칸을 더하면 표가 흔들린다. */
.mx-grid-draggable { cursor: grab; }
.mx-grid-row-dragging { opacity: 0.4; cursor: grabbing; }
.mx-grid-drop-before > td { box-shadow: inset 0 2px 0 0 var(--nu-brand-text); }
.mx-grid-drop-after  > td { box-shadow: inset 0 -2px 0 0 var(--nu-brand-text); }

/* 바 왼쪽 안내 — 단추들이 오른쪽에 몰려 있으므로 남은 자리를 차지한다 */
.mx-grid-note {
  margin-right: auto; align-self: center;
  font-size: 0.72rem; color: var(--nu-txt3);
}

.mx-grid-empty, .mx-grid-loading, .mx-grid-error {
  padding: 24px 8px; text-align: center; color: var(--nu-txt3); font-size: 0.82rem;
}
.mx-grid-error { color: var(--nu-alert-text); }

/* 컬럼 메뉴 — 단추 바로 아래 붙는다 */
.mx-grid-menu {
  position: absolute; top: 30px; right: 0; z-index: 20; width: 260px;
  background: var(--nu-card); border: 1px solid var(--nu-border);
  border-radius: var(--nu-r-medium); box-shadow: var(--nu-elev-medium);
}
.mx-grid-menu-list { max-height: 320px; overflow: auto; padding: 6px; }
.mx-grid-menu-item {
  display: flex; align-items: center; justify-content: space-between; gap: 6px;
  padding: 4px 6px; border-radius: var(--nu-r-small); font-size: 0.8rem;
}
.mx-grid-menu-item:hover { background: var(--nu-surface-2); }
.mx-grid-menu-item label { display: flex; align-items: center; gap: 6px; cursor: pointer; }
.mx-grid-dragging { opacity: 0.5; }
.mx-grid-menu-move { display: flex; gap: 2px; }
.mx-grid-menu-arrow {
  font-size: 0.68rem; font-family: inherit; padding: 1px 4px;
  color: var(--nu-txt2); background: var(--nu-surface-2);
  border: 1px solid var(--nu-border-l); border-radius: var(--nu-r-small); cursor: pointer;
}
.mx-grid-menu-arrow:disabled { opacity: 0.4; cursor: default; }
.mx-grid-menu-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 6px;
  padding: 6px; border-top: 1px solid var(--nu-border-l);
}
.mx-grid-menu-note { font-size: 0.72rem; color: var(--nu-txt3); }

/* ── 고리가 0 에서 제 값까지 쓸리기 (SVG) ─────────────────────────────────
   처음 그릴 때 고리·원 채움이 12시에서 시계 방향으로 쓸린다. Chart.js 막대·선이
   바닥에서 솟는 것(board-shell.js)과 같은 박자다.

   ★ **마크업 규약** — 이 클래스는 아래를 전제한다. 안 지키면 오류 없이 엉뚱하게 돈다.
       <circle class="ring-sweep" pathLength="100"
               stroke-dasharray="100" stroke-dashoffset="100*(1-채운몫)" />
     `pathLength="100"` 으로 **자를 통일한다.** 반지름이 달라 둘레가 달라도 0~100 한
     자로 돌아 키프레임 하나가 다 먹는다. 12시 출발은 그리는 쪽이 돌린다
     (`transform="rotate(-90 cx cy)"` 또는 svg 에 CSS 회전).
   ★ 끝값을 키프레임에 안 적는다 - 요소에 적힌 dashoffset 이 곧 끝이라, 값이 바뀌어도
     여기를 손댈 일이 없다.
   ★ 가운데를 꽉 채운 원도 **면이 아니라 선으로** 그린다(r = 반지름/2, stroke-width =
     반지름). 면으로 그린 조각은 각도를 CSS 로 못 움직인다.
   ★ 차례를 늦추는 것(바깥 고리부터)은 화면이 `animation-delay` 로 준다. 그 규칙은
     이 클래스보다 선택자가 같거나 높아야 한다.
   ★ 움직임을 줄이라고 한 사람에게는 끝 모습만 바로 보여 준다. 화면이 `animation`
     묶음 속성을 더 높은 선택자로 다시 적으면 이 끄기를 이기므로, 늦추기는 낱 속성으로만. */
@keyframes ringSweep { from { stroke-dashoffset: 100; } }
.ring-sweep { animation: ringSweep 850ms cubic-bezier(.22, .61, .36, 1) both; }
@media (prefers-reduced-motion: reduce) {
  .ring-sweep { animation: none; }
}

/* ── 제작사 표기 푸터 ─────────────────────────────────────────
   화면 아래에 만든 곳을 남긴다. 데스크톱 앱(WPF·WinForms)이 쓰는 모양 그대로다 -
   왼쪽에 로고와 저작권, 오른쪽에 판 번호. 두 벌이 되면 어느 것이 맞는지 모르게 된다.

   ★ 고객사 CI 와 층이 다르다. 고객사 로고는 사이드바·로그인 화면에 크게 있고,
     우리 표기는 여기에만 작게 둔다. 크기가 비슷해지면 그때부터 문제가 된다.

   ★ 판 번호가 이 푸터의 실질적 값어치다. 지원 문의 때 「어느 판을 보고 계십니까」가
     그 자리에서 풀린다. */
.vendor-footer {
  display: flex; align-items: center; gap: 10px;
  padding: 6px 14px;
  border-top: 1px solid var(--nu-border-l);
  background: var(--nu-surface-2, var(--nu-card));
  color: var(--nu-txt2);
  font-size: 0.72rem;
}
/* 로고는 인라인 SVG 이고 **글자색을 따른다**(0.35.4). 흰 상자를 얹던 PNG 는 줄이면 뭉개졌다.
   높이 12px 가 글자 몸 전체다 - PNG 는 위아래 여백까지 16px 이라 글자는 7px 남짓이었다.
   ★ 고대비에서 색을 **못박는다** - 크롬은 SVG 에 직접 준 color 를 시스템 색으로 안 바꾼다(부모에게서 물려받은 것만 바꾼다).
     안 적었더니 검은 바탕에 검은 로고가 됐다(0.35.4 전 개발판 실화면 계산값 rgb(17,24,39)). 아래 forced-colors 절. */
.vendor-footer__logo {
  height: 12px; width: auto; flex: none; display: block;
  color: var(--nu-txt1, currentColor);
}
.vendor-footer__copy { white-space: nowrap; }
/* 판 번호는 오른쪽 끝. 자리수가 바뀌어도 안 흔들리게 숫자 폭을 고정한다 */
.vendor-footer__ver {
  margin-left: auto; font-variant-numeric: tabular-nums;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* 좁은 화면에서는 저작권 문구가 먼저 접힌다 - 판 번호가 더 쓸모 있다 */
@media (max-width: 560px) {
  .vendor-footer__copy { overflow: hidden; text-overflow: ellipsis; }
}

@media (forced-colors: active) {
  /* 배경으로 그린 경계는 시스템이 지운다 */
  .vendor-footer { border-top-color: CanvasText; }
  .vendor-footer__logo { color: CanvasText; }
}

/* 제작사 표기 스위치 (사이트 설정) */
.vendor-toggle {
  display: flex; align-items: center; gap: 8px;
  margin: 10px 0; cursor: pointer;
}

/* ── 피벗 표 (0.29.0 · 0.30.0, pivot.js) - 품목 줄 × 날짜 칸 ────────────────────────────
   서열계획 조회(오토젠 demand-seq)의 표 규칙을 꾸러미로 올린 것이다 - 합계까지 고정 · 주말 파랑 · 공휴일 빨강 · 휴가 보라 ·
   고대비는 그 칸만 우리 색.
   ★ 선택자는 `.mx-pv .mx-pv-tb` 로 두 단 - 사이트 CSS(`.layout-root td` · `.layout-root tbody td[colspan]`)에 밀리지 않게.
   ★ 자리 · 폭 · 머리 높이는 pivot.js 가 표에 싣는 CSS 변수다(CSP 가 style 속성을 막는다).
   ★ 고대비 절은 이 블록 맨 끝이다 - 앞에 두면 평상시 규칙이 이긴다. */
.mx-pv { --mx-pv-card: var(--jv-card, var(--nu-card)); --mx-pv-wk: var(--jv-info-light); --mx-pv-hol: var(--jv-danger-light);
  --mx-pv-vac: var(--jv-violet-light); --mx-pv-edge: var(--jv-primary-mid, var(--nu-primary));
  position: relative; display: flex; flex-direction: column; min-height: 0; min-width: 0; }
/* 단추 줄은 공용 그리드 것(.mx-grid-bar · .mx-grid-btn · .mx-grid-menu)을 그대로 쓴다 - 두 부품이 한 모양 */
.mx-pv-body { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.mx-pv-wrap { flex: 1; min-height: 120px; overflow: auto; border: 1px solid var(--mx-grid-edge, var(--nu-border)); border-radius: var(--nu-r-medium, 6px);
  background: var(--mx-pv-card); box-shadow: var(--mx-grid-lift, var(--mx-lift)); }   /* 그리드와 같은 떠 보이기(0.38.0) */
.mx-pv .mx-pv-tb { border-collapse: separate; border-spacing: 0; width: max-content; font-size: 12.5px; font-variant-numeric: tabular-nums; }
.mx-pv .mx-pv-tb th, .mx-pv .mx-pv-tb td { height: 28px; padding: 0 7px; white-space: nowrap; border-bottom: 1px solid var(--mx-line-col, var(--nu-border)); border-right: 1px solid var(--mx-line-col, var(--nu-border)); }
.mx-pv .mx-pv-tb tbody td { background: var(--mx-pv-card); }
.mx-pv .mx-pv-tb thead th { position: sticky; top: 0; z-index: 2; font-weight: 700; text-align: center;
  background: linear-gradient(var(--nu-primary-tint), var(--nu-primary-tint)), var(--mx-pv-card); }
.mx-pv .mx-pv-tb thead tr.mx-pv-h2 th { top: var(--mx-pv-h1, 26px); }
.mx-pv .mx-pv-tb thead tr.mx-pv-h3 th { top: var(--mx-pv-h2, 52px); font-size: 11.5px; font-weight: 600; }
.mx-pv .mx-pv-tb thead th.mx-pv-band { font-size: 11.5px; font-weight: 600; color: var(--nu-txt2); height: 24px; text-align: left; }
/* 묶음 이름은 고정 칸 끝 · 화면 오른쪽 끝 사이에 머문다 - 한 묶음이 화면보다 넓어도 글자가 보인다.
   사이트가 머리글을 가운데로 묶어도(오토젠 styles-project.css) 같이 먹는다 */
.mx-pv-tb .mx-pv-bandt { display: inline-block; position: sticky; left: calc(var(--mx-pv-fzw, 0px) + 8px); right: 8px; }
.mx-pv .mx-pv-tb tfoot td { position: sticky; bottom: 0; z-index: 2; font-weight: 700;
  background: linear-gradient(var(--nu-surface-2), var(--nu-surface-2)), var(--mx-pv-card); border-top: 2px solid var(--nu-border-strong); }
/* 합계 줄이 여럿이면 아래 줄부터 쌓는다 - 맨 아래가 b0 */
.mx-pv .mx-pv-tb tfoot tr.mx-pv-b1 > td { bottom: var(--mx-pv-b1, 29px); }
.mx-pv .mx-pv-tb tfoot tr.mx-pv-b2 > td { bottom: var(--mx-pv-b2, 58px); }
.mx-pv .mx-pv-tb tfoot tr.mx-pv-b3 > td { bottom: var(--mx-pv-b3, 87px); }
.mx-pv .mx-pv-tb tbody tr.mx-pv-grp > td { font-weight: 700; background: linear-gradient(var(--nu-surface-2), var(--nu-surface-2)), var(--mx-pv-card);
  border-top: 2px solid var(--nu-border); }
.mx-pv .mx-pv-tb tbody tr.mx-pv-l1 > td { border-top: 1px dashed var(--nu-border); }

/* 고정 칸 */
.mx-pv .mx-pv-tb .mx-pv-fz { position: sticky; z-index: 1; overflow: hidden; text-overflow: ellipsis; }
.mx-pv .mx-pv-tb thead .mx-pv-fz, .mx-pv .mx-pv-tb tfoot .mx-pv-fz, .mx-pv .mx-pv-tb tr.mx-pv-grp .mx-pv-fz { z-index: 3; }
.mx-pv-tb .mx-pv-fzi0 { left: var(--mx-pv-l0, 0px); width: var(--mx-pv-w0, 80px); min-width: var(--mx-pv-w0, 80px); max-width: var(--mx-pv-w0, 80px); }
.mx-pv-tb .mx-pv-fzi1 { left: var(--mx-pv-l1, 0px); width: var(--mx-pv-w1, 80px); min-width: var(--mx-pv-w1, 80px); max-width: var(--mx-pv-w1, 80px); }
.mx-pv-tb .mx-pv-fzi2 { left: var(--mx-pv-l2, 0px); width: var(--mx-pv-w2, 80px); min-width: var(--mx-pv-w2, 80px); max-width: var(--mx-pv-w2, 80px); }
.mx-pv-tb .mx-pv-fzi3 { left: var(--mx-pv-l3, 0px); width: var(--mx-pv-w3, 80px); min-width: var(--mx-pv-w3, 80px); max-width: var(--mx-pv-w3, 80px); }
.mx-pv-tb .mx-pv-fzi4 { left: var(--mx-pv-l4, 0px); width: var(--mx-pv-w4, 80px); min-width: var(--mx-pv-w4, 80px); max-width: var(--mx-pv-w4, 80px); }
.mx-pv-tb .mx-pv-fzi5 { left: var(--mx-pv-l5, 0px); width: var(--mx-pv-w5, 80px); min-width: var(--mx-pv-w5, 80px); max-width: var(--mx-pv-w5, 80px); }
.mx-pv-tb .mx-pv-fzi6 { left: var(--mx-pv-l6, 0px); width: var(--mx-pv-w6, 80px); min-width: var(--mx-pv-w6, 80px); max-width: var(--mx-pv-w6, 80px); }
.mx-pv-tb .mx-pv-fzi7 { left: var(--mx-pv-l7, 0px); width: var(--mx-pv-w7, 80px); min-width: var(--mx-pv-w7, 80px); max-width: var(--mx-pv-w7, 80px); }
.mx-pv-tb .mx-pv-fzi8 { left: var(--mx-pv-l8, 0px); width: var(--mx-pv-w8, 80px); min-width: var(--mx-pv-w8, 80px); max-width: var(--mx-pv-w8, 80px); }
.mx-pv-tb .mx-pv-fzi9 { left: var(--mx-pv-l9, 0px); width: var(--mx-pv-w9, 80px); min-width: var(--mx-pv-w9, 80px); max-width: var(--mx-pv-w9, 80px); }
.mx-pv-tb .mx-pv-fzi10 { left: var(--mx-pv-l10, 0px); width: var(--mx-pv-w10, 80px); min-width: var(--mx-pv-w10, 80px); max-width: var(--mx-pv-w10, 80px); }
.mx-pv-tb .mx-pv-fzi11 { left: var(--mx-pv-l11, 0px); width: var(--mx-pv-w11, 80px); min-width: var(--mx-pv-w11, 80px); max-width: var(--mx-pv-w11, 80px); }
.mx-pv-tb .mx-pv-fzi12 { left: var(--mx-pv-l12, 0px); width: var(--mx-pv-w12, 80px); min-width: var(--mx-pv-w12, 80px); max-width: var(--mx-pv-w12, 80px); }
.mx-pv-tb .mx-pv-fzlabel { left: 0; width: var(--mx-pv-wlabel, 0px); min-width: var(--mx-pv-wlabel, 0px); max-width: var(--mx-pv-wlabel, 0px); }
/* ★ 합친 이름 칸은 왼쪽 - 사이트의 `.layout-root tbody td[colspan]` 가운데 규칙보다 한 단 위 */
.mx-pv .mx-pv-tb tbody tr > td.mx-pv-fzlabel, .mx-pv .mx-pv-tb tfoot tr > td.mx-pv-fzlabel { text-align: left; }
.mx-pv .mx-pv-tb tbody td.mx-pv-fzi0 { color: var(--nu-txt3); font-size: 11.5px; }
.mx-pv .mx-pv-tb .mx-pv-sumc { background: linear-gradient(var(--nu-primary-tint), var(--nu-primary-tint)), var(--mx-pv-card); font-weight: 700; }
.mx-pv .mx-pv-tb .mx-pv-edge { border-right: 2px solid var(--mx-pv-edge); }
.mx-pv .mx-pv-tb th.mx-pv-sortable { cursor: pointer; user-select: none; }
.mx-pv-dir { margin-left: 4px; font-size: 0.72rem; color: var(--nu-brand-text); }

/* 날짜 머리 · 칸 */
.mx-pv .mx-pv-tb th.mx-pv-day { min-width: 46px; }
/* 날짜(하위) 칸은 한 폭 - pivot.js 가 머리 셋째 줄 표시(.mx-pv-mk)를 뺀 가장 넓은 날짜 칸을 재서 --mx-pv-dw 로 싣는다.
   표시는 그 폭 안에서 줄을 바꾼다(공휴일 이름이 길어도 칸이 안 넓어진다) */
.mx-pv-tb.mx-pv-measure .mx-pv-mk { display: none; }
.mx-pv-tb.mx-pv-even .mx-pv-mk { white-space: normal; word-break: keep-all; overflow-wrap: anywhere; }
.mx-pv .mx-pv-tb.mx-pv-even td.mx-pv-v, .mx-pv .mx-pv-tb.mx-pv-even th.mx-pv-sub, .mx-pv .mx-pv-tb.mx-pv-even th.mx-pv-day:not([colspan]) {
  width: var(--mx-pv-dw, 46px); min-width: var(--mx-pv-dw, 46px); max-width: var(--mx-pv-dw, 46px); }
.mx-pv-tb .mx-pv-d { display: block; font-size: 12.5px; }
.mx-pv-tb .mx-pv-dt { display: block; font-size: 11px; font-weight: 500; color: var(--nu-txt2); }
.mx-pv-tb .mx-pv-mk { display: block; font-size: 10px; font-weight: 500; color: var(--nu-txt3); line-height: 1.1; }
.mx-pv-tb .mx-pv-red, .mx-pv-tb .mx-pv-k-hol .mx-pv-dt { color: var(--jv-danger-text); }
.mx-pv .mx-pv-tb .mx-pv-first { border-left: 2px solid var(--nu-border-strong); }
.mx-pv .mx-pv-tb td.mx-pv-zero { color: var(--nu-txt3); }

/* 날짜 갈래 - 칸 전체(머리 · 값 · 소계 · 합계) */
.mx-pv .mx-pv-tb .mx-pv-k-wk  { background: linear-gradient(var(--mx-pv-wk), var(--mx-pv-wk)), var(--mx-pv-card); }
.mx-pv .mx-pv-tb .mx-pv-k-hol { background: linear-gradient(var(--mx-pv-hol), var(--mx-pv-hol)), var(--mx-pv-card); }
.mx-pv .mx-pv-tb .mx-pv-k-vac { background: linear-gradient(var(--mx-pv-vac), var(--mx-pv-vac)), var(--mx-pv-card); }
.mx-pv .mx-pv-tb .mx-pv-k-out { color: var(--nu-txt3); background: repeating-linear-gradient(135deg, transparent 0 5px, var(--nu-surface-2) 5px 7px), var(--mx-pv-card); }
.mx-pv .mx-pv-tb .mx-pv-k-pad { color: var(--nu-txt3); background: var(--nu-surface-2); }
.mx-pv-tb .mx-pv-k-out .mx-pv-d, .mx-pv-tb .mx-pv-k-out .mx-pv-dt, .mx-pv-tb .mx-pv-k-pad .mx-pv-d, .mx-pv-tb .mx-pv-k-pad .mx-pv-dt { color: var(--nu-txt3); font-weight: 500; }

/* 칸 표시 - 글자로도 말한다(색만 바꾸면 고대비에서 사라진다) */
.mx-pv-tb td.mx-pv-up, .mx-pv-tb td.mx-pv-dn { font-weight: 700; }
.mx-pv-tb td.mx-pv-up { color: var(--jv-danger-text); }
.mx-pv-tb td.mx-pv-dn { color: var(--jv-info-text); }
.mx-pv-tb td.mx-pv-up::before { content: "\25B2"; font-size: 9px; margin-right: 3px; vertical-align: 1px; }
.mx-pv-tb td.mx-pv-dn::before { content: "\25BC"; font-size: 9px; margin-right: 3px; vertical-align: 1px; }
.mx-pv-tb td.mx-pv-x { font-weight: 700; outline: 2px solid var(--jv-warning, var(--nu-warning)); outline-offset: -3px; }
.mx-pv-tb td.mx-pv-under { color: var(--jv-danger-text); }
.mx-pv-tb td.mx-pv-over { color: var(--jv-info-text); }
.mx-pv-tb td.mx-pv-fore { font-style: italic; }

.mx-pv .mx-pv-tb td.mx-pv-empty, .mx-pv .mx-pv-tb td.mx-pv-more, .mx-pv-note { padding: 14px; text-align: center; color: var(--nu-txt3); font-size: 13px; }

.mx-pv-legend { display: flex; flex-wrap: wrap; gap: 6px 16px; font-size: 12px; color: var(--nu-txt3); }
.mx-pv-legend span { display: inline-flex; align-items: center; gap: 5px; }
.mx-pv-sw { display: inline-block; width: 14px; height: 14px; border-radius: 3px; border: 1px solid var(--nu-border-strong); background: var(--nu-card); }
.mx-pv-sw.mx-pv-sumc { background: linear-gradient(var(--nu-primary-tint), var(--nu-primary-tint)), var(--nu-card); }
.mx-pv-sw.mx-pv-k-wk { background: linear-gradient(var(--jv-info-light), var(--jv-info-light)), var(--nu-card); }
.mx-pv-sw.mx-pv-k-hol { background: linear-gradient(var(--jv-danger-light), var(--jv-danger-light)), var(--nu-card); }
.mx-pv-sw.mx-pv-k-vac { background: linear-gradient(var(--jv-violet-light), var(--jv-violet-light)), var(--nu-card); }
.mx-pv-sw.mx-pv-k-out { background: repeating-linear-gradient(135deg, transparent 0 4px, var(--nu-border-strong) 4px 5px), var(--nu-card); }
.mx-pv-sw.mx-pv-k-pad { background: var(--nu-surface-2); }

/* 고대비 - 날짜 갈래는 색이 곧 정보라 그 칸만 우리 색을 지킨다(흰 글자와 7:1 넘는 짙은 셋 + 흐린 칸).
   머리글 글자(토 · 일 · 공휴일 이름)와 ▲ ▼ 가 색 없이도 말한다. 테두리 · 윤곽은 시스템 색으로 남는다 */
@media (forced-colors: active) {
  .mx-pv .mx-pv-tb .mx-pv-k-wk,  .mx-pv-sw.mx-pv-k-wk  { forced-color-adjust: none; background: #1d4a7a; color: #fff; }
  .mx-pv .mx-pv-tb .mx-pv-k-hol, .mx-pv-sw.mx-pv-k-hol { forced-color-adjust: none; background: #7a1f2e; color: #fff; }
  .mx-pv .mx-pv-tb .mx-pv-k-vac, .mx-pv-sw.mx-pv-k-vac { forced-color-adjust: none; background: #553589; color: #fff; }
  .mx-pv .mx-pv-tb .mx-pv-k-out, .mx-pv .mx-pv-tb .mx-pv-k-pad, .mx-pv-sw.mx-pv-k-out, .mx-pv-sw.mx-pv-k-pad { forced-color-adjust: none; background: #2e2e2e; color: #cfcfcf; }
  /* 소계 · 합계 줄은 열 칠을 안 따른다 - 줄 전체가 한 바탕이어야 한 줄로 읽힌다.
     열 칠(forced-color-adjust: none)을 풀어 나머지 칸과 같은 시스템 색이 되게 한다(2026-09-28 사용자) */
  .mx-pv .mx-pv-tb tr.mx-pv-grp > td[class*="mx-pv-k-"], .mx-pv .mx-pv-tb tfoot td[class*="mx-pv-k-"] { forced-color-adjust: auto; }
  .mx-pv-tb .mx-pv-k-wk .mx-pv-d, .mx-pv-tb .mx-pv-k-wk .mx-pv-dt, .mx-pv-tb .mx-pv-k-wk .mx-pv-mk,
  .mx-pv-tb .mx-pv-k-hol .mx-pv-d, .mx-pv-tb .mx-pv-k-hol .mx-pv-dt, .mx-pv-tb .mx-pv-k-hol .mx-pv-mk,
  .mx-pv-tb .mx-pv-k-vac .mx-pv-d, .mx-pv-tb .mx-pv-k-vac .mx-pv-dt, .mx-pv-tb .mx-pv-k-vac .mx-pv-mk { color: #fff; }
  .mx-pv-tb .mx-pv-k-out .mx-pv-d, .mx-pv-tb .mx-pv-k-out .mx-pv-dt, .mx-pv-tb .mx-pv-k-pad .mx-pv-d, .mx-pv-tb .mx-pv-k-pad .mx-pv-dt { color: #cfcfcf; }
  .mx-pv-tb td.mx-pv-up.mx-pv-k-wk, .mx-pv-tb td.mx-pv-up.mx-pv-k-hol, .mx-pv-tb td.mx-pv-up.mx-pv-k-vac { color: #ffb4a8; }
  .mx-pv-tb td.mx-pv-dn.mx-pv-k-wk, .mx-pv-tb td.mx-pv-dn.mx-pv-k-hol, .mx-pv-tb td.mx-pv-dn.mx-pv-k-vac { color: #b8dcff; }
  .mx-pv-tb td.mx-pv-zero.mx-pv-k-wk, .mx-pv-tb td.mx-pv-zero.mx-pv-k-hol, .mx-pv-tb td.mx-pv-zero.mx-pv-k-vac { color: #d0d0d0; }
  .mx-pv-tb td.mx-pv-x { outline-color: CanvasText; }
  .mx-pv-tb td.mx-pv-x.mx-pv-k-wk, .mx-pv-tb td.mx-pv-x.mx-pv-k-hol, .mx-pv-tb td.mx-pv-x.mx-pv-k-vac { outline-color: #ffd54a; }
  .mx-pv .mx-pv-tb .mx-pv-edge { border-right-color: CanvasText; }
  .mx-pv .mx-pv-tb .mx-pv-first { border-left-color: CanvasText; }
}

/* ── 화면 틀 부품 — screen-host.js 와 짝 ────────────────────────────────────
   흐름이 있는 화면(요청 -> 결과 -> 확정)이 함께 쓰는 넷. 하는 일이 달라 생김새도 다르다.

     .mx-tabs        이 화면에서 무엇을 볼지 (화면 안, 되돌릴 수 있다)  -> 고른 것만 채운 알약
     .mx-steps       흐름의 어느 단계인지    (화면 밖으로 간다)         -> 이어붙인 한 덩어리
     .mx-badge-info  정보                    (누르는 것이 아니다)       -> 테두리 없는 글자
     .mx-nextbar     끝났으면 어디로         (이동만. 되돌릴 수 없는 행동은 위쪽 행동 줄에)

   ★ 선택을 테두리로 알리지 않는다. 고대비는 transparent 테두리까지 보이게 만들어 안 고른 것에도
     밑줄이 선다. 채움으로 알리고 고대비에서는 Highlight 로 못박는다(이 절 끝). */
.mx-tabs { display: flex; gap: 4px; align-items: center; flex-wrap: wrap; }
/* 단추는 부모 글꼴을 물려받지 않는다(브라우저 기본 글꼴로 뜬다). 보드 전역에 button 글꼴 규칙이 없으면
   탭 글자만 오류 없이 다른 글꼴이 된다 - 부품이 스스로 물려받는다. */
.mx-tabs button {
  background: none; border: 0; border-radius: var(--nu-r-pill);
  padding: 5px 12px; cursor: pointer; color: var(--jv-txt3);
  font-family: inherit; font-size: 12px; line-height: 1.4;
}
.mx-tabs button:hover { color: var(--jv-txt1); background: var(--nu-surface-2); }
.mx-tabs button.on { background: var(--nu-primary-deep); color: var(--nu-on-accent); font-weight: 600; }

/* 칸마다 상자면 「목록」으로 읽힌다. 이어붙이면 「진행」으로 읽힌다. */
.mx-steps {
  display: flex; align-items: stretch; width: fit-content; max-width: 100%;
  border: 1px solid var(--jv-border); border-radius: var(--nu-r-small); overflow: hidden;
}
.mx-steps a,
.mx-steps > span {
  display: flex; align-items: center; gap: 6px; padding: 5px 11px;
  border-left: 1px solid var(--jv-border);
  color: var(--jv-txt3); text-decoration: none;
  font-size: 11px; font-weight: 500; line-height: 1.4; white-space: nowrap;
}
.mx-steps > :first-child { border-left: 0; }
.mx-steps .n { font-variant-numeric: tabular-nums; color: var(--jv-txt4); }
.mx-steps .cur { background: var(--nu-primary-deep); color: var(--nu-on-accent); }
.mx-steps .cur .n { color: var(--nu-on-accent); }
.mx-steps a:hover { background: var(--nu-primary-tint); color: var(--jv-txt1); }
.mx-steps .off { opacity: .5; }

.mx-badge-info { padding: 4px 2px; color: var(--jv-txt3); font-size: 11.5px; line-height: 1.3; white-space: nowrap; }
.mx-badge-info b { color: var(--jv-txt1); font-weight: 600; }

/* 바닥에 붙인다. 표가 제 스크롤을 가지면 그냥 둔 줄은 표 아래로 밀려 화면 밖에 서고, 내용이 끝난 것처럼
   읽혀 아무도 못 찾는다. 바탕색을 반드시 준다 - 투명하면 지나가는 표 글자와 겹친다. */
.mx-nextbar {
  display: flex; align-items: center; gap: 10px;
  margin-top: 16px; padding: 10px 14px;
  border-top: 1px solid var(--jv-border);
  position: sticky; bottom: 0; z-index: 2; background: var(--nu-page);
}
.mx-nextbar__t { color: var(--jv-txt3); margin-right: auto; font-size: 12px; line-height: 1.4; }

/* 진행 표시 - BoardScreens.progress() 가 채운다. 끝을 모르는 일이라 막대가 오간다. */
.mx-progress {
  display: none; align-items: center; gap: 10px; margin: 0 0 10px; padding: 10px 12px;
  border: 1px solid var(--nu-primary); border-radius: var(--nu-r-medium); background: var(--nu-primary-tint);
}
.mx-progress.on { display: flex; }
.mx-progress__track { flex: 1; height: 6px; background: var(--jv-border-l); border-radius: 3px; overflow: hidden; }
.mx-progress__track i {
  display: block; height: 100%; width: 30%; background: var(--nu-primary); border-radius: 3px;
  animation: mx-progress-slide 1.4s ease-in-out infinite;
}
@keyframes mx-progress-slide { 0% { margin-left: -30%; } 100% { margin-left: 100%; } }
/* 움직임을 줄인 사람에게는 오가지 않는 막대 - 도는 중이라는 것은 경과 초가 알린다 */
@media (prefers-reduced-motion: reduce) {
  .mx-progress__track i { animation: none; width: 100%; opacity: .45; }
}
.mx-progress__txt { font-size: 12px; color: var(--jv-txt1); }
.mx-progress__el { font-size: 12px; font-variant-numeric: tabular-nums; color: var(--jv-txt2); white-space: nowrap; }

/* 표 밖의 놓는 자리 - MarunexGrid.dropZone() 이 받는 동안 over 를 단다 */
.mx-dropzone {
  border: 1px dashed var(--nu-border-strong); border-radius: var(--nu-r-small);
  padding: 8px; margin-top: 6px; text-align: center; color: var(--jv-txt3); font-size: 11px;
}
.mx-dropzone.over { border-color: var(--nu-primary); color: var(--nu-brand-text); background: var(--nu-primary-tint); }

/* 고대비 - 위 규칙과 명시도가 같아서 반드시 뒤에 둔다 */
@media (forced-colors: active) {
  /* 선택은 채움으로 알린다. 시스템이 배경을 지우므로 못박아야 남는다 */
  .mx-tabs button.on,
  .mx-steps .cur { forced-color-adjust: none; background: Highlight; color: HighlightText; }
  .mx-steps .cur .n { color: HighlightText; }
  .mx-steps { border-color: CanvasText; }
  .mx-steps a, .mx-steps > span { border-left-color: CanvasText; }
  .mx-nextbar { border-top-color: CanvasText; }
  /* 배경으로만 그린 막대는 시스템이 지운다 - 홈통은 테두리로, 막대는 Highlight 로 */
  .mx-progress__track { forced-color-adjust: none; background: Canvas; border: 1px solid CanvasText; }
  .mx-progress__track i { forced-color-adjust: none; background: Highlight; }
  .mx-dropzone.over { border-color: Highlight; outline: 2px solid Highlight; }
  .mx-grid-table tbody tr.mx-grid-group > td { border-top-color: CanvasText; border-bottom-color: CanvasText; }
  /* 손잡이 선은 배경으로 그려 시스템이 지운다 - 선에만 풀고 Highlight 로(머리글 칸에 걸면 칸 전체가 밝아진다) */
  .mx-grid-resize::after { forced-color-adjust: none; }
  .mx-grid-table thead th:hover > .mx-grid-resize::after { background: CanvasText; }
  .mx-grid-resize:hover::after,
  .mx-grid-resize:focus-visible::after,
  .mx-grid-resizing > .mx-grid-resize::after { background: Highlight; }
}

/* ── 날짜 넘기개 (0.31.0, datenav.js) - ◀ 날짜(요일) ▶ 오늘 [달력] ────────────────────────
   설비 상세현황의 모양이 정본이다(2026-09-28). 단추는 공통 단추(.mx-btn--sm)를 그대로 쓴다.
   ★ 갈 곳이 없는 단추는 자리를 지킨 채 감춘다(visibility) - 빼면 날짜 글자가 좌우로 움직인다. */
.mx-dnav { display: inline-flex; align-items: center; gap: 6px; flex-wrap: nowrap; vertical-align: middle; }
.mx-dnav-name { font-size: 13px; color: var(--jv-txt2); margin-right: 2px; white-space: nowrap; }
.mx-dnav-step { min-width: 34px; padding-left: 8px; padding-right: 8px; }
.mx-dnav-label { min-width: 9.2em; text-align: center; font-weight: 700; color: var(--jv-txt1);
  font-variant-numeric: tabular-nums; white-space: nowrap; }
.mx-dnav--month .mx-dnav-label { min-width: 6.6em; }
.mx-dnav-off { visibility: hidden; }

/* 달력 부품(0.35.0) - 한 달을 칸으로. 켜짐은 ✓ 글자 + 굵은 테두리(색만으로 안 알린다), 주말은 날 숫자 색 + 요일 머리,
   공휴일은 칸 안 이름 글자. 칸 크기는 폭을 일곱으로 나눈다 - 좁은 판(비가동 등록 왼쪽 단)에도 들어간다 */
.mx-cal { display: flex; flex-direction: column; gap: 6px; }
.mx-cal-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
/* 좁은 판에서는 달 넘기개도 줄을 바꾼다 - 달 고르기 칸이 판 밖으로 잘리지 않게 */
.mx-cal-head .mx-dnav { flex-wrap: wrap; row-gap: 4px; }
.mx-cal-hint { font-size: 11px; color: var(--jv-txt3); }
.mx-cal-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 3px; }
.mx-cal-grid.is-busy { opacity: .6; pointer-events: none; }
.mx-cal-wd { height: 22px; border: 0; background: none; font: inherit; font-size: 11.5px; font-weight: 700; color: var(--jv-txt2);
  border-radius: var(--nu-r-small); cursor: pointer; }
.mx-cal-wd:hover { background: var(--jv-hover); color: var(--jv-txt1); }
.mx-cal-wd.is-sun, .mx-cal-day.is-sun .mx-cal-n { color: var(--mx-cal-sun); }
.mx-cal-wd.is-sat, .mx-cal-day.is-sat .mx-cal-n { color: var(--mx-cal-sat); }
.mx-cal-day { position: relative; display: flex; flex-direction: column; align-items: flex-start; gap: 1px; min-height: 42px; min-width: 0;
  padding: 3px 4px 2px 5px; border: 1px solid var(--jv-border); border-radius: var(--nu-r-small); background: var(--jv-card);
  font: inherit; text-align: left; color: var(--jv-txt1); cursor: pointer; overflow: hidden; }
.mx-cal-day:hover { border-color: var(--jv-primary-mid); }
.mx-cal-day:focus-visible { outline: 2px solid var(--jv-primary); outline-offset: 1px; }
.mx-cal-day.is-blank { border: 0; background: none; cursor: default; }
.mx-cal-n { font-size: 12.5px; font-weight: 700; font-variant-numeric: tabular-nums; line-height: 1.1; }
.mx-cal-mark { position: absolute; top: 2px; right: 4px; font-size: 12px; font-weight: 800; line-height: 1; color: var(--jv-primary); }
.mx-cal-name { max-width: 100%; font-size: 10.5px; line-height: 1.2; color: var(--jv-txt2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* 켜짐 - 굵은 테두리 + 옅은 강조 바탕 + ✓ */
.mx-cal-day.is-on { border: 2px solid var(--jv-primary); padding: 2px 3px 1px 4px; background: var(--jv-primary-light); }
/* 쉬는 날인데 일하는 날(주말 특근 · 공휴일 근무) - 점선 테두리로 「예외」를 알린다 */
.mx-cal-day.is-work { border-style: dashed; }
/* 쉬는 날인데 안 켜진 칸(날을 고르는 달력에서 주말 · 공휴일) - 옅은 바탕 + 점선 테두리. 고대비에서는 테두리가 남는다 */
.mx-cal-day.is-rest:not(.is-on) { background: var(--jv-page); border-style: dotted; }
.mx-cal-day.is-today .mx-cal-n { text-decoration: underline; text-underline-offset: 2px; }
.mx-cal-day.is-disabled { cursor: default; opacity: .45; }
.mx-cal-day.is-disabled:hover { border-color: var(--jv-border); }

/* 공휴일 · 휴무 등록 부품(0.35.0) - 달력 탭 · 목록 탭. 칸 · 단추 · 탭은 공통 부품 그대로, 여기는 자리만 */
.mx-hol { display: flex; flex-direction: column; gap: 8px; min-height: 0; flex: 1; }
.mx-hol-head { display: flex; align-items: center; gap: 10px; }
.mx-hol-sum { font-size: 12px; color: var(--jv-txt2); }
.mx-hol-sum b { color: var(--jv-txt1); font-variant-numeric: tabular-nums; }
.mx-hol-tabs { margin: 0; }
.mx-hol-msg { font-size: 12px; color: var(--jv-txt2); min-height: 1em; }
.mx-hol-msg.is-error { color: var(--jv-danger); font-weight: 600; }
.mx-hol-pane { display: flex; flex-direction: column; gap: 8px; min-height: 0; flex: 1; }
.mx-hol-pane[hidden] { display: none; }
.mx-hol-bar { margin: 0; }
.mx-hol-check { display: inline-flex; align-items: center; gap: 5px; height: var(--mx-ctl-h); font-size: var(--mx-ctl-label-size); color: var(--jv-txt1); white-space: nowrap; cursor: pointer; }
.mx-hol-grid { flex: 1; min-height: 160px; display: flex; flex-direction: column; }
.mx-hol-past-d { color: var(--jv-txt3); }
.mx-hol-wk-btn[aria-pressed="true"] { font-weight: 700; text-decoration: underline; }
.mx-hol-note { margin: 0; font-size: 11px; line-height: 1.5; color: var(--jv-txt3); }
.mx-hol-note b { color: var(--jv-txt2); }
@media (forced-colors: active) {
  .mx-cal-day { border-color: CanvasText; }
  .mx-cal-day.is-on { forced-color-adjust: none; background: Highlight; color: HighlightText; border-color: Highlight; }
  .mx-cal-day.is-on .mx-cal-n, .mx-cal-day.is-on .mx-cal-name, .mx-cal-day.is-on .mx-cal-mark { color: HighlightText; }
  .mx-cal-day.is-disabled { color: GrayText; border-color: GrayText; opacity: 1; }
  .mx-cal-wd:hover { outline: 1px solid CanvasText; }
}
/* 달력 칸은 입력 칸 한 벌(input.mx-input)을 따른다(0.32.0) - 폭만 여기서 */
input.mx-input.mx-dnav-pick { width: auto; }

/* ── 입력 칸 한 벌 (0.32.0) - 골라 상자 · 글 · 숫자 · 검색 · 날짜 · 달 칸 · 이름표 · 필터 줄 · 설정 폼 ────────────
   치수는 tokens.css 의 --mx-ctl-* 에만 있다. 사이트 설정 「입력 칸 모양」(<html data-ctl>)이 두 모양을 오간다:
     stacked(기본)  이름표 위 · 칸 28px          inline  이름표 왼쪽 · 칸 30px
   ★ 선택자를 요소 + 클래스로 둔다(input.mx-input) - 공통 입력 규칙(input[type=…])과 명시도가 같아야 뒤에 오는 이쪽이 이긴다.
   ★ 화면이 이 칸의 높이 · 여백 · 글자 · 모서리를 다시 적지 않는다 - 보드 규칙 점검 hand-control 이 잡는다. 폭만 화면 몫이다.
   ★ 「필터 걸림」은 CSS 가 스스로 안다: 필터 줄 안에서 빈 값(전체) 선택지가 있는데 그것이 안 골린 골라 상자,
     글자가 든 검색 칸. 스크립트로 다는 화면은 .is-on 을 붙여도 된다. */
input.mx-input, select.mx-select, textarea.mx-input {
  box-sizing: border-box; height: var(--mx-ctl-h); min-width: 0;
  font: inherit; font-size: var(--mx-ctl-font-size); line-height: normal; color: var(--jv-txt1);
  background-color: var(--jv-card); border: 1px solid var(--mx-ctl-border); border-radius: var(--mx-ctl-radius);
  padding: 0 var(--mx-ctl-pad-x); outline: none;
  transition: border-color .12s, box-shadow .12s, background-color .12s;
}
textarea.mx-input { height: auto; min-height: calc(var(--mx-ctl-h) * 2); padding-top: 5px; padding-bottom: 5px; }
select.mx-select {
  appearance: none; -webkit-appearance: none; cursor: pointer;
  padding-right: calc(var(--mx-ctl-pad-x) + var(--mx-ctl-icon-gap));
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%236B7280' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right var(--mx-ctl-pad-x) center; background-size: 12px 12px;
}
input.mx-input.mx-search {
  padding-left: calc(var(--mx-ctl-pad-x) + var(--mx-ctl-icon-gap) + 2px);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%239CA3AF' stroke-width='2.2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='m20 20-3.5-3.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: left var(--mx-ctl-pad-x) center; background-size: 14px 14px;
}
input.mx-input.mx-num { text-align: right; font-variant-numeric: tabular-nums; }
input.mx-input[type="date"], input.mx-input[type="month"] { font-variant-numeric: tabular-nums; }
input.mx-input::placeholder { color: var(--jv-txt4); }

input.mx-input:hover, select.mx-select:hover, textarea.mx-input:hover { border-color: var(--mx-ctl-border-hover); }
input.mx-input:focus, select.mx-select:focus-visible, textarea.mx-input:focus {
  border-color: var(--jv-primary-mid); box-shadow: 0 0 0 3px var(--jv-primary-light);
}
/* 필터 걸림 - 무엇으로 거르고 있는지 한눈에 */
.mx-filterbar select.mx-select:has(option[value=""]):not(:has(option[value=""]:checked)),
.mx-filterbar input.mx-search:not(:placeholder-shown),
input.mx-input.is-on, select.mx-select.is-on {
  border-color: var(--jv-primary-mid); background-color: var(--jv-primary-light); color: var(--nu-brand-text); font-weight: 600;
}
input.mx-input:disabled, select.mx-select:disabled, textarea.mx-input:disabled {
  background-color: var(--jv-page); color: var(--jv-txt4); border-color: var(--jv-border); cursor: default;
}
input.mx-input[aria-invalid="true"], select.mx-select[aria-invalid="true"], textarea.mx-input[aria-invalid="true"] {
  border-color: var(--jv-danger);
}
.mx-ctl-error { font-size: 11.5px; color: var(--jv-danger); }
.mx-unit { font-size: var(--mx-ctl-label-size); color: var(--jv-txt3); white-space: nowrap; }

/* 이름표 + 칸. stacked 는 위, inline 은 왼쪽. <label class="mx-field">차종 <select class="mx-select">…</select></label> */
.mx-field {
  display: inline-flex; flex-direction: column; align-items: flex-start; gap: var(--mx-ctl-label-gap);
  font-size: var(--mx-ctl-label-size); font-weight: var(--mx-ctl-label-weight); color: var(--mx-ctl-label-color);
  white-space: nowrap;
}
:root[data-ctl="inline"] .mx-field { flex-direction: row; align-items: center; }
.mx-field > .mx-field__ctl { display: inline-flex; align-items: center; gap: 4px; }

/* 필터 줄 - 칸 · 단추 · 날짜 넘기개가 한 줄. stacked 는 아래 끝을, inline 은 가운데를 맞춘다 */
.mx-filterbar { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 10px 12px; }
:root[data-ctl="inline"] .mx-filterbar { align-items: center; gap: 10px 16px; }
.mx-filterbar__fill { flex: 1 1 auto; }

/* 설정 폼 - 칸 왼쪽 끝이 줄마다 맞는다. stacked 는 이름표 위 격자, inline 은 이름표 열 · 칸 열 */
.mx-form { display: grid; grid-template-columns: repeat(auto-fill, minmax(var(--mx-form-col), 1fr)); gap: 14px 18px; }
:root[data-ctl="inline"] .mx-form { grid-template-columns: repeat(auto-fill, minmax(var(--mx-form-col-inline), 1fr)); gap: 12px 32px; }
:root[data-ctl="inline"] .mx-form > .mx-field { display: grid; grid-template-columns: var(--mx-form-label) auto; justify-content: start; }

/* 표 안 칸(0.33.0) - `mx-input mx-input--cell` · `mx-select mx-select--cell`. 표 줄에 맞춘 한 치수(--mx-ctl-cell-*)로
   칸 폭을 꽉 채운다. 상태(올림 · 포커스 · 비활성 · 오류)는 입력 칸 한 벌을 그대로 물려받는다.
   ★ 그리드 칸에는 MarunexGrid.cellInput · cellSelect 로 만든다 - 화면이 손으로 짜면 다시 갈라진다
   ★ 고친 값은 .is-edited 하나 - 테두리 두께를 안 바꾸고(inset 그림자) 굵게. 칸 크기가 흔들리지 않는다 */
input.mx-input.mx-input--cell, select.mx-select.mx-select--cell {
  width: 100%; height: var(--mx-ctl-cell-h); font-size: var(--mx-ctl-cell-font-size);
  padding: 0 var(--mx-ctl-cell-pad-x); border-color: var(--jv-border); border-radius: var(--mx-ctl-cell-radius);
}
select.mx-select.mx-select--cell { padding-right: calc(var(--mx-ctl-cell-pad-x) + 14px); background-position: right 4px center; background-size: 10px 10px; }
input.mx-input--cell[type="number"] { -moz-appearance: textfield; appearance: textfield; }
input.mx-input--cell[type="number"]::-webkit-outer-spin-button,
input.mx-input--cell[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
input.mx-input.is-edited, select.mx-select.is-edited {
  border-color: var(--jv-primary); box-shadow: inset 0 0 0 1px var(--jv-primary); font-weight: 700;
}

/* 날짜 넘기개의 날짜 글자는 칸 글자보다 2px 크게 - 모양을 따라간다 */
.mx-dnav-label { font-size: calc(var(--mx-ctl-font-size) + 2px); }

/* 관리 화면 - 입력 칸 모양 고르기 */
.ctl-style-choices { display: flex; flex-wrap: wrap; gap: 12px; }
.ctl-style-choice { display: grid; grid-template-columns: auto 1fr; gap: 6px 10px; align-items: start; padding: 12px 14px;
  border: 1px solid var(--jv-border); border-radius: var(--nu-r-medium); cursor: pointer; min-width: 280px; }
.ctl-style-choice:has(input:checked) { border-color: var(--jv-primary-mid); background: var(--jv-primary-light); }
.ctl-style-text { display: flex; flex-direction: column; gap: 2px; font-size: 13px; }
.ctl-style-text em { font-style: normal; font-size: 12px; color: var(--jv-txt3); }
.ctl-style-demo { grid-column: 2; display: flex; gap: 10px; pointer-events: none; }
/* 미리보기는 사이트 설정과 무관하게 제 모양을 보인다 - 토큰을 그 자리에서 덮는다 */
.ctl-style-demo[data-ctl-demo="stacked"] { --mx-ctl-h: 28px; --mx-ctl-font-size: 12.5px; --mx-ctl-radius: 6px; --mx-ctl-pad-x: 8px;
  --mx-ctl-border: var(--jv-border-strong); --mx-ctl-label-size: 11.5px; --mx-ctl-label-weight: 500; --mx-ctl-label-color: var(--jv-txt3); --mx-ctl-label-gap: 3px; }
.ctl-style-demo[data-ctl-demo="inline"] { --mx-ctl-h: 30px; --mx-ctl-font-size: 13px; --mx-ctl-radius: var(--nu-r-medium); --mx-ctl-pad-x: 10px;
  --mx-ctl-border: var(--jv-border); --mx-ctl-label-size: 12.5px; --mx-ctl-label-weight: 400; --mx-ctl-label-color: var(--jv-txt2); --mx-ctl-label-gap: 6px; }
.ctl-style-demo[data-ctl-demo="stacked"] .mx-field { flex-direction: column; align-items: flex-start; }
.ctl-style-demo[data-ctl-demo="inline"] .mx-field { flex-direction: row; align-items: center; }
.ctl-style-demo select.mx-select { width: 84px; }

@media (forced-colors: active) {
  input.mx-input, select.mx-select, textarea.mx-input { border-color: CanvasText; }
  input.mx-input:focus, select.mx-select:focus-visible, textarea.mx-input:focus { outline: 2px solid Highlight; outline-offset: 1px; }
  .mx-filterbar select.mx-select:has(option[value=""]):not(:has(option[value=""]:checked)),
  .mx-filterbar input.mx-search:not(:placeholder-shown), input.mx-input.is-on, select.mx-select.is-on { outline: 2px solid Highlight; outline-offset: -2px; }
  input.mx-input[aria-invalid="true"], select.mx-select[aria-invalid="true"] { outline: 2px solid Mark; }
}

/* ── 카드 · 기간 넘기개 · 내 대시보드 · 홈 탭 (0.37.0) ──────────────────────────
   cards.js · period-nav.js · dashboard.js · home-tabs.js 의 모양. 계획: docs/카드_대시보드_계획_2026-09-29.md
   ★ 카드 모양은 오토젠 홈 카드(.hm-card)를 정본으로 했다 - 흰 바탕 · 얇은 테두리 · 작은 둥글기, 제목 · 부제 한 줄.
   ★ 켜짐 · 편집 중을 색만으로 알리지 않는다 - 글자(완료 · 편집 끝) · aria-pressed · 굵은 테두리. */
.mx-card { background: var(--jv-card); border: 1px solid var(--jv-border); border-radius: var(--nu-r-small);
  padding: 12px 14px; display: flex; flex-direction: column; gap: 8px; min-width: 0; min-height: 0; height: 100%; box-sizing: border-box;
  /* 판에서 떠 보이게 - 두 겹 그림자(--mx-lift, 0.38.0 「나2」)와 오른쪽 위 모서리 쪽 옅은 빛(0.37.18 「카드 판 D」). 고대비에서는 끈다(아래) */
  box-shadow: var(--mx-lift);
  background-image: linear-gradient(225deg, color-mix(in srgb, var(--jv-primary) 7%, transparent) 0%, transparent 38%); }
/* 상태 띠(0.37.12) - 숫자 카드 자료의 band. 왼쪽 안쪽에 굵은 선 하나(조각 ::before - 고대비에서 조각에만 보정을 끈다).
   띠는 거드는 것이다 - 뜻은 이름 · 값 글자에 있다 */
.mx-card[data-band] { position: relative; }
.mx-card[data-band]::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 4px;
  border-radius: var(--nu-r-small) 0 0 var(--nu-r-small); }
.mx-card[data-band="success"]::before { background: var(--nu-success); }
.mx-card[data-band="alert"]::before { background: var(--nu-alert); }
.mx-card[data-band="warning"]::before { background: var(--nu-warning); }
.mx-card[data-band="info"]::before { background: var(--nu-info); }
.mx-card-h { display: flex; align-items: center; gap: 7px; min-width: 0; flex-wrap: wrap; }
.mx-card-title { font-size: 15px; font-weight: 700; color: var(--jv-txt1); text-decoration: none; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
a.mx-card-title:hover { text-decoration: underline; }
.mx-card-go { margin-left: 3px; color: var(--jv-txt3); }
/* 부제는 제목 아래 줄(0.37.18, 사용자 패턴 선택 「카드 머리 B」) - 도구(기간 넘기개)는 제목 줄 오른쪽에 남는다 */
.mx-card-h { row-gap: 1px; }
.mx-card-sub { font-size: 12px; color: var(--jv-txt3); font-variant-numeric: tabular-nums; order: 3; flex-basis: 100%; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mx-card-sub:empty { display: none; }
.mx-card-tools { margin-left: auto; display: flex; align-items: center; gap: 6px; order: 2; }
.mx-card-b { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; gap: 8px; overflow: hidden; }
.mx-card-msg { margin: auto; font-size: 13px; color: var(--jv-txt3); text-align: center; }
.mx-card-msg.is-error { color: var(--jv-danger-text); }
/* 다시 읽는 동안 - 앞 기간의 숫자가 그대로 서 있어, 기간 이름만 바뀐 채 옛 값이 새 값으로 읽혔다(0.37.11, wht 「년」 한 번이 60초).
   흐리게 두고 머리에 「불러오는 중」을 단다(처음 읽을 때는 몸에 이미 그 글이 있어 안 단다). 흐림만 두지 않는다 - 고대비는 투명도를 못 믿는다 */
.mx-card[aria-busy="true"] .mx-card-b { opacity: .4; }
.mx-card[aria-busy="true"]:not(:has(> .mx-card-b > .mx-card-msg)) .mx-card-sub::after { content: '불러오는 중…'; margin-left: 6px; color: var(--jv-txt3); }
.mx-card-viz { position: relative; flex: 1 1 auto; min-height: 90px; height: auto; }   /* ★ 셸 .viz-wrap 의 고정 높이(20vh)를 끈다 - 카드 안에서는 카드가 남긴 높이를 쓴다. 안 끄면 머리가 한 줄 늘 때 그림이 카드 밖으로 넘쳤다(0.37.18) */
.mx-card-viz > canvas { position: absolute; inset: 0; width: 100% !important; height: 100% !important; }
.mx-kpi { display: flex; align-items: baseline; gap: 5px; }
.mx-kpi-v { font-size: 40px; font-weight: 700; color: var(--jv-txt1); font-variant-numeric: tabular-nums; line-height: 1.05; }
.mx-card[data-size="s"] .mx-kpi-v { font-size: 30px; }
/* 큰 수 옆 증감 칩(0.37.18) - 오른쪽 끝, 큰 수의 가운데 선에 */
.mx-kpi-chip { margin-left: auto; align-self: center; font-size: 12px; font-weight: 600; padding: 2px 8px; border-radius: 999px;
  background: var(--nu-surface-2); color: var(--jv-txt2); white-space: nowrap; font-variant-numeric: tabular-nums; }
.mx-kpi-chip.is-up { color: var(--nu-success-text, var(--jv-txt1)); }
.mx-kpi-chip.is-down { color: var(--nu-alert-text, var(--jv-txt1)); }
.mx-kpi-u { font-size: 13px; color: var(--jv-txt3); }
.mx-kpi.is-warn .mx-kpi-v { color: var(--jv-warning-text, var(--jv-txt1)); }
.mx-kpi.is-bad .mx-kpi-v { color: var(--jv-danger-text); }
.mx-kpi-note { font-size: 12.5px; color: var(--jv-txt3); }

/* 지표 칸 - 제목 · 큰 수치 · 짧은 보조 한 줄뿐인 칸(0.42.0, 2026-10-07 정호님 「정보가 적은 KPI 카드는 1줄로」).
   한 줄: 「제목  큰 수치 단위 …… 보조(오른쪽 끝)」. 보조가 그 칸에 안 들어가면 그 칸만 둘째 줄로 내려간다 - 칸은 최대 2줄,
   둘째 줄에서도 넘치면 「…」로 줄이므로 보조에는 title 로 전체 글을 단다.
     <div class="mx-stat"><span class="mx-stat-k">총 수요</span><span class="mx-stat-v">18,062<small>EA</small></span><span class="mx-stat-s" title="D ~ D+14">D ~ D+14</span></div>
   ★ 누르면 필터가 걸리는 칸은 <button class="mx-stat" aria-pressed> - 눌림은 파란 2px 테두리, 「필터 중」은 제목 뒤 .mx-stat-on.
   ★ 수치 색은 .is-up(빨강 - 늘어남) · .is-down(파랑 - 줄어듦) · .is-warn · .is-bad.
   ★ 차트 · 막대 · 표 · 목록 · 보조 둘 이상이 든 카드는 대상이 아니다 - MxKpiCard 등 카드 부품을 쓴다.
   ★ 줄(.mx-stats 또는 사이트 격자)은 grid 라 같은 줄 칸은 높이가 같다 - 접힌 칸이 있으면 그 줄 모두 그 높이, 글은 위에 맞춘다. */
.mx-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 10px; }
.mx-stat {
  display: flex; flex-wrap: wrap; align-items: baseline; align-content: flex-start; column-gap: 10px; row-gap: 0;
  min-width: 0; padding: 7px 12px; box-sizing: border-box; text-align: left; font: inherit; color: var(--jv-txt1);
  background: var(--jv-card); border: 1px solid var(--jv-border); border-radius: var(--nu-r-medium); box-shadow: var(--mx-lift);
}
.mx-stat-k { font-size: 12.5px; font-weight: 600; color: var(--jv-txt2); white-space: nowrap; }
.mx-stat-on { margin-left: 6px; color: var(--jv-primary); font-weight: 700; }
.mx-stat-v { font-size: 20px; font-weight: 700; line-height: 1.3; font-variant-numeric: tabular-nums; white-space: nowrap; }
.mx-stat-v small { margin-left: 3px; font-size: 12.5px; font-weight: 500; color: var(--jv-txt3); }
/* 보조 - 한 줄에 안 들어가면 둘째 줄로 내려가고, 둘째 줄에서도 넘치면 「…」(칸은 최대 2줄 - 정호님). 전체 글은 title 로 */
.mx-stat-s {
  margin-left: auto; max-width: 100%; font-size: 12px; color: var(--jv-txt3); text-align: right; font-variant-numeric: tabular-nums;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.mx-stat.is-up .mx-stat-v, .mx-stat.is-bad .mx-stat-v { color: var(--jv-danger-text); }
.mx-stat.is-down .mx-stat-v { color: var(--jv-info-text); }
.mx-stat.is-warn .mx-stat-v { color: var(--jv-warning-text, var(--jv-txt1)); }
button.mx-stat { cursor: pointer; }
button.mx-stat:hover:not(:disabled) { border-color: var(--jv-border-strong); }
button.mx-stat:focus-visible { outline: 2px solid var(--jv-primary); outline-offset: 1px; }
button.mx-stat[aria-pressed="true"] { border: 2px solid var(--jv-primary); padding: 6px 11px; background: var(--jv-primary-light); }
button.mx-stat:disabled { cursor: default; opacity: .7; }
@media (forced-colors: active) {
  .mx-stat { box-shadow: none; border-color: CanvasText; }
  button.mx-stat[aria-pressed="true"] { border-color: Highlight; }
}
/* 큰 수 아래 짧은 추이(0.37.13) - 큰 수와 보조 줄 사이 남는 높이를 채운다. 한 가지 색, 기준일만 진하게.
   값이 없는 날은 막대 대신 바닥에 점선 눈금 - 0 은 바닥에 붙은 얇은 막대(2px)라 둘이 갈린다 */
.mx-card-spark { flex: 1 1 auto; min-height: 28px; display: flex; flex-direction: column; justify-content: flex-end; gap: 3px; }
.mx-spark-bars { flex: 1 1 auto; min-height: 14px; max-height: 140px; display: flex; align-items: flex-end; gap: 3px; }
.mx-spark-b { flex: 1 1 0; min-width: 0; min-height: 2px; border-radius: 2px 2px 0 0;
  background: color-mix(in srgb, var(--chart-1) 30%, transparent); }
.mx-spark-b.is-at { background: var(--chart-1); }
.mx-spark-b.is-none { height: 0; min-height: 0; background: transparent; border-top: 2px dotted var(--jv-txt3); border-radius: 0; opacity: .7; }
.mx-spark-cap { display: flex; justify-content: space-between; gap: 6px; font-size: 11px; color: var(--jv-txt3);
  font-variant-numeric: tabular-nums; white-space: nowrap; }
.mx-spark-cap > span:nth-child(2) { overflow: hidden; text-overflow: ellipsis; }
.mx-card-strip { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 10px; min-width: 0; }
/* 화면 카드 줄(0.37.17) - 카드 높이는 줄의 가장 긴 카드에 맞춘다(grid 기본 stretch) */
/* ★ 낮은 칸에서는 추이 막대가 먼저 양보한다(0.37.20) - 창이 조금만 낮아도(1920x900 · 947) 셋째 보조 줄이 잘렸다.
     판(대시보드 · 홈 기본 탭) 안에서만 - 화면 카드 줄은 높이가 내용을 따라가서 크기 봉쇄(container-type: size)를 걸면 0 이 된다.
     몸이 180px 이하이면 막대 밑 날짜 줄을 빼고 막대는 16px 까지 줄인다. 숫자 · 보조 줄은 그대로 선다 */
.mx-dash .mx-card-b { container-type: size; container-name: mxcardb; }
@container mxcardb (max-height: 180px) {
  .mx-spark-cap { display: none; }
  .mx-card-spark { min-height: 12px; }
  .mx-spark-bars { min-height: 8px; }
  .mx-card-lines { gap: 2px; }
}
.mx-card-spark + .mx-card-lines { border-top: 1px solid var(--jv-border); padding-top: 6px; }
/* 줄 막대 · 카드 밑 줄 · 도넛 곁값(0.37.14) */
.mx-card-lines.has-bars li { flex-wrap: wrap; row-gap: 3px; }
.mx-card-lines.is-ruled { gap: 2px; }
.mx-card-lines.is-ruled li { line-height: 1.35; }   /* 여섯 줄 목록이 1920x900 에서 8px 넘쳤다(0.37.20) */
.mx-card-lines.is-ruled li + li { border-top: 1px solid var(--jv-border); padding-top: 2px; }   /* 줄 사이 선은 촘촘히 - 낮은 창(카드 몸 168px)에서 여섯 줄 목록이 넘쳤다(0.37.19) */   /* 줄 카드 줄 사이 선(0.37.18) */
.mx-line-bar { flex: 1 0 100%; height: 6px; border-radius: 3px; background: var(--jv-border); overflow: hidden; }
.mx-line-bar > s { display: block; height: 100%; border-radius: 3px; background: var(--chart-1); text-decoration: none; }
.mx-card-lines li.is-warn .mx-line-bar > s { background: var(--nu-warning, var(--chart-3)); }
/* 낮은 카드에서 줄 막대 목록을 조인다 - 운영 1920x947 에서 가용일수 카드가 3px 넘쳤다.
   ★ 위 기본 규칙 **뒤에** 둔다 - 명시도가 같아 앞에 두면 기본 규칙이 이기고 조용히 안 먹는다(0.37.21 이 그랬다) */
@container mxcardb (max-height: 180px) {
  .mx-card-spark + .mx-card-lines { padding-top: 4px; }
  .mx-card-lines.has-bars li { row-gap: 1px; }
  .mx-line-bar { height: 4px; }
}
.mx-card-note { margin-top: auto; }
.mx-card-foot { list-style: none; margin: 0; padding: 6px 0 0; border-top: 1px solid var(--jv-border);
  display: flex; flex-wrap: wrap; gap: 4px 18px; font-size: 13px; color: var(--jv-txt3); }
.mx-card-foot b { margin-left: 4px; font-weight: 600; color: var(--jv-txt1); font-variant-numeric: tabular-nums; }
.mx-card-foot b small { margin-left: 2px; font-size: 11px; font-weight: 400; color: var(--jv-txt3); }
.mx-card-foot li.is-warn, .mx-card-foot li.is-warn b { color: var(--jv-warning-text, var(--jv-txt1)); font-weight: 700; }
.mx-card-foot li:last-child:not(:first-child) { margin-left: auto; }
.mx-donut-lg li.is-first { border-top: 1px solid var(--jv-border); padding-top: 3px; margin-top: 2px; }
.mx-donut-lg li.is-more > span { color: var(--jv-txt3); }
@media (forced-colors: active) {
  /* 막대는 바탕으로 그린 조각 - 조각에만 보정을 끈다(홈통은 GrayText, 채움은 CanvasText) */
  .mx-line-bar { forced-color-adjust: none; background: GrayText; }
  .mx-line-bar > s, .mx-card-lines li.is-warn .mx-line-bar > s { background: CanvasText; }
}
@media (forced-colors: active) {
  /* 막대는 바탕으로만 그린 조각이라 강제되면 사라진다 - 조각에만 보정을 끄고 시스템 색으로 */
  /* 고대비 - **모양으로 가른다**(0.40.3, 2026-10-05 정호님 결정). 회색(GrayText) · 흰색(CanvasText)이 사용자 팔레트에서 잘 안 갈렸다.
     기준일만 꽉 채우고(CanvasText) 다른 날은 테두리만(속 빈 막대) - 팔레트가 어떤 색이든 모양으로 갈린다.
     Highlight 는 사용자 검은 팔레트에서 2.7:1 - 마크 색으로 안 쓴다 */
  .mx-spark-b { forced-color-adjust: none; background: transparent; box-shadow: inset 0 0 0 1px CanvasText; }
  .mx-spark-b.is-at { background: CanvasText; box-shadow: none; }
  .mx-spark-b.is-none { background: transparent; box-shadow: none; border-top-color: GrayText; }
}
.mx-card-lines { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.mx-card-lines li { display: flex; align-items: baseline; gap: 6px; font-size: 13.5px; white-space: nowrap; }
.mx-card-lines li > span { color: var(--jv-txt3); overflow: hidden; text-overflow: ellipsis; }
.mx-card-lines li > b { margin-left: auto; font-weight: 600; font-variant-numeric: tabular-nums; color: var(--jv-txt1); }
.mx-card-lines li > b small { margin-left: 2px; font-size: 11.5px; font-weight: 400; color: var(--jv-txt3); }
.mx-card-lines li.is-warn > b { color: var(--jv-warning-text, var(--jv-txt1)); }
.mx-card-lines li.is-bad > b { color: var(--jv-danger-text); }
/* 고리는 도넛 짜임(.mx-donut-row · .mx-card-viz · .mx-donut-c · .mx-donut-lg)을 그대로 쓴다(0.37.16) - 고리만의 짜임 규칙을 두지 않는다 */
.mx-gauge { position: absolute; inset: 0; width: 100%; height: 100%; }
.mx-gauge-bg { stroke: var(--nu-surface-2); }
.mx-gauge-fg { stroke: var(--jv-primary); }   /* 끝은 도넛 조각처럼 각지게(0.37.16) - 둥근 끝이 8% 를 덩어리로 보이게 했다 */
.mx-gauge-fg.is-full { stroke: var(--jv-success); }
/* 차트 모양(0.40.0) - 계기판 · 진행 막대. 고리와 같은 색(--jv-primary · 100% 이상 --jv-success)이고 짜임은 도넛 줄을 그대로 쓴다.
   ★ 계기판 상자는 반원 비율(100 : 58)이라 고리 상자(정사각)보다 낮다 - 남는 높이는 가운데 정렬로 */
.mx-meter-box { flex: 1 1 50%; align-self: stretch; position: relative; container-type: size; min-width: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; }
/* 반원은 상자 폭을 다 쓰되 값 글자 자리(약 30px)를 남긴 높이를 넘지 않는다 */
.mx-meter { display: block; width: min(100%, calc((100cqh - 30px) * 1.724)); height: auto; aspect-ratio: 100 / 58; }
.mx-meter-bg { stroke: var(--nu-surface-2); }
.mx-meter-fg { stroke: var(--jv-primary); }
.mx-meter-fg.is-full { stroke: var(--jv-success); }
.mx-meter-tk { stroke: var(--jv-txt3); stroke-width: 1; }
.mx-meter-nd { stroke: var(--jv-txt1); }
.mx-meter-hub { fill: var(--jv-txt1); }
.mx-meter-c { display: flex; justify-content: center; pointer-events: none; line-height: 1; }
.mx-meter-c b { font-size: clamp(14px, 10cqmin, 30px); font-weight: 700; color: var(--jv-txt1); font-variant-numeric: tabular-nums; }
.mx-meter-c b i { font-style: normal; font-size: .6em; font-weight: 600; margin-left: 1px; color: var(--jv-txt3); }
.mx-card-progress { height: 12px; border-radius: 6px; background: var(--nu-surface-2); overflow: hidden; flex: none; }
.mx-card-progress > s { display: block; height: 100%; background: var(--jv-primary); border-radius: 6px; }
.mx-card-progress > s.is-full { background: var(--jv-success); }
/* 카드 머리 넘기개(0.40.0) - 시간이 없는 판에 선 기준일 · 기간 카드. 머리 한 줄 안에 들어가게 작게 */
.mx-card-nav { display: inline-flex; align-items: center; min-width: 0; font-size: 12px; }
.mx-cnav { gap: 2px; }
.mx-cnav-b { width: 22px; height: 22px; padding: 0; border: 1px solid var(--jv-border); border-radius: var(--nu-r-small); background: var(--jv-card);
  color: var(--jv-txt2); font-size: 10px; line-height: 1; cursor: pointer; }
.mx-cnav-b:hover { background: var(--jv-hover); }
.mx-cnav-d { position: relative; padding: 0 4px; font-size: 12.5px; font-weight: 600; color: var(--jv-txt1); font-variant-numeric: tabular-nums; cursor: pointer; white-space: nowrap; }
/* 날짜 칸은 글자 위에 투명하게 겹친다 - 누르면 달력, 글자는 「10-05(월)」 그대로 */
.mx-cnav-in { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; border: 0; padding: 0; cursor: pointer; }
/* 표는 카드 높이 안에서 굴러간다 - 묶지 않으면 카드가 줄 때 아래 줄이 카드 안에서 잘렸다(2026-09-30 「사출기별 샷 · 가동률」 6호기) */
.mx-card-table { flex: 1 1 auto; overflow: auto; min-height: 0; }
.mx-card-table table { width: 100%; border-collapse: collapse; font-size: 12.5px; font-variant-numeric: tabular-nums; }
.mx-card-table th, .mx-card-table td { padding: 4px 8px; border-bottom: 1px solid var(--jv-border); white-space: nowrap; }
.mx-card-table th { font-weight: 600; color: var(--jv-txt2); background: var(--jv-card); border-bottom-color: var(--jv-border-strong, var(--jv-border)); position: sticky; top: 0; }
/* 표는 줄무늬(0.37.18, 사용자 패턴 선택 「표 B」) - 머리글은 바탕 없이 굵은 밑줄 */
.mx-card-table tbody tr:nth-child(even) td { background: color-mix(in srgb, var(--nu-surface-2) 60%, transparent); }
.mx-card-table .tb-al-r { text-align: right; }
.mx-card-table .tb-al-c { text-align: center; }
.mx-card-table .tb-al-l { text-align: left; }
.mx-card--gone { border-style: dashed; }
.mx-donut-row { flex: 1 1 auto; min-height: 0; display: flex; align-items: center; gap: 12px; }
.mx-donut-row > .mx-card-viz { flex: 1 1 50%; align-self: stretch; container-type: size; }
/* 도넛 가운데 합계(0.37.15) - 도넛 크기를 따라 글자가 커진다(구멍 지름의 62% 안에 여섯 자리가 들어가게) */
.mx-donut-c { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center;
  pointer-events: none; line-height: 1.1; }
.mx-donut-c b { font-size: clamp(12px, 11cqmin, 40px); font-weight: 700; color: var(--jv-txt1); font-variant-numeric: tabular-nums; }
.mx-donut-c i { font-style: normal; font-size: clamp(10px, 5cqmin, 16px); color: var(--jv-txt3); }
.mx-donut-c.is-one b i { font-size: .6em; font-weight: 600; margin-left: 1px; }   /* 고리 「99%」 한 줄(0.37.18) */
.mx-donut-lg { flex: 1 1 50%; min-width: 0; max-height: 100%; overflow: auto; }
.mx-donut-lg li.is-sum { border-bottom: 1px solid var(--jv-border); padding-bottom: 3px; margin-bottom: 2px; }
.mx-donut-lg li.is-sum > span { color: var(--jv-txt2); font-weight: 600; }
.mx-sw { display: inline-block; width: 10px; height: 10px; margin-right: 6px; border-radius: 2px; vertical-align: -1px; background: var(--jv-border); }

/* 기간 넘기개 - 단위 택일 + ◀ 기간 ▶ */
.mx-pnav { display: inline-flex; align-items: center; gap: 6px; }
.mx-pnav-label { min-width: 7.5em; text-align: center; font-size: 13px; font-weight: 600; color: var(--jv-txt1); font-variant-numeric: tabular-nums; }
.mx-card .mx-pnav-label { min-width: 6.5em; font-size: 12px; }

/* 내 대시보드 격자 - 칸 좌표는 dashboard.js 가 화소로 적는다 */
.mx-dash { position: relative; }
.mx-dash-grid { position: relative; }
.mx-dash-item { position: absolute; box-sizing: border-box; transition: left .12s, top .12s, width .12s, height .12s; }
.mx-dash-item > section { height: 100%; }
.mx-dash-item.is-drag { transition: none; z-index: 5; opacity: .85; }
.mx-dash.is-stacked .mx-dash-grid { display: flex; flex-direction: column; gap: 12px; }
.mx-dash.is-stacked .mx-dash-item { position: relative; }
.mx-dash-empty { padding: 40px 16px; text-align: center; color: var(--jv-txt3); border: 1px dashed var(--jv-border); border-radius: var(--nu-r-small); }
.mx-dash.is-editing .mx-dash-item > section { outline: 2px dashed var(--jv-primary); outline-offset: -1px; }
/* 편집 단추 줄은 가리키거나 초점이 든 카드에만 - 늘 세워 두면 작은 카드의 보조 줄을 가렸고(3x2 「총 수요」),
   자리를 비우면 카드가 작음 단계로 줄어 보조 줄이 아예 안 섰다(2026-09-30 개발 판). 끌기 모서리는 늘 보인다 */
.mx-dash.is-editing .mx-dash-tools { opacity: 0; pointer-events: none; transition: opacity .12s; }
.mx-dash.is-editing .mx-dash-item:hover .mx-dash-tools,
.mx-dash.is-editing .mx-dash-item:focus-within .mx-dash-tools { opacity: 1; pointer-events: auto; }
.mx-dash.is-editing .mx-dash-item:focus-visible { outline: 3px solid var(--jv-primary); outline-offset: 2px; }
.mx-dash.is-editing .mx-dash-resize { pointer-events: auto; opacity: 1; }
.mx-dash.is-editing .mx-card-h { cursor: move; }
.mx-dash-tools { position: absolute; left: 6px; right: 6px; bottom: 6px; display: flex; flex-wrap: wrap; align-items: center; gap: 2px;
  padding: 3px 5px; background: var(--jv-card); border: 1px solid var(--jv-border); border-radius: var(--nu-r-small);
  box-shadow: 0 2px 6px rgba(0, 0, 0, .12); z-index: 3; }
.mx-dash-grip { cursor: move; padding: 0 4px; color: var(--jv-txt3); user-select: none; }
.mx-dash-sep { width: 1px; height: 16px; background: var(--jv-border); margin: 0 3px; }
.mx-dash-btn { min-width: 24px; height: 24px; padding: 0 4px; font-size: 11px; line-height: 1; color: var(--jv-txt2);
  background: transparent; border: 1px solid transparent; border-radius: var(--nu-r-small); cursor: pointer; }
.mx-dash-btn:hover:not([aria-disabled="true"]) { border-color: var(--jv-border); background: var(--jv-hover); color: var(--jv-txt1); }
.mx-dash-btn[aria-disabled="true"] { opacity: .3; cursor: not-allowed; }
.mx-dash-btn[data-act="remove"] { color: var(--jv-danger-text); }
.mx-dash-param { height: 24px; font-size: 12px; max-width: 120px; }
.mx-dash-resize { position: absolute; right: -6px; bottom: -6px; width: 14px; height: 14px; cursor: nwse-resize;
  border-right: 3px solid var(--jv-primary); border-bottom: 3px solid var(--jv-primary); }
.mx-dash.is-stacked .mx-dash-resize, .mx-dash.is-stacked .mx-dash-grip { display: none; }
/* 빈 자리 「+」 - 편집 중에 판을 4 × 3 으로 고르게 나눈 칸 중 카드가 없는 칸 */
.mx-dash-slot { position: absolute; box-sizing: border-box; display: flex; align-items: stretch; z-index: 0; }
.mx-dash-slot-add { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
  font: inherit; font-size: 13px; color: var(--jv-txt3); background: transparent; cursor: pointer;
  border: 2px dashed var(--jv-txt4); border-radius: var(--nu-r-small); }
.mx-dash-slot-add b { font-size: 28px; font-weight: 400; line-height: 1; }
.mx-dash-slot-add:hover:not(:disabled), .mx-dash-slot-add:focus-visible { color: var(--jv-primary); border-color: var(--jv-primary); background: var(--jv-hover); }
.mx-dash-slot-add:disabled { cursor: default; opacity: .5; }
.mx-dash-pick { position: relative; width: min(560px, calc(100vw - 32px)); max-height: min(640px, calc(100vh - 64px)); display: flex; flex-direction: column;
  background: var(--jv-card); border: 1px solid var(--jv-border); border-radius: var(--nu-r-medium); box-shadow: 0 10px 30px rgba(0, 0, 0, .2); }
.mx-dash-pick-h { display: flex; align-items: center; gap: 10px; padding: 12px 16px; border-bottom: 1px solid var(--jv-border); }
.mx-dash-pick-h b { font-size: 15px; }
.mx-dash-pick-n { margin-left: auto; font-size: 12px; color: var(--jv-txt3); font-variant-numeric: tabular-nums; }
.mx-dash-pick-full { margin: 10px 16px 0; font-size: 13px; color: var(--jv-danger-text); }
/* 시간이 있는 판에서 빠진 카드 - 몇 장이 왜 빠졌는지(0.40.0) */
.mx-dash-pick-why { margin: 10px 16px 0; font-size: 12.5px; color: var(--jv-txt3); }
.mx-dash-pick-b { overflow: auto; padding: 8px 16px 14px; }
.mx-dash-pick-b h4 { margin: 12px 0 6px; font-size: 12px; color: var(--jv-txt3); font-weight: 700; }
.mx-dash-pick-b ul { list-style: none; margin: 0; padding: 0; }
.mx-dash-pick-b li { display: flex; align-items: center; gap: 8px; padding: 5px 0; border-bottom: 1px solid var(--jv-border); font-size: 13.5px; }
.mx-dash-pick-b li > span { flex: 1; }

/* 홈 탭 - 기본 탭과 내 대시보드.
   ★ 탭 모양도 꾸러미가 준다(0.37.11). 여태 「사이트 .hm-tab 을 그대로 입는다」여서 그 규칙이 있는 오토젠에서만 탭으로 보이고
     cheil · wht 에서는 맨 단추로 섰다(2026-09-30 적용 점검). 오토젠 .hm-tab 규칙을 그대로 옮겼다 - 오토젠 모양은 안 바뀐다.
   ★ 탭 줄은 밑선에 붙인다 - 탭 아래로, 단추 · 줄 끝 글은 밑선 위에 띄운다
   ★ 탭 높이(줄 높이 1.5 · 38.5px)는 단추(28px · 아래 5px)와 가운데 선이 맞는 값이다. 1.4(37px)에서는 탭이 단추보다 1.5px
     아래였다(0.40.6, cheil · wht - 오토젠 탭은 제 규칙이 줄 높이를 덮어 이미 38.5px 였다) */
.mx-home-bar { display: flex; align-items: flex-end; gap: 6px; flex-wrap: wrap; border-bottom: 1px solid var(--jv-border); }
.mx-home-bar > .mx-btn { margin-bottom: 5px; }
.mx-home-tab { font: inherit; font-size: 15px; font-weight: 500; line-height: 1.5; color: var(--jv-txt2);
  background: none; border: 1px solid transparent; border-radius: var(--nu-r-small) var(--nu-r-small) 0 0;
  padding: 7px 15px; margin-bottom: -1px; cursor: pointer; }
.mx-home-tab:hover { color: var(--jv-txt1); }
.mx-home-tab[aria-selected="true"] { background: var(--jv-card); border-color: var(--jv-border);
  border-bottom-color: var(--jv-card); color: var(--jv-txt1); font-weight: 700; }
.mx-home-tab:focus-visible { outline: 2px solid var(--chart-1); outline-offset: 1px; }
/* 고대비 - 탭 셋이 모두 흰 글자 · 같은 테두리가 되어 어느 탭인지 안 보였다(2026-09-30 cheil 고대비 실화면).
   고른 탭은 .mx-seg 고른 칸과 같게 Highlight 로 채운다 */
@media (forced-colors: active) {
  .mx-home-tab[aria-selected="true"] { forced-color-adjust: none; background: Highlight; color: HighlightText; border: 2px solid CanvasText; }
}
.mx-home-tabs { display: flex; align-items: flex-end; gap: 4px; flex-wrap: wrap; min-width: 0; }
.mx-home-tabs.is-editing { align-items: center; gap: 6px; padding: 4px 0; }
.mx-home-fill { flex: 1 1 auto; }
.mx-home-dico { margin-right: 5px; font-size: .85em; color: var(--jv-txt3); }
.mx-home-etab { display: inline-flex; align-items: center; gap: 2px; padding: 3px 4px 3px 10px; font-size: 13px;
  border: 1px solid var(--jv-border); border-radius: var(--nu-r-small); background: var(--jv-card); cursor: grab; }
.mx-home-etab.is-hidden .mx-home-elabel { color: var(--jv-txt3); text-decoration: line-through; }
.mx-home-etab.is-hidden small { text-decoration: none; }
.mx-home-elabel { margin-right: 4px; white-space: nowrap; }
.mx-home-ebtn { height: 22px; min-width: 22px; padding: 0 5px; font-size: 11px; color: var(--jv-txt2); background: transparent;
  border: 1px solid transparent; border-radius: var(--nu-r-small); cursor: pointer; }
.mx-home-ebtn:hover:not(:disabled) { border-color: var(--jv-border); background: var(--jv-hover); }
.mx-home-ebtn:disabled { opacity: .3; cursor: default; }
.mx-home-ebtn.is-danger { color: var(--jv-danger-text); font-weight: 700; }
.mx-home-rename { width: 10em; height: 24px; font-size: 13px; }
.mx-home-edit[aria-pressed="true"] { font-weight: 700; border-color: var(--jv-primary); color: var(--jv-primary); }
.mx-home-flash { font-size: 12.5px; color: var(--jv-danger-text); }
.mx-home-dtools { display: flex; align-items: center; gap: 8px; margin: 10px 0; }
.mx-home-dtools [aria-pressed="true"] { font-weight: 700; border-color: var(--jv-primary); color: var(--jv-primary); }
.mx-home-dhint { font-size: 12px; color: var(--jv-txt3); }
.mx-home-link { display: inline-flex; align-items: center; gap: 5px; font-size: 12.5px; color: var(--jv-txt2); cursor: pointer; }
/* 내 대시보드 시간(0.40.0) - 판 머리 넘기개는 편집 단추 앞, 방식 · 단위 고르기는 편집 중에만 */
.mx-home-dtime { display: inline-flex; align-items: center; margin-right: 8px; }
.mx-home-tmode { display: inline-flex; align-items: center; gap: 5px; font-size: 12.5px; color: var(--jv-txt2); }
.mx-home-tmode select { height: 28px; width: auto; }
.mx-home-tunits { display: inline-flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--jv-txt2); }
.mx-home-tunits label { display: inline-flex; align-items: center; gap: 3px; cursor: pointer; }
/* 카드 편집의 차트 모양 고르기(0.40.0) */
.mx-home-cchart { height: 24px; width: auto; font-size: 12px; padding: 0 4px; }
/* 카드 화면 단추 줄(0.40.0) - 화면 머리 줄 안 */
.mx-cscreen-bar { display: inline-flex; align-items: center; gap: 6px; }
.mx-cscreen-bar [aria-pressed="true"] { font-weight: 700; border-color: var(--jv-primary); color: var(--jv-primary); }
/* 기본 탭 프리셋 판(0.37.13) - 편집 줄 + 판. 판이 남은 높이를 채운다(fit 이 편집 줄만큼 뺀다) */
.mx-home-pmount { display: flex; flex-direction: column; min-height: 0; }
.mx-home-preset { flex: 1 1 auto; min-height: 0; }
.mx-home-ctools { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin: 0 0 10px; }
/* ★ hidden 을 display:flex 가 덮어 빈 편집 줄이 아래 여백(10px)을 먹었다 - 판이 그만큼 내려가 탭 칸이 2px 굴렀다(0.37.19, 1920x947 실측 778 / 776) */
.mx-home-ctools[hidden] { display: none; }
.mx-home-hidden { display: inline-flex; align-items: center; flex-wrap: wrap; gap: 4px; font-size: 12.5px; color: var(--jv-txt3); }
.mx-home-hidden .mx-home-ebtn { border-color: var(--jv-border); }
.mx-home-cedit[aria-pressed="true"] { font-weight: 700; border-color: var(--jv-primary); color: var(--jv-primary); }
.mx-home-empty { margin: 40px auto; font-size: 13px; color: var(--jv-txt3); text-align: center; }
/* 카드 편집 단추 - 카드 머리 오른쪽 위에 늘 선다(가리킬 때만 세우면 키보드 · 터치로 못 찾는다).
   ★ 판 칸(.mx-dash-item)은 이미 absolute 라 단추의 기준이 된다 - relative 로 덮으면 칸이 흐름으로 떨어져 대각선으로 쌓였다(0.37.13 실화면) */
.mx-dash-item.is-cedit > section { outline: 2px dashed var(--jv-border-strong); outline-offset: -2px; }
/* 카드 편집 중에는 카드 머리 오른쪽 도구(상태 표시 · 제 넘기개)를 감춘다 - 편집 단추 줄이 그 자리를 덮는다(0.40.0, 사출 설비현황 「활성」 칩).
   자리는 지켜 머리 높이가 안 흔들린다 */
.mx-dash-item.is-cedit .mx-card-tools { visibility: hidden; }
.mx-home-cbar { position: absolute; top: 6px; right: 6px; display: flex; gap: 2px; padding: 2px;
  background: var(--jv-card); border: 1px solid var(--jv-border); border-radius: var(--nu-r-small); z-index: 2; }
@media (forced-colors: active) {
  .mx-card, .mx-dash-tools, .mx-home-etab, .mx-dash-pick { border-color: CanvasText; }
  .mx-card { box-shadow: none; background-image: none; }   /* 떠 보이기는 고대비에서 끈다 - 테두리가 대신 가른다 */
  .mx-grid, .mx-pv-wrap, .widget-panel, .mx-surface { box-shadow: none; border-color: CanvasText; }
  /* 상태 띠 - 배경으로만 그린 조각이라 강제되면 사라진다. 조각에만 보정을 끈다(글자는 사용자 팔레트) */
  .mx-card[data-band]::before { forced-color-adjust: none; }
  .mx-dash.is-editing .mx-dash-item > section { outline: 2px dashed CanvasText; }
  .mx-dash-resize { border-color: CanvasText; }
  .mx-dash-slot-add { border-color: GrayText; color: CanvasText; }
  .mx-dash-slot-add:hover:not(:disabled), .mx-dash-slot-add:focus-visible { border: 2px solid CanvasText; }
  .mx-dash-btn, .mx-home-ebtn { border-color: GrayText; }
  .mx-dash-btn[aria-disabled="true"], .mx-home-ebtn:disabled { color: GrayText; }
  /* ★ 홈통은 **굵기로** 가른다 - 굵은 고리(0.37.15)에서 홈통이 호와 같은 굵기로 GrayText 가 되면
       「—」 와 8% 가 꽉 찬 고리로 읽혔다(2026-09-30 오토젠 고대비 실화면). 홈통만 가늘게 */
  .mx-gauge-bg { stroke: GrayText; stroke-width: 3px; }
  /* 채운 호는 Highlight - CanvasText 로 두면 바탕 고리(GrayText)와 가까워 97% 와 100% 가 온통 흰 고리로 섰다(2026-09-30 cheil 고대비 실화면) */
  .mx-gauge-fg, .mx-gauge-fg.is-full { stroke: Highlight; }
  /* 계기판 · 진행 막대(0.40.0) - 고리와 같은 규칙: 홈통은 가늘게 GrayText, 채운 것은 Highlight, 바늘 · 눈금은 글자색 */
  .mx-meter-bg { stroke: GrayText; stroke-width: 3px; }
  .mx-meter-fg, .mx-meter-fg.is-full { stroke: Highlight; }
  .mx-meter-nd, .mx-meter-tk { stroke: CanvasText; }
  .mx-meter-hub { fill: CanvasText; }
  .mx-card-progress { forced-color-adjust: none; background: Canvas; border: 1px solid CanvasText; }
  .mx-card-progress > s, .mx-card-progress > s.is-full { background: Highlight; }
  .mx-cscreen-bar [aria-pressed="true"] { border: 2px solid CanvasText; }
  .mx-cnav-b { border-color: CanvasText; }
    .mx-home-edit[aria-pressed="true"], .mx-home-dtools [aria-pressed="true"], .mx-home-cedit[aria-pressed="true"] { border: 2px solid CanvasText; }
  .mx-home-cbar { border-color: CanvasText; }
  .mx-dash-item.is-cedit > section { outline-color: CanvasText; }
  /* 범례 견본은 도넛 조각과 같은 색이어야 한다 - 강제 색상이 바탕을 지워 견본이 사라졌다(2026-09-30 실화면) */
  .mx-sw { forced-color-adjust: none; outline: 1px solid CanvasText; }
}
