/* ============================================================
   컴포넌트 — 순수 CSS. 라이브러리 없음.
   ============================================================ */

/* ---------- 아이콘 ---------------------------------------- */
.icon {
  width: 16px; height: 16px; flex: none;
  stroke: currentColor; fill: none;
  stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round;
}
.icon--sm { width: 13px; height: 13px; }
.icon--lg { width: 20px; height: 20px; }

/* ---------- 패널 ------------------------------------------ */
.panel {
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: var(--r-panel);
  display: flex; flex-direction: column;
  min-width: 0;
}
.panel__head {
  display: flex; align-items: center; gap: 10px;
  padding: 12px var(--panel-pad);
  border-bottom: 1px solid var(--line);
  min-height: 44px;
}
.panel__title {
  font-size: var(--fs-tbl); font-weight: 600; letter-spacing: -0.01em;
  display: flex; align-items: center; gap: 7px;
}
.panel__title .icon { color: var(--fg-faint); }
.panel__meta { font-size: var(--fs-xs); color: var(--fg-faint); }
.panel__spacer { flex: 1 1 auto; }
.panel__body { padding: var(--panel-pad); }
.panel__body--flush { padding: 0; }

.grid { display: grid; gap: var(--gap-panel); }
.section { display: flex; flex-direction: column; gap: var(--gap-panel); }
.section__label {
  font-size: var(--fs-xs); font-weight: 600; letter-spacing: .06em;
  color: var(--fg-faint); text-transform: uppercase;
}

/* ---------- 상태 칩 --------------------------------------- */
.chip {
  display: inline-flex; align-items: center; gap: 5px;
  height: 20px; padding: 0 7px;
  border-radius: var(--r-ctl);
  font-size: var(--fs-xs); font-weight: 600; line-height: 1;
  white-space: nowrap;
  border: 1px solid transparent;
}
.chip__dot { width: 6px; height: 6px; border-radius: 50%; flex: none; background: currentColor; }
.chip--normal  { background: var(--chip-normal-bg);  color: var(--st-normal-fg);  border-color: var(--chip-normal-ln); }
.chip--watch   { background: var(--chip-watch-bg);   color: var(--st-watch-fg);   border-color: var(--chip-watch-ln); }
.chip--caution { background: var(--chip-caution-bg); color: var(--st-caution-fg); border-color: var(--chip-caution-ln); }
.chip--fault   { background: var(--chip-fault-bg);   color: var(--st-fault-fg);   border-color: var(--chip-fault-ln); }
.chip--service { background: var(--chip-service-bg); color: var(--st-service-fg); border-color: var(--chip-service-ln); }
/* 측정 불가 = 색이 아니라 값의 부재. 채도를 주지 않는다. */
.chip--unknown {
  background: var(--bg-inset); background-image: var(--hatch);
  color: var(--st-unknown-fg); border-color: var(--line-strong);
  border-style: dashed;
}
.chip--unknown .chip__dot { background: none; box-shadow: inset 0 0 0 1px currentColor; }

.chip--sm { height: 18px; padding: 0 6px; font-size: var(--fs-2xs); }

/* 알람 생명주기 배지 (심각도 축과 분리) */
.state {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: var(--fs-xs); color: var(--fg-faint); white-space: nowrap;
}
.state__mark { width: 7px; height: 7px; border-radius: 2px; flex: none; }
.state--open    .state__mark { background: var(--fg); }
.state--ack     .state__mark { background: none; box-shadow: inset 0 0 0 1px var(--fg-faint); }
.state--cleared .state__mark { background: none; box-shadow: inset 0 0 0 1px var(--line-strong); }
.state--cleared { color: var(--fg-dim); }

/* ---------- KPI ------------------------------------------- */
.kpis {
  display: grid; gap: var(--gap-panel);
  grid-template-columns: repeat(5, minmax(0, 1fr));
}
.kpi {
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: var(--r-panel);
  padding: 13px 16px 14px;
  display: flex; flex-direction: column; gap: 8px;
  min-width: 0;
  position: relative; overflow: hidden;
}
.kpi__label {
  font-size: var(--fs-xs); color: var(--fg-faint);
  display: flex; align-items: center; gap: 6px;
  letter-spacing: .01em;
}
.kpi__label .icon { width: 13px; height: 13px; }
.kpi__val { display: flex; align-items: baseline; gap: 1px; min-width: 0; }
.kpi__n {
  font-family: var(--ff-mono); font-size: var(--fs-kpi); font-weight: 500;
  line-height: 1; letter-spacing: -0.03em; color: var(--fg);
}
/* 분모 표기 — 숫자를 홀로 두지 않는다 */
.kpi__den {
  font-family: var(--ff-mono); font-size: var(--fs-lg); font-weight: 400;
  color: var(--fg-faint); line-height: 1; letter-spacing: -0.02em;
}
.kpi__unit { font-size: var(--fs-sm); color: var(--fg-faint); margin-left: 5px; }
.kpi__foot { font-size: var(--fs-xs); color: var(--fg-faint); display: flex; align-items: center; gap: 6px; }
.kpi__bar { height: 3px; border-radius: 2px; background: var(--bg-inset); overflow: hidden; }
.kpi__bar > i { display: block; height: 100%; border-radius: 2px; background: var(--fg-faint); }
.kpi--accent .kpi__bar > i { background: var(--accent); }
.kpi--fault  .kpi__n { color: var(--st-fault-fg); }
.kpi--fault  .kpi__bar > i { background: var(--st-fault); }
.kpi--normal .kpi__bar > i { background: var(--st-normal); }

/* ---------- 상태 분포 바 (6단계) --------------------------- */
.dist { display: flex; flex-direction: column; gap: 10px; }
.dist__bar {
  display: flex; height: 26px; border-radius: var(--r-ctl);
  overflow: hidden; background: var(--bg-inset);
  border: 1px solid var(--line);
}
.dist__seg {
  position: relative; min-width: 2px;
  display: flex; align-items: center; justify-content: center;
  transition: filter var(--dur) var(--ease);
}
.dist__seg + .dist__seg { border-left: 1px solid var(--bg-panel); }
.dist__seg:hover { filter: brightness(1.18); }
.dist__seg--normal  { background: var(--st-normal); }
.dist__seg--watch   { background: var(--st-watch); }
.dist__seg--caution { background: var(--st-caution); }
.dist__seg--fault   { background: var(--st-fault); }
.dist__seg--service { background: var(--st-service); }
.dist__seg--unknown { background: var(--bg-raised); background-image: var(--hatch); }
.dist__seg b {
  font-family: var(--ff-mono); font-size: var(--fs-xs); font-weight: 700;
  color: var(--on-status); letter-spacing: -0.02em;
}
.dist__seg--unknown b, .dist__seg--service b { color: var(--on-status-light); }

.legend { display: flex; flex-wrap: wrap; gap: 4px 18px; }
.legend__i { display: flex; align-items: center; gap: 7px; font-size: var(--fs-sm); }
.legend__sw { width: 9px; height: 9px; border-radius: 2px; flex: none; }
.legend__sw--normal  { background: var(--st-normal); }
.legend__sw--watch   { background: var(--st-watch); }
.legend__sw--caution { background: var(--st-caution); }
.legend__sw--fault   { background: var(--st-fault); }
.legend__sw--service { background: var(--st-service); }
.legend__sw--unknown { background: var(--bg-raised); background-image: var(--hatch); box-shadow: inset 0 0 0 1px var(--line-strong); }
.legend__l { color: var(--fg-muted); }
.legend__n { font-family: var(--ff-mono); color: var(--fg); font-weight: 500; }
.legend__d { font-family: var(--ff-mono); color: var(--fg-faint); font-size: var(--fs-xs); }

/* ---------- 표 -------------------------------------------- */
.tablewrap {
  overflow: auto;
  border-radius: 0 0 var(--r-panel) var(--r-panel);
}
.tablewrap--tall { max-height: 620px; }
.tablewrap--mid  { max-height: 460px; }

table.t {
  width: 100%; border-collapse: separate; border-spacing: 0;
  font-size: var(--fs-tbl);
}
table.t caption {
  text-align: left; padding: 0 var(--panel-pad) 8px;
  font-size: var(--fs-xs); color: var(--fg-faint);
}
table.t thead th {
  position: sticky; top: 0; z-index: 5;
  background: var(--bg-inset);
  padding: var(--cell-pad);
  font-size: var(--fs-xs); font-weight: 600; letter-spacing: .03em;
  color: var(--fg-faint); text-align: left; white-space: nowrap;
  border-bottom: 1px solid var(--line);
  height: 30px;
}
table.t tbody td {
  padding: var(--cell-pad);
  height: var(--row-h);
  border-bottom: 1px solid var(--line);
  color: var(--fg-muted);
  vertical-align: middle;
  white-space: nowrap;
}
table.t tbody tr { transition: background var(--dur) var(--ease); }
table.t tbody tr:hover td { background: var(--bg-raised); }
table.t tbody tr[aria-selected="true"] td {
  background: var(--accent-weak);
  color: var(--fg);
}
table.t tbody tr[aria-selected="true"] td:first-child { box-shadow: inset 2px 0 0 var(--accent); }
table.t td.strong { color: var(--fg); font-weight: 500; }
table.t td.n, table.t th.n { text-align: right; font-family: var(--ff-mono); font-variant-numeric: tabular-nums; }
table.t td.mono { font-family: var(--ff-mono); font-size: var(--fs-sm); color: var(--fg-faint); }
table.t td.wrap { white-space: normal; }
table.t td.faint { color: var(--fg-faint); }
table.t tbody tr:last-child td { border-bottom: 0; }

/* 정렬 가능한 헤더 */
th.sortable > button {
  all: unset; cursor: pointer;
  display: inline-flex; align-items: center; gap: 5px;
  height: 22px; padding: 0 5px; margin: 0 -5px;
  border-radius: 4px;
  color: inherit; font: inherit; letter-spacing: inherit;
}
th.sortable > button:hover { background: var(--bg-raised); color: var(--fg); }
th.sortable .icon { width: 12px; height: 12px; opacity: .45; }
th[aria-sort] > button { color: var(--accent); }
th[aria-sort] .icon { opacity: 1; }
th.n.sortable > button { flex-direction: row-reverse; }

/* 행 진입 stagger — 12행까지만 */
@keyframes rowin { from { opacity: 0; transform: translateY(3px); } to { opacity: 1; transform: none; } }
.stagger tbody tr:nth-child(-n+12) { animation: rowin var(--dur) var(--ease) backwards; }
.stagger tbody tr:nth-child(1){animation-delay:0ms}   .stagger tbody tr:nth-child(2){animation-delay:24ms}
.stagger tbody tr:nth-child(3){animation-delay:48ms}  .stagger tbody tr:nth-child(4){animation-delay:72ms}
.stagger tbody tr:nth-child(5){animation-delay:96ms}  .stagger tbody tr:nth-child(6){animation-delay:120ms}
.stagger tbody tr:nth-child(7){animation-delay:144ms} .stagger tbody tr:nth-child(8){animation-delay:168ms}
.stagger tbody tr:nth-child(9){animation-delay:192ms} .stagger tbody tr:nth-child(10){animation-delay:216ms}
.stagger tbody tr:nth-child(11){animation-delay:240ms}.stagger tbody tr:nth-child(12){animation-delay:264ms}

/* ---------- 값 표기 --------------------------------------- */
.val { font-family: var(--ff-mono); color: var(--fg); font-weight: 500; }
.val__u { color: var(--fg-faint); font-weight: 400; font-size: .86em; margin-left: 2px; }
/* 측정 불가 — 0 으로 접지 않는다 */
.val--none {
  display: inline-flex; align-items: center; gap: 6px;
  color: var(--st-unknown-fg); font-family: var(--ff-sans); font-size: var(--fs-sm);
}
.val--none::before {
  content: ""; width: 18px; height: 12px; border-radius: 2px;
  background: var(--bg-inset); background-image: var(--hatch);
  box-shadow: inset 0 0 0 1px var(--line-strong);
  flex: none;
}
/* 분모 표기 */
.den { color: var(--fg-faint); font-weight: 400; }

/* ---------- 버튼 · 컨트롤 --------------------------------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  height: 30px; padding: 0 11px;
  border-radius: var(--r-ctl);
  border: 1px solid var(--line-strong);
  background: var(--bg-raised);
  color: var(--fg-muted);
  font-size: var(--fs-sm); font-weight: 500;
  cursor: pointer; white-space: nowrap;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.btn:hover { color: var(--fg); border-color: var(--fg-faint); }
.btn--ghost { background: transparent; border-color: transparent; color: var(--fg-faint); }
.btn--ghost:hover { background: var(--bg-raised); color: var(--fg); border-color: transparent; }
.btn--primary { background: var(--accent); color: var(--accent-fg); border-color: transparent; font-weight: 600; }
.btn--primary:hover { filter: brightness(1.08); color: var(--accent-fg); }
.btn--icon { width: 30px; padding: 0; }
/* 터치 타겟 — 시각 크기는 유지하고 히트 영역만 넓힌다 */
.btn::after {
  content: ""; position: absolute; inset: -7px;
}
.btn { position: relative; }

.field {
  display: inline-flex; align-items: center; gap: 7px;
  height: 30px; padding: 0 10px;
  border-radius: var(--r-ctl);
  border: 1px solid var(--line-strong);
  background: var(--bg-inset);
  color: var(--fg-faint);
  transition: border-color var(--dur) var(--ease);
}
.field:focus-within { border-color: var(--accent); }
.field input {
  all: unset; min-width: 0; width: 100%;
  font-size: var(--fs-sm); color: var(--fg);
}
.field input::placeholder { color: var(--fg-faint); }
.field .icon { width: 14px; height: 14px; }

select.sel {
  height: 30px; padding: 0 26px 0 10px;
  border-radius: var(--r-ctl);
  border: 1px solid var(--line-strong);
  background: var(--bg-inset);
  color: var(--fg-muted);
  font-size: var(--fs-sm);
  -webkit-appearance: none; appearance: none;
  background-image: var(--sel-caret);
  background-repeat: no-repeat; background-position: right 8px center; background-size: 13px;
  cursor: pointer;
}
select.sel:hover { color: var(--fg); }

/* 세그먼트 필터 (상태 6단계) */
.segs { display: flex; gap: 4px; flex-wrap: wrap; }
.seg {
  display: inline-flex; align-items: center; gap: 6px;
  height: 28px; padding: 0 9px;
  border-radius: var(--r-ctl);
  border: 1px solid var(--line);
  background: transparent;
  color: var(--fg-faint);
  font-size: var(--fs-sm); cursor: pointer; white-space: nowrap;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.seg:hover { background: var(--bg-raised); color: var(--fg); }
.seg[aria-pressed="true"] {
  background: var(--accent-weak); color: var(--accent); border-color: var(--accent-line);
}
.seg__sw { width: 8px; height: 8px; border-radius: 2px; flex: none; }
.seg__n { font-family: var(--ff-mono); font-size: var(--fs-xs); opacity: .8; }

.toolbar {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 10px var(--panel-pad);
  border-bottom: 1px solid var(--line);
  background: var(--bg-panel);
}
.toolbar__spacer { flex: 1 1 auto; }
.toolbar__count { font-size: var(--fs-sm); color: var(--fg-faint); }
.toolbar__count b { font-family: var(--ff-mono); color: var(--fg); font-weight: 600; }

/* ---------- 센서 셀 그리드 -------------------------------- */
.cellgrid {
  display: grid;
  grid-template-columns: repeat(auto-fill, var(--cell-size));
  gap: var(--cell-gap);
}
.cell {
  width: var(--cell-size); height: var(--cell-size);
  border-radius: 4px;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--ff-mono); font-size: var(--fs-2xs); font-weight: 500;
  color: var(--on-status);
  cursor: default; position: relative;
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.cell:hover { transform: scale(1.14); box-shadow: 0 0 0 2px var(--bg-panel), 0 0 0 3px var(--accent); z-index: 2; }
.cell--normal  { background: var(--st-normal); }
.cell--watch   { background: var(--st-watch); }
.cell--caution { background: var(--st-caution); }
.cell--fault   { background: var(--st-fault); }
.cell--service { background: var(--st-service); color: var(--on-status-light); }
.cell--unknown {
  background: var(--bg-inset); background-image: var(--hatch);
  box-shadow: inset 0 0 0 1px var(--line-strong);
  color: var(--st-unknown-fg);
}
.cell--unknown:hover { box-shadow: inset 0 0 0 1px var(--line-strong), 0 0 0 2px var(--bg-panel), 0 0 0 3px var(--accent); }
/* 다른 설비의 센서 — 상태는 유지하되 뒤로 물린다. 이 설비 22개가 어디에 있는지 보인다 */
.cell.is-off { opacity: .22; border-radius: 3px; transform: scale(.82); }
.cell.is-off:hover { opacity: .85; transform: scale(1); box-shadow: none; z-index: 1; }

/* 미니 도트 (개요 맵) */
.dots { display: flex; flex-wrap: wrap; gap: 3px; }
.dot {
  width: 9px; height: 9px; border-radius: 2px; flex: none;
  transition: transform var(--dur) var(--ease);
}
.dot:hover { transform: scale(1.5); }
.dot--normal  { background: var(--st-normal); }
.dot--watch   { background: var(--st-watch); }
.dot--caution { background: var(--st-caution); }
.dot--fault   { background: var(--st-fault); }
.dot--service { background: var(--st-service); }
.dot--unknown { background: var(--bg-inset); background-image: var(--hatch); box-shadow: inset 0 0 0 1px var(--line-strong); }

/* ---------- 스파크라인 ------------------------------------ */
.spark { width: 100%; height: 26px; display: block; overflow: visible; }
.spark path { fill: none; stroke-width: 1.5; vector-effect: non-scaling-stroke; }
.spark--normal  path { stroke: var(--st-normal); }
.spark--watch   path { stroke: var(--st-watch); }
.spark--caution path { stroke: var(--st-caution); }
.spark--fault   path { stroke: var(--st-fault); }
.spark--service path { stroke: var(--st-service); }
.spark--none {
  background: var(--bg-inset); background-image: var(--hatch);
  border-radius: 4px; box-shadow: inset 0 0 0 1px var(--line);
}

/* ---------- 상태 3종: 로딩 / 빈 / 에러 -------------------- */
.skel { display: none; }
[data-loading="1"] .skel { display: block; }
[data-loading="1"] .tablewrap { display: none; }
.skel__row {
  display: flex; align-items: center; gap: 12px;
  height: var(--row-h); padding: var(--cell-pad);
  border-bottom: 1px solid var(--line);
}
.skel__b {
  height: 9px; border-radius: 3px;
  background: linear-gradient(90deg, var(--bg-raised) 0%, rgba(213,222,228,.10) 50%, var(--bg-raised) 100%);
  background-size: 220% 100%;
  animation: shimmer 1.1s linear infinite;
}
@keyframes shimmer { from { background-position: 120% 0; } to { background-position: -120% 0; } }

.empty, .errorbox {
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  padding: 46px 20px 52px; text-align: center;
}
.empty__icon, .errorbox__icon {
  width: 38px; height: 38px; border-radius: 10px;
  display: grid; place-items: center;
  background: var(--bg-inset); box-shadow: inset 0 0 0 1px var(--line);
  color: var(--fg-faint);
}
.errorbox__icon { color: var(--st-fault-fg); }
.empty__t, .errorbox__t { font-size: var(--fs-md); font-weight: 600; color: var(--fg); }
.empty__d, .errorbox__d { font-size: var(--fs-sm); color: var(--fg-faint); max-width: 46ch; line-height: 1.55; }
.empty[hidden], .errorbox[hidden] { display: none; }

/* ---------- 오버레이 (팝오버) — 그림자는 여기에만 --------- */
.pop {
  position: absolute; top: calc(100% + 8px); right: 0; z-index: 60;
  width: 340px; padding: 13px 14px;
  background: var(--bg-raised);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-panel);
  box-shadow: var(--shadow-overlay);
  font-size: var(--fs-sm); line-height: 1.6; color: var(--fg-muted);
  text-align: left;
}
.pop[hidden] { display: none; }
.pop b { color: var(--fg); font-weight: 600; }
.pop__t { font-size: var(--fs-tbl); font-weight: 600; color: var(--fg); margin-bottom: 6px; }

/* ---------- 상태 보존 토스트 ------------------------------ */
.toast {
  position: fixed; left: 50%; bottom: 22px; z-index: 80;
  transform: translate(-50%, 10px);
  display: flex; align-items: center; gap: 10px;
  padding: 9px 14px;
  background: var(--bg-raised);
  border: 1px solid var(--accent-line);
  border-radius: 999px;
  box-shadow: var(--shadow-overlay);
  font-size: var(--fs-sm); color: var(--fg-muted);
  opacity: 0; pointer-events: none;
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.toast[data-show="1"] { opacity: 1; transform: translate(-50%, 0); }
.toast .icon { color: var(--accent); width: 14px; height: 14px; }
.toast b { color: var(--fg); font-weight: 600; }
.toast .num { color: var(--accent); }
