/* 공용 UI 컴포넌트 — 폼 컨트롤·배지.
   브라우저 기본 컨트롤은 OS마다 생김새가 달라 화면 톤이 깨진다.
   여기서 입력 요소를 한 벌로 통일한다. (style.css의 색 토큰을 그대로 사용) */

/* ── 필드 ── */
.ui-field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.ui-label { font-size: 13px; font-weight: 600; color: var(--text); }
.ui-hint { font-size: 11px; color: var(--muted); line-height: 1.4; }

.ui-input-wrap { position: relative; display: block; }
.ui-input {
  width: 100%; box-sizing: border-box;
  padding: 10px 12px; font: inherit; font-size: 14px; color: var(--text);
  background: #fff; border: 1px solid var(--border); border-radius: 8px;
  transition: border-color .15s, box-shadow .15s;
}
.ui-input::placeholder { color: #b6bcc4; }
.ui-input:focus {
  outline: none; border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(16, 163, 127, .14);   /* --accent 14% */
}
.ui-input:disabled { background: #f5f6f7; color: var(--muted); cursor: not-allowed; }
.ui-input:invalid:not(:placeholder-shown) { border-color: #e0857e; }

/* 숫자 입력의 스피너 제거 — 단위 라벨과 겹쳐서 */
.ui-input[type="number"]::-webkit-outer-spin-button,
.ui-input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.ui-input[type="number"] { -moz-appearance: textfield; appearance: textfield; }

/* 단위 접미 — 입력값과 겹치지 않게 우측 패딩 확보 */
.ui-input-wrap.has-unit .ui-input { padding-right: 52px; }
.ui-unit {
  position: absolute; right: 12px; top: 50%; transform: translateY(-50%);
  font-size: 12px; color: var(--muted); pointer-events: none;
}

/* ── 커스텀 드롭다운 ── */
.ui-select { position: relative; }
.ui-select-trigger {
  width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 10px 12px; font: inherit; font-size: 14px; color: var(--text); text-align: left;
  background: #fff; border: 1px solid var(--border); border-radius: 8px; cursor: pointer;
  transition: border-color .15s, box-shadow .15s;
}
.ui-select.open .ui-select-trigger,
.ui-select-trigger:focus-visible {
  outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(16, 163, 127, .14);
}
.ui-select-value { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 화살표는 글꼴 글리프(▾) 대신 CSS 삼각형 — 폰트에 따라 얇게/깨져 보이는 것 방지 */
.ui-select-arrow {
  flex: none; width: 0; height: 0; font-size: 0; color: transparent;
  border-left: 4.5px solid transparent; border-right: 4.5px solid transparent;
  border-top: 5px solid #8a9099; transition: transform .15s; transform-origin: 50% 40%;
}
.ui-select.open .ui-select-arrow { transform: rotate(180deg); }

/* 화면 기준으로 띄운다(좌표는 여는 시점에 JS가 넣는다) — overflow를 가진 조상 안에서
   잘리지 않게. 표 스크롤 영역·카드·모달 어디에 있어도 목록이 온전히 보인다. */
.ui-select-pop {
  position: fixed; z-index: 60;
  background: #fff; border: 1px solid var(--border); border-radius: 8px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, .10); padding: 6px; max-height: 280px;
  display: flex; flex-direction: column; gap: 6px;
}
.ui-select-pop.hidden { display: none; }
/* 위로 펼침 — 화면 하단에 붙은 드롭다운용 */
.ui-select-pop.up { box-shadow: 0 -8px 24px rgba(0, 0, 0, .10); }
.ui-select-search {
  padding: 8px 10px; font: inherit; font-size: 13px;
  border: 1px solid var(--border); border-radius: 6px; outline: none;
}
.ui-select-search:focus { border-color: var(--accent); }
.ui-select-options { list-style: none; margin: 0; padding: 0; overflow-y: auto; }
.ui-select-options li {
  padding: 8px 10px; font-size: 14px; border-radius: 6px; cursor: pointer;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ui-select-options li:hover, .ui-select-options li.active { background: #f0f3f5; }
.ui-select-options li.sel { color: var(--accent); font-weight: 600; }
.ui-select-options li.sel::after { content: " ✓"; }

/* ── 배지 ── */
.ui-badge {
  display: inline-block; font-size: 11px; font-weight: 600; line-height: 1.5;
  border-radius: 4px; padding: 2px 7px; white-space: nowrap;
}
.ui-badge-ok { background: #e3f5ee; color: #0d7a5f; }

/* ── 폼 그리드 ── */
.ui-form-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 14px 18px;
}
@media (max-width: 560px) { .ui-form-grid { grid-template-columns: 1fr; } }

/* 네이티브 select — 커스텀 드롭다운(.ui-select)과 같은 외형으로 맞춘다.
   개발 도구(법정동 선택·조회 종류·HTTP 메서드)처럼 목록이 OS에 맡겨진 곳에도
   테두리·화살표·여백은 동일하게 보이도록. */
select.ui-input, .preset-row select, .console-req select {
  appearance: none; -webkit-appearance: none;
  padding: 10px 30px 10px 12px; font: inherit; font-size: 14px; color: var(--text);
  background: #fff url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%2347505a' stroke-width='1.5'/%3E%3C/svg%3E") no-repeat right 11px center;
  border: 1px solid var(--border); border-radius: 8px; cursor: pointer;
}
select.ui-input:hover, .preset-row select:hover, .console-req select:hover { border-color: #c4cbd3; }
select.ui-input:focus, .preset-row select:focus, .console-req select:focus {
  outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(16, 163, 127, .14);
}
select.ui-input:disabled, .preset-row select:disabled { background-color: #f5f6f7; color: var(--muted); cursor: not-allowed; }

/* 화면에는 안 보이고 스크린리더만 읽는 텍스트 */
.sr-only {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ── 로딩 자리표시(스켈레톤) ───────────────────────────────
   들어올 것과 같은 모양을 먼저 깔아 둔다. 화면이 비었다가 튀지 않고,
   기다리는 동안 무엇이 올지 짐작이 된다. */
.skel {
  display: block; border-radius: 6px;
  background: linear-gradient(90deg,
              var(--skel-base, #eceff1) 25%,
              var(--skel-shine, #f6f8f9) 37%,
              var(--skel-base, #eceff1) 63%);
  background-size: 400% 100%;
  animation: skel-sweep 1.4s ease-in-out infinite;
}
@keyframes skel-sweep { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }
/* 움직임을 줄이도록 설정한 사용자에게는 흐르지 않게 한다 */
@media (prefers-reduced-motion: reduce) { .skel { animation: none; } }

.skel-line { height: 12px; }
.skel-big { height: 26px; width: 62%; }
.skel-media { height: 132px; border-radius: 10px; }
.skel-stack { display: flex; flex-direction: column; gap: 9px; }

.skel-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; }
@media (max-width: 1180px) { .skel-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 720px) { .skel-grid { grid-template-columns: 1fr; } }
.skel-card { border: 1px solid var(--line, #e6e9e6); border-radius: 10px; padding: 12px;
             display: flex; flex-direction: column; gap: 12px; }

.skel-metrics { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 12px; }
.skel-metric { border: 1px solid var(--line, #e6e9e6); border-radius: 10px; padding: 16px;
               display: flex; flex-direction: column; gap: 12px; }

.skel-table { display: flex; flex-direction: column; gap: 12px; }
.skel-row { display: grid; grid-template-columns: repeat(var(--skel-cols, 4), 1fr); gap: 12px; }
.skel-wrap { margin-top: 4px; }
