/* ==========================================================================
   CON TII Liquor Finder — 관리자 화면
   base.css 의 변수를 그대로 사용합니다.
   ========================================================================== */

.admin {
  background: var(--bg-soft);

  /* 본문 + 설명 패널을 합친 최대 폭.
     설명 패널을 더해도 본문이 예전보다 좁아지지 않도록 늘렸습니다. */
  --admin-max: 1640px;

  /* 설명 패널 폭. 표 가독성을 해치지 않는 선에서 가장 좁게 잡았습니다. */
  --help-w: 300px;

  /* 설명이 바뀔 때의 페이드. help-panel.js 의 FADE 와 같은 값입니다. */
  --help-fade: 110ms;
}

/* 토큰 게이트가 열려 있는 동안에는 hidden 속성으로 감춰집니다. */
.admin-shell {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

.admin-shell[hidden] {
  display: none;
}

/* --------------------------------------------------------------------------
   토큰 게이트
   -------------------------------------------------------------------------- */

.gate {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background: var(--bg);
  z-index: 100;
}

/*
  hidden 속성으로 감출 수 있게 합니다.

  브라우저 기본 규칙 [hidden] { display: none } 은 특정도가 0-0-1 이라
  위의 .gate { display: flex } (0-1-0) 에 집니다.
  이 규칙이 없으면 로그인에 성공해 gate.hidden = true 를 설정해도
  게이트가 계속 화면에 남고, position:fixed + z-index:100 때문에
  정상 렌더된 관리자 화면을 통째로 덮습니다.
  (사용자에게는 "접속을 눌러도 아무 일이 안 일어남" 으로 보입니다)

  .admin-shell 에는 같은 규칙이 있었는데 여기에만 빠져 있었습니다.
*/
.gate[hidden] {
  display: none;
}

.gate-card {
  width: 100%;
  max-width: 360px;
  padding: 32px 28px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow);
}

.gate-brand {
  display: flex;
  align-items: baseline;
  gap: 9px;
  margin-bottom: 18px;
}

.gate-desc {
  font-size: 13px;
  color: var(--muted);
  line-height: 1.7;
  margin-bottom: 16px;
}

.gate-desc code,
.gate-hint code {
  font-family: var(--font-num);
  font-size: 12px;
  background: var(--bg-sunken);
  padding: 1px 5px;
  border-radius: 4px;
  color: var(--ink-2);
}

.gate input[type="password"] {
  width: 100%;
  height: 44px;
  padding: 0 14px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: var(--bg);
  font-family: var(--font-num);
  font-size: 13px;
}

.gate input:focus {
  outline: none;
  border-color: var(--gold);
  box-shadow: 0 0 0 3px var(--gold-soft);
}

.gate-error {
  margin-top: 10px;
  font-size: 12.5px;
  color: var(--up);
}

.gate-hint {
  margin-top: 14px;
  font-size: 11.5px;
  color: var(--muted);
  line-height: 1.6;
}

/* --------------------------------------------------------------------------
   헤더 / 네비게이션
   -------------------------------------------------------------------------- */

.admin-header {
  position: sticky;
  top: 0;
  z-index: 20;
  background: var(--bg);
  border-bottom: 1px solid var(--line);
}

.admin-header-inner {
  max-width: var(--admin-max);
  margin: 0 auto;
  padding: 0 20px;
  height: 56px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}

.admin-header-right {
  display: flex;
  align-items: center;
  gap: 12px;
}

.link-plain {
  font-size: 12.5px;
  color: var(--muted);
  text-decoration: none;
}

.link-plain:hover {
  color: var(--ink);
}

.env-badge {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  padding: 3px 8px;
  border-radius: 4px;
  background: var(--bg-sunken);
  color: var(--ink-2);
  text-transform: uppercase;
}

.env-badge[data-env="prod"] {
  background: var(--up-soft);
  color: var(--up);
}

.admin-nav {
  max-width: var(--admin-max);
  margin: 0 auto;
  padding: 0 20px;
  display: flex;
  gap: 2px;
  overflow-x: auto;
}

.nav-tab {
  position: relative;
  display: inline-flex;
  align-items: center;
  padding: 11px 14px;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--muted);
  white-space: nowrap;
  border-bottom: 2px solid transparent;
  transition: color 0.13s ease;
}

.nav-tab:hover {
  color: var(--ink-2);
}

.nav-tab[aria-current="page"] {
  color: var(--ink);
  border-bottom-color: var(--gold);
}

.nav-badge {
  display: inline-block;
  min-width: 18px;
  height: 18px;
  margin-left: 6px;
  padding: 0 5px;
  border-radius: var(--radius-pill);
  background: var(--up);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  line-height: 18px;
  text-align: center;
  vertical-align: 1px;
}

/* --------------------------------------------------------------------------
   본문
   -------------------------------------------------------------------------- */

/* 본문 + 오른쪽 설명 패널.
   폭은 아래 '기능 설명 패널' 절에서 정합니다. */
.admin-body {
  max-width: var(--admin-max);
  margin: 0 auto;
  padding: 0 20px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--help-w);
  gap: 28px;
  align-items: start;
}

/* 설명 패널을 접으면 본문이 폭을 전부 씁니다. */
.admin-body[data-help="off"] {
  grid-template-columns: minmax(0, 1fr);
}

.admin-main {
  /* min-width:0 이 없으면 grid 칸이 표 너비만큼 밀려 나가
     .table-scroll 의 가로 스크롤이 동작하지 않습니다. */
  min-width: 0;
  padding: 24px 0 64px;
}

.view-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 18px;
  flex-wrap: wrap;
}

.view-title {
  font-size: 19px;
  font-weight: 700;
  letter-spacing: -0.02em;
}

.view-sub {
  font-size: 12.5px;
  color: var(--muted);
  margin-top: 3px;
}

.view-actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

/* --------------------------------------------------------------------------
   버튼
   -------------------------------------------------------------------------- */

.btn {
  height: 36px;
  padding: 0 14px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line-strong);
  background: var(--surface);
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  transition: all 0.13s ease;
  white-space: nowrap;
}

.btn:hover:not(:disabled) {
  border-color: var(--ink-2);
}

.btn:disabled {
  opacity: 0.45;
  cursor: default;
}

.btn-primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-ink);
}

.btn-primary:hover:not(:disabled) {
  opacity: 0.87;
}

.btn-danger {
  color: var(--up);
  border-color: var(--up);
}

.btn-danger:hover:not(:disabled) {
  background: var(--up-soft);
}

.btn-ghost {
  border-color: transparent;
  background: transparent;
  color: var(--muted);
}

.btn-ghost:hover:not(:disabled) {
  background: var(--bg-sunken);
  color: var(--ink);
}

.btn-sm {
  height: 28px;
  padding: 0 10px;
  font-size: 12px;
}

.btn-block {
  width: 100%;
  margin-top: 4px;
}

/* --------------------------------------------------------------------------
   카드 / 통계
   -------------------------------------------------------------------------- */

.panel {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
}

.panel + .panel {
  margin-top: 18px;
}

.panel-head {
  padding: 14px 18px;
  border-bottom: 1px solid var(--line);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}

.panel-title {
  font-size: 14px;
  font-weight: 700;
}

.panel-body {
  padding: 18px;
}

.panel-body-flush {
  padding: 0;
}

.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
  gap: 12px;
  margin-bottom: 18px;
}

.stat {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  padding: 14px 16px;
}

.stat-label {
  font-size: 12px;
  color: var(--muted);
}

.stat-value {
  margin-top: 5px;
  font-size: 24px;
  font-weight: 700;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
}

.stat-hint {
  margin-top: 3px;
  font-size: 11.5px;
  color: var(--muted);
}

.stat[data-tone="warn"] {
  border-color: var(--warn);
  background: var(--warn-soft);
}

.stat[data-tone="warn"] .stat-value,
.stat[data-tone="warn"] .stat-label {
  color: var(--warn);
}

.stat[data-tone="alert"] {
  border-color: var(--up);
  background: var(--up-soft);
}

.stat[data-tone="alert"] .stat-value,
.stat[data-tone="alert"] .stat-label {
  color: var(--up);
}

/* --------------------------------------------------------------------------
   테이블
   -------------------------------------------------------------------------- */

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

.dtable {
  width: 100%;
  font-size: 13px;
  min-width: 720px;
}

.dtable thead th {
  position: sticky;
  top: 0;
  background: var(--bg-soft);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.03em;
  color: var(--muted);
  text-align: left;
  padding: 9px 12px;
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}

.dtable th.num,
.dtable td.num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.dtable tbody td {
  padding: 10px 12px;
  border-bottom: 1px solid var(--line);
  vertical-align: middle;
}

.dtable tbody tr:last-child td {
  border-bottom: none;
}

.dtable tbody tr:hover {
  background: var(--bg-soft);
}

.dtable tbody tr[data-inactive="true"] {
  color: var(--muted);
}

.dtable tbody tr[data-inactive="true"] .cell-strong {
  text-decoration: line-through;
}

.cell-strong {
  font-weight: 600;
}

.cell-sub {
  display: block;
  font-size: 11.5px;
  color: var(--muted);
  margin-top: 1px;
}

.cell-actions {
  display: flex;
  gap: 6px;
  justify-content: flex-end;
  flex-wrap: wrap;
}

.code {
  font-family: var(--font-num);
  font-size: 12px;
  color: var(--ink-2);
}

/* --------------------------------------------------------------------------
   배지 / 태그
   -------------------------------------------------------------------------- */

.badge {
  display: inline-flex;
  align-items: center;
  height: 20px;
  padding: 0 8px;
  border-radius: 4px;
  font-size: 11px;
  font-weight: 700;
  white-space: nowrap;
}

.badge-ok {
  background: var(--down-soft);
  color: var(--down);
}

.badge-warn {
  background: var(--warn-soft);
  color: var(--warn);
}

.badge-alert {
  background: var(--up-soft);
  color: var(--up);
}

.badge-muted {
  background: var(--bg-sunken);
  color: var(--ink-2);
}

.badge-vat {
  background: var(--warn-soft);
  color: var(--warn);
}

/* --------------------------------------------------------------------------
   폼 / 필터
   -------------------------------------------------------------------------- */

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

.field {
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.field-label {
  font-size: 11.5px;
  font-weight: 600;
  color: var(--muted);
}

.field-hint {
  font-size: 11.5px;
  color: var(--muted);
  line-height: 1.55;
}

.field-hint strong {
  color: var(--warn);
}

input[type="text"],
input[type="search"],
input[type="number"],
input[type="file"],
select,
textarea {
  height: 36px;
  padding: 0 11px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  font-size: 13px;
  min-width: 0;
}

textarea {
  height: auto;
  min-height: 72px;
  padding: 9px 11px;
  resize: vertical;
  line-height: 1.5;
}

input[type="file"] {
  padding: 6px 8px;
  height: auto;
}

input:focus,
select:focus,
textarea:focus {
  outline: none;
  border-color: var(--gold);
  box-shadow: 0 0 0 3px var(--gold-soft);
}

.check {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 13px;
  cursor: pointer;
  user-select: none;
}

.check input {
  width: 15px;
  height: 15px;
  accent-color: var(--gold);
}

.form-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 14px;
}

.form-grid .span-2 {
  grid-column: span 2;
}

.form-section {
  margin-top: 18px;
  padding-top: 16px;
  border-top: 1px solid var(--line);
}

.form-section-title {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.05em;
  color: var(--muted);
  margin-bottom: 12px;
}

/* --------------------------------------------------------------------------
   모달
   -------------------------------------------------------------------------- */

.modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(10, 12, 15, 0.5);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 40px 20px;
  overflow-y: auto;
  z-index: 60;
}

.modal {
  width: 100%;
  max-width: 640px;
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow);
  border: 1px solid var(--line);
}

/*
  넓은 창. 열이 15개인 표를 900px 안에 넣으면 한 칸이 40px 이 되고,
  그 상태로는 값을 읽을 수 없습니다 (STEP 21-C.3).
  PC 관리자 화면(1366~1920) 기준으로 잡되 화면을 넘지 않게 합니다.
*/
.modal-wide {
  max-width: min(1400px, 94vw);
}

.modal-head {
  padding: 16px 20px;
  border-bottom: 1px solid var(--line);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.modal-title {
  font-size: 15px;
  font-weight: 700;
}

.modal-body {
  padding: 20px;
}

.modal-foot {
  padding: 14px 20px;
  border-top: 1px solid var(--line);
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  background: var(--bg-soft);
  border-radius: 0 0 var(--radius) var(--radius);
}

/* --------------------------------------------------------------------------
   토스트
   -------------------------------------------------------------------------- */

.toasts {
  position: fixed;
  right: 18px;
  bottom: 18px;
  z-index: 200;
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-width: min(440px, calc(100vw - 36px));
}

.toast {
  padding: 12px 15px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line);
  background: var(--surface);
  box-shadow: var(--shadow);
  font-size: 13px;
  line-height: 1.5;
  animation: toast-in 0.16s ease;
}

.toast[data-tone="ok"] {
  border-left: 3px solid var(--down);
}

.toast[data-tone="error"] {
  border-left: 3px solid var(--up);
  color: var(--up);
}

.toast[data-tone="warn"] {
  border-left: 3px solid var(--warn);
}

@keyframes toast-in {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
}

/* --------------------------------------------------------------------------
   상태 표시
   -------------------------------------------------------------------------- */

.empty {
  padding: 44px 20px;
  text-align: center;
  color: var(--muted);
  font-size: 13px;
}

.loading {
  padding: 40px 20px;
  text-align: center;
  color: var(--muted);
  font-size: 13px;
}

.error-box {
  padding: 14px 16px;
  border: 1px solid var(--up);
  border-radius: var(--radius-sm);
  background: var(--up-soft);
  color: var(--up);
  font-size: 13px;
  line-height: 1.6;
}

.notice {
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--bg-soft);
  font-size: 12.5px;
  color: var(--ink-2);
  line-height: 1.65;
}

.notice-warn {
  border-color: var(--warn);
  background: var(--warn-soft);
  color: var(--warn);
}

.pager {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 18px;
  border-top: 1px solid var(--line);
  font-size: 12.5px;
  color: var(--muted);
  flex-wrap: wrap;
}

.pager-buttons {
  display: flex;
  gap: 6px;
}

/* --------------------------------------------------------------------------
   업로드 / 검수 전용
   -------------------------------------------------------------------------- */

.upload-form {
  display: flex;
  gap: 12px;
  align-items: flex-end;
  flex-wrap: wrap;
}

.batch-note {
  font-family: var(--font-num);
  font-size: 11.5px;
  color: var(--ink-2);
  background: var(--bg-sunken);
  padding: 9px 12px;
  border-radius: var(--radius-sm);
  line-height: 1.6;
  word-break: break-all;
}

.row-status {
  display: inline-flex;
  align-items: center;
  height: 21px;
  padding: 0 8px;
  border-radius: 4px;
  font-size: 11px;
  font-weight: 700;
  white-space: nowrap;
}

.row-status[data-s="auto_matched"],
.row-status[data-s="approved"],
.row-status[data-s="committed"] {
  background: var(--down-soft);
  color: var(--down);
}

.row-status[data-s="review_required"] {
  background: var(--warn-soft);
  color: var(--warn);
}

.row-status[data-s="unmatched"],
.row-status[data-s="rejected"] {
  background: var(--up-soft);
  color: var(--up);
}

.note-cell {
  font-size: 11.5px;
  color: var(--muted);
  line-height: 1.5;
  max-width: 340px;
}

.commit-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 14px 18px;
  border-top: 1px solid var(--line);
  background: var(--bg-soft);
  flex-wrap: wrap;
}

.commit-summary {
  font-size: 13px;
  color: var(--ink-2);
}

.commit-summary strong {
  color: var(--ink);
}

/* --------------------------------------------------------------------------
   공통 셀 표시
   -------------------------------------------------------------------------- */

/* 값이 없는 것과 0 은 다릅니다. '자료 없음' 을 흐리게 표시합니다. */
.cell-muted {
  color: var(--muted);
}

.cell-alert {
  color: var(--up);
  font-weight: 700;
}

/*
  가격 차이 표시.
  app.css 에도 같은 규칙이 있지만 admin.html 은 app.css 를 읽지 않습니다.
  대시보드와 CUBE 화면이 함께 씁니다.
*/
.price-diff {
  font-family: var(--font-num);
  font-size: 12.5px;
  font-weight: 700;
  white-space: nowrap;
}

.price-diff[data-dir="down"] {
  color: var(--down);
}

.price-diff[data-dir="up"] {
  color: var(--up);
}

.price-diff[data-dir="flat"] {
  color: var(--muted);
}

.check-inline {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12.5px;
  white-space: nowrap;
}

/* 상태 배지의 색을 의미(tone)로 지정할 때 */
.row-status[data-tone="ok"] {
  background: var(--down-soft);
  color: var(--down);
}

.row-status[data-tone="warn"] {
  background: var(--warn-soft);
  color: var(--warn);
}

.row-status[data-tone="alert"] {
  background: var(--up-soft);
  color: var(--up);
}

.row-status[data-tone="muted"] {
  background: var(--bg-sunken);
  color: var(--muted);
}

/* --------------------------------------------------------------------------
   화면 내부 탭 (CUBE 섹션 전환)
   -------------------------------------------------------------------------- */

.subnav {
  display: flex;
  gap: 4px;
  margin-bottom: 16px;
  border-bottom: 1px solid var(--line);
  overflow-x: auto;
}

.subnav-tab {
  appearance: none;
  display: inline-flex;
  align-items: center;
  border: 0;
  background: transparent;
  color: var(--muted);
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  padding: 9px 14px;
  border-bottom: 2px solid transparent;
  cursor: pointer;
  white-space: nowrap;
}

.subnav-tab:hover {
  color: var(--ink-2);
}

.subnav-tab[aria-current="page"] {
  color: var(--ink);
  border-bottom-color: var(--gold);
}

/* --------------------------------------------------------------------------
   CUBE 연동 상태
   -------------------------------------------------------------------------- */

.cube-status {
  padding: 16px 18px;
  margin-bottom: 16px;
}

.cube-status-main {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 14px;
  flex-wrap: wrap;
}

.cube-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--muted);
  flex: none;
}

.cube-dot[data-tone="ok"] {
  background: var(--down);
}

.cube-dot[data-tone="warn"] {
  background: var(--warn);
}

.cube-dot[data-tone="alert"] {
  background: var(--up);
}

.cube-status-title {
  display: block;
  font-size: 14px;
  font-weight: 700;
}

.cube-status-note {
  display: block;
  font-size: 12px;
  color: var(--muted);
  margin-top: 2px;
}

.stat-grid-tight {
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 10px;
  margin-bottom: 12px;
}

.cube-lastsync {
  border-top: 1px solid var(--line);
  padding-top: 12px;
}

.cube-sync-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
  gap: 10px;
}

.cube-sync-item {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.cube-sync-kind {
  font-size: 11.5px;
  color: var(--muted);
}

.cube-sync-time {
  font-size: 13px;
  font-weight: 600;
}

.cube-error-note {
  margin-top: 12px;
  padding: 9px 12px;
  border-radius: var(--radius-sm);
  background: var(--up-soft);
  color: var(--up);
  font-size: 11.5px;
  line-height: 1.6;
}

/* 계산 근거를 화면에 밝힙니다. 숫자만 보여주면 신뢰하기 어렵습니다. */
.cube-policy {
  font-size: 11.5px;
  color: var(--muted);
  margin: -6px 0 14px;
}

.cube-summary {
  padding: 10px 18px;
  border-bottom: 1px solid var(--line);
  font-size: 12.5px;
  color: var(--ink-2);
}

.cube-foot-note {
  padding: 12px 18px;
  border-top: 1px solid var(--line);
  background: var(--bg-soft);
  font-size: 11.5px;
  color: var(--muted);
  line-height: 1.6;
}

/* --------------------------------------------------------------------------
   가격 연동 (거래처 카드)
   -------------------------------------------------------------------------- */

.source-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 14px;
  margin-bottom: 18px;
}

.source-card {
  padding: 16px 18px;
  margin-bottom: 0;
}

.source-card[data-tone="alert"] {
  border-color: var(--up);
}

.source-card-head {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 12px;
  flex-wrap: wrap;
}

.source-card-title {
  font-size: 14px;
  font-weight: 700;
}

/* 실제 거래처 가격이 아님을 분명히 알립니다 */
.source-demo-note {
  margin-bottom: 12px;
  padding: 8px 10px;
  border-radius: var(--radius-sm);
  background: var(--warn-soft);
  color: var(--warn);
  font-size: 11.5px;
  line-height: 1.6;
}

.source-warning {
  margin-bottom: 12px;
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  background: var(--up-soft);
  color: var(--up);
  font-size: 12px;
  line-height: 1.7;
}

.source-facts {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 4px 12px;
  margin: 0;
  font-size: 12.5px;
}

.source-facts dt {
  color: var(--muted);
  white-space: nowrap;
}

.source-facts dd {
  margin: 0;
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.source-stale {
  margin-top: 12px;
  padding: 8px 10px;
  border-radius: var(--radius-sm);
  background: var(--bg-sunken);
  font-size: 11.5px;
  color: var(--ink-2);
  line-height: 1.6;
}

.source-card-foot {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--line);
}

/* --------------------------------------------------------------------------
   반응형
   -------------------------------------------------------------------------- */

@media (max-width: 720px) {
  .admin-main {
    padding: 18px 14px 56px;
  }

  .admin-header-inner,
  .admin-nav {
    padding: 0 14px;
  }

  .form-grid .span-2 {
    grid-column: span 1;
  }

  .modal-backdrop {
    padding: 16px 12px;
  }
}

/* ------------------------------------------------------------------ */
/* 시세 화면                                                            */
/*                                                                     */
/* 매입 · 시장 · 판매를 눈으로도 갈라 놓습니다. 색이 같으면 옆 칸의    */
/* 숫자를 같은 성격으로 읽게 되고, 면세점 소비자가를 매입가로          */
/* 착각하는 일이 바로 그렇게 생깁니다.                                  */
/* ------------------------------------------------------------------ */

.dtable th.group-buy,
.dtable th.group-market,
.dtable th.group-sell {
  text-align: center;
  font-size: 12px;
  letter-spacing: .04em;
  border-bottom: 2px solid transparent;
}

.dtable th.group-buy {
  color: #7fb2ff;
  border-bottom-color: rgba(127, 178, 255, .5);
}

.dtable th.group-market {
  color: #d4a24c;
  border-bottom-color: rgba(212, 162, 76, .5);
}

.dtable th.group-sell {
  color: #4caf7d;
  border-bottom-color: rgba(76, 175, 125, .5);
}

.dtable tr.detail-row > td {
  background: rgba(0, 0, 0, .18);
  padding: 0;
}

.subpanel { padding: 14px 18px; }

.subpanel-title {
  font-size: 13px;
  font-weight: 600;
  margin-bottom: 10px;
}

.dtable-sub { font-size: 12px; }
.dtable-sub th { font-weight: 500; }

.badge-danger {
  background: rgba(224, 87, 74, .16);
  color: #e0574a;
}

.muted { color: #98a2b3; }

/* ------------------------------------------------------------------ */
/* 시세 커버리지 숫자                                                   */
/*                                                                     */
/* 큰 숫자는 상품 수, 작은 숫자는 행 수입니다. 한 상품에 거래처가      */
/* 여럿 붙으므로 둘은 다릅니다. 크기를 달리해 섞어 읽지 않게 합니다.   */
/* ------------------------------------------------------------------ */

.kpi-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 1px;
  background: var(--line, #2a313b);
  padding: 1px;
}

.kpi {
  padding: 16px 18px;
  background: var(--panel, #171b21);
}

.kpi-label {
  font-size: 12px;
  color: var(--muted, #98a2b3);
  margin-bottom: 6px;
}

.kpi-value {
  font-size: 26px;
  font-weight: 700;
  line-height: 1.1;
}

.kpi-unit {
  font-size: 13px;
  font-weight: 400;
  color: var(--muted, #98a2b3);
  margin-left: 3px;
}

.kpi-rows {
  display: block;
  margin-top: 5px;
  font-size: 11px;
  color: var(--muted, #98a2b3);
}

/* --------------------------------------------------------------------------
   기능 설명 패널

   작은 title 속성과 역할이 다릅니다.

       title 속성   아이콘 · 버튼 · 배지 같은 작은 UI 설명
       이 패널      "이 화면에서 무슨 일을 하는가" 업무 설명

   본문을 좁히지 않는 것이 원칙입니다. 그래서 전체 폭(--admin-max)을
   패널만큼 넓혔고, 좁은 화면에서는 고정 패널 대신 서랍으로 바뀝니다.
   -------------------------------------------------------------------------- */

.help-panel {
  position: sticky;
  /* 헤더(56) + 메뉴(약 40) 아래에 붙습니다. */
  top: 100px;
  display: flex;
  flex-direction: column;
  margin-top: 24px;
  max-height: calc(100vh - 124px);
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
}

/* 브라우저 기본 [hidden] 은 display:flex 에 집니다. */
.help-panel[hidden] {
  display: none;
}

.help-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 12px 14px 8px;
}

.help-eyebrow {
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--muted);
}

/*
   최소 높이를 두어 설명 길이가 달라도 패널이 들썩이지 않게 합니다.
   높이가 바뀌면 옆 표까지 밀려 읽는 중에 시선을 잃습니다.
*/
.help-body {
  padding: 2px 16px 18px;
  min-height: 300px;
  opacity: 1;
  transition: opacity var(--help-fade) ease;
}

.help-body[data-swap="1"] {
  opacity: 0;
}

.help-title {
  margin: 0 0 6px;
  font-size: 15px;
  font-weight: 700;
  color: var(--ink);
}

.help-desc {
  margin: 0;
  font-size: 12.5px;
  line-height: 1.75;
  color: var(--ink-2);
}

.help-block {
  margin-top: 16px;
}

.help-label {
  display: block;
  margin-bottom: 6px;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}

.help-list,
.help-steps {
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: 12.5px;
  line-height: 1.7;
  color: var(--ink-2);
}

.help-list li {
  position: relative;
  padding-left: 11px;
}

.help-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 9px;
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: var(--line-strong);
}

.help-steps {
  counter-reset: help-step;
}

.help-steps li {
  position: relative;
  padding-left: 20px;
  counter-increment: help-step;
}

.help-steps li::before {
  content: counter(help-step);
  position: absolute;
  left: 0;
  top: 2px;
  width: 15px;
  height: 15px;
  border-radius: 50%;
  background: var(--bg-sunken);
  color: var(--muted);
  font-family: var(--font-num);
  font-size: 9.5px;
  font-weight: 700;
  line-height: 15px;
  text-align: center;
}

/*
   주의는 있을 때만 강조합니다. 모든 문장을 경고색으로 만들면
   어느 것이 실제 위험인지 알 수 없게 됩니다.
*/
.help-warn {
  margin: 16px 0 0;
  padding: 9px 11px;
  border-left: 2px solid var(--warn);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  background: var(--warn-soft);
  color: var(--warn);
  font-size: 12px;
  line-height: 1.65;
}

/* --------------------------------------------------------------------------
   메뉴 안의 물음표

   마우스가 없는 환경의 진입점입니다. hover 가 되는 넓은 화면에서는
   감춰 두어 메뉴를 어지럽히지 않습니다.
   -------------------------------------------------------------------------- */

/* 메뉴 이름과 물음표를 한 칸에 묶습니다.
   물음표는 버튼 밖에 있어야 합니다 — button 안에 누를 수 있는 것을
   또 넣으면 안 되는 마크업입니다. */
.nav-item,
.subnav-item {
  display: inline-flex;
  align-items: center;
}

.help-dot {
  display: none;
  margin-left: -4px;
  margin-right: 4px;
  width: 15px;
  height: 15px;
  border-radius: 50%;
  background: var(--bg-sunken);
  color: var(--muted);
  font-size: 10px;
  font-weight: 700;
  line-height: 15px;
  text-align: center;
  cursor: pointer;
}

.help-dot:hover,
.help-dot:focus-visible {
  background: var(--line-strong);
  color: var(--ink);
}

.help-backdrop {
  position: fixed;
  inset: 0;
  z-index: 55;
  background: rgba(16, 18, 22, 0.42);
}

.help-backdrop[hidden] {
  display: none;
}

/* 키보드로 옮겨도 같은 설명이 뜹니다. 어디에 있는지 보이게 합니다. */
.nav-tab:focus-visible,
.subnav-tab:focus-visible,
.help-dot:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: -2px;
}

/* --------------------------------------------------------------------------
   좁은 화면 — 고정 패널 대신 서랍

   1240px 은 300px 패널을 놓고도 본문 표가 읽히는 하한입니다.
   help-panel.js 의 docked() 와 같은 값이어야 합니다.
   -------------------------------------------------------------------------- */

@media (max-width: 1239px) {
  .admin-body {
    grid-template-columns: minmax(0, 1fr);
    max-width: 1280px;
  }

  .help-panel {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    z-index: 60;
    display: none;
    width: min(360px, 92vw);
    max-height: none;
    margin: 0;
    border: 0;
    border-left: 1px solid var(--line);
    border-radius: 0;
  }

  /* 서랍으로 열렸을 때만 보입니다. */
  .help-panel[data-drawer="1"] {
    display: flex;
  }

  .help-dot {
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
}

@media (min-width: 1240px) {
  .help-backdrop {
    display: none;
  }
}

/* 마우스가 없는 환경에서는 폭과 무관하게 물음표를 보여 줍니다. */
@media (hover: none) {
  .help-dot {
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
}


/* --------------------------------------------------------------------------
   진행 순서

   처음 보는 사람이 '지금 어디까지 왔는가' 를 알 수 있게 적습니다.
   장식이 아니라 안내이므로 번호를 또렷하게 둡니다.
   -------------------------------------------------------------------------- */

.flow-steps {
  margin: 0;
  padding: 4px 18px 14px;
  list-style: none;
  counter-reset: flow-step;
  display: flex;
  flex-wrap: wrap;
  gap: 6px 18px;
  font-size: 12.5px;
  color: var(--ink-2);
}

.flow-steps li {
  position: relative;
  padding-left: 24px;
  counter-increment: flow-step;
  line-height: 1.7;
}

.flow-steps li::before {
  content: counter(flow-step);
  position: absolute;
  left: 0;
  top: 3px;
  width: 17px;
  height: 17px;
  border-radius: 50%;
  background: var(--gold-soft);
  color: var(--gold);
  font-family: var(--font-num);
  font-size: 10px;
  font-weight: 700;
  line-height: 17px;
  text-align: center;
}


/* --------------------------------------------------------------------------
   지금 할 일

   숫자를 먼저 크게 보여 주고, 무엇인지와 왜인지를 그 아래에 답니다.
   누르면 그 화면 그 필터로 가므로 카드 전체가 버튼입니다.
   -------------------------------------------------------------------------- */

.todo-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 10px;
  padding: 4px 18px 18px;
}

.todo-card {
  appearance: none;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  padding: 14px 15px;
  border: 1px solid var(--line);
  border-left: 3px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  text-align: left;
  cursor: pointer;
  transition: border-color 0.13s ease, background 0.13s ease;
}

.todo-card:hover {
  background: var(--bg-sunken);
}

.todo-card:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: -2px;
}

/* 실제로 손을 대야 하는 것만 색을 씁니다. 전부 빨갛게 만들면
   어느 것이 급한지 알 수 없습니다. */
.todo-card[data-tone="alert"] {
  border-left-color: var(--up);
}

.todo-card[data-tone="warn"] {
  border-left-color: var(--warn);
}

.todo-count {
  font-family: var(--font-num);
  font-size: 22px;
  font-weight: 700;
  line-height: 1.2;
  color: var(--ink);
}

.todo-label {
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
}

.todo-note {
  font-size: 11.5px;
  line-height: 1.55;
  color: var(--muted);
}

/* ---------------------------------------------------------------
   일일보고 (STEP 16)
   --------------------------------------------------------------- */

/* 이름/값 두 칸 표. 지점별 금액처럼 짧은 쌍을 나열할 때 씁니다. */
.kv {
  width: 100%;
  font-size: 13px;
  border-collapse: collapse;
}

.kv th,
.kv td {
  padding: 7px 0;
  border-bottom: 1px solid var(--line);
  text-align: left;
  vertical-align: baseline;
}

.kv th {
  width: 40%;
  font-weight: 500;
  color: var(--ink-2);
}

.kv td {
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.kv tr:last-child th,
.kv tr:last-child td {
  border-bottom: 0;
}

/* 카카오톡 미리보기 말풍선.
   실제로 나갈 메시지를 건별로 그대로 보여 줍니다. 글자 수를 함께
   적는 이유는 200자 한도를 눈으로 확인할 수 있어야 하기 때문입니다. */
.kakao-bubble {
  margin-top: 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--bg-soft);
  overflow: hidden;
}

.kakao-meta {
  padding: 6px 12px;
  border-bottom: 1px solid var(--line);
  font-size: 11.5px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.kakao-bubble pre {
  margin: 0;
  padding: 12px;
  font-family: inherit;
  font-size: 12.5px;
  line-height: 1.75;
  white-space: pre-wrap;
  word-break: break-word;
  color: var(--ink);
}

/* ======================================================================
   CUBE 상품 연결 — 단계 표시와 요약 (STEP 21-C.1)

   기존 .panel / .kpi / .badge / .notice 를 그대로 쓰고, 여기서는
   그것으로 표현되지 않는 것만 더합니다. 같은 모양을 두 벌 만들면
   한쪽만 고쳐진 채 남습니다.
   ====================================================================== */

.steps {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  list-style: none;
  margin: 0 0 16px;
  padding: 0;
}

.step {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  border: 1px solid var(--line, #2a313b);
  border-radius: 999px;
  font-size: 12px;
  color: var(--muted, #98a2b3);
}

.step-no {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--line, #2a313b);
  font-size: 11px;
}

/* 지금 어디에 있는지가 한눈에 보여야 합니다. */
.step-now {
  border-color: var(--accent, #4c8dff);
  color: var(--fg, #e6edf3);
  font-weight: 600;
}

.step-now .step-no {
  background: var(--accent, #4c8dff);
  color: #fff;
}

.step-done {
  opacity: 0.7;
}

/* 파일·매장·기준일처럼 짧은 값을 한 줄에 늘어놓습니다. */
.kv-inline {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 24px;
  margin: 0 0 16px;
}

.kv-inline dt {
  color: var(--muted, #98a2b3);
  font-size: 12px;
}

.kv-inline dd {
  margin: 0 16px 0 0;
  font-size: 13px;
}

.compact {
  margin: 8px 0;
  padding-left: 18px;
  font-size: 13px;
  color: var(--muted, #98a2b3);
}

/* '연결됨'(저장됨) 과 '추천'(미저장) 을 절대 같은 색으로 칠하지
   않습니다. 같으면 승인한 적 없는 연결을 승인한 것으로 읽습니다. */
.badge-info {
  background: rgba(76, 141, 255, 0.15);
  color: var(--accent, #4c8dff);
}

.kpi-tone-warn .kpi-value {
  color: var(--warn, #f0b429);
}

.kpi-tone-ok .kpi-value {
  color: var(--ok, #3fb950);
}

.kpi-row-accent {
  margin-top: 1px;
}

.panel-actions {
  display: flex;
  gap: 8px;
  align-items: center;
}

/* ======================================================================
   CUBE 파일 설정 창 (STEP 21-C.3)

   예전 창의 문제는 하나였습니다 — 읽을 수가 없었습니다. 미리보기가
   한 줄로 붙어 나오고, 드롭다운이 그 위를 덮었습니다.

   그래서 **위에 표, 아래에 열 지정** 으로 세로로 쌓습니다. 좌우로
   나누면 15열짜리 표가 절반 폭에 들어가 다시 못 읽게 됩니다.
   ====================================================================== */

.setup-grid {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.setup-block h3 {
  margin: 0 0 10px;
  font-size: 14px;
  display: flex;
  align-items: center;
  gap: 10px;
}

.setup-fields {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 12px;
}

/* 미리보기는 가로로 스크롤합니다. 줄바꿈으로 접으면 행이 어디서
   끝나는지 알 수 없습니다. */
.preview-scroll {
  overflow-x: auto;
  max-height: 320px;
  overflow-y: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.table-preview {
  font-size: 12px;
  white-space: nowrap;
  border-collapse: separate;
  border-spacing: 0;
}

/* 세로로 스크롤해도 어느 열인지 보여야 합니다. */
.table-preview thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--surface);
  border-bottom: 1px solid var(--line);
  min-width: 90px;
}

.table-preview .col-no,
.table-preview th.col-no {
  position: sticky;
  left: 0;
  z-index: 2;
  background: var(--surface);
  min-width: 40px;
  text-align: right;
  color: var(--muted);
}

.table-preview .col-index {
  display: inline-block;
  min-width: 16px;
  margin-right: 4px;
  color: var(--muted);
  font-weight: 400;
}

/* 긴 상품명이 표를 밀지 않게. 전체 값은 title 로 봅니다. */
.table-preview .cell {
  display: inline-block;
  max-width: 240px;
  overflow: hidden;
  text-overflow: ellipsis;
  vertical-align: bottom;
}

.table-mapping td {
  vertical-align: top;
}

.table-mapping select {
  width: 100%;
  min-width: 220px;
}

.map-stat {
  margin-top: 4px;
  min-height: 16px;
}

.map-state .ok {
  color: var(--ok, #3fb950);
}

.map-state .warn {
  color: var(--warn, #f0b429);
}

.small {
  font-size: 11px;
}

/* ======================================================================
   매칭 근거 상세 (STEP 21-C.5)

   '봤지만 쓰지 않은' 근거를 흐리게 둡니다. 같은 진하기로 두면
   찾은 것과 못 찾은 것이 구별되지 않습니다.
   ====================================================================== */

.muted-row td {
  opacity: 0.55;
}

.src-cell .badge {
  margin-right: 2px;
}

/* 상태 셀을 버튼으로 만들되 버튼처럼 보이지 않게 합니다. */
button.link-plain {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  color: inherit;
  cursor: pointer;
  text-align: left;
}

button.link-plain:hover .muted {
  color: var(--accent, #4c8dff);
}

/* ======================================================================
   매칭 상세 모달 (STEP 21-C.6)

   예전에는 6열짜리 표 하나였습니다. 출처·필드·방법·찾은 값·
   CON TII 상품·비고가 한 줄에 몰려서, 긴 설명이 셀 안에서 제멋대로
   접히고 무엇이 중요한 값인지 알 수 없었습니다.

   이 화면은 개발자가 디버깅하는 표가 아니라 매장 운영자가 상품
   매칭을 판단하는 화면입니다. 그래서 정보 계층 · 여백 · 상태 표현을
   기능보다 앞에 둡니다.

   전용 접두사(cube-match-)를 씁니다. 전역 table/modal 스타일을
   덮어쓰면 다른 화면이 같이 흔들립니다.
   ====================================================================== */

.cube-match-detail {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

/* ---- 머리 ---- */

.cube-match-detail__header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  padding-bottom: 16px;
  border-bottom: 1px solid var(--line);
}

/* 상품명이 길어도 오른쪽 배지를 밀어내지 않게 합니다. */
.cube-match-detail__heading {
  min-width: 0;
  flex: 1 1 auto;
}

.cube-match-detail__eyebrow {
  margin: 0 0 4px;
  font-size: 11px;
  letter-spacing: 0.04em;
  color: var(--muted);
  text-transform: uppercase;
}

.cube-match-detail__title {
  margin: 0;
  font-size: 20px;
  line-height: 1.3;
  /* 긴 상품명·바코드가 레이아웃을 밀지 않게 합니다. */
  overflow-wrap: anywhere;
}

.cube-match-detail__subtitle {
  margin: 6px 0 0;
  font-size: 13px;
  color: var(--muted);
}

/* ---- 카드 ---- */

.cube-match-detail__card {
  padding: 16px 18px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--panel, #171b21);
}

.cube-match-detail__card-title {
  margin: 0 0 12px;
  font-size: 13px;
  font-weight: 600;
  color: var(--muted);
}

.cube-match-detail__grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px 20px;
}

.cube-match-detail__grid--wide {
  grid-template-columns: minmax(0, 1fr);
  margin-top: 12px;
}

.cube-match-detail__field {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}

.cube-match-detail__label {
  font-size: 11px;
  color: var(--muted);
}

.cube-match-detail__value {
  font-size: 14px;
  overflow-wrap: anywhere;
}

/* ---- 판정 ----
   색만으로 뜻을 전하지 않습니다. 왼쪽 띠는 보조이고, 상태는 언제나
   글자 배지로도 적혀 있습니다. */

.cube-match-detail__result {
  border-left: 3px solid var(--line);
}

.cube-match-status--matched {
  border-left-color: var(--ok, #3fb950);
}

.cube-match-status--review {
  border-left-color: var(--warn, #f0b429);
}

.cube-match-status--unmatched {
  border-left-color: var(--muted, #98a2b3);
}

.cube-match-detail__result-badge {
  margin: 0 0 8px;
}

.cube-match-detail__result-text {
  margin: 0 0 12px;
  font-size: 14px;
  line-height: 1.6;
}

/* ----------------------------------------------------------------------
   재고 미확인 시장가 (STEP 24-J)
   ----------------------------------------------------------------------

   재고가 확인된 값과 전체 수집가를 같은 모양으로 찍으면, 지금 살 수
   없는 값을 보고 판매가를 정하게 됩니다. 숫자는 읽히되 확정값보다
   약하게, 그리고 '재고 미확인' 이라는 글자가 반드시 함께 보이도록
   합니다. 색만으로 구분하지 않습니다. */
.market-unconfirmed {
  display: inline-flex;
  flex-direction: column;
  align-items: flex-end;
  line-height: 1.3;
  color: var(--text-muted, #8b949e);
}

.market-unconfirmed__note {
  font-size: 10px;
  letter-spacing: -0.2px;
  white-space: nowrap;
  color: var(--warn, #f0b429);
}

/* KPI 타일 안에서는 가운데 정렬을 따릅니다. */
.kpi-value .market-unconfirmed {
  align-items: center;
}

/* ======================================================================
   CUBE 검수 목록 (STEP 21-C.8)
   ======================================================================

   200여 행을 훑는 표입니다. 한 행을 읽는 시간이 아니라 **200행을
   훑는 시간**을 줄이는 것이 목적이라, 규칙 세 가지를 지킵니다.

       행 높이가 들쭉날쭉하지 않을 것   눈이 다시 줄을 찾지 않게
       1차 정보가 가장 진할 것         이름 > 코드 > 나머지
       상태를 색으로만 말하지 말 것     기호와 낱말을 함께

   `.table` 의 기본 스타일 위에 얹습니다. 표 자체를 새로 만들지
   않았습니다 — 다른 표와 여백·테두리가 어긋나면 같은 화면이
   아닌 것처럼 보입니다. */

.cube-rows__bar {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 12px;
}

.cube-rows__filters {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

/* 필터 칩. 건수를 함께 적어 '눌러 봐야 아는' 상태를 없앱니다. */
.cube-filter {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  padding: 5px 10px;
  border: 1px solid var(--border, #30363d);
  border-radius: 999px;
  background: transparent;
  color: var(--text-muted, #8b949e);
  font-size: 13px;
  line-height: 1.4;
  cursor: pointer;
}

.cube-filter:hover:not(:disabled) {
  border-color: var(--accent, #58a6ff);
  color: var(--text, #c9d1d9);
}

.cube-filter.is-active {
  border-color: var(--accent, #58a6ff);
  background: rgba(88, 166, 255, 0.12);
  color: var(--text, #c9d1d9);
  font-weight: 600;
}

.cube-filter:disabled {
  opacity: 0.45;
  cursor: default;
}

.cube-filter__count {
  font-variant-numeric: tabular-nums;
  font-size: 12px;
  opacity: 0.85;
}

.cube-rows__tools {
  display: flex;
  align-items: center;
  gap: 10px;
}

/* 이 프로젝트의 입력은 element 선택자로 꾸밉니다(.input 클래스가
   없습니다). 없는 클래스를 새로 만들지 않고 그 규칙에 얹습니다. */
.cube-search input {
  min-width: 260px;
}

/* 눈에는 안 보이지만 화면 낭독기에는 읽히는 라벨.
   placeholder 만 두면 낭독기 사용자에게는 이름 없는 입력칸입니다. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.cube-rows__count {
  font-size: 12px;
  color: var(--text-muted, #8b949e);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* 표를 스크롤하는 동안 머리글이 남아 있어야 어느 칸인지 압니다. */
.cube-rows__scroll {
  max-height: 68vh;
  overflow: auto;
}

.cube-rows__table thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--panel, #161b22);
}

.cube-rows__table td {
  vertical-align: top;
  padding-top: 8px;
  padding-bottom: 8px;
}

.cube-row:hover td {
  background: rgba(88, 166, 255, 0.06);
}

.cube-row__num {
  width: 48px;
  text-align: right;
  color: var(--text-muted, #8b949e);
  font-variant-numeric: tabular-nums;
}

.cube-row__qty {
  width: 64px;
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.cube-row__evidence {
  width: 200px;
}

.cube-row__actions {
  width: 132px;
  white-space: nowrap;
}

.cube-row__actions .btn + .btn {
  margin-left: 4px;
}

.cube-row__empty {
  padding: 24px 12px;
  text-align: center;
  color: var(--text-muted, #8b949e);
}

/* ---- 이름 + 부가 정보 ---- */

.cube-cell {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 180px;
}

.cube-cell__name {
  font-size: 13px;
  line-height: 1.45;
  color: var(--text, #c9d1d9);
  /* 긴 이름은 두 줄까지. 세 줄이 되면 행 높이가 흔들려서 훑기가
     어려워집니다. 잘린 전체 이름은 title 로 볼 수 있습니다. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  word-break: break-word;
}

.cube-cell__meta {
  font-size: 11px;
  line-height: 1.4;
  color: var(--text-muted, #8b949e);
  font-variant-numeric: tabular-nums;
}

/* ---- 판정 ---- */

.cube-verdict {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 3px;
}

.cube-verdict__pill {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 9px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
  line-height: 1.5;
  white-space: nowrap;
}

.cube-verdict__mark {
  font-size: 11px;
  opacity: 0.9;
}

.cube-verdict__pill--matched {
  background: rgba(63, 185, 80, 0.16);
  color: var(--ok, #3fb950);
}

.cube-verdict__pill--review {
  background: rgba(240, 180, 41, 0.16);
  color: var(--warn, #f0b429);
}

.cube-verdict__pill--unmatched {
  background: rgba(139, 148, 158, 0.16);
  color: var(--text-muted, #8b949e);
}

.cube-verdict__pill--error {
  background: rgba(248, 81, 73, 0.16);
  color: var(--danger, #f85149);
}

.cube-verdict__pill--muted {
  background: rgba(139, 148, 158, 0.1);
  color: var(--text-muted, #8b949e);
}

/* '기록 갱신 필요' 는 판정이 아닙니다. 알약이 아니라 작은 글자로
   두어야 사람이 판정으로 읽지 않습니다. */
.cube-verdict__note {
  font-size: 11px;
  line-height: 1.4;
  color: var(--text-muted, #8b949e);
  white-space: nowrap;
}

/* ---- 근거 칩 ---- */

.cube-chip {
  display: inline-block;
  margin: 0 3px 3px 0;
  padding: 2px 7px;
  border-radius: 4px;
  font-size: 11px;
  line-height: 1.5;
  white-space: nowrap;
}

.cube-chip--evidence {
  background: rgba(88, 166, 255, 0.12);
  color: var(--accent, #58a6ff);
}

/* 판매처는 '이 상품이 어디서 팔린다' 이지 매칭 근거가 아닙니다.
   테두리만 두고 채우지 않아 한눈에 갈라 보입니다. */
.cube-chip--reference {
  border: 1px dashed var(--border, #30363d);
  background: transparent;
  color: var(--text-muted, #8b949e);
}

/* 좁은 화면에서는 검색창이 줄을 독차지하게 둡니다. 기존 표는
   .table-scroll 이 이미 가로 스크롤을 맡고 있어 건드리지 않습니다. */
@media (max-width: 900px) {
  .cube-rows__bar {
    flex-direction: column;
    align-items: stretch;
  }

  .cube-rows__tools {
    flex-wrap: wrap;
  }

  .cube-search input {
    min-width: 0;
    width: 100%;
  }

  .cube-rows__scroll {
    max-height: none;
  }
}

/* 저장된 판정이 지금 규칙과 다를 때의 안내.
   경고가 아니라 사실 안내입니다 — 틀린 것이 아니라 옛 규칙으로
   저장됐을 뿐이라 붉은색을 쓰지 않습니다. */
.cube-match-detail__stale {
  margin: 12px 0 0;
  padding: 10px 12px;
  border-left: 3px solid var(--warn, #f0b429);
  border-radius: 0 6px 6px 0;
  background: rgba(240, 180, 41, 0.08);
  font-size: 13px;
  line-height: 1.6;
  color: var(--text-muted, #8b949e);
}

.cube-match-status-badge--matched {
  background: rgba(63, 185, 80, 0.16);
  color: var(--ok, #3fb950);
}

.cube-match-status-badge--review {
  background: rgba(240, 180, 41, 0.16);
  color: var(--warn, #f0b429);
}

.cube-match-status-badge--unmatched,
.cube-match-status-badge--muted {
  background: rgba(152, 162, 179, 0.16);
  color: var(--muted, #98a2b3);
}

/* ---- 근거 카드 ---- */

.cube-match-detail__summary-line {
  margin: -4px 0 14px;
  font-size: 13px;
  color: var(--muted);
}

.cube-match-detail__evidence {
  display: grid;
  gap: 12px;
}

.cube-match-evidence {
  padding: 14px 16px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface, #12161b);
}

/* 확인했지만 결과가 없는 출처는 흐리게. 같은 진하기로 두면
   찾은 것과 못 찾은 것이 구별되지 않습니다. */
.cube-match-evidence--none {
  opacity: 0.62;
}

.cube-match-evidence__header {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 10px;
}

.cube-match-evidence__mark {
  width: 18px;
  text-align: center;
  font-weight: 700;
}

.cube-match-evidence--found .cube-match-evidence__mark,
.cube-match-evidence--candidate .cube-match-evidence__mark {
  color: var(--ok, #3fb950);
}

.cube-match-evidence--none .cube-match-evidence__mark {
  color: var(--muted);
}

.cube-match-evidence__source {
  margin: 0;
  font-size: 14px;
  font-weight: 600;
  flex: 1 1 auto;
  min-width: 0;
  overflow-wrap: anywhere;
}

.cube-match-source-badge--found {
  background: rgba(63, 185, 80, 0.16);
  color: var(--ok, #3fb950);
}

.cube-match-source-badge--candidate {
  background: rgba(76, 141, 255, 0.16);
  color: var(--accent, #4c8dff);
}

.cube-match-source-badge--none {
  background: rgba(152, 162, 179, 0.14);
  color: var(--muted, #98a2b3);
}

/* 이름과 값을 두 칸으로. 표처럼 여섯 칸에 몰아넣지 않습니다. */
.cube-match-evidence__meta {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 6px 20px;
}

.cube-match-evidence__meta-row {
  display: flex;
  gap: 10px;
  min-width: 0;
  font-size: 13px;
}

.cube-match-evidence__meta-label {
  flex: 0 0 120px;
  color: var(--muted);
}

.cube-match-evidence__meta-value {
  min-width: 0;
  overflow-wrap: anywhere;
}

/* 긴 설명은 카드 폭을 다 쓰는 한 문단으로. 셀 안에서 접히지
   않게 하는 것이 이번 개선의 핵심입니다. */
.cube-match-evidence__description {
  margin: 10px 0 0;
  font-size: 13px;
  line-height: 1.65;
  color: var(--fg, #e6edf3);
}

.cube-match-evidence__provenance {
  margin: 8px 0 0;
  font-size: 12px;
  color: var(--muted);
}

/* ---- 안내 ---- */

.cube-match-detail__legend {
  padding: 14px 16px;
  border: 1px dashed var(--line);
  border-radius: var(--radius);
  font-size: 12px;
  color: var(--muted);
}

.cube-match-detail__legend ul {
  margin: 0 0 8px;
  padding-left: 18px;
  line-height: 1.8;
}

.cube-match-detail__legend p {
  margin: 0;
  line-height: 1.6;
}

/* ---- 좁은 화면 ----
   가로 스크롤을 기본 해결책으로 쓰지 않습니다. */

@media (max-width: 720px) {
  .cube-match-detail__grid {
    grid-template-columns: minmax(0, 1fr);
  }

  .cube-match-evidence__meta {
    grid-template-columns: minmax(0, 1fr);
  }

  .cube-match-evidence__meta-label {
    flex-basis: 96px;
  }

  .cube-match-detail__header {
    flex-direction: column;
    gap: 10px;
  }
}

/* ── 외부 근거 (V2-02G.1C) ────────────────────────────────────────
   검수 줄에 딸린 보조 정보입니다. 새 화면이 아니라 곁들이는 것이라
   기존 패널보다 한 단계 조용하게 둡니다. */
.evidence-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 6px 0 10px;
}

.evidence-card {
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 8px 10px;
  background: rgba(255, 255, 255, 0.02);
}

.evidence-head {
  display: flex;
  align-items: baseline;
  gap: 8px;
  justify-content: space-between;
}

.evidence-value {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin: 2px 0 4px;
}

.evidence-value strong {
  font-size: 15px;
}

.evidence-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 6px;
}

/* --- 빠른 검수 (외부 근거) — STEP V2-02G.1E ------------------------------
   경고가 있는 줄은 눈에 띄되, 아무것도 자동으로 정하지 않습니다. */
.qr-table tbody tr.qr-warn td {
  background: var(--warn-soft);
}
.qr-table select,
.qr-table input[type="number"] {
  font: inherit;
  padding: 3px 6px;
  border: 1px solid var(--line, #d0d5dd);
  border-radius: 6px;
  background: var(--surface, #fff);
  color: inherit;
  max-width: 100%;
}
.qr-table select + select {
  margin-top: 4px;
  display: block;
}

/* --- 재고 · 외부 판매가 — IMPLEMENT-01D ----------------------------------
   "확인되지 않음" 은 값이 아니라 상태입니다. 숫자처럼 보이지 않게 합니다. */
.iep-unknown {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 6px;
  background: var(--warn-soft);
  color: var(--warn);
  font-size: 12px;
  font-weight: 600;
}
.iep-table td {
  vertical-align: top;
}
