/* ═══════════════════════════════════════════════════════════════════════════
   이 보드 고유 화면 규칙
   ───────────────────────────────────────────────────────────────────────────
   공통 규칙은 @marunex/board-core 의 styles.css 가 준다. 여기 남은 것은 이
   프로젝트에만 있는 화면(협약 성과지표·사출기·추천·서열 …)과, 공통과 달라진 곳이다.

   ★ 이 파일은 꾸러미 styles.css **뒤에** 실린다. 같은 선택자면 여기가 이긴다.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── 컨텐츠 영역 ─────────────────────────────────────────────────── */
.content {
  display: flex;
  flex-direction: column;
  gap: 20px;
  padding: 24px 28px;
  flex: 1;
  min-height: 0;
  overflow-y: auto;
}

/* 세로가 짧은 화면에서 여백을 조인다.

   ★ **.content 를 여기 남겼으니 .content 의 @media 규칙도 여기 있어야 한다.**
     미디어 질의는 명시도를 올리지 않는다 — 기본 규칙만 이 파일(나중 로드)로 오고
     이것들이 꾸러미(먼저 로드)에 남으면 순서가 뒤집혀 **오류 없이 죽는다.**
     실제로 그랬다: 통합 전과 견줘 보니 880x760 에서 여백이 24/28 로 남아 있었고
     (원래는 16/22) 그 20px 이 표 열 폭까지 통째로 밀고 있었다.
     cheil-poc 은 처음부터 이렇게 함께 옮겨 두었다. */
@media (max-height: 780px) {
  .content { padding: 16px 22px; gap: 14px; }
}

@media (max-height: 700px) {
  .content { padding: 12px 20px; gap: 10px; }
}

@media (max-height: 820px) {
  .content { padding: 12px 18px; gap: 10px; }
}

/* 노트북 등 세로가 짧은 화면: 상단 고정 블록을 줄여 차트 자리를 확보 */
@media (max-height: 860px) {
  /* ※ KRI 배너(파란 줄) 관련 규칙은 여기 두지 않는다 — 아래 §KRI 배너 두께 조이기
     블록이 파일 뒤쪽에 있어 같은 특정도면 그쪽이 이긴다(여기 적으면 조용히 죽는다).
     짧은 창용 추가 압축은 그 블록 바로 뒤 미디어쿼리에 있다. */
  #layoutRoot.home-fill .home-kpi { padding: 10px 16px; }
  #layoutRoot.home-fill .home-kpi-v { font-size: 1.6rem; }
}

/* ── 홈 KRI 배너(파란 줄) 두께 조이기 ────────────────────────────────────────
   ★ 홈 전용이다(.home-fill). 같은 클래스를 쓰는 다른 화면의 총계 박스(.kri-totals)는
     건드리지 않는다 — 거기선 이 박스가 화면의 주인공이지만, 홈에서는 아래 차트 4장이
     주인공이고 이 줄은 고정 높이(flex:0 0 auto)라 두꺼워진 만큼 차트가 그대로 눌린다.
   ★ 줄인 건 여백·게이지 두께뿐이고 글자 크기·대비는 유지한다(§6-E 가독 기준). */
#layoutRoot.home-fill > .home-kri { padding: 8px 14px; }
#layoutRoot.home-fill .home-kri-cards { gap: 10px; }
#layoutRoot.home-fill .home-kri-card { padding: 7px 12px; }
#layoutRoot.home-fill .home-kri-goal { line-height: 1.35; }
#layoutRoot.home-fill .home-kri-goal b { font-size: 15px; }
#layoutRoot.home-fill .home-kri-desc { line-height: 1.4; margin-top: 3px; }
/* 진척 게이지 — 8px 는 이 카드에서 과하다. 6px 로도 채움 길이는 그대로 읽힌다 */
#layoutRoot.home-fill .kri-gauge { margin: 4px 0 3px; height: 6px; }
/* 짧은 창에서 한 단계 더 — 설명줄이 2줄로 접히는 게 이 배너 높이의 절반이라 먼저 줄인다 */
@media (max-height: 860px) {
  #layoutRoot.home-fill > .home-kri { padding: 6px 12px; }
  #layoutRoot.home-fill .home-kri-card { padding: 6px 11px; }
  #layoutRoot.home-fill .home-kri-desc { font-size: 10px; line-height: 1.35; }
}

/* ── 홈 재고현황 타일 (통계 카드 §6-D 하단형) ─────────────────────────── */
/* ★ 2026-09-14 에 완제품 재고 추이 선그래프를 걷었다(사용자 요청) - 타일 넷(원단 롤 · 재단품 ·
   완제품 · 팔레트)이 카드 높이를 채운다. 수치는 KPI 카드보다 한 단계 작게 둔다. */
#layoutRoot.home-fill .home-inv-row { gap: 10px; }
#layoutRoot.home-fill .home-inv {
  background: var(--jv-page); border: 1px solid var(--jv-border); border-radius: var(--nu-r-large); padding: 8px 10px;
}
#layoutRoot.home-fill .home-inv-l { font-size: 11px; color: var(--jv-txt3); margin-bottom: 3px; }
#layoutRoot.home-fill .home-inv-v {
  font-size: 20px; font-weight: 700; color: var(--jv-txt1);
  font-variant-numeric: tabular-nums; line-height: 1; letter-spacing: -0.02em;
}
#layoutRoot.home-fill .home-inv-v span { font-size: 12px; font-weight: 600; color: var(--jv-txt3); margin-left: 3px; }
#layoutRoot.home-fill .home-note { font-size: 10px; line-height: 1.35; color: var(--jv-txt4); margin-top: 6px; }

/* 재고현황 - 타일 줄이 카드 높이를 채우고 값은 타일 가운데 */
#layoutRoot.home-fill .home-inv-row { flex: 1 1 auto; align-items: stretch; min-height: 0; }
#layoutRoot.home-fill .home-inv { display: flex; flex-direction: column; justify-content: center; }

/* 짧은 창에서의 밀집 보정 — 무스크롤 규칙과 함께 동작 */
@media (max-height: 860px) {
  #layoutRoot.home-fill .jv-kpi { padding: 11px 14px; gap: 11px; }
  #layoutRoot.home-fill .jv-kpi-ico { width: 40px; height: 40px; border-radius: var(--nu-r-large); }
  #layoutRoot.home-fill .jv-kpi-ico svg { width: 19px; height: 19px; }
  #layoutRoot.home-fill .home-kpi-v { font-size: 22px; }
  /* 재고 타일은 기본값이 이미 20px 이라 더 줄인다 */
  #layoutRoot.home-fill .home-inv-v { font-size: 18px; }
}
@media (max-height: 720px) {
  #layoutRoot.home-fill .jv-kpi-ico { width: 34px; height: 34px; }
  #layoutRoot.home-fill .jv-kpi-ico svg { width: 17px; height: 17px; }
  #layoutRoot.home-fill .home-kpi-v { font-size: 19px; }
  #layoutRoot.home-fill .home-inv-v { font-size: 16px; }
  #layoutRoot.home-fill .home-note { margin-top: 5px; }
}
/* 로고 — 다크 배경용 흰 칩이 흰 사이드바에서 안 보이므로 칩 제거. */
.brand-ci { background: transparent; box-shadow: none; padding: 0; }
/* 머리말 영역을 나누는 경계선과 밴드 높이는 이 파일 끝의
   [좌측 메뉴 — 머리말 경계선 정렬 · 접기] 블록이 정한다(상단 바와 한 줄로 이어야 하므로).
   여기서 padding-bottom·border-bottom 을 다시 선언하지 말 것 — 두 곳이 되면 또 어긋난다. */

/* ── 아이콘 거터 ───────────────────────────────────────────────────────
   그룹명 앞 아이콘이 차지하는 폭. 하위 항목은 아이콘이 없으므로 이 폭만큼
   들여써서 "그룹명 글자"와 "하위 항목 글자"의 왼쪽 선을 맞춘다 —
   아이콘 열이 하나의 거터로 읽혀야 목록이 흐트러지지 않는다.
   아이콘 크기를 바꾸면 이 값도 같이 바꿀 것(--nav-ico + gap). */
:root {
  --nav-ico: 16px; --nav-ico-gap: 7px;
  /* 하위 항목 들여쓰기 — 사이드바 폭을 정하는 값이라 한 곳에서만 관리한다.
     예전에는 이 계산식이 기본 규칙과 압축 미디어쿼리 두 곳에 복사돼 있어서 한쪽만 고치면
     데스크톱에서만 어긋났다. 변수로 빼서 그 사고를 구조적으로 막는다.
     --nav-sub-line   가이드선의 x 위치
     --nav-sub-indent 하위 항목 글자의 x 위치 (둘 다 사이드바 안쪽 여백 기준) */
  --nav-sub-line: 14px;
  /* 33px = summary 왼쪽 padding 10 + 아이콘 16 + 갭 7.
     하위 항목 글자의 왼쪽 선을 그룹명 글자에 맞춘다(2026-09-01 요청).
     ※ 꾸러미 원본은 25px 이었다 — 사이드바 폭을 아끼려고 일부러 덜 들여썼던 값이다.
       폭 예산: 여백10 + 33 + "설비별 생산현황"(약 91) + 우여백10 + 여백10 ≈ 154px < 180px 라
       지금 메뉴에서는 넘치지 않는다. 더 긴 항목을 넣을 땐 이 계산을 다시 할 것. */
  --nav-sub-indent: 33px;
}

/* ═══════════════════════════════════════════════════════════════════════════
   좌측 메뉴 — 머리말 경계선 정렬 · 접기(본문 전체화면)
   앞쪽 규칙과 미디어쿼리(콤팩트 max-height:820px / 데스크톱 min-width:1201px)에
   흩어져 있던 값을 여기서 확정한다. 같은 특이도면 나중 블록이 이기므로 이 블록이 정본이다.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── ① 로고 밴드 높이 = 상단 바 높이 ───────────────────────────────────────
   사이드바 로고 아래 경계선과 본문 상단 바(.topbar) 아래 경계선이 화면을 가로지르는
   "한 줄"로 이어져야 한다. 어긋나 있던 이유는 두 가지였다.
     · 높이  — 로고 밴드는 사이드바 위여백(11) + 로고(32) + 아래여백(10) = 53px 였고 상단 바는 44px
     · 색    — 로고는 --jv-border-l(연한 선), 상단 바는 --jv-border 로 서로 다른 톤이었다
   높이를 --topbar-h 한 곳에서 읽게 하고 선 색도 같은 토큰으로 맞춘다. 값을 두 곳에
   적으면 한쪽만 고쳐 다시 어긋나므로 .topbar 도 이 변수를 쓴다.
   ★ 여백은 사이드바가 아니라 .nav 가 갖는다 — 사이드바에 위여백이 있으면 로고 밴드가
     그만큼 아래로 밀려 정렬이 다시 깨진다. (box-sizing: border-box 라 44px 안에 경계선 1px 포함) */
:root { --topbar-h: 44px; }
/* 로고는 밴드(44px - 경계선 1px) 안에 위아래 여백을 두고 들어가는 크기로 고정.
   앞쪽 규칙의 46px(기본)·32px(데스크톱)를 여기서 한 값으로 모은다. */
.brand-ci { height: 30px; }

.nav {
  padding: 8px 10px 12px;
  overflow-y: auto;
  min-height: 0;
  flex: 1;
  /* ★ .nav 는 grid 인데 flex:1 로 사이드바 높이를 채운다. 그리드의 기본 align-content 는
     stretch 라서, 내용이 짧아지면 **남는 높이가 행 사이로 배분된다** — 메뉴를 전부 접었을 때
     그룹명이 100px씩 떨어져 뜨던 원인이 이것이다(글자 크기 문제가 아니었다).
     start 로 고정해 행은 제 높이만 쓰고 남는 공간은 아래에 그대로 둔다 →
     펼쳤을 때와 접었을 때의 항목 간격(2px)·그룹 간격(8px)이 똑같이 유지된다. */
  align-content: start;
}

/* ═══ 신규 화면 (2026-08-12) — 추천·변동·수신상태·서열장·보정 ═══════════════════
   색은 전부 토큰 참조(색 리터럴 0 원칙). 표는 demand-grid 를 재사용하고
   여기서는 상태 표기(결품/부족/Δ/수신)만 얹는다. */

/* 추천 화면 — 커버 구간 강조·상태 배지 */
.demand-grid td.re-cover { background: var(--nu-primary-tint); }
.demand-grid thead th.re-cover-h { box-shadow: inset 0 -3px 0 var(--nu-primary); }
.demand-grid .re-rec { font-weight: 700; color: var(--nu-brand-text); }
.re-badge {
  display: inline-block; padding: 1px 7px; border-radius: var(--nu-r-pill);
  font-size: 0.72rem; font-weight: 700; vertical-align: 1px;
}
.re-urgent { background: var(--nu-alert-light);   color: var(--nu-alert-text);   border: 1px solid var(--nu-alert-border); }
.re-short  { background: var(--nu-warning-light); color: var(--nu-warning-text); border: 1px solid var(--nu-warning-border); }
.re-new    { background: var(--nu-success-light); color: var(--nu-success-text); border: 1px solid var(--nu-success-border); }
.re-gone   { background: var(--nu-surface-2);     color: var(--nu-txt3);         border: 1px solid var(--nu-border); }
.re-own    { background: var(--nu-info-light);    color: var(--nu-info-text);    border: 1px solid var(--nu-info-border); }
.demand-grid tr.re-row-urgent > td:first-child { box-shadow: inset 3px 0 0 var(--nu-alert); }
.demand-grid tr.re-row-short  > td:first-child { box-shadow: inset 3px 0 0 var(--nu-warning); }
.re-est { color: var(--nu-warning-text); font-weight: 700; margin-right: 2px; }
.re-warn { color: var(--nu-warning-text); font-weight: 700; }
.re-boxes { color: var(--nu-txt3); font-size: 0.78rem; }
/* ── 추천 표 컬럼 폭 (2026-08-18) ─────────────────────────────────────────
   v0.8.2 이식으로 컬럼이 10개 늘어 표가 가로로 넘쳤고, **정작 주인공인 추천량이
   화면 밖으로 밀렸다**(캡처로 확인). 데스크톱도 같은 이유로 '헤더 단축·폭 축소'를 했다.
   table-layout:fixed 라 **헤더 폭만 정하면 본문이 따라온다** — 그래서 th 에만 건다.
   품명은 폭을 주지 않고 남는 폭을 먹게 두고, 넘치면 말줄임(공통 규칙이 이미 걸려 있다). */
.re-grid thead th.re-w-st { width: 54px; }
.re-grid thead th.re-w-pn { width: 122px; }
.re-grid thead th.re-w-nm { width: 128px; }
.re-grid thead th.re-w-m  { width: 62px; }
.re-grid thead th.re-w-s  { width: 48px; }
.re-grid thead th.dm-day  { width: 38px; }
.re-grid thead th.re-t    { width: 56px; }
/* 좁아진 만큼 안쪽 여백도 줄인다 — 숫자가 잘리면 폭을 줄인 의미가 없다 */
.re-grid thead th, .re-grid tbody td { padding-left: 4px; padding-right: 4px; }

.re-kpi-urgent { color: var(--nu-alert-text); }
.re-kpi-short  { color: var(--nu-warning-text); }

/* ── 계획 대상일 줄 (2026-08-18, FlowTracer v0.8.2 PlanDateLabel 승계) ───────
   "D+1" 은 현장에서 안 읽힌다 — 오늘/내일/모레와 요일을 문장으로 쓴다.
   오늘분을 고치는 중이면 눈에 띄게, 지난 날짜면 경고색. 색만으로 알리지 않고 문장에 다 들어 있다. */
.re-plandate {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  padding: 7px 14px; border-radius: var(--nu-r-large);
  background: var(--nu-surface-2); border: 1px solid var(--nu-border);
  font-size: 0.9rem; color: var(--nu-txt1);
}
.re-plandate .re-pd-sub { font-size: 0.78rem; color: var(--nu-txt3); font-weight: 400; }
.re-pd-today { background: var(--nu-primary-tint); border-color: var(--nu-primary); color: var(--nu-brand-text); }
.re-pd-past  { background: var(--nu-alert-light);  border-color: var(--nu-alert-border); color: var(--nu-alert-text); }
.re-pd-btn {
  padding: 3px 10px; border-radius: var(--nu-r-pill); cursor: pointer;
  background: var(--nu-card); border: 1px solid var(--nu-border); color: var(--nu-txt2); font-size: 0.8rem;
}
.re-pd-btn:hover { border-color: var(--nu-primary); color: var(--nu-brand-text); }
/* 「데이터 유의사항」 - 대상일 안내 줄 오른쪽 끝. 펼치면 표를 밀지 않고 아래로 떠서 열린다
   (출하 실적·보정 .sa-data-note 와 같은 꼴 · 글 꼴은 .data-note > ul 공통, 2026-09-14 사용자 요청) */
.re-plandate > .re-pd-note { position: relative; margin-left: auto; align-self: center; font-weight: 400; }
.re-plandate > .re-pd-note > ul {
  position: absolute; right: 0; top: calc(100% + 6px); z-index: 30;
  width: min(620px, 80vw); max-height: 50vh; overflow: auto;
  background: var(--nu-card); border: 1px solid var(--nu-border);
  border-radius: 4px; box-shadow: 0 6px 20px rgba(0, 0, 0, .12);
  padding: 10px 14px 10px 28px;
}
/* 출하계획 조회 줄 - 창이 좁아 두 줄로 접힐 때 줄 사이(14px)가 넓어 보인다는 요청으로 줄 간격만 줄인다.
   칸 사이 가로 간격은 그대로. 사출 추천(같은 함수)은 건드리지 않는다. */
.re-ship-panel > .demand-toolbar { row-gap: 6px; }
/* 계획 대상일 컬럼 — 커버 구간(아래 실선)과 구분되게 위쪽에 표시한다 */
.demand-grid thead th.re-target-h { box-shadow: inset 0 -3px 0 var(--nu-primary), inset 0 3px 0 var(--nu-warning); }
/* 재고 근거 배지 — 색이 아니라 글자가 판정을 담는다(실사/계산/≈인수/—) */
.re-basis { font-size: 0.76rem; color: var(--nu-txt3); border-bottom: 1px dotted var(--nu-border); cursor: help; }
/* 재고 미상 — 결품(빨강)과 **다른 색**이어야 한다. 미상을 결품으로 읽게 하지 않는 것이 요점이다. */
.re-unknown { background: var(--nu-surface-2); color: var(--nu-txt3); border: 1px dashed var(--nu-border); }
.demand-grid tr.re-row-unknown > td:first-child { box-shadow: inset 3px 0 0 var(--nu-txt4); }
.demand-grid tr.re-row-unknown { opacity: 0.86; }

/* 사출 수량제안 — 금형 그룹 헤더 행 (금형 그룹핑 스티키는 표 헤더가 담당, 행은 구분띠만) */
.demand-grid tr.re-die-row > td {
  background: var(--nu-surface-2); color: var(--nu-txt2);
  font-weight: 700; font-size: 0.8rem; text-align: left; padding: 5px 10px;
  border-top: 2px solid var(--nu-border-strong);
}

/* 변동 분석 — Δ 방향색 (증가=경보 계열, 감소=정보 계열. 글자는 -text 톤으로 4.5:1 확보) */
.rd-up   { color: var(--nu-alert-text); font-weight: 600; }
.rd-down { color: var(--nu-info-text);  font-weight: 600; }

/* 수신 상태 — 수신/결측/주말 행 */
.rs-ok   { color: var(--nu-success-text); font-weight: 700; }
.rs-miss { color: var(--nu-alert-text);   font-weight: 700; }
.demand-grid tr.rs-weekend > td { color: var(--nu-txt4); }
.demand-grid tr.rs-missrow > td { background: var(--nu-alert-light-2); }

/* 보정 이력 — 취소(soft-cancel)된 이력은 흐리게 (이력 보존 lifecycle 표현) */
.demand-grid tr.corr-canceled > td { color: var(--nu-txt4); }
.demand-grid tr.corr-canceled .rd-up,
.demand-grid tr.corr-canceled .rd-down { color: var(--nu-txt4); }

/* 신규 화면의 넓은 표 — 열 폭 고정(서열계획 전용 규칙)에서 빠져나온다.
   ★ .demand-panel 은 fit-page 높이 배분(flex)을 담당하므로 그대로 두고, 표 레이아웃만 뒤집는다.
   서열계획 표는 좌측 5열을 못 박아 D+14 까지 한 화면에 넣는 설계지만, 여기 표들은 열 수가
   28개(추천)·17개(서열장)까지 늘어 같은 규칙을 쓰면 품번·헤더가 전부 말줄임으로 뭉개진다.
   → 내용에 맞춘 폭(auto) + 가로 스크롤(.demand-grid-wrap 이 이미 overflow:auto). */
.demand-panel.grid-auto .demand-grid { table-layout: auto; width: max-content; min-width: 100%; }
.demand-panel.grid-auto .demand-grid th,
.demand-panel.grid-auto .demand-grid td { overflow: visible; text-overflow: clip; }
/* 품명은 값이 길어(예: "FRT SECL LH 일체형 사출") 표 전체를 1920 밖으로 밀어낸다.
   열 자체를 좁히면 헤더까지 뭉개지므로 값만 말줄임하고 전체 문구는 title 툴팁으로 준다
   (1920x1080 무스크롤 기준 유지). */
.demand-panel.grid-auto .demand-grid .re-name {
  display: inline-block; max-width: 168px; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; vertical-align: bottom;
}
/* 추천 표(32열)는 위 max-width 로도 1920 을 넘겼다 — 이 표에서만 더 조인다.
   전문은 title 툴팁에 그대로 있다(§0-4 '수치엔 출처·설명' 규약 유지). */
.demand-panel.grid-auto .demand-grid.re-grid .re-name { max-width: 116px; }
.re-grid .dm-bd { font-size: 0.72rem; }
/* 32열 표는 글자 한 단계를 낮춰야 1920 안에 들어온다. 데스크톱도 같은 이유로 폭을 줄였다
   ('판단에 안 쓰는 것을 걷어내 한 화면에 더 보이게', v0.8.2). */
.re-grid { font-size: 0.76rem; }
/* 상태 열은 맨 앞(항상 보이는 자리)에 둔다 — 28열 표라 우측 끝은 가로 스크롤로 밀린다. */
.demand-panel.grid-auto .demand-grid .re-st { min-width: 54px; }
/* 플레이스홀더 표는 빈 표라 남는 높이를 먹으면 화면 대부분이 흰 여백이 된다 — 제 높이만 쓴다. */
#layoutRoot.fit-page > .panel > .demand-grid-wrap.ph-wrap { flex: 0 0 auto; min-height: 0; max-height: none !important; }

/* ═══ 사출기 연동 — 키오스크 작업 전시부 (2026-08-13 연동 사전자료 반영) ═══════════
   작업흐름 ①~⑩ 중 화면이 담당하는 부분: 다음 작업의 금형·수량·레시피를 크게 전시하고,
   작업자가 금형을 장착한 뒤 [작업 시작]을 누르면 서버가 ③~⑥을 연달아 수행한다. */
.inj-now {
  border: 1px solid var(--nu-primary-lightest); border-left: 5px solid var(--nu-primary);
  border-radius: var(--nu-r-large); background: var(--nu-primary-tint);
  padding: 14px 16px; display: flex; flex-direction: column; gap: 10px;
}
.inj-now.run { border-color: var(--nu-warning-border); border-left-color: var(--nu-warning); background: var(--nu-warning-light-3); }
.inj-now-head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.inj-now-tag {
  font-size: 0.74rem; font-weight: 800; padding: 2px 9px; border-radius: var(--nu-r-pill);
  background: var(--nu-primary); color: var(--nu-on-accent);
}
.inj-now.run .inj-now-tag { background: var(--nu-warning); color: var(--nu-ink); }
.inj-now-seq { font-size: 0.86rem; font-weight: 700; color: var(--nu-brand-text); }
.inj-now-item { font-size: 1.02rem; font-weight: 800; color: var(--nu-txt1); }
.inj-now-of { margin-left: auto; font-size: 0.78rem; color: var(--nu-txt3); }

.inj-now-body { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr); gap: 14px; align-items: stretch; }
@media (max-width: 1100px) { .inj-now-body { grid-template-columns: 1fr; } }
.inj-now-main { display: flex; flex-direction: column; gap: 6px; justify-content: center; }
.inj-now-kv { display: flex; align-items: baseline; gap: 10px; }
.inj-now-kv > span { width: 68px; flex: none; font-size: 0.78rem; color: var(--nu-txt3); }
.inj-now-kv > b { font-size: 0.98rem; color: var(--nu-txt1); }
/* 금형이름·수량은 작업자가 멀리서 확인하는 값이라 크게 — 키오스크 전시 목적 */
.inj-now-mold { font-size: 1.35rem !important; font-weight: 800; letter-spacing: 0.01em; font-family: 'Consolas', monospace; }
.inj-now-qty { font-size: 1.35rem !important; font-weight: 800; font-variant-numeric: tabular-nums; }
.inj-now-qty small { font-size: 0.8rem; font-weight: 600; color: var(--nu-txt3); margin-left: 2px; }

.inj-now-recipe { background: var(--nu-card); border: 1px solid var(--nu-border); border-radius: var(--nu-r-medium); padding: 10px 12px; }
.inj-rc-title { font-size: 0.82rem; font-weight: 700; color: var(--nu-txt2); margin-bottom: 7px; }
.inj-rc-title small { font-weight: 400; color: var(--nu-txt4); margin-left: 6px; }
.inj-rc-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 7px 12px; }
.inj-rc-item { display: flex; flex-direction: column; gap: 1px; }
.inj-rc-item span { font-size: 0.72rem; color: var(--nu-txt4); }
.inj-rc-item b { font-size: 0.9rem; color: var(--nu-txt1); }
.inj-rc-note { margin-top: 8px; font-size: 0.78rem; color: var(--nu-warning-text); }
.inj-rc-empty { font-size: 0.82rem; color: var(--nu-txt3); line-height: 1.5; }
.inj-rc-empty small { color: var(--nu-txt4); }

/* 금형 교체 분기 — "같은 금형이면 ⑦~⑩ 반복 / 다르면 ③ 장착부터 다시" */
.inj-mold-chg { font-size: 0.85rem; padding: 8px 12px; border-radius: var(--nu-r-medium); }
.inj-mc-keep   { background: var(--nu-success-light); color: var(--nu-success-text); }
.inj-mc-change { background: var(--nu-warning-light); color: var(--nu-warning-text); border: 1px solid var(--nu-warning-border); }
.inj-mc-mount  { background: var(--nu-info-light);    color: var(--nu-info-text);    border: 1px solid var(--nu-info-border); }
.inj-mc-none   { background: var(--nu-alert-light);   color: var(--nu-alert-text);   border: 1px solid var(--nu-alert-border); }

.inj-mount-chk { display: flex; align-items: center; gap: 8px; font-size: 0.86rem; color: var(--nu-txt2); cursor: pointer; }
.inj-mount-chk input { width: 17px; height: 17px; cursor: pointer; }

.inj-now-actions { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.inj-now-actions .inj-precond { flex: 1 1 260px; margin: 0; }
.inj-start-lg {
  flex: none; padding: 11px 30px; font-size: 1rem; font-weight: 800;
  border: none; border-radius: var(--nu-r-medium); cursor: pointer;
  background: var(--nu-primary); color: var(--nu-on-accent);
}
.inj-start-lg:hover:not(:disabled) { background: var(--nu-primary-dark); }
.inj-start-lg:disabled { background: var(--nu-surface-4); color: var(--nu-txt4); cursor: default; }

/* 단계바 화살표 */
.inj-step-arrow { color: var(--nu-txt4); font-weight: 700; }

/* 목록의 금형 유지/교체 배지 + 다음 차례 행 강조 */
.inj-chg { font-size: 0.72rem; font-weight: 700; padding: 1px 7px; border-radius: var(--nu-r-pill); }
.inj-chg.keep   { background: var(--nu-success-light); color: var(--nu-success-text); }
.inj-chg.change { background: var(--nu-warning-light); color: var(--nu-warning-text); }
.inv-grid tr.inj-r-next > td:first-child { box-shadow: inset 3px 0 0 var(--nu-primary); }
/* 전시 카드는 목록 높이를 덜 먹도록 조인다 — 1920x1080 한 화면에 목록까지 들어와야 한다. */
.inj-now { padding: 11px 14px; gap: 8px; }
.inj-now-body { gap: 12px; }
.inj-now-mold, .inj-now-qty { font-size: 1.22rem !important; }
.inj-rc-grid { gap: 5px 12px; }
.inj-now-actions { gap: 10px; }
/* 전송 이력은 참고 자료 — 남는 높이는 작업지시 목록이 먼저 가져간다 */
/* ★ fit-page 규칙이 .inv-grid-wrap 의 max-height 를 !important 로 풀어 버리므로 여기서 되돌린다 —
   안 그러면 이력이 자기 높이만큼 늘어나 정작 중요한 작업지시 목록이 두어 줄로 눌린다. */
#layoutRoot.fit-page > .panel > .inv-grid-wrap.inj-hist-wrap { flex: 0 0 auto; max-height: 132px !important; }

/* ═══ 협약 성과지표(KPI) 화면 — SIM-TD3-018/019/020 ══════════════════════════
   색은 tokens.css 의 --kpi-* 만 쓴다(hex 리터럴 0). 상태색은 채움 전용이고
   글자는 --nu-*-text 톤을 써서 4.5:1 을 지킨다(색 규칙 4). */
.kpi-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.kpi-head-title { font-size: 1.05rem; font-weight: 800; color: var(--nu-txt1); }
.kpi-head-title small { font-weight: 500; font-size: 0.78rem; color: var(--nu-txt3); margin-left: 8px; }
.kpi-head-sub { margin-top: 3px; font-size: 0.82rem; color: var(--nu-txt3); }
.kpi-muted { color: var(--nu-txt4); }

.kpi-cards { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
@media (max-width: 1100px) { .kpi-cards { grid-template-columns: 1fr; } }
.kpi-card {
  border: 1px solid var(--nu-border); border-left: 5px solid var(--nu-surface-4);
  border-radius: var(--nu-r-large); background: var(--nu-card);
  padding: 14px 16px; display: flex; flex-direction: column; gap: 8px;
}
.kpi-card.link { cursor: pointer; }
.kpi-card.link:hover { border-color: var(--nu-primary-lightest); box-shadow: var(--nu-elev-low); }
.kpi-c-achieved { border-left-color: var(--nu-primary); }
.kpi-c-on_track { border-left-color: var(--kpi-st-good); }
.kpi-c-warn     { border-left-color: var(--kpi-st-warn); }
.kpi-c-risk     { border-left-color: var(--kpi-st-risk); }
.kpi-c-no_data  { border-left-color: var(--nu-surface-4); }

.kpi-card-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.kpi-card-id { font-size: 0.72rem; font-weight: 800; color: var(--nu-txt4); font-family: 'Consolas', monospace; }
.kpi-card-name { font-size: 0.95rem; font-weight: 700; color: var(--nu-txt1); }
.kpi-badge { font-size: 0.72rem; font-weight: 700; padding: 1px 8px; border-radius: var(--nu-r-pill); }
.kpi-b-achieved { background: var(--nu-primary-tint);  color: var(--nu-brand-text); }
.kpi-b-on_track, .kpi-b-good { background: var(--nu-success-light); color: var(--nu-success-text); }
.kpi-b-warn     { background: var(--nu-warning-light); color: var(--nu-warning-text); }
.kpi-b-serious  { background: var(--nu-warning-light-2); color: var(--nu-warning-text-2); }
.kpi-b-risk     { background: var(--nu-alert-light);   color: var(--nu-alert-text); }
.kpi-b-no_data  { background: var(--nu-surface-2);     color: var(--nu-txt3); }
.kpi-b-method   { background: var(--nu-info-light);    color: var(--nu-info-text); }

.kpi-value { font-size: 2.1rem; font-weight: 800; color: var(--nu-txt1); line-height: 1.1; }
.kpi-value small { font-size: 0.95rem; font-weight: 700; color: var(--nu-txt3); margin-left: 4px; }
.kpi-sub { font-size: 0.84rem; color: var(--nu-txt3); }
.kpi-improve { margin-left: 8px; font-weight: 800; }
.kpi-improve.up   { color: var(--nu-brand-text); }   /* 개선(감소) — 파랑 ▼ */
.kpi-improve.down { color: var(--nu-alert-text); }   /* 악화 */
.kpi-foot { display: flex; justify-content: space-between; font-size: 0.78rem; color: var(--nu-txt3); }

/* 진척 게이지 — 채움 MIN(진척,120)/120, 100% 위치 눈금 고정 */
.kpi-gauge { position: relative; height: 10px; border-radius: var(--nu-r-pill); background: var(--nu-surface-3); overflow: hidden; }
.kpi-gauge-fill { height: 100%; border-radius: var(--nu-r-pill); transition: width 0.3s; }
.kpi-g-achieved { background: var(--nu-primary); }
.kpi-g-on_track { background: var(--kpi-st-good); }
.kpi-g-warn     { background: var(--kpi-st-warn); }
.kpi-g-risk     { background: var(--kpi-st-risk); }
.kpi-g-no_data  { background: var(--nu-surface-4); }
.kpi-gauge-100 { position: absolute; top: 0; bottom: 0; left: 83.33%; width: 2px; background: var(--nu-txt4); opacity: 0.6; }

/* 산출 불가 — 값을 지어내지 않고 사유와 막힌 소스를 보여준다 */
.kpi-nodata { font-size: 1.35rem; font-weight: 800; color: var(--nu-txt4); }
.kpi-nodata-why { font-size: 0.84rem; color: var(--nu-warning-text); }
.kpi-block-list { margin: 2px 0 0; padding-left: 18px; font-size: 0.8rem; color: var(--nu-txt3); }
.kpi-quality { font-size: 0.76rem; color: var(--nu-txt4); border-top: 1px solid var(--nu-border-l); padding-top: 7px; }
.kpi-quality.low { color: var(--nu-alert-text); }

.kpi-def-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
@media (max-width: 1100px) { .kpi-def-grid { grid-template-columns: 1fr; } }
.kpi-def { background: var(--nu-page); border-radius: var(--nu-r-medium); padding: 10px 13px; font-size: 0.84rem; color: var(--nu-txt2); }
.kpi-def b { display: block; margin-bottom: 3px; color: var(--nu-txt1); }

/* 산출식 전개 — 수식에 이번 기간 실제 값을 대입해 보여준다 */
.kpi-fx-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
@media (max-width: 1100px) { .kpi-fx-grid { grid-template-columns: 1fr; } }
.kpi-formula { border: 1px solid var(--nu-border); border-radius: var(--nu-r-medium); padding: 11px 14px; background: var(--nu-card); }
.kpi-fx-head { font-size: 0.86rem; font-weight: 700; color: var(--nu-txt2); margin-bottom: 8px; }
.kpi-fx-body { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.kpi-fx-out { font-size: 1.2rem; font-weight: 800; color: var(--nu-brand-text); }
.kpi-fx-eq { color: var(--nu-txt3); }
.kpi-fx-frac { display: inline-flex; flex-direction: column; text-align: center; font-size: 0.86rem; color: var(--nu-txt2); }
.kpi-fx-frac em { font-style: normal; padding: 0 8px 3px; border-bottom: 1px solid var(--nu-border-strong); }
.kpi-fx-frac i { font-style: normal; padding: 3px 8px 0; }
.kpi-fx-why { margin-top: 7px; font-size: 0.8rem; color: var(--nu-warning-text); }

/* 백데이터 표 — 보간·수기 구간 구분(색만으로 구분하지 않고 배지 병기) */
.kpi-flag { font-size: 0.7rem; font-weight: 700; padding: 1px 6px; border-radius: var(--nu-r-pill); }
.kpi-flag.est { background: var(--nu-warning-light); color: var(--nu-warning-text); }
.kpi-flag.man { background: var(--nu-info-light);    color: var(--nu-info-text); }
.inv-grid tr.kpi-r-est > td { background: var(--nu-warning-light-3); }

/* 충족률 격자 — 아이콘 + 라벨 + 색 3중 표기(색만으로 구분 금지) */
.kpi-legend { display: flex; gap: 10px; flex-wrap: wrap; font-size: 0.78rem; }
.kpi-lg { color: var(--nu-txt3); }
.kpi-lg-ok   { color: var(--nu-success-text); }
.kpi-lg-est  { color: var(--nu-warning-text); }
.kpi-lg-miss { color: var(--nu-alert-text); }
.kpi-lg-na   { color: var(--nu-txt4); }
.kpi-q-grid th.kpi-cell, .kpi-q-grid td.kpi-cell { width: 26px; min-width: 26px; text-align: center; padding: 4px 2px; font-size: 0.7rem; }
.kpi-cell-ok   { color: var(--nu-success-text); }
.kpi-cell-est  { color: var(--nu-warning-text); background: var(--nu-warning-light-3); }
.kpi-cell-miss { color: var(--nu-alert-text);   background: var(--nu-alert-light-2); }
.kpi-cell-na   { color: var(--nu-txt-disabled); }
/* 홈 KRI 배너 — 협약 성과지표 진척을 얹은 카드 */
.home-kri-card.kri-link { cursor: pointer; }
.kri-now { margin-left: 8px; font-size: 0.84rem; font-weight: 700; color: var(--nu-on-accent); opacity: 0.95; }
.kri-imp { margin-left: 6px; font-size: 0.82rem; font-weight: 800; color: var(--nu-on-accent); }
.home-kri-badge.kri-nd { background: var(--nu-alert-light); color: var(--nu-alert-text); }
.kri-gauge { margin: 6px 0 4px; height: 8px; background: rgba(255,255,255,0.25); }
/* KPI 화면 추가 — 산정월 선택·산출식 보조설명·합계행 */
.kpi-month { font-size: 0.84rem; color: var(--nu-txt3); display: flex; align-items: center; gap: 6px; }
.kpi-month select { padding: 5px 9px; border: 1px solid var(--nu-border); border-radius: var(--nu-r-medium);
  background: var(--nu-card); color: var(--nu-txt1); font-size: 0.84rem; }
.kpi-fx-sub { margin-top: 7px; font-size: 0.78rem; color: var(--nu-txt3); }
.inv-grid tr.kpi-r-sum > td { background: var(--nu-primary-tint); font-weight: 700; }
/* 잠정치 — 확정 전 값이라 '달성' 색을 쓰지 않는다(회색 계열로 눌러 표시) */
.kpi-c-provisional { border-left-color: var(--nu-txt4); }
.kpi-b-provisional { background: var(--nu-surface-2); color: var(--nu-txt2); }
.kpi-g-provisional { background: var(--nu-surface-4); }

/* ═══ 시뮬레이션 수행 중 영상 — 화면을 덮지 않는 보조 패널 ═══════════════════
   [스케줄링 시작] ~ 완료까지 우측 하단에 뜬다. 영상은 frontend/public/media/sim/ 이 정한다.
   ★ 원래 화면이 주인공이다. 스크림을 깔거나 화면 가운데를 차지하면 "영상을 보는 화면"이 되어
     정작 봐야 할 '생성중인 생산계획' 표가 가려진다 → 스크림 없음 + 우측 하단 고정 + 작은 폭.
   ★ 컨테이너는 pointer-events:none — 영상이 떠 있어도 뒤 화면을 그대로 클릭·조작할 수 있다.
     (카드만 auto 로 되돌려 버튼은 눌린다) */
.sim-video-ov {
  position: fixed; inset: 0; z-index: 1200;
  display: flex; align-items: flex-start; justify-content: center;   /* 중앙 상단 */
  padding: 18px 20px;
  pointer-events: none;            /* 뒤 화면 조작을 막지 않는다 */
}
.sim-video-box {
  pointer-events: auto;
  width: 510px; max-width: calc(100vw - 40px);
  background: var(--nu-card);
  border: 1px solid var(--nu-border);
  border-radius: var(--nu-r-large);
  box-shadow: var(--nu-elev-high);
  overflow: hidden;
  display: flex; flex-direction: column;
  animation: simVideoIn 0.22s ease-out;
}
/* 조용히 내려온다 — 갑자기 나타나면 그것대로 시선을 뺏는다(위치가 상단이라 방향도 위에서) */
@keyframes simVideoIn { from { opacity: 0; transform: translateY(-10px); } to { opacity: 1; transform: none; } }

.sim-video-head {
  display: flex; align-items: center; gap: 7px;
  padding: 7px 8px 7px 11px;
  background: var(--nu-primary-tint);
  color: var(--nu-brand-text);
  border-bottom: 1px solid var(--nu-border);
}

.sim-video-title { font-size: 0.86rem; font-weight: 700; }
.sim-video-time { margin-left: auto; font-size: 0.8rem; font-variant-numeric: tabular-nums; }
.sim-video-x {
  flex: none; width: 20px; height: 20px; padding: 0;
  display: flex; align-items: center; justify-content: center;
  border: none; border-radius: var(--nu-r-small);
  background: transparent; color: var(--nu-txt3);
  font-size: 0.8rem; cursor: pointer;
}
.sim-video-note {
  margin-right: auto; font-size: 0.74rem; color: var(--nu-txt4);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sim-video-btn {
  flex: none; padding: 3px 9px; font-size: 0.74rem; font-weight: 600;
  border: 1px solid var(--nu-border); border-radius: var(--nu-r-medium);
  background: var(--nu-card); color: var(--nu-txt3); cursor: pointer;
  transition: background 0.12s, color 0.12s;
}
}

/* ═══ 개발품(샘플) 일정 등록 ══════════════════════════════════════════════════
   2026-08-13 오토젠 회의 요구. 색은 전부 토큰 참조 — 상태색(alert/warning)은 상태 전용이라
   차트 시리즈 색으로 쓰지 않고, 반대로 여기서도 시리즈 색을 상태 표시에 끌어오지 않는다.
   글자에는 채움색(--nu-alert)이 아니라 --nu-*-text 를 쓴다(대비 4.5:1 — 색 규칙 4). */

/* ── D-day — 회의의 "반짝반짝 띄워 달라". 색만으로 알리지 않고 글자('D+3 초과')도 같이 준다 ── */
.di-dday { display: inline-block; min-width: 62px; font-variant-numeric: tabular-nums; font-size: 0.85rem; }
.di-d-crit { color: var(--nu-alert-text);   font-weight: 800; }   /* D-2 이내 또는 기한 경과 */
.di-d-warn { color: var(--nu-warning-text); font-weight: 700; }   /* D-3 ~ D-5 */
.di-d-ok   { color: var(--nu-txt2); }
.di-d-done { color: var(--nu-txt4); }                             /* 완료·취소 건은 재촉하지 않는다 */

.di-grid tr.di-row { cursor: pointer; }
.di-grid tr.di-row-cxl td { color: var(--nu-txt4); text-decoration: line-through; }
.di-sub { display: block; font-size: 0.74rem; font-weight: 400; color: var(--nu-txt3); }
.di-unset { color: var(--nu-txt4); }
.di-remain { color: var(--nu-alert-text); }

/* 상태·계획반영·우선순위 배지 — .re-badge(pill) 위에 색만 얹는다 */
.di-st-reg   { background: var(--nu-surface-2);       color: var(--nu-txt2); }
.di-st-plan  { background: var(--nu-info-light);      color: var(--nu-info-text); }
.di-st-prog  { background: var(--nu-primary-tint);    color: var(--nu-brand-text); }
.di-st-done  { background: var(--nu-success-light);   color: var(--nu-success-text); }
.di-st-cxl   { background: var(--nu-surface-3);       color: var(--nu-txt4); }
.di-pl-yes   { background: var(--nu-success-light);   color: var(--nu-success-text); }
.di-pl-no    { background: var(--nu-surface-2);       color: var(--nu-txt3); }
.di-pr-urgent{ background: var(--nu-alert-light);     color: var(--nu-alert-text); font-weight: 800; }

.di-toolbar { flex-wrap: wrap; row-gap: 8px; }
/* 필터가 많아 검색칸이 눌린다 — 남는 폭을 검색이 가져가고 [신규 등록]은 오른쪽 끝에 붙인다 */
.di-toolbar input[type="text"] { flex: 1 1 200px; min-width: 160px; }
.di-toolbar .di-new { flex: none; }
.di-chips { display: inline-flex; align-items: center; gap: 5px; font-size: 0.84rem; color: var(--nu-txt3); }
.di-chip {
  padding: 3px 11px; border: 1px solid var(--nu-border);
  border-radius: var(--nu-r-pill); background: var(--nu-card);
  color: var(--nu-txt2); font-size: 0.8rem; cursor: pointer;
}
.di-chip:hover { background: var(--nu-hover); }
.di-chip.on { background: var(--nu-primary); border-color: var(--nu-primary); color: var(--nu-on-accent); font-weight: 700; }
.di-sum-card { cursor: pointer; }
/* 날짜 입력은 전용 클래스를 쓴다 — .popup-form-date 는 달력 아이콘에 invert(1) 을 걸어 두고 있어
   라이트 톤(흰 배경)에서 아이콘이 하얗게 지워진다. */
.di-date, .di-toolbar input[type="date"] {
  padding: 5px 9px; border: 1px solid var(--nu-border); border-radius: var(--nu-r-medium);
  background: var(--nu-card); color: var(--nu-txt1); font-size: 0.84rem; font-family: inherit;
}

/* ── 상세·등록 팝업 ─────────────────────────────────────────────────────── */
.di-popup { width: 720px; max-width: calc(100vw - 48px); max-height: calc(100vh - 64px); overflow-y: auto; }
.di-pop-sub { margin: -6px 0 12px; font-size: 0.86rem; color: var(--nu-txt3); display: flex; align-items: center; gap: 10px; }
.di-tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--nu-border); margin-bottom: 14px; }
.di-tab {
  padding: 7px 16px; border: none; background: transparent;
  color: var(--nu-txt3); font-size: 0.88rem; font-weight: 600; cursor: pointer;
  border-bottom: 2px solid transparent;
}
.di-tab.on { color: var(--nu-primary); border-bottom-color: var(--nu-primary); }

.di-f-row { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; font-size: 0.87rem; }
.di-f-row-top { align-items: flex-start; }
.di-f-row > label:first-child { min-width: 104px; text-align: right; color: var(--nu-txt3); flex: none; }
.di-req { color: var(--nu-alert-text); }
.di-unit { font-size: 0.8rem; color: var(--nu-txt4); }
.di-f-hint, .di-f-note { font-size: 0.78rem; color: var(--nu-txt3); line-height: 1.5; }
.di-f-note {
  margin: 4px 0 14px 114px; padding: 7px 11px;
  background: var(--nu-primary-tint); color: var(--nu-brand-text);
  border-radius: var(--nu-r-medium);
}
.di-f-hint { margin-top: 5px; color: var(--nu-txt4); }
.di-mach-box { flex: 1; }
.di-mach-chk { display: inline-flex; align-items: center; gap: 5px; margin: 0 12px 4px 0; font-size: 0.84rem; cursor: pointer; }
.di-mach-chk input { width: 15px; height: 15px; accent-color: var(--nu-primary); cursor: pointer; }
.di-f-meta {
  margin: 12px 0 0 114px; padding-top: 10px; border-top: 1px solid var(--nu-border-l);
  font-size: 0.78rem; color: var(--nu-txt3); line-height: 1.6;
}
.di-f-meta code { background: var(--nu-surface-2); padding: 1px 5px; border-radius: var(--nu-r-small); }
.di-form textarea { resize: vertical; font-family: inherit; }

/* ── 실적 탭 ────────────────────────────────────────────────────────────── */
.di-prog { margin-bottom: 14px; }
.di-prog-nums { display: flex; gap: 18px; align-items: baseline; font-size: 0.86rem; color: var(--nu-txt3); margin-bottom: 6px; }
.di-prog-nums b { font-size: 1.05rem; color: var(--nu-txt1); font-variant-numeric: tabular-nums; }
.di-prog-pct { margin-left: auto; font-weight: 800; color: var(--nu-txt2); font-variant-numeric: tabular-nums; }
.di-gauge { height: 10px; }
.di-r-form {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 11px 13px; margin-bottom: 12px;
  background: var(--nu-row-alt); border: 1px solid var(--nu-border); border-radius: var(--nu-r-medium);
  font-size: 0.84rem; color: var(--nu-txt3);
}
.di-r-form label { display: flex; align-items: center; gap: 6px; }
.di-r-memo-l { flex: 1; min-width: 180px; }
.di-r-wrap { max-height: 240px; overflow-y: auto; border: 1px solid var(--nu-border); border-radius: var(--nu-r-medium); margin-bottom: 10px; }
.di-r-act { white-space: nowrap; }
.di-r-act button + button { margin-left: 5px; }
/* 저장 후 팝업을 닫지 않는 흐름(실적 연속 입력)에서 "됐다"를 알리는 짧은 안내 */
.di-toast {
  display: none; margin: 8px 0 0; padding: 6px 11px;
  background: var(--nu-success-light); color: var(--nu-success-text);
  border-radius: var(--nu-r-medium); font-size: 0.82rem; font-weight: 600;
}
.di-toast.on { display: block; }

/* ── 홈 대시보드 '기한 임박 개발품' 줄 ──────────────────────────────────────
   임박 건이 0이면 아예 렌더하지 않으므로(app.js devSoonStrip) 평소 홈 레이아웃은 그대로다.
   뜰 때만 한 줄을 차지하고, 아래 차트가 flex 로 그만큼 양보한다.
   ★ 그래서 이 줄은 **얇아야 한다** — 뜬 순간 아래 차트 2줄이 각각 그 절반씩 낮아진다.
     눈에 띄는 건 두께가 아니라 색(alert/warning)과 D-표기가 맡는다. 여백·글자를
     다시 키우지 말 것. 한 줄 높이 약 30px(테두리 포함)이 상한이다. */
#layoutRoot.home-fill > .di-home { flex: 0 0 auto; }
.di-home {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 5px 12px; cursor: pointer; line-height: 1.3;
  background: var(--nu-warning-light); color: var(--nu-warning-text);
  border: 1px solid var(--nu-warning-border); border-radius: var(--nu-r-large);
  font-size: 0.8rem;
}
.di-home.crit { background: var(--nu-alert-light); color: var(--nu-alert-text); border-color: var(--nu-alert-border); }
.di-home:hover { filter: brightness(0.98); }
.di-home-t { font-weight: 800; flex: none; }
.di-home-list { display: flex; gap: 6px; flex-wrap: wrap; min-width: 0; }
.di-home-item {
  padding: 1px 8px; border-radius: var(--nu-r-pill);
  background: var(--nu-card); color: var(--nu-txt2);
  font-size: 0.76rem; white-space: nowrap;
}
.di-home-item b { color: var(--nu-warning-text); font-variant-numeric: tabular-nums; }
.di-home-item.crit b { color: var(--nu-alert-text); }
.di-home-item i { font-style: normal; color: var(--nu-txt3); }
.di-home-more { font-size: 0.79rem; opacity: 0.8; }

@media (max-width: 1100px) {
  .di-popup { width: auto; }
  .di-f-note, .di-f-meta { margin-left: 0; }
  .di-f-row { flex-wrap: wrap; }
  .di-f-row > label:first-child { min-width: 0; text-align: left; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   금형 레시피 관리 (#mold-master) — 키오스크 전시 정보 등록 화면
   ─────────────────────────────────────────────────────────────────────────── */
.mm-sum .home-kri-card { cursor: default; }
.mm-toolbar { display: flex; align-items: center; gap: 10px; }
.mm-toolbar #mmSearch { min-width: 320px; }
.mm-spacer { flex: 1 1 auto; }
.mm-note { line-height: 1.6; }

.mm-grid td { vertical-align: middle; }
.mm-thumb-c { text-align: center; }
.mm-thumb {
  width: 40px; height: 40px; object-fit: contain;
  background: var(--nu-surface-2); border-radius: var(--nu-r-small);
  vertical-align: middle;
}
.mm-noimg { color: var(--nu-txt4); }
.mm-upd { color: var(--nu-txt3); font-size: 0.8rem; }
.mm-row { cursor: pointer; }
.mm-row-ghost { background: var(--nu-warning-light-3); }
.mm-ghost-msg { color: var(--nu-warning-text); font-size: 0.82rem; }

/* 대조 배지 — 색만으로 알리지 않는다. 글자에 판정이 그대로 들어 있다(§0-4 색 규칙). */
.mm-m-ok   { background: var(--nu-success-light); color: var(--nu-success-text); }
.mm-m-none { background: var(--nu-warning-light); color: var(--nu-warning-text); }
.mm-m-off  { background: var(--nu-alert-light);   color: var(--nu-alert-text); }

/* ── 등록·수정 팝업 ──────────────────────────────────────────────────────── */
.mm-popup { width: 980px; max-width: 96vw; }
.mm-pop-sub {
  margin: -4px 0 14px; padding: 8px 12px;
  background: var(--nu-warning-light-3); color: var(--nu-warning-text);
  border-radius: var(--nu-r-medium); font-size: 0.82rem; line-height: 1.5;
}
.mm-form { display: grid; grid-template-columns: minmax(0, 1fr) 260px; gap: 20px; }
.mm-col { min-width: 0; }
.mm-f-row { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; font-size: 0.87rem; }
.mm-f-row-top { align-items: flex-start; }
.mm-f-row > label:first-child { min-width: 104px; text-align: right; color: var(--nu-txt3); flex: none; }
.mm-f-row .popup-form-input { flex: 1 1 auto; min-width: 0; }
.mm-f-trio span { display: inline-flex; align-items: center; gap: 4px; }
.mm-f-trio i { font-style: normal; color: var(--nu-txt4); font-size: 0.8rem; }
.mm-match-line { margin: -4px 0 10px 114px; }
.mm-ml { font-size: 0.8rem; line-height: 1.5; }
.mm-ml-idle { color: var(--nu-txt4); }
.mm-ml-ok   { color: var(--nu-success-text); }
.mm-ml-warn { color: var(--nu-alert-text); }

/* 이미지 — 파일 선택 + 드래그&드롭 */
.mm-img-title { font-size: 0.85rem; font-weight: 700; color: var(--nu-txt2); margin-bottom: 8px; }
.mm-img-title small { font-weight: 400; color: var(--nu-txt4); margin-left: 6px; }
.mm-drop {
  height: 200px; display: flex; align-items: center; justify-content: center;
  background: var(--nu-surface-2); border: 1px dashed var(--nu-border-strong);
  border-radius: var(--nu-r-medium); overflow: hidden;
}
.mm-drop.has { border-style: solid; background: var(--nu-card); }
.mm-drop.over { border-color: var(--nu-primary); background: var(--nu-primary-tint); }
.mm-drop-hint { color: var(--nu-txt4); font-size: 0.8rem; text-align: center; line-height: 1.6; }
.mm-img-prev { max-width: 100%; max-height: 100%; object-fit: contain; }
.mm-img-meta { margin-top: 8px; font-size: 0.78rem; color: var(--nu-txt3); word-break: break-all; }
.mm-img-btns { margin-top: 8px; display: flex; gap: 6px; }
.mm-pick { display: inline-block; }
.mm-img-hint { margin-top: 8px; font-size: 0.76rem; color: var(--nu-txt4); line-height: 1.5; }

/* 사출조건 편집 */
.mm-params { margin-top: 16px; }
.mm-p-head {
  display: flex; align-items: center; gap: 8px;
  font-size: 0.85rem; font-weight: 700; color: var(--nu-txt2); margin-bottom: 8px;
}
.mm-p-head small { font-weight: 400; color: var(--nu-txt4); flex: 1 1 auto; }
.mm-p-wrap { max-height: 260px; overflow: auto; border: 1px solid var(--nu-border); border-radius: var(--nu-r-medium); }
.mm-p-grid { margin: 0; }
.mm-p-grid th { position: sticky; top: 0; z-index: 1; }
.mm-p-grid td { padding: 4px 6px; }
.mm-p-grid .popup-form-input { width: 100%; }
.mm-p-act { display: flex; gap: 4px; justify-content: center; align-items: center; }
/* 행 이동·삭제 버튼은 아이콘 하나짜리다 — 기본 padding 을 그대로 두면 칸을 밀어낸다. */
.mm-p-act button { padding: 3px 0; min-width: 26px; line-height: 1.2; }
.mm-toast { margin-top: 6px; }

@media (max-width: 1100px) {
  .mm-popup { width: auto; }
  .mm-form { grid-template-columns: minmax(0, 1fr); }
  .mm-match-line { margin-left: 0; }
  .mm-f-row { flex-wrap: wrap; }
  .mm-f-row > label:first-child { min-width: 0; text-align: left; }
}

/* ── 사출기 연동·키오스크 전시 카드에 얹히는 제품 이미지·사출조건 ───────────
   레시피 원천은 위 관리 화면이다. 이미지는 주소만 받아 <img> 가 따로 가져온다
   (2초 폴링 응답에 사진 바이트를 싣지 않는다). */
.inj-rc-body { display: flex; gap: 12px; align-items: flex-start; }
.inj-rc-img {
  flex: none; width: 132px; height: 132px;
  display: flex; align-items: center; justify-content: center;
  background: var(--nu-surface-2); border-radius: var(--nu-r-medium); overflow: hidden;
}
.inj-rc-img img { max-width: 100%; max-height: 100%; object-fit: contain; }
.inj-rc-main { flex: 1 1 auto; min-width: 0; }
.inj-rc-params { margin-top: 9px; display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.inj-rc-chip {
  display: inline-flex; align-items: baseline; gap: 5px;
  padding: 3px 9px; border-radius: var(--nu-r-pill);
  background: var(--nu-surface-2); font-size: 0.78rem; white-space: nowrap;
}
.inj-rc-chip i { font-style: normal; color: var(--nu-txt3); }
.inj-rc-chip b { color: var(--nu-txt1); }
.inj-rc-more summary {
  cursor: pointer; font-size: 0.78rem; color: var(--nu-brand-text);
  padding: 3px 4px; list-style: none;
}
.inj-rc-more summary::-webkit-details-marker { display: none; }
.inj-rc-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }

/* ═══════════════════════════════════════════════════════════════════════════
   출하 실적 입력 (#ship-actual) — 미출하·서열장 지원 인라인 입력 그리드
   ─────────────────────────────────────────────────────────────────────────── */
.sa-toolbar { display: flex; align-items: center; gap: 10px; }
.sa-toolbar #saSearch { min-width: 240px; }
/* 「데이터 유의사항」 - 조회 줄 오른쪽 끝(화면 우측 상단). 펼치면 표를 밀지 않고 아래로 떠서 열린다
   (발주 정책값 .op-note · 자재 소요 .fr-note 와 같은 꼴, 2026-09-14 사용자 요청) */
.sa-toolbar > .sa-data-note { position: relative; }
.sa-toolbar > .sa-data-note > ul {
  position: absolute; right: 0; top: calc(100% + 6px); z-index: 30;
  width: min(620px, 80vw); max-height: 50vh; overflow: auto;
  background: var(--nu-card); border: 1px solid var(--nu-border);
  border-radius: 4px; box-shadow: 0 6px 20px rgba(0, 0, 0, .12);
  padding: 10px 14px 10px 28px;
}

/* 열 폭을 값 길이에 맞춰 줄였다(app.js 머리글 주석). 창이 좁아 비고가 사라질 만큼 줄면
   접히지 말고 가로로 구르게 하한을 둔다 = 고정 열 합 1,070 + 비고 120. */
.sa-grid { min-width: 1190px; }
.sa-grid tbody td { padding-inline: 6px; }
/* 머리글 가운데는 사이트 전체 규칙(아래 「표 머리글은 사이트 전체 가운데」)이 맡는다.
   여기는 좁힌 열에 맞춘 여백 · 줄바꿈만 - 두 낱말 머리글은 <br> 에서 접는다.
   `.layout-root thead th.tb-al-*` 의 14px 여백을 이기려고 id 로 올린다. */
#layoutRoot .sa-grid thead th {
  padding: 5px 4px; line-height: 1.25;
  white-space: normal; word-break: keep-all; vertical-align: middle;
}

.sa-grid td { vertical-align: middle; }
.sa-grid .sa-in { padding: 3px 5px; }
/* 입력 열은 헤더부터 구분해 둔다 — 어디를 채워야 하는지 한눈에 보여야 한다. */
.sa-th-in { background: var(--nu-primary-tint); }
.sa-num, .sa-txt {
  width: 100%; box-sizing: border-box;
  padding: 4px 6px; font-size: 0.85rem;
  color: var(--nu-txt1); background: var(--nu-card);
  border: 1px solid var(--nu-border); border-radius: var(--nu-r-small);
}
.sa-num { text-align: right; font-variant-numeric: tabular-nums; }
.sa-num:focus, .sa-txt:focus { outline: none; border-color: var(--nu-primary); background: var(--nu-primary-tint); }
/* 입력값이 있는 행만 진하게 — 나머지는 '미입력'이라는 사실이 보여야 한다. */
.sa-row.on { background: var(--nu-primary-tint); }
.sa-row.on td { font-weight: 600; }
.sa-ledger { color: var(--nu-txt3); }
.sa-ship b { font-variant-numeric: tabular-nums; }
.sa-neg { color: var(--nu-alert-text); }
.sa-d-minus { color: var(--nu-alert-text); }
.sa-d-plus { color: var(--nu-success-text); }
.sa-planchg {
  display: inline-block; margin-left: 6px; padding: 1px 6px;
  border-radius: var(--nu-r-pill); font-size: 0.7rem;
  background: var(--nu-warning-light); color: var(--nu-warning-text);
}
.sa-b-missing { margin-left: 6px; background: var(--nu-alert-light); color: var(--nu-alert-text); }
.sa-yard-txt { color: var(--nu-txt3); font-size: 0.82rem; }
/* 지원 수량이 있는데 서열장이 비면 눈에 띄게 — 저장은 막지 않지만 알려는 준다. */
.sa-f-yard.need { border-color: var(--nu-warning-border); background: var(--nu-warning-light-3); }
.sa-dirty {
  display: none; padding: 3px 10px; border-radius: var(--nu-r-pill);
  background: var(--nu-warning-light); color: var(--nu-warning-text); font-size: 0.8rem;
}
.sa-dirty.on { display: inline-block; }

/* ── 보정 이력(#inv-corrections) - 검색 줄과 표 부품 줄을 한 줄로 (2026-09-14 사용자 요청) ──
   「컬럼 · 내보내기」 줄(.mx-grid-bar)은 꾸러미 표 부품이 그리고, 다시 그릴 때(배치 불러오기 등)
   제 상자를 통째로 비운다. 그래서 DOM 을 옮기지 않고 **검색 줄을 그 줄 위에 포갠다** -
   옮기면 다시 그릴 때 검색 칸이 지워지거나 단추 줄이 두 벌 생긴다.
   오른쪽은 단추 둘(컬럼 · 내보내기) 자리만큼 비운다. */
.corr-panel { position: relative; }
.corr-panel > .demand-toolbar {
  position: absolute; top: 18px; left: 20px; right: 150px; z-index: 3;
  height: 28px; flex-wrap: nowrap;
}
/* 검색 칸 아래 끝 → 표 윗단을 다른 판과 같은 16px 로 둔다(09-14 사용자 요청, 출하 실적·보정 실측 16px).
   단추 줄(28px)이 검색 칸(30px)보다 낮아 여백 18px 을 줘야 보이는 간격이 16px 이 된다.
   표 상자를 flex 로 세운 뒤로 이 줄이 눌려 여백이 0 이 됐다 - 줄어들지 않게 막는다. */
.corr-panel .mx-grid-bar { min-height: 28px; flex: 0 0 auto; padding-bottom: 18px; }
/* 표가 판 아래로 넘치지 않게 - 남은 높이를 받아 표만 안에서 구른다.
   ★ 표 부품은 붙는 상자(#corrGrid)에 .mx-grid 를 달지 않아 그 상자가 block 으로 남는다 →
     안쪽 감싸개가 높이를 못 받아 5천 행이 판 밖으로 흘렀다(09-14 실측 16만 px). 여기서 flex 로 세운다. */
#layoutRoot.fit-page > .corr-panel > #corrGrid {
  display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0;
}
#layoutRoot.fit-page > .corr-panel .mx-grid-wrap { flex: 1 1 auto; min-height: 0; }
/* 좁은 화면에서는 검색 칸이 단추를 덮으니 제 줄로 돌린다 */
@media (max-width: 900px) {
  .corr-panel > .demand-toolbar { position: static; height: auto; flex-wrap: wrap; }
}

/* 출하현황(#shipment)에 얹는 보정 열 — 원천이 다르므로 배경으로 구분한다. */
.sh-adj-th { background: var(--nu-primary-tint); }
.sh-adj { background: var(--nu-row-alt); }
/* 며칠분이 반영된 보정인지 — 기간 합계만 보면 하루만 입력한 품번이 '전 기간 완료'로 읽힌다. */
.sh-adj-d { display: block; font-style: normal; font-size: 0.7rem; color: var(--nu-txt4); }

/* ═══════════════════════════════════════════════════════════════════════════
   계획 외 물량 (#dev-items) — 긴급 물량 / 개발품 구분
   ─────────────────────────────────────────────────────────────────────────── */
/* 구분 배지 — 색만으로 알리지 않는다. 글자에 구분이 그대로 들어 있다(§0-4 색 규칙). */
.di-ot-urgent { background: var(--nu-warning-light); color: var(--nu-warning-text); }
.di-ot-dev    { background: var(--nu-surface-2);     color: var(--nu-txt2); }
.di-reason { color: var(--nu-warning-text); }

/* 등록 팝업의 구분 선택 */
.di-ot-pick { display: flex; gap: 8px; }
.di-ot-opt {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 14px; cursor: pointer;
  background: var(--nu-card); color: var(--nu-txt2);
  border: 1px solid var(--nu-border); border-radius: var(--nu-r-pill);
  font-size: 0.85rem;
}
.di-ot-opt:hover { background: var(--nu-hover); }
.di-ot-opt.on {
  background: var(--nu-primary-tint); border-color: var(--nu-primary);
  color: var(--nu-brand-text); font-weight: 700;
}
.di-ot-help { line-height: 1.6; }
/* 필수(*)가 아니라 권장 — 막지는 않지만 넣는 편이 낫다는 표시 */
.di-rec {
  margin-left: 5px; padding: 1px 6px; border-radius: var(--nu-r-pill);
  background: var(--nu-warning-light); color: var(--nu-warning-text);
  font-size: 0.68rem; font-weight: 700;
}

/* 계획 화면 상단 알림 배너 — 홈 배너(.di-home)와 같은 모양을 쓰되 여백만 조정한다. */
.di-plan-banner { margin: 0 0 12px; }

/* 계획 외 물량 — 생산 실적 직접 입력 (2026-08-13 회의 §다-4)
   양산품은 공정별 바코드 리딩으로 MES에 실적이 자동 집계되지만, 계획 외 물량은 그 통로가 없다. */
.di-prod-cell { cursor: pointer; }
.di-prod-cell:hover { background: var(--nu-primary-tint); }
/* 실적이 0인 칸은 '0'이 아니라 '입력'이라고 적는다 — 0은 "안 만들었다"로 읽히지만
   실제로는 "아직 안 넣었다"인 경우가 대부분이다. */
.di-prod-none {
  padding: 1px 8px; border-radius: var(--nu-r-pill);
  background: var(--nu-warning-light); color: var(--nu-warning-text);
  font-size: 0.74rem; font-weight: 700;
}
.di-why {
  margin: 10px 0 6px; padding: 9px 12px;
  background: var(--nu-surface-2); color: var(--nu-txt2);
  border-radius: var(--nu-r-medium); font-size: 0.82rem; line-height: 1.6;
}
.di-why.urgent { background: var(--nu-warning-light-3); color: var(--nu-warning-text); }

/* ── 자료 업로드 화면 (2026-08-18, FlowTracer 업로드 이관) ────────────────── */
.up-drop {
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  padding: 22px 16px; border: 2px dashed var(--nu-border); border-radius: var(--nu-r-large);
  background: var(--nu-surface-2); color: var(--nu-txt2); text-align: center;
}
.up-drop[aria-disabled="true"] { opacity: 0.75; }
.up-drop-ico { font-size: 22px; line-height: 1; color: var(--nu-txt3); }
.up-drop-sub { font-size: 0.8rem; color: var(--nu-txt3); }
.up-tbl { font-size: 0.76rem; color: var(--nu-txt3); }
.up-warn { background: var(--nu-warning-light); border-color: var(--nu-warning-border); color: var(--nu-warning-text); }
.up-notes { margin: 0; padding-left: 18px; color: var(--nu-txt2); font-size: 0.85rem; display: flex; flex-direction: column; gap: 4px; }

/* 받는 자료 고르기 · 끌어다 놓기 · 미리보기 (2026-09-19, 실제로 받기 시작) */
.up-kinds { display: flex; flex-wrap: wrap; gap: 8px; }
.up-kind {
  display: flex; align-items: baseline; gap: 6px; padding: 8px 12px;
  border: 1px solid var(--nu-border); border-radius: var(--nu-r-medium);
  background: var(--nu-surface-1); cursor: pointer;
}
.up-kind:has(input:checked) { border-color: var(--nu-primary-dark); background: var(--nu-surface-2); }
.up-drop.is-over { border-color: var(--nu-primary-dark); background: var(--nu-surface-3); }
.up-sum-head { margin: 2px 0 6px; color: var(--nu-txt2); font-size: 0.88rem; }
.up-miss { margin-top: 8px; }
.up-actions { display: flex; align-items: center; gap: 8px; margin-top: 10px; }
/* 서열계획 미리보기의 며칠 뒤별 표 - 기본은 일주일, 「더 보기」를 누르면 나머지 날이 펴진다 */
.up-day-more { display: none; }
.up-days-all .up-day-more { display: table-row; }

/* ═══════════════════════════════════════════════════════════════════════════
   화면 공통 표기 — 접은 유의사항 · 더 있는 표
   앞의 app.js NOTATION 상수가 어느 요소에 걸지 정하고, 여기는 모양만 맡는다.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── 접어 둔 데이터 유의사항 ──
   닫힘 상태는 한 줄(약 26px). 펼치면 원문이 그대로 나온다. */
.data-note { margin: 0; }

.data-note > summary::before { content: "\24D8"; font-size: 0.82rem; line-height: 1; }
.data-note > summary::after { content: "\25BE"; font-size: 0.62rem; color: var(--nu-txt4); }
.data-note[open] > summary::after { content: "\25B4"; }

.data-note[open] > summary { margin-bottom: 6px; }
/* 접힌 안쪽 본문은 제 배경·테두리를 벗는다 — 상자 안에 상자가 겹쳐 보인다. */
.data-note > .inv-note,
.data-note > .home-note,
.data-note > .sched-mold-note,
.data-note > .di-f-note,
.data-note > .sa-note,
.data-note > .sa-f-note,
.data-note > .mm-f-note { background: none; border: 0; padding: 0 2px; margin: 0; }

/* 목록으로 적은 유의사항 — 곁말이지 본문이 아니다. 본문과 같은 크기·농도로 두면
   접어 둔 뜻이 없어지고, 펼치는 순간 표보다 이쪽이 먼저 읽힌다. */
.data-note > ul {
  margin: 0; padding-left: 16px;
  font-size: 0.78rem; line-height: 1.65; color: var(--nu-txt3);
}
.data-note > ul > li { margin: 0 0 2px; }
.data-note > ul > li::marker { color: var(--nu-txt4); }
/* 강조는 한 단계만 올린다 — 굵게까지 검게 하면 다시 본문이 된다. */
.data-note > ul b { font-weight: 600; color: var(--nu-txt2); }
.data-note > ul code {
  background: var(--nu-surface-2); color: var(--nu-txt2);
  padding: 0 4px; border-radius: 3px; font-size: 0.74rem;
}

/* ── 표 머리글은 사이트 전체 가운데 (2026-09-14 사용자 요청) ──
   꾸러미 규칙(README 「표 공통 규칙」 0번: 머리글은 값과 같은 쪽)을 이 사이트에서만 뒤집는다 - 꾸러미는 고치지 않는다.
   머리글을 좌우로 미는 규칙이 여럿이라(손 표 tb-al-* · 공용 그리드 mx-grid-th-* · mx-grid-no ·
   th 에 붙은 dm-num · inv-num · 인라인 style) 명시도로 하나하나 이기지 않고 !important 한 줄로 덮는다.
   값(td) 정렬은 그대로 둔다. */
thead th { text-align: center !important; }
/* 업로드 이력 — 머리 판(안내 · 갈피 · 요약)은 내용만큼만 차지한다.
   `fit-page` 가 `.panel` 마다 `flex: 1` 을 줘서, 그대로 두면 표 판과 높이를 반씩 갈라
   머리 판에 200px 넘는 빈 자리가 생긴다(2026-09-21 실화면에서 쟀다). */
#layoutRoot.fit-page > .panel.uh-intro { flex: 0 0 auto; }

/* 손 표 판정이 머리글 한쪽에만 주는 14px 여백을 반대쪽에도 줘서 글자가 칸 한가운데 서게 한다 */
.layout-root thead th.tb-al-l { padding-right: 14px; }
.layout-root thead th.tb-al-r { padding-left: 14px; }

/* ── 아직 더 있는 표 — 아래를 옅게 흐린다 ──
   .has-more 는 app.js 의 markScrollableTables() 가 실제 넘침을 재서 붙인다.
   ※ 카드에 건다(스크롤 상자에 걸면 내용과 같이 밀려 올라간다). */
#layoutRoot .panel.has-more,
#layoutRoot .viz-card.has-more,
#layoutRoot .home-card.has-more,
#layoutRoot .util-card.has-more,
#layoutRoot .ep-card.has-more,
#layoutRoot .inv-card.has-more,
#layoutRoot .sh-card.has-more,
#layoutRoot .sched-section.has-more { position: relative; }
#layoutRoot .panel.has-more::after,
#layoutRoot .viz-card.has-more::after,
#layoutRoot .home-card.has-more::after,
#layoutRoot .util-card.has-more::after,
#layoutRoot .ep-card.has-more::after,
#layoutRoot .inv-card.has-more::after,
#layoutRoot .sh-card.has-more::after,
#layoutRoot .sched-section.has-more::after {
  content: ""; position: absolute; left: 1px; right: 1px; bottom: 1px; height: 26px;
  background: linear-gradient(to bottom, transparent, var(--panel) 80%);
  border-radius: 0 0 var(--nu-r-large) var(--nu-r-large);
  pointer-events: none;
}
/* .sched-section 만 라운드가 한 단계 작다 — 그대로 두면 모서리에서 그림자가 삐져나온다. */
#layoutRoot .sched-section.has-more::after {
  border-radius: 0 0 var(--nu-r-medium) var(--nu-r-medium);
}


/* ═══════════════════════════════════════════════════════════════════════════
   §  style= 를 걷어내며 생긴 규칙들
   CSP 의 style-src 를 켜려면 마크업에 style= 가 하나도 없어야 한다. 값이 고정인 것은
   여기로 오고, 표 열너비처럼 그 표만의 수는 board-shell 의 paintInlineStyles 가 나른다.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── 패널 몸통 ────────────────────────────────────────────────────────────
   .panel 자체는 안쪽 여백이 없다. 화면마다 무엇을 담느냐에 따라 넷으로 갈린다. */

/* 표 하나를 담는 패널 — 제목·조회줄·표가 세로로 선다. */
.panel.is-table-body {
  padding: 12px 16px 14px;
  display: flex; flex-direction: column; gap: 8px;
}

/* 설비 카드 격자를 담는 패널. 칸 수는 화면이 --ep-cols 로 넣어 준다. */
.panel.is-card-grid {
  padding: 12px 16px 14px;
  display: flex; flex-direction: column; gap: 10px;
}

/* 위젯 여럿을 세로로 쌓는 패널. */
.panel.is-widget-stack {
  padding: 18px 20px;
  display: flex; flex-direction: column; gap: 12px;
}

/* 설계 골격 화면 — 글이 주인이라 여백을 넓게 준다. */
.panel.is-outline {
  padding: 24px 28px;
  display: flex; flex-direction: column; gap: 14px;
}
/* 남는 높이를 안쪽에 넘겨야 할 때. flex 자식이 안 줄어드는 것을 푼다.
   ★ 아이디로 짚는다. 좁은 폭에서 #layoutRoot.fit-page > .panel 이 min-height: auto 로
     덮기 때문이다 — 종전에는 인라인이라 그것을 이기고 있었다. 클래스만으로는 진다. */
#layoutRoot .panel.is-outline.is-shrink { min-height: 0; }

/* 안내문만 있는 패널 — 아직 자료가 없거나 조건이 안 맞을 때 세운다. */
.panel.is-notice { padding: 28px; }

/* 자료를 부르는 동안 세우는 패널 안의 곁말. */
.pnl-note { color: var(--nu-txt3); }

/* ── 패널 안의 글 ─────────────────────────────────────────────────────── */

.pnl-title { margin: 0 0 8px; }
/* 바로 아래 설명이 따라붙는 제목은 더 좁게. */
.pnl-title.is-tight { margin-bottom: 4px; }

.pnl-desc { color: var(--nu-txt3); font-size: 0.9rem; }

/* 아직 확정되지 않은 것을 알리는 상자. */
.pnl-warn {
  padding: 12px 16px; 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.9rem;
}
/* 참고로 덧붙이는 상자 — 경고보다 한 단 낮다. */
.pnl-info {
  padding: 12px 16px; border-radius: var(--nu-r-medium);
  background: var(--nu-info-light); border: 1px solid var(--nu-info-border);
  color: var(--nu-info-text); font-size: 0.85rem;
}

.pnl-list {
  margin: 0; padding-left: 18px;
  color: var(--nu-txt2); font-size: 0.85rem;
  display: flex; flex-direction: column; gap: 4px;
}

/* 한 줄에 나란히 세우는 조각들. */
.pnl-row { display: flex; gap: 10px; align-items: center; }
/* 좁은 폭에서 접히는 변형 — 조각이 많은 줄에 쓴다. */
.pnl-row.is-wrap { gap: 12px; flex-wrap: wrap; }

/* ── 위젯 제목 사이 띄우기 ─────────────────────────────────────────────
   .viz-title 은 margin-bottom 만 갖는다. 한 패널에 위젯이 여럿일 때 위쪽도 띄운다. */
.viz-title.is-flush { margin: 0; }
.viz-title.is-gap { margin: 4px 0 0; }
.viz-title.is-gap-lg { margin: 6px 0 0; }

/* ── 그 밖 ────────────────────────────────────────────────────────────── */

/* 설비 칩 — 꾸러미 기본(130/120)보다 한 치수 좁게 세운다. */
.ep-mach-card.is-narrow { flex: 1 1 110px; min-width: 100px; }

/* 표 안에 들어가는 작은 배지. 꾸러미 기본은 단독으로 설 때의 크기다. */
.inj-badge.is-s { font-size: 0.72rem; padding: 1px 8px; }

/* 목록 머리말이 줄 맨 앞에 설 때 — 앞의 조각이 없으므로 들여쓰기를 뺀다. */
.inv-count.is-flush { margin-left: 0; }

/* 줄 오른쪽 끝으로 밀어 두는 버튼. */
.inj-del-btn.is-right { margin-left: auto; }

/* 시간·수량처럼 자릿수를 맞춰 읽는 칸. */
.dt-num { text-align: right; }

/* 팝업 안 좁은 선택기 — 교대처럼 값이 짧은 칸은 늘어나면 오히려 읽기 나쁘다. */
.popup-form-sel.is-narrow { max-width: 120px; }

/* ═══════════════════════════════════════════════════════════════════════════
   병합으로 옮겨 온 것 — 옛 styles.css 에 있던 이 보드 고유 규칙 (2026-09-01)
   ───────────────────────────────────────────────────────────────────────────
   꾸러미 도입 전에 styles.css 에 쌓아 둔 화면 규칙이다. 그 파일이 없어졌으므로
   여기로 옮긴다. 관리 화면(.theme-actions·.site-name-input)은 꾸러미가 제 것을
   들고 있어 옮기지 않았다.
   ═══════════════════════════════════════════════════════════════════════════ */

/* 서버가 자리를 고정한 앞 4항목 — 접힘 목록의 나머지와 구별되게 세운다. */
.inj-rc-chip.key { background: var(--nu-primary-tint); font-weight: 600; }
.inj-rc-chip.key i { color: var(--nu-brand-text); }
.inj-rc-src { font-size: 0.74rem; color: var(--nu-txt4); margin-left: 2px; }

/* 스케줄확정 — 시뮬레이션 확정분 표시 (2026-08-19).
   현장 확정분(작업지시서 파일)과 이 시스템의 확정분을 한 표에 담되 출처를 구분한다.
   색이 아니라 글자('시뮬')가 판정을 담는다 — 색만으로 정보를 전달하지 않는다(§0-4). */
.sc-sim { background: var(--nu-info-light); color: var(--nu-info-text); border: 1px solid var(--nu-info-border); margin-left: 4px; }
/* 스케줄확정 — 확정분이 다른 계획일에 있을 때의 안내줄 */
.sc-hint { margin-top: 4px; }
.sc-hint .sc-jump { color: var(--nu-on-accent); text-decoration: underline; cursor: pointer; }

/* 스케줄확정 — [작업요청] 줄 (2026-08-19). 표 아래 우측에 둔다(목록을 다 본 뒤 누르는 동작이라). */
.sc-req-bar { display: flex; align-items: center; justify-content: flex-end; gap: 12px; padding-top: 4px; }
.sc-req-note { font-size: 0.82rem; color: var(--nu-txt3); }
.sc-req-btn {
  padding: 8px 22px; border-radius: var(--nu-r-medium); border: 0; cursor: pointer;
  background: var(--nu-primary); color: var(--nu-on-accent); font-size: 0.92rem; font-weight: 700;
}
.sc-req-btn:hover { filter: brightness(1.06); }
.sc-req-btn:disabled { cursor: not-allowed; opacity: 0.75; }
/* 완료 상태 — 색만이 아니라 글자('작업완료')가 상태를 담는다 */
.sc-req-btn.done { background: var(--nu-success-light); color: var(--nu-success-text); border: 1px solid var(--nu-success-border); }

/* ── 금형정보 관리 (015) — 금형자료 목록 + 상세(레시피·금형번호 매핑·제품/이미지) ──
   왼쪽은 훑는 목록, 오른쪽은 한 건을 깊게 본다. 매핑이 비어 있는 금형을 눈에 띄게 두는 것이
   이 화면의 일이라, '미지정'·'0' 은 흐리게가 아니라 **경고색**으로 둔다. */
/* ★위=금형목록, 아래=제품목록. 두 표는 성격이 다르다 — 위는 금형을 **찾는** 표,
   아래는 제품을 **관리하는** 표(사진을 붙인다). 한 표에 섞으면 금형 한 줄이 제품 수만큼
   늘어나 금형을 훑을 수 없게 된다. */
.mi-list, .mi-detail { padding: 12px 14px; margin-bottom: 14px; }
/* 목록은 높이를 묶는다 — 36건이 다 펼쳐지면 아래 제품 표가 화면 밖으로 밀린다 */
.mi-grid-wrap { max-height: 340px; overflow: auto; }
.mi-cap { margin-right: 12px; font-size: 14px; font-weight: 800; color: var(--nu-txt2); }
.mi-grid thead th small { margin-left: 6px; font-weight: 500; color: var(--nu-txt4); }
.mi-pcd { font-family: 'Consolas', monospace; }
.mi-psub { color: var(--nu-txt3); margin-left: 6px; }
.mi-more-n { margin-left: 6px; font-size: 11px; color: var(--nu-txt4); }
.mi-b-img { background: var(--nu-success-light); color: var(--nu-success-text); }
.mi-cnt { margin-left: 6px; color: var(--nu-brand-text); }
/* ★금형 목록은 줄 배경색을 쓰지 않는다 — 얼룩(zebra)·hover·선택 전부.
   이 표에는 이미 「미지정」·「제품 미매핑」 경고색이 칸 단위로 들어가 있어서, 줄 배경까지 깔면
   무엇이 경고이고 무엇이 그냥 짝수 줄인지 구분이 안 된다. 색은 경고에만 남긴다.
   ※ .inv-grid 공통 규칙(얼룩·hover)을 여기서만 덮어쓴다 — 다른 화면은 그대로 둔다. */
.mi-grid tbody tr { cursor: pointer; }
.mi-grid tbody tr,
.mi-grid tbody tr:nth-child(even),
.mi-grid tbody tr:hover,
.mi-grid tbody tr:hover td,
.mi-row.sel td { background: transparent; }

/* 선택 표시는 배경 대신 **왼쪽 막대 + 굵은 글자**로 — 배경을 뺐으니 다른 신호가 필요하다 */
.mi-row.sel td { font-weight: 700; }
.mi-row.sel td:first-child { box-shadow: inset 3px 0 0 var(--nu-primary); }
.mi-grid tbody tr:hover td { text-decoration-color: var(--nu-border-strong); }
.mi-name { font-family: 'Consolas', monospace; font-weight: 700; }
.mi-none { color: var(--nu-txt4); }
.mi-warn { color: var(--nu-warning-text); font-weight: 700; }

.mi-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; padding: 4px 2px 12px; }
.mi-h-name { font-size: 22px; font-weight: 800; font-family: 'Consolas', monospace; }
.mi-h-sub { margin-top: 4px; font-size: 13px; color: var(--nu-txt3); }
.mi-h-tag { flex: none; padding: 3px 12px; border-radius: var(--nu-r-pill);
  background: var(--nu-surface-2); color: var(--nu-txt2); font-size: 12px; font-weight: 700; }

.mi-sec { padding: 12px 0; border-top: 1px solid var(--nu-border); }
.mi-sec-t { font-size: 15px; font-weight: 800; color: var(--nu-txt2); margin-bottom: 10px; }
.mi-sec-t small { margin-left: 8px; font-size: 12px; font-weight: 500; color: var(--nu-txt3); }
.mi-sec-t2 { margin-top: 14px; }

.mi-tiles { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 8px; }
@media (max-width: 1600px) { .mi-tiles { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.mi-tile { padding: 8px 10px; border-radius: var(--nu-r-medium); background: var(--nu-surface-2); }
.mi-tile > span { display: block; font-size: 12px; color: var(--nu-txt3); }
.mi-tile > b { display: block; margin-top: 2px; font-size: 17px; font-weight: 800; word-break: break-all; }
.mi-tiles-sm .mi-tile > b { font-size: 14px; }

/* ── 수기 등록 레시피 절 (금형정보 관리, 2026-09-06 합침) ──────────────────
   따로 있던 「금형 레시피 관리」 화면을 이 상세 칸으로 들였다. 값은 여기서 안 고치고
   기존 팝업을 그대로 연다 — 그 팝업이 사출조건 행 조작과 이미지를 이미 갖고 있다. */
.mi-rc-none {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 2px; font-size: 13px; color: var(--nu-txt3);
}
.mi-rc-foot {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin-top: 8px; font-size: 12px; color: var(--nu-txt3);
}
.mi-rc-n b { color: var(--nu-txt1); font-weight: 800; }
/* 준비 메모가 있다는 것만 알린다 — 본문은 툴팁으로. 단말에는 안 띄우는 값이라
   여기서도 크게 펼치지 않는다 */
.mi-rc-note {
  padding: 1px 7px; border-radius: var(--nu-r-pill);
  background: var(--nu-primary-tint); color: var(--nu-brand-text); font-weight: 700;
}
/* 언제·누가 고쳤는지는 오른쪽 끝으로 민다 — 단추가 그 다음이다 */
.mi-rc-when { margin-left: auto; font-variant-numeric: tabular-nums; }

.mi-more summary { cursor: pointer; font-size: 14px; font-weight: 800; color: var(--nu-brand-text); padding: 10px 2px; }
.mi-more summary small { margin-left: 8px; font-size: 12px; font-weight: 500; color: var(--nu-txt3); }
.mi-more[open] > .mi-tiles { margin-top: 8px; }
.mi-dwrap { display: flex; flex-direction: column; gap: 6px; margin-top: 4px; }
.mi-dblock { display: flex; gap: 10px; align-items: baseline; }
.mi-dkind { flex: none; width: 92px; font-size: 12px; font-weight: 700; color: var(--nu-txt3); }
.mi-dlines { display: flex; flex-wrap: wrap; gap: 6px; }
.mi-dlines i { font-style: normal; font-size: 12px; padding: 2px 10px;
  border-radius: var(--nu-r-pill); background: var(--nu-surface-2); white-space: nowrap; }

.mi-form { display: flex; flex-wrap: wrap; gap: 8px 12px; align-items: flex-end; }
.mi-form label { display: flex; flex-direction: column; gap: 3px; font-size: 12px; color: var(--nu-txt3); }
.mi-form input, .mi-form select { min-width: 160px; }
.mi-form .mi-wide input { min-width: 280px; }
.mi-addrow { margin-top: 10px; }

.mi-ptable td { vertical-align: middle; }
.mi-p-img { width: 74px; }
.mi-p-img img { width: 64px; height: 44px; object-fit: contain;
  background: var(--nu-surface-2); border-radius: var(--nu-r-small); }
.mi-p-cd { font-family: 'Consolas', monospace; font-weight: 700; white-space: nowrap; }
.mi-p-primary td { background: var(--nu-success-light); }
.mi-badge { margin-left: 6px; padding: 1px 8px; border-radius: var(--nu-r-pill);
  background: var(--nu-primary); color: var(--nu-on-accent); font-size: 11px; font-weight: 700; }
.mi-p-act { white-space: nowrap; }
.mi-mini { margin-left: 4px; padding: 3px 10px; border-radius: var(--nu-r-small);
  border: 1px solid var(--nu-border-strong); background: var(--nu-card);
  font-family: inherit; font-size: 12px; cursor: pointer; }
.mi-mini.mi-del { color: var(--nu-alert-text); border-color: var(--nu-alert-text); }
/* 파일 입력은 브라우저마다 모양이 달라 버튼처럼 보이게 감싼다 */
.mi-upload { display: inline-block; padding: 3px 10px; border-radius: var(--nu-r-small);
  border: 1px solid var(--nu-border-strong); background: var(--nu-card);
  font-size: 12px; cursor: pointer; }
.mi-upload input { display: none; }

.mi-msg { margin-top: 10px; padding: 10px 14px; border-radius: var(--nu-r-large); font-weight: 700; }
.mi-msg.good { background: var(--nu-success-light); color: var(--nu-success-text); }
.mi-msg.fail { background: var(--nu-alert-light); color: var(--nu-alert-text); }

/* ── 사출기 연동 · 현장 화면 미러 (2026-08-26) ─────────────────────────────
   8/21 회의 §5 — 사무실에서 키오스크와 **같은 그림**을 본다. 다른 점은 조작이 잠겨 있다는 것뿐.
   A안일 때만 [생산시작]이 살아난다(현장이 준비완료를 보낸 뒤). */
.inj-mirror { padding: 12px 16px; margin-bottom: 14px; }
.inj-mirror-cap { display: flex; align-items: center; gap: 10px; font-size: 15px; font-weight: 800; color: var(--nu-txt2); margin-bottom: 10px; }
.inj-mirror-cap small { font-weight: 500; font-size: 12px; color: var(--nu-txt3); }
.inj-mode-sw { margin-left: auto; font-size: 12px; color: var(--nu-txt3); display: flex; align-items: center; gap: 6px; }
.inj-mode-btn { padding: 4px 14px; border-radius: var(--nu-r-pill); border: 1px solid var(--nu-border-strong);
  background: var(--nu-card); font-family: inherit; font-size: 12px; font-weight: 700; cursor: pointer; }
.inj-mode-btn.on { background: var(--nu-primary); color: var(--nu-on-accent); border-color: var(--nu-primary); }

.inj-mirror-body { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr); gap: 14px; align-items: stretch; }
@media (max-width: 1200px) { .inj-mirror-body { grid-template-columns: 1fr; } }
.inj-mcard { padding: 14px 18px; border-radius: var(--nu-r-large); background: var(--nu-surface-2); display: flex; flex-direction: column; gap: 8px; }
.inj-mhead { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.inj-mseq { padding: 2px 12px; border-radius: var(--nu-r-pill); background: var(--nu-primary-tint); color: var(--nu-brand-text); font-size: 13px; font-weight: 800; }
.inj-mitem { font-size: 20px; font-weight: 800; }
.inj-mpause { padding: 2px 10px; border-radius: var(--nu-r-pill); background: var(--nu-warning-light); color: var(--nu-warning-text); font-size: 13px; font-weight: 800; }
.inj-mkv { display: flex; align-items: baseline; gap: 14px; }
.inj-mkv > span { width: 44px; flex: none; font-size: 13px; color: var(--nu-txt3); }
.inj-mkv > b { font-size: 26px; font-weight: 800; font-family: 'Consolas', monospace; }
.inj-mkv > b i { font-style: normal; font-size: 13px; color: var(--nu-txt3); margin-left: 4px; font-family: inherit; }
.inj-mqty { margin-top: 4px; padding: 10px 14px; border-radius: var(--nu-r-medium); background: var(--nu-warning-light); }
.inj-mqty-head { display: flex; align-items: baseline; justify-content: space-between; font-size: 13px; font-weight: 700; color: var(--nu-warning-text); }
.inj-mqty-head i { font-style: normal; font-size: 11px; opacity: 0.8; }
.inj-mqty-num { font-size: 30px; font-weight: 900; font-variant-numeric: tabular-nums; margin: 2px 0 6px; }
.inj-mqty-num small { font-size: 15px; color: var(--nu-txt3); font-weight: 700; }
.inj-mqty-sub { margin-top: 6px; font-size: 12px; color: var(--nu-txt3); }
.inj-mwait { margin-top: 4px; padding: 14px; border-radius: var(--nu-r-medium); background: var(--nu-card); color: var(--nu-txt3); font-size: 15px; font-weight: 700; text-align: center; }

.inj-mside { display: flex; flex-direction: column; gap: 10px; justify-content: center; }
.inj-mhint { padding: 12px 14px; border-radius: var(--nu-r-medium); background: var(--nu-surface-2); font-size: 13px; font-weight: 600; color: var(--nu-txt2); line-height: 1.5; }
.inj-macts { display: flex; gap: 10px; }
.inj-mbtn { flex: 1; min-height: 62px; border: none; border-radius: var(--nu-r-large);
  font-family: inherit; font-size: 22px; font-weight: 900; color: var(--nu-on-accent); cursor: pointer; }
.inj-mbtn:disabled { background: var(--nu-surface-4); color: var(--nu-txt4); cursor: default; }
.inj-mbtn.start { background: var(--nu-primary); }
.inj-mbtn.pause { background: var(--kpi-st-warn, #b7791f); }
.inj-mbtn.end { background: var(--k-miss, #d93025); flex: 0 0 130px; }
.inj-mbtn.wait { background: var(--nu-surface-4); color: var(--nu-txt3); }

/* 호기 카드 → 설비 상세현황 링크 (2026-08-26)
   누를 수 있다는 것이 보여야 한다 — 손 커서·테두리·살짝 떠오름. 색은 쓰지 않는다
   (카드 색은 달성률 등급을 뜻하므로, 링크 표시에 색을 쓰면 등급과 헷갈린다). */
.ep-card.ep-link { cursor: pointer; transition: transform 0.08s, box-shadow 0.12s, border-color 0.12s; }
.ep-card.ep-link:hover { transform: translateY(-2px); box-shadow: var(--nu-elev-medium); border-color: var(--nu-border-strong); }
.ep-card.ep-link:focus-visible { outline: 3px solid var(--nu-primary); outline-offset: 2px; }
.ep-card.ep-link::after {
  content: '상세 ›'; position: absolute; right: 12px; bottom: 10px;
  font-size: 11px; font-weight: 700; color: var(--nu-txt3); opacity: 0; transition: opacity 0.12s;
}
.ep-card.ep-link { position: relative; }
.ep-card.ep-link:hover::after, .ep-card.ep-link:focus-visible::after { opacity: 1; }

/* 접은 메뉴 (2026-08-27) — 지운 것이 아니라 **감춘** 것이다.
   라우트·코드·권한은 그대로여서 주소로는 열린다. 되살리기는 HTML 에서 class 만 빼면 된다.
   근거: docs/화면정리_검토_2026-08-27.md */
.nav-sub a.nav-folded { display: none; }
/* ── 사이드바 층 소제목 (2026-09-06 재구성) ───────────────────────────────
   기준정보 / 업무 / 분석 / 운영 넷을 가르는 줄이다. **접히지 않는다** —
   층까지 <details> 로 만들면 3단이 되어 항목 하나 찾는 데 두 번 펴야 한다.

   글자는 묶음 머리(--nu-txt3)와 항목(--nu-txt2)보다 한 단 위라 --nu-txt1 이다.
   ★ 색 리터럴을 쓰지 않는다. 꾸러미 기본값은 어두운 사이드바를 전제하는데 이
     보드는 흰 면이라, 흰색 알파를 적었더니 글자가 통째로 안 보였다. 토큰을 쓰면
     톤을 바꿔도 따라 돈다. */
.nav-section {
  /* 여백은 되도록 아낀다 — 소제목 넷이 사이드바를 205px 늘렸고(실측 1214->1419)
     보이는 높이는 1036 이라 이미 스크롤된다 */
  margin: 9px 0 1px;
  padding: 5px 12px 4px;
  color: var(--nu-txt1);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  border-top: 1px solid var(--nu-border-l);
}
/* 첫 층은 홈 바로 아래라 선을 긋지 않는다 — 홈과 갈라 놓을 것이 없다 */
.nav-section:first-of-type { margin-top: 10px; border-top: none; }

/* 층 바로 아래 평평하게 두는 링크. 묶을 만큼 화면이 많지 않은 자리에 쓴다
   (기준정보 · 분석). 꾸러미의 .nav-group .nav-sub a 와 같은 들여쓰기·크기라
   묶음 안의 항목과 나란히 보인다. */
.nav-flat { display: grid; gap: 5px; }
.nav-flat a { padding-left: 24px; font-size: 0.88rem; }
.nav-flat a.nav-folded { display: none; }


/* ── CSP 대응 (2026-09-01) ────────────────────────────────────────────────
   style= 속성은 style-src 가 막는다(꾸러미 0.11.0). 값이 그때그때 다른 것은
   data-fill-w 로 넘겨 셸이 칠하고, 고정값은 여기 이름을 붙인다. */
.inv-empty.inj-mirror-empty { padding: 26px; }   /* 현장 화면 미러 — 빈 상태 */
.k-track.inj-mtrack { height: 14px; }            /* 미러의 진행 막대는 본 화면보다 낮다 */
.panel.inv-empty.mi-empty { padding: 24px; }     /* 금형정보 — 금형을 고르기 전 안내 */

/* ── 그룹 헤더를 제목처럼 세운다 (2026-09-01 요청) ─────────────────────────
   꾸러미 원본은 그룹 헤더를 "제목"이 아니라 **작고 자간 넓은 라벨**(11px/700,
   데스크톱 10.5px)로 두었다. 여기서는 그 판단을 뒤집어 크고 굵게 간다 —
   그룹이 9개라 훑을 때 먼저 걸리는 것이 그룹명이어야 한다는 요청이다.

   ★ 이 한 줄이 꾸러미의 기본 규칙과 데스크톱 미디어쿼리(min-width:1201px)를
     한꺼번에 이긴다 — 미디어 질의는 명시도를 올리지 않고, 이 파일이 나중에 실린다.
     그래서 여기 값을 지우면 10.5px 로 되돌아간다(두 곳을 고칠 필요는 없다).
   ★ 자간은 줄인다. 0.06em 은 작은 라벨이라 넣었던 값이고, 13px 에서는 글자가
     흩어져 보인다.
   ★ 높이 예산 — 그룹 하나당 약 +4px(9그룹 = 약 +36px). 모든 그룹을 펼친
     관리자 화면에서는 사이드바가 스크롤될 수 있다. 그때는 항목 padding 을
     5px → 4px 로 줄여 되사면 된다(항목 1px = 전체 약 28px). */
.nav-group > summary {
  font-size: 13px;
  font-weight: 800;
  letter-spacing: 0.01em;
}

/* ── 스케줄확정 — 소요시간·시작/완료 예상 · 금형교체 (2026-09-01) ────────
   회의 요구(08-13 작업지시별 소요시간·예상 시각 / 05-21·07-30 금형교체 횟수). */
.sc-dur { font-variant-numeric: tabular-nums; white-space: nowrap; }
/* 차종 대표 C/T 로 낸 추정치 표시 — 색이 아니라 기호가 뜻을 담는다(§0-4) */
.sc-est { margin-left: 3px; color: var(--nu-txt3); font-weight: 700; }
.sc-goal-sub { margin-left: 6px; font-size: 0.78rem; font-weight: 500; color: var(--nu-txt3); }
/* 목표를 넘긴 금형교체 — 상태색은 채움 전용이라 글자에는 text 톤을 쓴다 */
.home-kri-goal b.sc-over { color: var(--nu-warning-text); }

/* ═══ 「생성중인 생산계획」 6단계 진행 보드 (2026-09-01) ══════════════════
   cheil_poc 에서 역이식했다. 원래 SimAPS 의 단계 표시를 저쪽이 가져가 다듬은 것을
   다시 받아 온 것이다. 칸은 **과정을 보여 주는 것**이지 구간을 잰 계측값이 아니다
   (근거·규칙은 app.js 의 SIM_STEPS 머리주석).
   ★ 깜빡임(simVideoPulse)은 꾸러미 styles.css 가 이미 정의해 두었다 — 다시 만들지 말 것. */
.sched-steps-slot { margin-bottom: 10px; }

.sched-steps-board { border: 1px solid var(--border); border-radius: var(--nu-r-large);
  background: var(--panel); padding: 12px 14px 14px; }
/* 실행 중인 작업이 없을 때 — 칸 없이 한 줄. 박스도 그만큼 낮아진다. */
.sched-steps-board.is-idle { padding: 10px 14px; }
.sched-steps-empty { font-size: .84rem; color: var(--nu-txt4); }

.sched-steps-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 12px; flex-wrap: wrap; }
.sched-steps-name { font-size: .95rem; font-weight: 800; color: var(--nu-txt1); }
.sched-steps-meta { font-size: .78rem; color: var(--nu-txt3); }
.sched-steps-time { margin-left: auto; font-size: .82rem; color: var(--nu-txt2);
  font-variant-numeric: tabular-nums; }
.sched-steps-time b { font-weight: 800; color: var(--nu-warning-text); }
.sched-steps-time.is-done { color: var(--nu-success-text); font-weight: 700; }
.sched-steps-time.is-done b { color: var(--nu-success-text); }

.sched-steps { display: flex; align-items: stretch; gap: 6px; }
.sched-step { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column;
  align-items: center; gap: 7px; padding: 14px 8px 12px;
  background: var(--nu-surface-2); border: 1px solid var(--border);
  border-radius: var(--nu-r-large); transition: background .2s, border-color .2s; }
.sched-step-no { display: flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; border-radius: var(--nu-r-pill);
  background: var(--nu-surface-3); color: var(--nu-txt4); font-size: .82rem; font-weight: 800; }
.sched-step-label { font-size: .78rem; font-weight: 600; line-height: 1.35;
  color: var(--nu-txt3); text-align: center; }
.sched-step-state { min-height: 16px; font-size: .74rem; font-weight: 700; color: transparent; }
.sched-step-arrow { align-self: center; color: var(--nu-txt4); font-size: 1rem; flex: none; }

/* 끝난 칸 — 번호를 성공색으로, 상태는 ✓ */
.sched-step.is-done .sched-step-no { background: var(--nu-success-text); color: var(--nu-on-accent); }
.sched-step.is-done .sched-step-label { color: var(--nu-txt2); }
.sched-step.is-done .sched-step-state { color: var(--nu-success-text); }

/* 지금 도는 칸 — 강조 테두리 + 깜빡이는 '진행중' */
.sched-step.is-active { background: var(--nu-primary-tint); border-color: var(--nu-primary); }
.sched-step.is-active .sched-step-no { background: var(--accent2); color: var(--nu-on-accent); }
.sched-step.is-active .sched-step-label { color: var(--nu-txt1); }
.sched-step-state.is-run { color: var(--nu-warning-text); animation: simVideoPulse 1.2s ease-in-out infinite; }

@media (max-width: 1100px) {
  .sched-step-label { font-size: .72rem; }
  .sched-step-arrow { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .sched-step-state.is-run { animation: none; }
}

/* ─── 엔진이 낸 시뮬레이션 결과 ────────────────────────────────────────────────
   표본 결과와 컬럼이 달라 표시도 갈라 둔다. 어느 쪽을 보고 있는지가 화면에
   드러나야 한다 — 같은 모양이면 표본을 실제로 착각한다. */
.simr-engine-tag {
  margin-left: .5rem; padding: .12rem .5rem; border-radius: 999px;
  font-size: .76rem; color: var(--nu-txt3);
  background: var(--nu-bg3); border: 1px solid var(--nu-line);
}
.simr-engine-summary {
  display: flex; flex-wrap: wrap; gap: .35rem .9rem;
  padding: .55rem .75rem; margin-bottom: .6rem;
  background: var(--nu-bg2); border: 1px solid var(--nu-line); border-radius: 6px;
}
.simr-sum-cell { font-size: .82rem; color: var(--nu-txt3); }
.simr-sum-cell b { font-size: .95rem; color: var(--nu-txt1); margin-right: .15rem; }

/* 시간축에서 창 안에 못 끝낸 자원 — 병목이 어디인지 한눈에 보이게 한다 */
.sched-table tr.is-blocked td { background: color-mix(in srgb, var(--kpi-st-warn) 12%, transparent); }
.sched-table tr.is-blocked td:first-child { font-weight: 600; }

/* 엔진이 안 떠 있는 것을 화면이 말하는 자리. 조용한 빈 화면과 구분한다 */
.sched-steps-board.is-engine-down {
  border-color: var(--nu-warn, #c2703a);
  background: var(--nu-bg2);
}
.sched-hint { margin-top: .5rem; font-size: .8rem; color: var(--nu-txt4); }
/* 스케줄링 설정 — 하단 액션 바의 [스케줄링 요청현황] 은 오른쪽 끝에 세운다.
   왼쪽은 '이 화면에서 정하는 것'(옵션·이름·비가동), 오른쪽은 '여기서 나가는 길'이라
   자리로 역할이 갈린다. 바가 flex 라 margin-left:auto 하나면 된다. */
.sched-action-bar .sched-status-btn { margin-left: auto; }

/* 비가동 화면 하단 — [스케줄링 설정] 과 [스케줄링 시작] 이 붙지 않게 사이를 띄운다.
   꾸러미의 .sched-bottom-bar 는 flex-end 만 걸려 있고 gap 이 없다. 결과 화면의 같은
   바에는 영향이 없도록 이 화면으로 한정한다. */
#layoutRoot.sim-downtime-page .sched-bottom-bar { gap: 8px; }

/* ── 스케줄링 요청내역 표 ──────────────────────────────────────────────
   자동 정렬 판정(applyTableAlignment)에서 뺀 표라 정렬을 여기서 정한다.
   전부 가운데, 스케줄링명만 왼쪽 — 이름은 읽는 값이라 왼쪽이 눈이 편하고
   나머지는 형식이 일정한 일시·코드라 가운데가 줄이 맞는다.
   너비는 table-layout:fixed 로 못박는다. auto 로 두면 내용 길이에 따라
   열이 매번 달라져 "폭을 키웠다"가 자료에 따라 도로 좁아진다. */
.sched-hist-wrap .sched-hist-table { table-layout: fixed; }
.sched-hist-wrap .sched-hist-table th,
.sched-hist-wrap .sched-hist-table td { text-align: center; }

/* 스케줄링명 — 왼쪽 정렬. 길면 말줄임하고 전체는 title 로 보인다(잘린 줄 모르면 안 된다). */
.sched-hist-wrap .sched-hist-table th:nth-child(1),
.sched-hist-wrap .sched-hist-table td:nth-child(1) {
  text-align: left;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* 날짜 열이 내용보다 100px 씩 벌어져 있던 여유를 스케줄링명으로 옮긴다(127px → 313px).
   ★2026-09-10 에 둘째 자리로 **출처**가 들어와 뒤가 한 칸씩 밀렸다. 폭은 자리
     번호로 매기므로 칸을 끼우면 여기도 같이 옮겨야 한다 — 안 옮기면 날짜 열이
     소요시간 폭(5%)을 받아 글자가 줄바꿈된다. */
.sched-hist-wrap .sched-hist-table th:nth-child(1) { width: 17%; }
.sched-hist-wrap .sched-hist-table th:nth-child(2) { width: 6%; }   /* 출처 */
.sched-hist-wrap .sched-hist-table th:nth-child(3) { width: 11%; }
.sched-hist-wrap .sched-hist-table th:nth-child(4),
.sched-hist-wrap .sched-hist-table th:nth-child(5),
.sched-hist-wrap .sched-hist-table th:nth-child(6) { width: 12%; }
.sched-hist-wrap .sched-hist-table th:nth-child(7) { width: 8%; }
.sched-hist-wrap .sched-hist-table th:nth-child(8) { width: 5%; }
.sched-hist-wrap .sched-hist-table th:nth-child(9) { width: 8%; }
.sched-hist-wrap .sched-hist-table th:nth-child(10) { width: 13%; }

/* ── 담당자 관리 (기준정보) ─────────────────────────────────────────────
   배정 줄과 목록만 있는 화면이라 새 얼개를 만들지 않고 기존 표·버튼을 그대로 쓴다.
   여기 있는 것은 그 사이를 벌리는 최소한이다. */
.ma-form { display: flex; flex-wrap: wrap; gap: 12px; align-items: flex-end; padding: 12px 4px; }
.ma-form label { display: flex; flex-direction: column; gap: 4px; font-size: 12px; color: var(--text-muted, #667); }
.ma-form select, .ma-form input { min-width: 150px; }
.ma-act { white-space: nowrap; }
.ma-act button { margin-right: 6px; font-size: 12px; padding: 2px 8px; cursor: pointer; }
/* 끝난 담당은 지우지 않고 남긴다. 남은 것이 현재 것처럼 보이면 안 되므로 흐린다. */
tr.ma-ended td { opacity: .55; }
/* 스케줄확정의 '내 담당만' — 호기 고르개 옆에 나란히 선다 */
.sc-mine { display: inline-flex; align-items: center; gap: 4px; font-size: 12px; cursor: pointer; }

/* ── 새 스케줄링 요청 — 부족한 것을 고르는 표 ───────────────────────────
   바탕(.sched-table · .sched-orders-wrapper · .re-badge)은 board-core 것을 그대로
   쓴다. 여기 있는 것은 **이 화면에만 있는 네 가지**다 — 담기 칸 · 수량 입력 ·
   뺀 줄 · 목록 밖 품번을 더하는 줄.
   ★board-core 를 고치지 않는다. 거기서 고치면 다음 판을 받을 때 덮인다. */
.sched-pick-cell { text-align: center; }
.sched-pick-cell input { cursor: pointer; }

/* 뺀 줄을 지우지 않고 흐린다. 지우면 무엇을 뺐는지가 안 보여 되돌릴 수 없다. */
tr.sched-row-dropped td { opacity: .45; }

/* 표 안에서 고치는 수량. 오른쪽 정렬이라야 위아래 자릿수가 맞는다 */
.sched-qty-input {
  width: 92px; text-align: right; font-size: 0.83rem; padding: 2px 6px;
  background: var(--panel); color: var(--text); border: 1px solid var(--border);
  border-radius: 4px;
}
.sched-qty-input:focus { outline: 2px solid var(--accent, #3b82f6); outline-offset: -1px; }

.sched-add-bar {
  display: flex; flex-wrap: wrap; gap: 8px; align-items: center;
  padding: 10px 4px;
}

/* 이 화면의 잔글씨. board-core 의 .sched-label 과 같은 톤이되 줄 안에 섞여 선다 */
.simreq-note { color: var(--muted); font-size: 0.78rem; }
/* 수량을 치는 동안 합계는 아직 그 값이 아니다. 숫자를 고쳐 쓰지 않고 흐려서
   「지금 값이 아니다」만 말한다 — 치는 중에 다시 그리면 커서가 튄다. */
.simreq-note.is-stale { opacity: .4; }

/* ── 안 비교 표 ─────────────────────────────────────────────────────────
   가동 목록 바로 위에 선다. 아래 표가 **지금 고른 안의 것**이라 이 표가 그것을
   설명한다 — 자리를 바꾸면 무엇을 보고 있는지 모른 채 숫자를 읽게 된다. */
.simr-cand-table td, .simr-cand-table th { white-space: nowrap; }
/* 고른 줄을 칠한다. 순위 1등과 다를 수 있으므로 순위만으로는 못 가린다. */
tr.simr-cand-picked td { background: var(--row-hover, rgba(59, 130, 246, .10)); font-weight: 600; }
.simr-pick-btn { font-size: 11px; padding: 2px 8px; cursor: pointer; white-space: nowrap; }

/* ── 결과 재생 ──────────────────────────────────────────────────────────
   세운 계획을 시간축 위로 훑는 화면. 엔진에 시계를 안 넣었으므로 여기는 **재생**이고,
   돌리는 동안 엔진은 아무것도 안 한다.
   ★자리(left·width)는 JS 가 넣는다 — 인라인 style 속성은 CSP 가 막는다. */
.simr-play-btn { margin-left: auto; }

.simplay-bar {
  display: flex; flex-wrap: wrap; gap: 10px; align-items: center;
  padding: 10px 4px;
}
.simplay-scrub { flex: 1 1 240px; min-width: 180px; cursor: pointer; }
.simplay-clock {
  font-variant-numeric: tabular-nums; font-size: 0.9rem; font-weight: 600;
  color: var(--text); white-space: nowrap;
}
.simplay-metrics { margin-bottom: 10px; }

/* 호기 카드 — 지금 무엇을 하고 있나 */
.simplay-cards {
  display: grid; gap: 8px; margin-bottom: 12px;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
}
.simplay-card {
  border: 1px solid var(--border); border-radius: var(--nu-r-medium, 8px);
  background: var(--panel); padding: 8px 10px;
}
.simplay-card-head { font-weight: 600; font-size: 0.85rem; color: var(--text); }
/* 쉼이 기본이다. 칠하지 않는 것이 「지금 안 돈다」를 말한다 */
.simplay-state { font-size: 0.78rem; color: var(--muted); margin-top: 2px; }
.simplay-card.is-work .simplay-state { color: var(--nu-success-text, #15803d); font-weight: 600; }
.simplay-card.is-setup .simplay-state { color: var(--kpi-st-warn, #b45309); font-weight: 600; }
.simplay-what {
  font-size: 0.76rem; color: var(--muted); margin-top: 2px;
  min-height: 1.1em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.simplay-progress {
  height: 4px; margin-top: 6px; border-radius: 2px;
  background: var(--border); overflow: hidden;
}
.simplay-progress > i { display: block; height: 100%; width: 0; background: var(--jv-primary, #2563eb); }
.simplay-card.is-setup .simplay-progress > i { background: var(--kpi-st-warn, #b45309); }

/* 호기별 띠. 띠가 없는 자리는 쉼이다 — 칠하지 않는다 */
.simplay-chart { padding: 4px 0; }
.simplay-row { display: flex; align-items: center; gap: 8px; margin-bottom: 4px; }
.simplay-row-label {
  flex: 0 0 84px; font-size: 0.78rem; color: var(--muted);
  text-align: right; white-space: nowrap;
}
.simplay-track {
  position: relative; flex: 1 1 auto; height: 16px;
  background: var(--row-hover, rgba(0, 0, 0, .04));
  border-radius: 3px; overflow: hidden;
}
.simplay-block { position: absolute; top: 2px; height: 12px; border-radius: 2px; }
.simplay-block.is-work { background: var(--jv-primary, #2563eb); }
.simplay-block.is-setup { background: var(--kpi-st-warn, #b45309); }
/* 지금 보고 있는 시각. 띠 위에 서야 하므로 z-index 를 준다 */
.simplay-cursor {
  position: absolute; top: 0; width: 2px; height: 100%;
  background: var(--kpi-st-serious, #b91c1c); z-index: 2;
}

/* 전략에 딸린 설명은 **줄을 바꿔** 놓는다. 한 줄에 이으면 「금형 교체 최소화 호기 안
   순번을 가중치로 다시 짠다」처럼 한 문장으로 읽혀 전략 이름이 어디까지인지 흐려진다. */
.simr-cand-note { display: block; margin-top: 2px; }
/* 전략 칸만 줄바꿈을 허용한다 - 나머지는 숫자라 nowrap 이 맞다 */
.simr-cand-table td:nth-child(4) { white-space: normal; }
/* 목록에서 빠진 긴급을 알리는 줄. 경고가 아니라 **설명**이라 붉게 칠하지 않는다 */
.simreq-hidden { margin-left: 10px; border-left: 2px solid var(--kpi-st-warn, #b45309); padding-left: 8px; }

/* ── 고대비(forced-colors)에서도 재생이 읽히게 ─────────────────────────
   윈도우 고대비를 켜면 브라우저가 **`background-color` 를 통째로 덮는다.** 그러면
   이 화면에서 정보를 나르는 것이 전부 죽는다 - 띠도 커서도 진행바도 검정이 되어
   트랙과 구별되지 않는다. 실제로 이 PC 에서 그렇게 보였다(2026-09-10).

   ★**`forced-color-adjust: none` 으로 우리 색을 우기지 않는다.** 그것은 사용자가
     켜 둔 접근성 설정을 무르는 것이다. 대신 고대비가 **허용하는 시스템 색**
     (Highlight · Canvas · CanvasText · ButtonBorder)으로 다시 칠한다.
   ★가동과 교체를 **색이 아니라 꼴로도** 가른다 - 고대비 팔레트는 색 수가 적어
     둘을 색만으로 가르면 같은 색이 될 수 있다. 교체는 테두리만 남겨 속을 비운다. */
@media (forced-colors: active) {
  /* 이 PC 의 고대비 팔레트에서 검정 바탕과 갈리는 것은 셋뿐이다 -
     CanvasText 흰색 · ButtonBorder 노랑 · LinkText 연보라.
     Highlight 는 짙은 회색(82,82,82)이라 검정 위에서 흐리다 - 쓰지 않는다. */
  .simplay-track { border: 1px solid GrayText; }
  /* 가동 = 채운 띠 (연보라) */
  .simplay-block.is-work { background: LinkText; }
  /* 교체 = 속 빈 띠 + 노랑 테두리. 색과 꼴을 **둘 다** 달리해 색 하나에 안 기댄다 */
  .simplay-block.is-setup { background: Canvas; border: 1px solid ButtonBorder; }
  /* 지금 시각. 가장 얇은 요소라 안 보이면 화면의 뜻이 사라진다 -
     띠 둘과 겹치지 않게 흰색을 여기 쓴다 */
  .simplay-cursor { background: CanvasText; width: 3px; }
  .simplay-progress { border: 1px solid GrayText; }
  .simplay-progress > i,
  .simplay-card.is-setup .simplay-progress > i { background: LinkText; }
  /* 지금 도는 호기를 테두리로도 말한다 - 고대비에서는 글자색이 다 같아진다 */
  .simplay-card.is-work { outline: 2px solid LinkText; outline-offset: -2px; }
  .simplay-card.is-setup { outline: 2px dashed ButtonBorder; outline-offset: -2px; }
}

/* ── 키오스크 현 화면 조회 (사출 > 사출기 연동) ─────────────────────────
   설계서 260908 의 화면을 **그대로** 옮긴다 — 칸 비율·색·글자 크기까지 맞춘다.
   원본에서 잰 비율: 현재·차기 카드 62% · 목록 38% · 이미지 60% · 레시피 40%.
   ★현장 단말은 17인치 터치라 절대 크기가 크다. 여기는 보드 안이라 **비율은 같게,
     절대 크기만** 줄였다. 비율이 달라지면 「같은 화면」이 아니게 된다.
   ★조회 전용이다. 조작 칸 셋은 눌리지 않는다. */
.kv-screen { border: 1px solid #c9cfda; border-radius: 4px; overflow: hidden;
  background: #fff; font-size: 14px; color: #2b3245; }
.kv-hdr { display: flex; justify-content: space-between; align-items: center;
  background: #1f3864; color: #fff; padding: 8px 18px; }
.kv-hdr-name { font-size: 22px; font-weight: 700; letter-spacing: .5px; }
.kv-hdr-right { display: flex; align-items: center; gap: 14px; font-size: 13px; }
.kv-hdr-user { background: #2f5597; padding: 5px 16px; border-radius: 2px; font-size: 13px; }

/* ①② — 카드 62% : 목록 38% */
.kv-top { display: grid; grid-template-columns: 62fr 38fr; gap: 10px; padding: 10px; align-items: start; }
.kv-bigs { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.kv-big { border: 2px solid #dfe3ea; border-radius: 4px; background: #f2f4f8;
  padding: 12px 10px; text-align: center; cursor: pointer; min-height: 138px;
  display: flex; flex-direction: column; justify-content: center; gap: 7px; }
.kv-big.cur { background: #fff; border-color: #2f5597; }
.kv-big.on { box-shadow: inset 0 0 0 2px #8aa8d8; }
.kv-big.off { opacity: .45; cursor: default; }
.kv-big-lbl { font-size: 25px; font-weight: 700; color: #8a93a6; line-height: 1.1; }
.kv-big.cur .kv-big-lbl { color: #1f3864; }
.kv-big-mold { font-size: 20px; font-weight: 700; word-break: keep-all; color: #1f3864; line-height: 1.2; }
.kv-big.cur .kv-big-mold { color: #16264a; }
.kv-big-qty { font-size: 38px; font-weight: 700; color: #2f5597; line-height: 1; }

.kv-list-hd { display: flex; align-items: center; gap: 5px; margin-bottom: 5px; }
.kv-chip { font-size: 13px; padding: 5px 14px; border-radius: 3px; font-weight: 700; }
.kv-chip.done { background: #e2efda; color: #375623; }
.kv-chip.left { background: #fbe5d6; color: #833c0c; }
.kv-pg { font-size: 13px; padding: 5px 12px; border: 1px solid #d5dae3; background: #eef1f6;
  border-radius: 3px; cursor: pointer; color: #3b4252; }
.kv-pg:disabled { opacity: .4; cursor: default; }
.kv-pgn { font-size: 13px; color: #5a6478; margin: 0 4px; }

.kv-t { width: 100%; border-collapse: collapse; }
.kv-t th { background: #2f5597; color: #fff; font-weight: 600; padding: 6px 8px; font-size: 13px; }
.kv-t td { border-bottom: 1px solid #e8ebf0; padding: 6px 8px; font-size: 14px; }
.kv-t tfoot td { background: #eef2f8; font-weight: 700; text-align: center; }
.kv-qt th:first-child, .kv-qt td:first-child { width: 56px; }
.kv-c { text-align: center; }
.kv-r { text-align: right; }
.kv-nm { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 340px; }
.kv-qr { cursor: pointer; }
.kv-qr.on { background: #eef2f8; font-weight: 600; }
.kv-empty { text-align: center; color: #9aa2b1; padding: 12px; }
.kv-good { color: #2e7d32; font-weight: 700; }
/* 원천이 없어 못 채우는 칸. 0 으로 보이면 안 된다 — 흐리게 두고 툴팁이 까닭을 적는다 */
.kv-na { color: #aab1bf; }
.kv-swatch { display: inline-block; width: 38px; height: 17px; border: 1px solid #c9cfda;
  vertical-align: middle; border-radius: 2px; }
.kv-items { margin: 0 12px; width: calc(100% - 24px); }

/* ④⑤ — 이미지 60% : 레시피 40% */
.kv-mid { display: grid; grid-template-columns: 60fr 40fr; gap: 10px; padding: 10px; }
.kv-img { border: 1px solid #e8ebf0; border-radius: 3px; height: 168px; background: #f7f8fa;
  display: flex; align-items: center; justify-content: center; }
.kv-img img { max-height: 158px; max-width: 100%; }
.kv-rt { font-size: 12px; color: #7a8397; margin-bottom: 6px; }
.kv-rg { display: grid; grid-template-columns: 1fr 1fr; gap: 9px; }
.kv-rc { border: 1px solid #dfe3ea; border-radius: 3px; padding: 9px 14px; height: 70px;
  display: flex; flex-direction: column; justify-content: center; }
.kv-rc-l { font-size: 12px; color: #8a93a6; margin-bottom: 4px; }
.kv-rc-v { font-size: 26px; font-weight: 700; color: #1f3864; line-height: 1; }
.kv-rn { font-size: 11px; margin-top: 7px; }

/* ⑨ */
.kv-alarm { display: flex; align-items: center; gap: 10px; padding: 0 10px 8px; flex-wrap: nowrap; }
.kv-tag { background: #d9dde5; color: #3b4252; padding: 6px 14px; border-radius: 2px; font-size: 13px;
  white-space: nowrap; }
.kv-alarm-v { flex: 1 1 200px; color: #7a8397; background: #f7f8fa; border: 1px solid #e8ebf0;
  padding: 6px 12px; border-radius: 2px; font-size: 13px; }
.kv-alarm-v.on { color: #c0392b; font-weight: 700; background: #fdecea; border-color: #f5c6c0; }
.kv-recv { flex: 1 1 280px; background: #f7f8fa; border: 1px solid #e8ebf0; padding: 6px 12px;
  border-radius: 2px; font-size: 13px; white-space: nowrap; overflow: hidden;
  text-overflow: ellipsis; }
.kv-recv b { margin: 0 12px 0 4px; color: #1f3864; }

/* ⑩⑥⑦ — 운전 모드 · 금형 장착 · 생산. 눌리지 않는다 */
.kv-foot { display: grid; grid-template-columns: 1fr 1fr 1.5fr; gap: 10px; padding: 0 10px 10px; }
.kv-mode, .kv-mount, .kv-act { border: 2px solid #dfe3ea; border-radius: 4px;
  padding: 11px 10px; text-align: center; font-weight: 700; font-size: 19px;
  display: flex; align-items: center; justify-content: center; gap: 10px; }
.kv-mode span { font-weight: 400; color: #8a93a6; font-size: 17px; }
.kv-mode b { font-size: 26px; }
/* 수동·셋업이면 금형자료를 바꿀 수 있다(초록). 자동·반자동이면 거절된다(파랑) — 설계서 ⑩ */
.kv-mode-ok { border-color: #2e7d32; } .kv-mode-ok b { color: #2e7d32; }
.kv-mode-auto { border-color: #2f5597; } .kv-mode-auto b { color: #2f5597; }
.kv-mode-none b { color: #aab1bf; }
.kv-check { color: #2e7d32; font-size: 24px; }
.kv-act { font-size: 26px; letter-spacing: 4px; }
.kv-act-start { background: #2f5597; border-color: #2f5597; color: #fff; }
.kv-act-run { background: #ed7d31; border-color: #ed7d31; color: #fff; }
.kv-act-done { background: #4caf50; border-color: #4caf50; color: #fff; }
.kv-act-load { background: #ffd966; border-color: #ffd966; color: #7f6000; }
.kv-act-warn { background: #fbe5d6; border-color: #ed7d31; color: #833c0c; }
.kv-act-idle { color: #aab1bf; }
/* 조작 칸은 눌리지 않는다. 색은 살린다 — 설계서 ⑦ 이 「버튼 글자가 곧 상태」라
   흐리게 만들면 그 상태를 못 읽는다. 못 누른다는 것은 자물쇠와 커서가 말한다. */
.kv-lock { cursor: default; user-select: none; }
@media (max-width: 1180px) {
  .kv-top, .kv-mid { grid-template-columns: 1fr; }
  .kv-foot { grid-template-columns: 1fr; }
}

/* 화면 하나만 서는 자리 — 판(panel) 겉을 두르지 않는다. 설계서 화면 위에 다른 것이
   서면 「현장 단말에 뜬 그대로」가 아니게 된다. */
/* 현장 단말은 17인치다. 폭을 제한하지 않고 꽉 채운다 — 좁게 두면 같은 화면이 아니다 */
.kv-wrap { width: 100%; }
/* 데이터 설명 — 기본으로 접어 둔다. 왜 「—」인지는 반드시 묻는 사람이 생기고,
   그때 답이 화면 안에 있어야 한다. 늘 펴 두면 화면의 주인이 설명문이 된다. */
.kv-img { position: relative; }

/* 세로가 더 좁은 화면(1080 보다 낮거나 크롬이 두꺼운 경우)에서 한 번 더 조인다.
   ★강조(수량·운전모드·생산버튼)는 마지막까지 지킨다 — 그것을 줄이면 이 화면의
     쓸모가 없어진다. 줄이는 것은 여백과 상자 높이다. */
@media (max-height: 900px) {
  .kv-big { min-height: 116px; padding: 9px 8px; gap: 5px; }
  .kv-big-lbl { font-size: 21px; }
  .kv-big-mold { font-size: 18px; }
  .kv-t th, .kv-t td { padding: 4px 8px; }
  .kv-img { height: 132px; }
  .kv-img img { max-height: 124px; }
  .kv-rc { height: 58px; padding: 7px 12px; }
  .kv-rc-v { font-size: 22px; }
  .kv-mode, .kv-mount, .kv-act { padding: 8px 10px; }
}
/* ③ 품목이 많으면 줄을 줄인다 — 설계서가 「페이지 없이, 개수에 맞춰 행 높이와 글자가
   커지고 작아진다」고 적었다. 쪽을 나누면 작업자가 제 품번을 찾으려고 화면을 넘겨야 한다. */
.kv-items.dense td { padding: 3px 8px; font-size: 13px; }
.kv-items.dense th { padding: 4px 8px; font-size: 12px; }
.kv-items.dense .kv-swatch { height: 14px; width: 32px; }
.kv-items.denser td { padding: 1px 8px; font-size: 12px; }
.kv-items.denser th { padding: 3px 8px; font-size: 11px; }
.kv-items.denser .kv-swatch { height: 12px; width: 28px; }

/* ── 자재 소요·발주계획 ─────────────────────────────────────────────────
   ★높이를 고정한다. 역할·재질·기간을 바꿀 때마다 행 수가 크게 달라지는데
     (재단품 95종 · 게이트 68 · 표피 39), 높이가 따라 변하면 필터를 누를 때마다
     화면이 튀어 어디를 보고 있었는지 잃는다.
   ★그래프 : 표(검색줄 포함) = **4 : 6**. 판 전체 높이를 정하고 둘이 나눠 갖는다.
   ★canvas 에 높이를 직접 주지 않는다. Chart.js 가 `maintainAspectRatio:false` 로
     **부모 크기에 맞춰 canvas 를 제 손으로 늘린다** — 거기에 !important 로 높이를
     박으면 둘이 싸워 canvas 가 넘치고, 아래 검색줄을 덮어 클릭이 안 먹는다
     (2026-09-10 에 실제로 그랬다). 높이는 **부모에만** 준다. */
/* 높이를 직접 주지 않는다. `#layoutRoot.fit-page > .panel` 이 이미 **총계 띠를 빼고
   남은 높이**를 판에 준다 — 거기에 height 를 박으면 둘이 싸운다.
   판이 받은 그 높이를 그래프 4 : 표 6 으로 나눈다. */
#layoutRoot.fit-page > .fr-panel { gap: 8px; }
#layoutRoot.fit-page > .fr-panel > .viz-card {
  flex: 4 1 0; min-height: 0; display: flex; flex-direction: column; }
#layoutRoot.fit-page > .fr-panel > .viz-card > .viz-title { flex: 0 0 auto; }
#layoutRoot.fit-page > .fr-panel > .fr-body {
  flex: 6 1 0; min-height: 0; display: flex; flex-direction: column; gap: 8px; }
.fr-body > .inv-filter-bar, .fr-body > .inv-note, .fr-body > .data-note { flex: 0 0 auto; }
/* 「데이터 유의사항」은 표 밑이 아니라 제목줄 오른쪽 끝(화면 우측 상단)에 둔다(2026-09-14 사용자 요청).
   펼치면 아래로 **떠서** 열린다 - 발주 정책값(.op-note)·홈 카드와 같은 꼴. 줄 안에서 자라면 그래프가 눌린다. */
.fr-title { display: flex; align-items: baseline; gap: 0; }
.fr-title > .fr-note { position: relative; margin-left: auto; font-weight: 400; font-size: 0.8rem; }
.fr-title > .fr-note > ul {
  position: absolute; right: 0; top: calc(100% + 6px); z-index: 30;
  width: min(560px, 78vw); max-height: 46vh; overflow: auto;
  background: var(--nu-card); border: 1px solid var(--nu-border);
  border-radius: 4px; box-shadow: 0 6px 20px rgba(0, 0, 0, .12);
  padding: 10px 14px 10px 28px;
}
/* ★flex-basis 를 0 으로 준다. auto 로 두면 높이가 내용에서 나오고, 그 내용인 canvas 는
   또 부모 높이를 보므로 순환이 되어 Chart.js 가 제 기본 비율로 부푼다. */
.fr-chart-fix { flex: 1 1 0; min-height: 0; height: auto; }
/* 표는 머리·꼬리를 붙여 두고 몸통만 구른다 — 날짜 칸이 스무 개까지 가므로 가로도 구른다 */
.fr-table-fix { flex: 1 1 0; min-height: 0; height: auto; overflow: auto; }
.fr-table-fix thead th { position: sticky; top: 0; z-index: 2; }
.fr-table-fix tfoot td { position: sticky; bottom: 0; z-index: 2; background: var(--row-hl, #eef2f8); }
.fr-no { white-space: nowrap; font-variant-numeric: tabular-nums; }
/* 재고가 소요를 못 덮는 원단 — 이 화면이 답해야 할 질문이라 눈에 띄어야 한다 */
tr.fr-short td { background: #fff7f5; }
.fr-lack { color: #c0392b; font-weight: 700; }

/* ── 총계 박스를 낮춘다 (2026-09-10) ────────────────────────────────────
   화면마다 맨 위에 서는 상자라 여기서 먹은 높이가 **본문에서 그대로 빠진다.**
   꾸러미 기본값(padding 12/18 · card 10/14 · 아래여백 14)이 넉넉해서, 표가 긴
   화면은 그만큼 덜 보인다. 글자 크기는 지키고 **여백만** 깎는다 — 숫자를 줄이면
   총계 박스를 둔 뜻이 없어진다.
   ★꾸러미(board-core)를 고치지 않는다. 세 사이트가 함께 쓰므로 다음 판에 덮인다. */
#layoutRoot > .home-kri { padding: 8px; margin-bottom: 8px; }
#layoutRoot .home-kri-cards { gap: 8px; }
#layoutRoot .home-kri-card { padding: 6px 12px; }
#layoutRoot .home-kri-goal { line-height: 1.3; }
#layoutRoot .home-kri-desc { margin-top: 2px; line-height: 1.35; }

/* 홈은 담을 것이 가장 많다 — 한 번 더 깎는다.
   ★홈은 「한 화면 무스크롤」로 짜여 있어(.home-fill) 여기서 번 높이가 곧 카드 높이다. */
#layoutRoot.home-fill > .home-kri { padding: 6px; margin-bottom: 6px; }
#layoutRoot.home-fill .home-kri-cards { gap: 7px; }
#layoutRoot.home-fill .home-kri-card { padding: 5px 10px; }
#layoutRoot.home-fill .home-kri-goal { line-height: 1.25; }
#layoutRoot.home-fill .home-kri-goal b { font-size: 1.18rem; }
#layoutRoot.home-fill .home-kri-desc { margin-top: 1px; line-height: 1.3; }

/* 세로가 좁으면 설명줄부터 접는다 — 숫자는 마지막까지 남긴다 */
@media (max-height: 900px) {
  #layoutRoot > .home-kri { padding: 6px; margin-bottom: 6px; }
  #layoutRoot .home-kri-card { padding: 5px 10px; }
  #layoutRoot .home-kri-desc { font-size: 0.72rem; line-height: 1.3; }
}
/* 지난 납품일 — 둘 다 예정치지만 성격이 다르다. 「그때의 예정」이라 흐리게 둔다.
   ★지우거나 빼지 않는다. 스냅샷 기준일이 오늘보다 앞서면 그 날들도 계획의 일부다 —
     빼면 합계가 달라지고, 왜 달라졌는지 아무도 모른다. */
.dm-day.fr-past { opacity: .62; }
td.dm-num.fr-past { color: var(--text-muted, #8a93a6); }

/* ── 출하 실적·보정 — 실적 원장과 역산 제안 ─────────────────────────────
   ★역산은 **제안일 뿐 저장값이 아니다.** 눌러야 미출하 칸에 들어가고, 들어간 뒤에도
     사람이 고칠 수 있다 — 계획 − 실적이 곧 미출하인 것은 대개 맞지만 늘 맞지는 않는다
     (지원·반품이 섞인다). 그래서 버튼처럼 보이게 두고 자동으로 채우지 않는다. */
.sa-sug-btn { border: 1px solid var(--line, #d8dbe2); background: #eef3fb; color: #2f5597;
  border-radius: 3px; padding: 1px 8px; font-size: 12px; font-weight: 600; cursor: pointer;
  font-variant-numeric: tabular-nums; }
.sa-sug-btn:hover { background: #dce7f7; }
/* 궤적 값으로 대신한 실적 — 원장에 없다는 표시. 숫자를 믿는 정도가 다르다 */
.sa-src { margin-left: 3px; color: var(--text-muted, #99a); font-size: 11px; }
/* 실적·달성률 — 계획 카드 옆에 곁들인다. 100% 를 넘을 수 있다(계획보다 더 나간 품번이 있다) */
.sa-rate { font-size: 12px; font-weight: 500; color: rgba(255,255,255,0.78); margin-left: 10px; }


/* 원천이 멎었을 때 화면이 다는 알림.
   ★붉은 경고로 두지 않는다. 시스템 고장이 아니라 **자료가 안 들어온 것**이라,
     붉게 두면 매일 보는 사람이 곧 무시하게 된다. 노란 띠로 사실만 적는다. */
.fr-banner.ep-stale { background: #fdf6e3; border: 1px solid #e8d9a8; color: #6b5a20;
  border-radius: 4px; padding: 10px 14px; font-size: 12px; line-height: 1.6; margin-bottom: 8px; }
.fr-banner.ep-stale code { background: #f4ecd3; padding: 1px 5px; border-radius: 3px; font-size: 11px; }
/* 사출 설비현황 「데이터 유의사항」 - 기준일 줄 오른쪽 끝(화면 우측 상단). 최상단 띠(ep-stale)와 판 밑 주석을 여기로 모았다
   (2026-09-15 사용자 요청). 펼치면 카드 · 차트를 밀지 않고 아래로 떠서 열린다 - 글 꼴은 .data-note > ul 공통 */
.inv-filter-bar > .ep-data-note { position: relative; margin-left: 10px; }
.inv-filter-bar > .ep-data-note > ul {
  position: absolute; right: 0; top: calc(100% + 6px); z-index: 30;
  width: min(620px, 80vw); max-height: 50vh; overflow: auto;
  background: var(--nu-card); border: 1px solid var(--nu-border);
  border-radius: 4px; box-shadow: 0 6px 20px rgba(0, 0, 0, .12);
  padding: 10px 14px 10px 28px;
}

/* ── 설비 상세현황 ──────────────────────────────────────────────────────
   ★비설비(INJT00)를 목록에서 지우지 않는다. 실적이 실제로 거기 모이므로 감추면
     그 실적이 어디로 갔는지 아무도 못 찾는다. 대신 **갈라 두고 흐리게** 한다. */
.ed-mgap { display: inline-block; margin: 0 8px; color: var(--text-muted, #aab1bf); }
.ed-mbtn.ed-nonequip { opacity: .68; border-style: dashed; }
/* 자원 속성 메모 — 자원 대장이 적어 둔 말을 그대로 옮기는 자리.
   우리가 지어낸 말이 아니라는 것을 오른쪽 꼬리표가 밝힌다. */
.fr-banner.ed-attr { background: #f4f7fb; border: 1px solid #d9e2ee; color: #33415c;
  border-radius: 4px; padding: 9px 14px; font-size: 12px; line-height: 1.6; margin-bottom: 8px; }
.fr-banner.ed-attr code { background: #e6edf6; padding: 1px 5px; border-radius: 3px; font-size: 11px; }
.ed-attr-src { float: right; color: #8a93a6; font-size: 11px; }

/* ── 설비 상세현황 : 최근 추이 띠 ────────────────────────────────────────
   높이를 여기서 못 박는다. 표는 fit-page 가 남는 높이를 다 가져가므로(flex:1),
   추이 띠가 flex 로 늘어나면 표가 눌린다. 0 0 auto 로 제 키만 갖게 한다. */
#layoutRoot.fit-page > .panel > .ed-trend { flex: 0 0 auto; }
.ed-trend { display: flex; flex-direction: column; gap: 4px; }
.ed-trend-head {
  font-size: 12px; font-weight: 600; color: var(--nu-txt2);
  display: flex; align-items: baseline; gap: 8px;
}
.ed-trend-head span { font-weight: 400; font-size: 11px; color: var(--nu-txt3); }
/* 캔버스가 아니라 **부모**가 높이를 갖는다 — maintainAspectRatio:false 가 이것을 따른다. */
.ed-trend-wrap { height: 118px; min-height: 118px; position: relative; }
.ed-trend-wrap canvas { cursor: pointer; }

/* ── 생산현황 목록 — 계획과 실적이 한 줄에 ──────────────────────────────
   ★일체형은 한 번 찍어 둘을 얻는다. 둘째 줄의 소요분에 시간을 다시 적으면
     그 호기가 두 배로 바쁜 것처럼 읽힌다 — 「같은 샷」이라고 흐리게 적는다.
   ★모르는 값과 나쁜 값을 같은 색으로 칠하지 않는다. 달성률이 '—' 인 것은
     실적 기록이 없다는 뜻이지 못 만들었다는 뜻이 아니다(흐리게), 100% 미만은
     실제로 모자란 것이다(경고색). */
.ed-plan .ed-dim { color: var(--nu-txt3); font-weight: 400; font-size: 11px; }
.ed-plan .ed-under { color: var(--nu-warning-text); }
/* 계획 밖 실적 · 실적 없는 계획 — 줄 자체를 살짝 눕혀 눈이 먼저 걸리게 한다. */
.ed-plan tr.ed-r-out > td { background: var(--nu-surface-2); }
.ed-plan tr.ed-r-miss > td { background: var(--nu-warning-light); }
.ed-tag {
  display: inline-block; background: var(--nu-primary-selection); color: var(--nu-primary);
  border-radius: 3px; padding: 1px 6px; font-size: 11px; white-space: nowrap;
}
.ed-tag.is-alt { background: var(--nu-warning-light); color: var(--nu-warning-text); }
.ed-tag.is-off { background: var(--nu-surface-2); color: var(--nu-txt3); }
.ed-remark { font-size: 11px; color: var(--nu-txt2); }

/* ── 자재 발주·입고 : 상태 ──────────────────────────────────────────────
   ★색을 셋으로 가른다. 「완료」와 「미입고」 사이에 **판정 불가**가 있다.
     품번이 비어 있거나(발주 27건) 입고 원천 밖인 레이어(14건)는 늦은 것이 아니라
     견줄 자료가 없는 것이라, 미입고와 같은 색으로 칠하면 없는 사실을 만든다. */
.wr-b { display: inline-block; padding: 1px 7px; border-radius: 3px; font-size: 11px; white-space: nowrap; }
.wr-b + .wr-b { margin-left: 4px; }
.wr-b-ok   { background: var(--nu-success-light); color: var(--nu-success-text); }
.wr-b-part { background: var(--nu-warning-light); color: var(--nu-warning-text); }
.wr-b-none { background: var(--nu-alert-light);   color: var(--nu-alert-text); }
.wr-b-late { background: var(--nu-alert);         color: #fff; }
.wr-b-x    { background: var(--nu-surface-2);     color: var(--nu-txt3); }
.wr-st { white-space: nowrap; }
.wr-short { color: var(--nu-alert-text); font-weight: 600; }
.wr-grid tr.wr-r-late > td { background: var(--nu-alert-light); }
.wr-grid tr.wr-r-x > td { background: var(--nu-surface-2); color: var(--nu-txt3); }
/* 유의사항은 접힌 채로 시작한다 — 표가 주인이고 이건 곁말이다. */
#layoutRoot.fit-page > .wr-panel > .wr-note { flex: 0 0 auto; }
.wr-note { margin-bottom: 2px; }

/* ── 출하 실적·보정 : 재고 흐름과 실사 ──────────────────────────────────
   기초·기말은 **입력 칸이 아니라 원천이 계산해 둔 수위**다. 입력 칸(sa-th-in)과
   같은 무게로 그리면 사람이 고칠 수 있는 값으로 읽는다 — 흐리게 눕혀 둔다. */
.sa-grid .sa-lvl { color: var(--nu-txt3); background: var(--nu-surface-2); }
/* 실사 차이 = 소실량. 값이 있는 날이 드물어(활성 1행) 열 대신 품번 옆 꼬리표로 단다. */
.sa-b-survey { background: var(--nu-warning-light); color: var(--nu-warning-text); }
.sa-b-survey.is-minus { background: var(--nu-alert-light); color: var(--nu-alert-text); }

/* ── 사출 설비현황 : 품목 축 ────────────────────────────────────────────
   호기별 도넛을 걷어낸 자리다. 도넛은 호기 카드와 같은 말을 두 번 하고 있었고,
   그 자리에 **다른 축**(품목)을 놓아야 한 화면에서 두 축이 다 보인다.
   표가 viz-card 안에 들어가므로 남는 높이를 표에 넘기고 표만 안에서 구른다. */
.ep-item-card { display: flex; flex-direction: column; min-height: 0; }
.ep-item-card > .viz-title { flex: 0 0 auto; }
.ep-item-wrap { flex: 1 1 auto; min-height: 0; overflow: auto; }
.ep-item-grid { font-size: 12px; }
.ep-item-grid th { position: sticky; top: 0; z-index: 1; background: var(--nu-surface-2); }
/* 호기 칸은 한 품번이 여러 호기에 걸릴 수 있어 좁게 눕힌다. */
.ep-item-m { font-size: 11px; color: var(--nu-txt3); white-space: nowrap; }

/* ── 재고현황 : 팔레트 보유량 탭 ────────────────────────────────────────
   앞 세 탭은 옮겨 온 원천을 읽지만 이 탭만 **사람이 넣는다** — 원천이 없어서다.
   입력 칸이 주인이라 표를 넉넉히 두고, 아래 변동 그래프는 제 키만 갖는다. */
.plt-panel { display: flex; flex-direction: column; gap: 8px; min-height: 0; }
#layoutRoot.fit-page > .inv-tab-content > .plt-panel > .plt-note,
#layoutRoot.fit-page > .inv-tab-content > .plt-panel > .plt-trend { flex: 0 0 auto; }
.plt-trend-wrap { height: 132px; min-height: 132px; position: relative; }
.plt-grid .plt-off > td { opacity: .55; }
/* 여유가 음수 = 팔레트가 모자란다. 이 공장에서 그것은 곧 생산 제약이라 눈에 걸려야 한다. */
.plt-grid .plt-free { font-weight: 600; }
.plt-del {
  border: 0; background: transparent; color: var(--nu-txt4);
  cursor: pointer; font-size: 12px; line-height: 1; padding: 2px 4px;
}
.plt-del:hover { color: var(--nu-alert); }

/* ── 변동 분석 : 보기 전환 · 기간별 비교 ────────────────────────────────
   같은 원천을 두 축으로 본다. 전환 단추는 화면 꼭대기에 두어 「지금 어느 축인가」가
   먼저 읽히게 한다 — 두 축의 숫자가 서로 다른 뜻이라 헷갈리면 값을 잘못 읽는다. */
.rd-viewbar { display: flex; align-items: center; gap: 0; margin-bottom: 10px; flex-wrap: wrap; }
.rd-vb {
  border: 1px solid var(--nu-border); background: transparent; color: var(--nu-txt2);
  font-size: 12.5px; padding: 5px 16px; cursor: pointer;
}
.rd-vb:first-of-type { border-radius: 4px 0 0 4px; }
.rd-vb + .rd-vb { border-radius: 0 4px 4px 0; border-left: 0; }
.rd-vb.active { background: var(--nu-primary-selection); color: var(--nu-primary); font-weight: 600; }
.rd-vb-hint { margin-left: 12px; font-size: 11.5px; color: var(--nu-txt3); }

/* 흔들림 — 이 화면의 신호값. 증감(rd-up/rd-down)과 다른 뜻이라 색을 따로 쓴다. */
.rd-churn { color: var(--nu-warning-text); font-weight: 600; }

/* 그래프는 제 키만 갖고, 남는 높이는 표가 가져간다. */
#layoutRoot.fit-page > .rd-churn-panel > .rd-chart { flex: 0 0 auto; }
.rd-chart-wrap { height: 188px; min-height: 188px; position: relative; }
.rd-chart-wrap canvas { cursor: pointer; }
.rd-item-grid .dm-num { font-variant-numeric: tabular-nums; }
/* 「데이터 유의사항」 - 조회 줄 오른쪽 끝(화면 우측 상단). 펼치면 표·그래프를 밀지 않고 아래로 떠서 열린다.
   글 꼴은 다른 화면과 같은 .data-note > ul 규칙을 그대로 받는다(2026-09-14 사용자 요청) */
.rd-churn-panel .demand-toolbar > .rd-data-note { position: relative; margin-left: auto; }
.rd-churn-panel .demand-toolbar > .rd-data-note > ul {
  position: absolute; right: 0; top: calc(100% + 6px); z-index: 30;
  width: min(620px, 80vw); max-height: 50vh; overflow: auto;
  background: var(--nu-card); border: 1px solid var(--nu-border);
  border-radius: 4px; box-shadow: 0 6px 20px rgba(0, 0, 0, .12);
  padding: 10px 14px 10px 28px;
}

/* 발표 이력 팝업 — 읽기 전용이라 입력 칸이 없다. */
.rc-pop-box { max-width: 480px; }
.rc-pop-body { margin-top: 6px; }
.rc-pop-sum { margin: 0 0 10px; font-size: 13px; color: var(--nu-txt2); line-height: 1.7; }
.rc-pop { width: 100%; font-size: 12.5px; }
.rc-pop th { position: sticky; top: 0; background: var(--nu-surface-2); }

/* ── 기준정보 : 발주 정책값 ──────────────────────────────────────────────
   조회 전용이다 — 입력 칸이 없다. 대신 **전역과 품번 예외**가 한눈에 갈려야 한다.
   전역 줄은 바탕을 깔아 「이것이 기본값이고 나머지가 그것을 덮는다」를 드러낸다. */
.op-panel { display: flex; flex-direction: column; gap: 8px; min-height: 0; }
#layoutRoot.fit-page > .op-panel > .op-dest { flex: 0 0 auto; }

/* 유의사항은 **제 줄을 차지하지 않는다.** 조회줄 오른쪽 끝에 접혀 있다가, 펼치면
   아래로 **떠서** 열린다 — 줄 안에서 자라면 조회줄이 밀려 표가 아래로 내려간다.
   곁말이지 본문이 아니라는 것을 자리로도 말한다. */
.inv-filter-bar > .op-note { position: relative; margin-left: auto; }
.inv-filter-bar > .op-note > ul {
  position: absolute; right: 0; top: calc(100% + 6px); z-index: 20;
  width: min(560px, 78vw); max-height: 46vh; overflow: auto;
  background: var(--nu-card); border: 1px solid var(--nu-border);
  border-radius: 4px; box-shadow: 0 6px 20px rgba(0, 0, 0, .12);
  padding: 12px 16px 12px 30px;
}
.op-grid tr.op-global > td { background: var(--nu-surface-2); }
.op-grid .op-key { font-family: ui-monospace, monospace; font-size: 12px; }
.op-grid .op-src, .op-grid .op-tbl { font-size: 11px; color: var(--nu-txt3); }
.op-grid .op-tbl code { font-size: 10.5px; }

/* 납품처 — 표가 아니라 꼬리표 줄이다. 고를 것이 아니라 「얼마가 걸리나」를 보는 자리라서. */
.op-dest { border-top: 1px solid var(--nu-border); padding-top: 10px; }
.op-dest-row { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.op-dest-chip {
  display: flex; flex-direction: column; gap: 1px; padding: 5px 11px;
  border: 1px solid var(--nu-border); border-radius: 4px; background: var(--nu-surface-2);
  font-size: 11.5px; line-height: 1.35;
}
.op-dest-chip b { font-size: 12.5px; }
.op-dest-chip span { color: var(--nu-txt3); }
.op-dest-chip.has { border-color: var(--nu-primary); }

/* ── 홈 카드 제목줄의 「데이터 유의사항」 (2026-09-14) ─────────────────────────
   카드 밑에 설명 줄을 두면 한 화면 무스크롤 홈에서 그만큼 차트가 눌린다. 제목줄 오른쪽에 접어 두고,
   펼치면 아래로 **떠서** 열린다 - 발주 정책값(.op-note)과 같은 꼴. */
#layoutRoot.home-fill .home-card-t.has-note { display: flex; align-items: center; gap: 8px; }
.home-card-t > .home-card-note { position: relative; margin-left: auto; font-weight: 400; letter-spacing: 0; }
.home-card-t > .home-card-note > ul {
  position: absolute; right: 0; top: calc(100% + 6px); z-index: 30;
  width: min(460px, 70vw); max-height: 46vh; overflow: auto;
  background: var(--nu-card); border: 1px solid var(--nu-border);
  border-radius: 4px; box-shadow: 0 6px 20px rgba(0, 0, 0, .12);
  padding: 10px 14px 10px 28px;
}

/* ── 홈 사출기 가동현황 툴팁 - 캔버스 밖(body)에 뜬다 ───────────────────────
   Chart.js 기본 툴팁은 캔버스 안에 그려져 카드 높이에서 반제품 목록이 잘렸다(2026-09-14). */
.home-tip {
  position: fixed; z-index: 1000; display: none; pointer-events: none;
  min-width: 220px; max-width: min(420px, 90vw);
  background: var(--nu-card); color: var(--nu-txt2); border: 1px solid var(--nu-border);
  border-radius: 4px; box-shadow: 0 6px 20px rgba(0, 0, 0, .16);
  padding: 8px 10px; font-size: 11.5px; line-height: 1.45;
}
.home-tip.on { display: block; }
.home-tip-h { font-weight: 700; }
.home-tip-s { color: var(--nu-txt3); margin: 1px 0 4px; }
.home-tip ul { list-style: none; margin: 0; padding: 0; }
.home-tip li { display: flex; justify-content: space-between; gap: 12px; }
.home-tip li i { font-style: normal; color: var(--nu-txt3); margin-left: 5px; }
.home-tip li b { font-variant-numeric: tabular-nums; font-weight: 600; }
.home-tip li.more { color: var(--nu-txt3); }

/* ── 홈 차종별 목표대비 실적 - 차트를 위아래로 키운다 (2026-09-14 요청) ─────────
   가운데 줄(차종별 · 일별 추이)이 아래 줄보다 높이를 조금 더 갖고, 이 카드는 제목 아래 · 카드 밑 여백을 줄인다.
   범례 아래 · 그래프 위 여백은 차트 옵션(app.js renderDashboardPage)이 줄인다. */
#layoutRoot.home-fill > .home-mid { flex-grow: 1.25; }
#layoutRoot.home-fill .home-card.home-card-veh { padding-bottom: 6px; }
#layoutRoot.home-fill .home-card-veh > .home-card-t { margin-bottom: 2px; }

/* ── 홈 재고현황 타일 다듬기 (2026-09-14 요청) ─────────────────────────────────
   층 흐름을 왼쪽에서 오른쪽으로 읽게 둔다 - 원단(롤) › 재단품 › 완제품 | 팔레트.
   타일마다 아이콘 · 이름 / 값 / 기준 한 줄 - 타일 안 가운데 정렬. 음수는 붉게 적는다(재고는 음수일 수 없다 - 원천 확인 필요). */
#layoutRoot.home-fill .home-inv-row { gap: 4px; align-items: stretch; }
#layoutRoot.home-fill .home-inv {
  flex: 1 1 0; min-width: 0; text-align: center; align-items: center; justify-content: center; gap: 6px;
  background: var(--jv-page); border: 1px solid var(--jv-border); border-radius: var(--nu-r-large);
  padding: 10px 12px;
}
.home-inv-top { display: flex; align-items: center; justify-content: center; gap: 7px; min-width: 0; max-width: 100%; }
#layoutRoot.home-fill .home-inv-ico {
  flex: none; width: 26px; height: 26px; border-radius: 7px; display: grid; place-items: center;
}
.home-inv-ico svg { width: 15px; height: 15px; }
#layoutRoot.home-fill .home-inv-l {
  margin: 0; font-size: 12px; font-weight: 600; color: var(--jv-txt2);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
#layoutRoot.home-fill .home-inv-v { font-size: 22px; }
.home-inv-c { font-size: 10.5px; color: var(--jv-txt4); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#layoutRoot.home-fill .home-inv.neg { border-color: var(--nu-alert-light, var(--jv-border)); }
#layoutRoot.home-fill .home-inv.neg .home-inv-v,
#layoutRoot.home-fill .home-inv.neg .home-inv-c { color: var(--nu-alert-text); }
.home-inv-arrow { flex: none; align-self: center; color: var(--jv-txt4); font-size: 18px; line-height: 1; padding: 0 1px; }
.home-inv-sep { flex: none; align-self: stretch; width: 1px; margin: 6px 6px; background: var(--jv-border); }
@media (max-height: 860px) {
  #layoutRoot.home-fill .home-inv { padding: 8px 10px; gap: 4px; }
  #layoutRoot.home-fill .home-inv-v { font-size: 19px; }
}
@media (max-height: 720px) {
  #layoutRoot.home-fill .home-inv-v { font-size: 16px; }
  .home-inv-c { display: none; }
}
@media (max-width: 900px) {
  .home-inv-arrow, .home-inv-sep { display: none; }
}

/* 확정 스케줄 관리 안내 칸 안의 「사출작업지시서」 덩이 (2026-09-16 · 임시).
   판을 따로 두지 않고 안내 칸 안에 둔다 - 판을 더 붙이면 화면 높이 셈이 어긋나 글이 겹친다.
   새 화면이 서면 이 덩이와 함께 걷는다. */
.sc-wo-box { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--nu-border); }
.sc-wo-box .sc-wo-title { margin: 0 0 4px; font-size: 15px; font-weight: 700; color: var(--nu-text); }
.sc-wo-box .inv-filter-bar { margin-top: 10px; }
.sc-wo-box .simr-top-btn { text-decoration: none; display: inline-flex; align-items: center; }
