:root {
  color-scheme: light;
  --ink: #17242d;
  --muted: #60717e;
  --line: #d8e1e7;
  --panel: #ffffff;
  --page: #eef3f6;
  --brand: #0067a6;
  --brand-strong: #004f80;
  /* No.1: 아이템 통합 조회에서 요청 경계를 가르는 교차색. 색은 보조 신호이고
     요청번호 열·구분 행이 본 신호다(색각 이상·흑백 인쇄). */
  --rollup-group-a: #ffffff;
  --rollup-group-b: #eef4f8;
  --good: #24754f;
  --warn: #965c00;
  --bad: #b3261e;
  font-family: "Noto Sans KR", "Apple SD Gothic Neo", Inter, system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
}

* {
  box-sizing: border-box;
}

[hidden] {
  display: none !important;
}

.environment-badge {
  position: fixed;
  z-index: 2000;
  top: 12px;
  right: 14px;
  display: inline-flex;
  align-items: center;
  min-height: 24px;
  border: 1px solid transparent;
  border-radius: 999px;
  padding: 3px 9px;
  font-size: 10px;
  font-weight: 900;
  letter-spacing: .08em;
  line-height: 1;
  pointer-events: none;
}

/* 헤더 안에 놓인 배지는 흐름을 따른다. fixed 그대로 두면 우상단에 겹쳐 떠서
   사용자 메뉴를 가린다(공개 페이지는 헤더가 없어 fixed를 유지한다). */
.topbar-actions .environment-badge {
  position: static;
  flex: 0 0 auto;
}

.environment-badge[data-environment="customizing"] { border-color: #8ec5ff; background: #e8f4ff; color: #07598d; }
.environment-badge[data-environment="testing"] { border-color: #f2c467; background: #fff4d8; color: #865500; }
.environment-badge[data-environment="production"] { border-color: #8ed8aa; background: #e6f7ec; color: #17653a; }

body {
  margin: 0;
  min-height: 100vh;
  background: var(--page);
  color: var(--ink);
  font-family: "Noto Sans KR", "Apple SD Gothic Neo", Inter, system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

button,
input,
select,
textarea {
  font: inherit;
}

button {
  cursor: pointer;
}

a {
  color: inherit;
}

.public-body {
  background: #f4f7f9;
}

.public-page {
  width: min(780px, calc(100% - 28px));
  margin: 0 auto;
  padding: 24px 0 42px;
}

.intake-body {
  background: #fff;
}

.intake-page {
  width: min(700px, calc(100% - 32px));
  padding: 22px 0 64px;
}

.work-form,
.panel,
.detail-panel,
.editor-panel,
.master-card,
.qa-card {
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--panel);
  box-shadow: 0 14px 34px rgba(26, 43, 54, 0.07);
}

.work-form {
  padding: 24px;
}

.intake-form {
  border: 0;
  border-radius: 0;
  padding: 0;
  background: transparent;
  box-shadow: none;
}

.form-head {
  margin-bottom: 20px;
  padding-bottom: 16px;
  border-bottom: 1px solid var(--line);
}

.intake-head {
  margin-bottom: 22px;
  padding-bottom: 0;
  border-bottom: 0;
  text-align: left;
}

.intake-head h1 {
  color: #24465c;
  font-size: 29px;
}

.form-head strong,
.mono {
  color: var(--brand);
  font-family: "SFMono-Regular", Consolas, monospace;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 0;
}

h1,
h2,
h3,
p {
  margin-top: 0;
}

h1 {
  margin-bottom: 0;
  font-size: 34px;
  line-height: 1.1;
  letter-spacing: 0;
}

h2 {
  margin-bottom: 8px;
  font-size: 24px;
}

h3 {
  margin-bottom: 12px;
  font-size: 17px;
}

.field-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
}

.field-grid.compact {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

.intake-fields {
  display: grid;
  gap: 26px;
}

.intake-fields.after-upload {
  margin-top: 30px;
}

.wide {
  grid-column: 1 / -1;
}

label {
  display: grid;
  gap: 7px;
  color: #2a3a45;
  font-size: 14px;
  font-weight: 700;
}

.intake-field {
  display: grid;
  gap: 7px;
  color: #17242d;
  font-size: 13px;
  font-weight: 750;
}

.field-title b,
.phone-field b {
  color: var(--bad);
}

.field-help {
  margin-top: -3px;
  color: var(--muted);
  font-size: 12px;
  font-weight: 500;
}

.char-counter {
  justify-self: end;
  color: var(--muted);
  font-size: 12px;
  font-weight: 500;
}

input,
select,
textarea {
  width: 100%;
  min-height: 42px;
  border: 1px solid #c6d2da;
  border-radius: 6px;
  padding: 9px 11px;
  background: #fff;
  color: var(--ink);
  outline: none;
}

/* 275_: 바로 위 규칙은 텍스트 입력을 위한 것인데 체크박스·라디오까지 100% 폭 ·
   42px 높이로 키운다. flex 라벨 안에서는 체크박스가 남은 폭을 다 먹어 글자를
   오른쪽 끝으로 밀어내고, 라벨 길이마다 밀리는 정도가 달라 체크박스가 층계처럼
   어긋난다.
   그동안 화면마다 따로 되돌려 왔다 - 256_ .checkbox-field, 252_ 라인 체크 셀,
   .inline-check, .comment-tabs. 그러고도 세 곳이 남아 있었다: 진행상태 드롭다운과
   요청 목록의 선택 열(머리글·행). 다섯 번째 개별 규칙을 붙이는 대신 여기서 한 번
   되돌린다. 기존 개별 규칙은 더 구체적이라 그대로 이기고, 값도 같은 방향이다. */
input[type="checkbox"],
input[type="radio"] {
  width: auto;
  min-height: auto;
}

/* 256_: 전역 input 규칙(width 100% · min-height 42px)이 checkbox 까지 키운다 -
   헤더 폼의 체크박스는 라벨 옆 16px 로 되돌린다. */
.checkbox-field {
  display: flex;
  align-items: center;
  gap: 8px;
}

.checkbox-field input[type="checkbox"] {
  width: 16px;
  height: 16px;
  min-height: 0;
  margin: 0;
  padding: 0;
  flex: 0 0 auto;
}

fieldset {
  min-width: 0;
}

.phone-field {
  margin: 0;
  border: 0;
  padding: 0;
}

.phone-field legend {
  margin-bottom: 7px;
  padding: 0;
}

.phone-row {
  display: grid;
  grid-template-columns: 106px minmax(0, 1fr);
  gap: 6px;
}

.address-search-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 76px;
  gap: 8px;
  align-items: center;
}

.address-search-btn {
  min-height: 42px;
  margin: 0;
}

textarea {
  min-height: 124px;
  resize: vertical;
  line-height: 1.45;
}

.intake-form textarea {
  min-height: 86px;
}

input:focus,
select:focus,
textarea:focus,
canvas:focus {
  border-color: var(--brand);
  box-shadow: 0 0 0 4px rgba(0, 103, 166, 0.18);
}

.upload-panel,
.signature-panel,
.editor-panel {
  display: grid;
  gap: 12px;
  margin-top: 18px;
  border: 1px dashed #9fb1bd;
  border-radius: 8px;
  padding: 16px;
  background: #f8fafb;
}

.completion-review {
  display: grid;
  gap: 14px;
  margin-bottom: 18px;
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 16px;
  background: #fbfcfd;
}

.completion-review > header {
  display: flex;
  justify-content: space-between;
  gap: 14px;
  align-items: start;
}

.completion-review > header p {
  margin: 4px 0 0;
  color: var(--muted);
  font-size: 13px;
}

.review-meta {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
  margin: 0;
}

.review-meta div,
.readonly-result {
  display: grid;
  gap: 5px;
  border: 1px solid #e1e8ed;
  border-radius: 8px;
  padding: 10px;
  background: #fff;
}

.review-meta dd {
  margin: 0;
  color: var(--ink);
  font-weight: 800;
}

.readonly-result p {
  margin-bottom: 0;
  color: var(--ink);
  white-space: pre-line;
}

/* G3d (92_ 4-7): the public completion page is a document the customer reads,
   keeps and prints - not a form. .completion-review above stays as it is because
   action.html still renders the approval panel with it. */
.completion-doc {
  display: grid;
  gap: 14px;
}

.completion-doc .form-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px 12px;
  margin-bottom: 4px;
}

.completion-doc .form-head h1 {
  flex: 1 1 auto;
  margin: 0;
}

/* CD-63 REQ-63-1/63-3/63-5 — 완료보고서 헤더 로고.
   .form-head strong 규칙(위쪽 .mono 계열)은 건드리지 않는다: .mono 32곳과
   공개화면 4개가 그 규칙을 공유하므로 폭발 반경이 크다.
   180px 은 REQ-63-1 의 화면 기준 160~200px 과 A4 40~50mm(151~189px)의 교집합
   160~189px 의 중앙값이고 인쇄 시 47.6mm 가 된다. */
.completion-doc .form-head .brand-logo {
  width: var(--brand-logo-width, 180px);
  height: auto;
  max-width: 40vw;
  flex: 0 0 auto;
}

.print-hint {
  margin: 0 0 16px;
  color: var(--muted);
  font-size: 13px;
  line-height: 1.6;
}

.doc-section {
  display: grid;
  gap: 8px;
  border: 1px solid #e1e8ed;
  border-radius: 8px;
  padding: 12px;
  background: #fff;
}

.doc-section-hint {
  color: var(--muted);
  font-size: 12px;
}

.doc-section-hint:empty {
  display: none;
}

.quote-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
  font-variant-numeric: tabular-nums;
}

.quote-table th,
.quote-table td {
  border-bottom: 1px solid var(--line);
  padding: 8px 6px;
  text-align: left;
}

.quote-table thead th {
  color: var(--muted);
  font-size: 12px;
  font-weight: 700;
  white-space: nowrap;
}

.quote-table .numeric {
  text-align: right;
}

.quote-table tfoot th,
.quote-table tfoot td {
  border-bottom: 0;
  border-top: 2px solid var(--ink);
  font-size: 14px;
  font-weight: 800;
}

.quote-table tfoot th {
  text-align: right;
}

.print-stamp {
  margin: 0;
  color: var(--muted);
  font-size: 11px;
}

/* Seven columns measure ~456px, so on a phone the table has to stop being a
   table. The header text moves into data-label on each cell; nothing is dropped,
   because a customer checking an amount needs every column. */
@media (max-width: 640px) {
  .quote-table thead {
    display: none;
  }

  .quote-table,
  .quote-table tbody,
  .quote-table tfoot,
  .quote-table tr,
  .quote-table th,
  .quote-table td {
    display: block;
    width: 100%;
  }

  .quote-table tbody tr {
    margin-bottom: 8px;
    border: 1px solid var(--line);
    border-radius: 8px;
    padding: 8px 10px;
  }

  .quote-table tbody td {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    border-bottom: 0;
    padding: 3px 0;
    text-align: right;
  }

  .quote-table tbody td::before {
    content: attr(data-label);
    color: var(--muted);
    font-size: 12px;
    font-weight: 700;
    text-align: left;
  }

  .quote-table tfoot tr {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 12px;
    border-top: 2px solid var(--ink);
    padding-top: 8px;
  }

  .quote-table tfoot th,
  .quote-table tfoot td {
    width: auto;
    border-top: 0;
    text-align: left;
  }
}

.upload-panel {
  cursor: pointer;
  transition: border-color 0.14s ease, background 0.14s ease, box-shadow 0.14s ease;
}

.intake-upload {
  margin-top: 30px;
  border: 0;
  border-radius: 0;
  padding: 0;
  background: transparent;
  cursor: pointer;
}

.upload-title-row {
  display: grid;
  gap: 4px;
  margin-bottom: 10px;
}

.upload-title-row strong {
  color: #17242d;
  font-size: 13px;
  font-weight: 750;
}

.upload-title-row span {
  color: var(--muted);
  font-size: 12px;
}

.drop-surface {
  min-height: 176px;
  display: grid;
  place-items: center;
  align-content: center;
  gap: 14px;
  border: 1px dashed #9fb1bd;
  background: #fff;
  color: #17242d;
  text-align: center;
}

.drop-surface p {
  margin: 0;
}

.drop-surface strong {
  color: #006fd6;
  font-weight: 500;
}

.drop-arrow {
  color: #111;
  font-size: 34px;
  line-height: 1;
}

.intake-upload > input[type="file"] {
  position: fixed;
  left: -9999px;
  top: auto;
  width: 1px;
  height: 1px;
  min-height: 0;
  margin: -1px;
  border: 0;
  padding: 0;
  overflow: hidden;
  opacity: 0;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
}

.upload-panel.dragging,
.upload-panel:focus {
  border-color: var(--brand);
  background: #eef7fc;
  box-shadow: 0 0 0 4px rgba(0, 103, 166, 0.14);
}

.intake-upload.dragging,
.intake-upload:focus {
  border-color: transparent;
  background: transparent;
  box-shadow: none;
  outline: none;
}

.intake-upload.dragging .drop-surface,
.intake-upload:focus .drop-surface {
  border-color: var(--brand);
  background: #eef7fc;
  box-shadow: 0 0 0 4px rgba(0, 103, 166, 0.14);
}

.upload-panel div:first-child,
.signature-panel div:first-child {
  display: flex;
  justify-content: space-between;
  gap: 14px;
  color: var(--muted);
  font-size: 13px;
}

.upload-panel strong,
.signature-panel strong {
  color: var(--ink);
  font-size: 15px;
}

.intake-upload .upload-title-row strong {
  color: #17242d;
  font-size: 13px;
}

.intake-upload .drop-surface strong {
  color: #006fd6;
  font-size: inherit;
  font-weight: 500;
}

.intake-upload .file-list {
  margin-top: 12px;
}

.file-list {
  display: grid;
  gap: 8px;
}

.file-row,
.file-card {
  display: grid;
  grid-template-columns: 50px minmax(0, 1fr) 38px;
  column-gap: 12px;
  row-gap: 8px;
  align-items: center;
  border: 1px solid #e0e7ec;
  border-radius: 8px;
  padding: 10px;
  background: #fff;
  font-size: 13px;
}

.file-card {
  grid-template-columns: 58px minmax(0, 1fr);
}

/* F1: cards that carry download/delete buttons get a trailing auto column so a
   long filename ellipsizes inside its own track instead of overrunning them. */
.file-card.has-actions {
  grid-template-columns: 58px minmax(0, 1fr) auto;
}

.file-row-content {
  display: grid;
  grid-template-columns: minmax(140px, 184px) minmax(0, 1fr);
  gap: 12px;
  align-items: center;
  min-width: 0;
}

.file-row select {
  width: 100%;
  min-width: 0;
  font-size: 13px;
  font-weight: 650;
  line-height: 1.25;
}

.file-row .icon-btn {
  justify-self: end;
}

.file-thumb,
.file-icon {
  width: 48px;
  height: 48px;
  border-radius: 8px;
  border: 1px solid #d9e3e9;
  background: #eef3f6;
}

.file-thumb {
  object-fit: cover;
}

.file-preview-button {
  width: 48px;
  height: 48px;
  border: 0;
  border-radius: 8px;
  padding: 0;
  background: transparent;
}

.file-preview-button:focus {
  outline: 3px solid rgba(0, 103, 166, 0.22);
  outline-offset: 2px;
}

.file-icon {
  display: grid;
  place-items: center;
  color: #fff;
  font-size: 11px;
  font-weight: 850;
  letter-spacing: 0;
}

.file-icon.excel {
  background: #217346;
}

.file-icon.powerpoint {
  background: #c43e1c;
}

.file-icon.word {
  background: #2b579a;
}

.file-icon.pdf {
  background: #b3261e;
}

.file-icon.archive {
  background: #6d5d00;
}

.file-icon.text {
  background: #536675;
}

.file-icon.file {
  background: var(--brand);
}

.file-meta {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  min-width: 0;
  width: 100%;
  gap: 2px;
  color: var(--ink);
  font-size: 13px;
  line-height: 1.34;
  overflow: hidden;
}

.file-name {
  display: -webkit-box;
  min-width: 0;
  width: 100%;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: normal;
  overflow-wrap: anywhere;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  font-size: 13px;
  font-weight: 750;
  line-height: 1.34;
}

.file-size {
  display: block;
  min-width: 0;
  line-height: 1.2;
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.file-card span,
.file-row small,
.review-meta dt,
.review-meta dd,
.muted {
  color: var(--muted);
  font-size: 13px;
}

.file-preview-backdrop {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: grid;
  place-items: center;
  padding: 18px;
  background: rgba(9, 20, 28, 0.72);
}

.file-preview-dialog {
  display: grid;
  gap: 12px;
  width: min(980px, 100%);
  max-height: calc(100vh - 36px);
  border-radius: 8px;
  padding: 14px;
  background: #fff;
  box-shadow: 0 24px 70px rgba(0, 0, 0, 0.24);
}

.file-preview-dialog header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.file-preview-image {
  width: 100%;
  max-height: calc(100vh - 132px);
  border: 1px solid var(--line);
  border-radius: 8px;
  object-fit: contain;
  background: #f7fafc;
}

/* PDF 미리보기. 이미지와 같은 자리를 쓰되 높이는 고정한다 — iframe 은 내용에
   맞춰 늘어나지 않으므로 뷰어가 자기 스크롤을 가질 공간이 필요하다. */
.file-preview-frame {
  width: 100%;
  height: calc(100vh - 132px);
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #f7fafc;
}

body.modal-open {
  overflow: hidden;
}

body.sidebar-open {
  overflow: hidden;
}

.readonly {
  margin-top: 8px;
}

.icon-btn {
  width: 34px;
  min-height: 34px;
  border: 1px solid #c6d2da;
  border-radius: 6px;
  background: #fff;
  color: #40515d;
}

.primary-btn,
.link-btn,
.segmented button,
.button-row button {
  min-height: 40px;
  border-radius: 6px;
  border: 1px solid transparent;
  padding: 0 14px;
  font-weight: 750;
  text-decoration: none;
  display: inline-grid;
  place-items: center;
}

.primary-btn {
  background: var(--brand);
  color: #fff;
}

.primary-btn:hover {
  background: var(--brand-strong);
}

.link-btn,
.button-row button {
  border-color: #b4c2cc;
  background: #fff;
  color: var(--ink);
}

.danger-link {
  border-color: #e2b3ad;
  color: var(--bad);
}

/* Every button style needs the disabled treatment. Only .link-btn had it, so a
   disabled .primary-btn still looked fully actionable (measured 2026-08-04:
   the guarded "생성" button read as enabled). */
.link-btn:disabled,
.primary-btn:disabled,
.segmented button:disabled,
.button-row button:disabled {
  cursor: not-allowed;
  opacity: 0.45;
  filter: grayscale(0.5);
}

.form-actions,
.button-row {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 18px;
}

.result {
  margin-top: 16px;
  border: 1px solid #bcdcca;
  border-radius: 8px;
  padding: 12px;
  background: #f2fbf5;
  color: #173d29;
}

.result.error {
  border-color: #ecc2bd;
  background: #fff7f6;
  color: #74201a;
}

.state-panel {
  outline: none;
}

.state-mark {
  width: 54px;
  height: 54px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  color: #fff;
  font-weight: 850;
  letter-spacing: 0;
}

.state-mark.good {
  background: var(--good);
}

.state-mark.bad {
  background: var(--bad);
}

.state-lead {
  margin: 14px 0 18px;
  color: #283946;
  font-size: 17px;
  line-height: 1.5;
}

.state-note {
  margin: 16px 0 0;
  color: var(--muted);
  line-height: 1.55;
}

.receipt-list {
  margin: 0;
  border: 1px solid var(--line);
  border-radius: 8px;
  overflow: hidden;
}

.receipt-list div {
  display: grid;
  grid-template-columns: minmax(120px, 160px) minmax(0, 1fr);
  border-top: 1px solid var(--line);
}

.receipt-list div:first-child {
  border-top: 0;
}

.receipt-list dt,
.receipt-list dd {
  margin: 0;
  padding: 12px 14px;
}

.receipt-list dt {
  background: #f5f8fa;
  color: var(--muted);
  font-size: 13px;
  font-weight: 800;
}

.receipt-list dd {
  min-width: 0;
  overflow-wrap: anywhere;
  font-weight: 750;
}

/* CD-36: 완료보고 등록 확인 모달. 접수 완료 화면(.state-mark · .receipt-list)과 같은 모양이다. */
.completion-done {
  width: min(480px, calc(100vw - 32px));
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 24px;
  color: #23343f;
}

.completion-done::backdrop {
  background: rgba(23, 36, 45, 0.45);
}

.completion-done h2 {
  margin: 14px 0 16px;
  font-size: 18px;
}

.completion-done-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 18px;
}

.compact-list div {
  grid-template-columns: minmax(100px, 130px) minmax(0, 1fr);
}

canvas {
  width: 100%;
  height: 180px;
  border: 1px solid #c6d2da;
  border-radius: 8px;
  background: #fff;
  touch-action: none;
}

.app-shell {
  min-height: 100vh;
  display: grid;
  grid-template-rows: auto 1fr;
}

.topbar {
  min-height: 72px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 0 28px;
  background: #0e2733;
  color: #f8fcff;
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.12), 0 8px 24px rgba(10, 27, 37, 0.14);
}

.topbar-actions {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  gap: 12px;
  min-width: max-content;
}

.topbar-actions:empty {
  display: none;
}

.brand {
  display: flex;
  flex: 1 1 auto;
  align-items: center;
  gap: 11px;
  min-width: 0;
  margin-right: auto;
}

.brand-mark {
  width: 40px;
  height: 40px;
  display: grid;
  place-items: center;
  border-radius: 6px;
  background: #0b84c6;
  font-weight: 850;
  flex: 0 0 auto;
}

.brand strong {
  display: block;
  color: #fff;
  font-size: 17px;
  line-height: 1.12;
  letter-spacing: 0;
}

.brand small {
  display: block;
  margin-top: 3px;
  color: #c7d8e3;
  font-size: 13px;
  font-weight: 650;
}

.topbar nav {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  gap: 6px;
  min-width: max-content;
}

.menu-toggle {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-width: 96px;
  min-height: 44px;
  border: 1px solid rgba(216, 231, 239, 0.64);
  border-radius: 6px;
  padding: 0 16px;
  background: rgba(255, 255, 255, 0.16);
  color: #fff;
  font-size: 15px;
  font-weight: 850;
  line-height: 1;
  white-space: nowrap;
  touch-action: manipulation;
}

.menu-toggle:hover,
.menu-toggle:focus-visible,
.topbar a:hover,
.topbar a:focus-visible {
  border-color: rgba(255, 255, 255, 0.72);
  background: rgba(255, 255, 255, 0.2);
  outline: none;
}

.menu-toggle-icon {
  display: grid;
  width: 18px;
  height: 18px;
  place-items: center;
  font-size: 16px;
  line-height: 1;
}

.menu-toggle-label {
  line-height: 1;
}

.topbar a {
  display: grid;
  min-height: 42px;
  place-items: center;
  border: 1px solid rgba(216, 231, 239, 0.18);
  border-radius: 6px;
  padding: 0 12px;
  color: #f2fbff;
  font-size: 15px;
  font-weight: 850;
  line-height: 1;
  text-decoration: none;
  white-space: nowrap;
}

.desk-page {
  width: min(1440px, calc(100% - 28px));
  margin: 0 auto;
  padding: 20px 0 42px;
}

.desk-layout {
  display: grid;
  grid-template-columns: 236px minmax(0, 1fr);
  gap: 18px;
  align-items: start;
}

.desk-layout.sidebar-collapsed {
  grid-template-columns: minmax(0, 1fr);
}

.desk-layout.sidebar-collapsed .desk-sidebar {
  display: none;
}

.desk-sidebar {
  position: sticky;
  top: 16px;
  display: grid;
  gap: 14px;
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 14px;
  background: #fff;
  box-shadow: 0 14px 34px rgba(26, 43, 54, 0.07);
}

.sidebar-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.sidebar-head strong {
  color: #1d2d38;
  font-size: 14px;
  font-weight: 800;
  line-height: 1.3;
}

.sidebar-head .icon-btn {
  display: none;
}

.sidebar-backdrop {
  display: none;
}

.desk-main {
  min-width: 0;
}

.sidebar-group {
  display: grid;
  gap: 5px;
  border-bottom: 1px solid #e5edf2;
  padding-bottom: 12px;
}

.sidebar-group:last-child {
  border-bottom: 0;
  padding-bottom: 0;
}

.sidebar-group h2 {
  margin: 0 0 4px;
  color: #637584;
  font-size: 11.5px;
  font-weight: 750;
  letter-spacing: 0;
  line-height: 1.25;
}

.sidebar-group button {
  min-height: 42px;
  border: 1px solid transparent;
  border-radius: 6px;
  padding: 9px 12px;
  background: transparent;
  color: #182b37;
  font-size: 14px;
  font-weight: 750;
  text-align: left;
  line-height: 1.35;
  letter-spacing: 0;
  touch-action: manipulation;
}

.sidebar-group button:hover {
  background: #edf4f8;
  border-color: #d4e2ea;
}

.sidebar-group button.active {
  border-color: #0874ad;
  background: #0877b3;
  color: #fff;
  font-weight: 800;
  box-shadow: inset 4px 0 0 rgba(255, 255, 255, 0.62);
}

.summary-strip {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 10px;
  margin-bottom: 14px;
}

/* CD-02: 접기/펼치기는 이제 전 폭에서 동작한다. 규칙이 @media (max-width: 980px)
   안에만 있던 탓에 데스크톱에서는 토글 버튼 자체가 display:none 이었고, 그래서
   "조회조건이 항상 펼쳐져 있다"는 요구가 나왔다. JS(toggleMobilePanel)는 원래부터
   폭에 무관한 클래스 토글이라 손대지 않았다. 클래스명의 mobile- 접두어는 남겨
   두었다 — html·css·계약테스트·스모크 9곳을 동시에 고칠 만큼의 이득이 없다. */
.mobile-collapse {
  overflow: hidden;
  margin-bottom: 14px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #fff;
}

.mobile-collapse-toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  width: 100%;
  min-height: 46px;
  border: 0;
  padding: 10px 12px;
  background: #fff;
  color: var(--ink);
  font-weight: 850;
  text-align: left;
  touch-action: manipulation;
}

.mobile-collapse-toggle strong {
  min-width: 0;
  overflow: hidden;
  color: var(--muted);
  font-size: 12px;
  font-weight: 750;
  text-align: right;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.mobile-collapse-toggle::after {
  content: "열기";
  flex: 0 0 auto;
  color: var(--brand);
  font-size: 12px;
}

.mobile-collapse:not(.mobile-collapsed) .mobile-collapse-toggle::after {
  content: "접기";
}

.mobile-collapse-body {
  display: block;
  padding: 10px;
  border-top: 1px solid #e5edf2;
}

/* .mobile-collapsed 가 .mobile-collapse-body 보다 특정도가 높아 위 display:block 을 이긴다. */
.mobile-collapsed .mobile-collapse-body {
  display: none;
}

.summary-cell {
  min-height: 74px;
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 12px;
  background: #fff;
  text-align: left;
}

.summary-cell strong {
  display: block;
  margin-bottom: 6px;
  font-size: 22px;
}

.summary-cell span {
  color: var(--muted);
  font-size: 13px;
}

.desk-toolbar {
  display: grid;
  grid-template-columns: minmax(240px, 1fr) 180px auto auto auto;
  align-items: center;
  gap: 10px;
  margin-bottom: 14px;
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 12px;
  background: #fff;
}

/* 275_: 검색창을 늘리려는 규칙이지 체크박스까지 늘리려는 규칙이 아니다.
   element+class 라 전역 체크박스 리셋과 특정도가 같고 뒤에 있어 이겨 버린다. */
.desk-toolbar input:not([type="checkbox"]):not([type="radio"]) {
  width: 100%;
}

.desk-toolbar select {
  max-width: 180px;
}

.request-advanced-filters {
  margin: -4px 0 14px;
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 12px;
  background: #fff;
}

.request-filter-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 10px;
  align-items: end;
}

.request-filter-grid label {
  display: grid;
  gap: 6px;
  min-width: 0;
  color: #435866;
  font-size: 12px;
  font-weight: 800;
}

/* 275_: 위와 같은 이유로 체크박스·라디오는 뺀다. */
.request-filter-grid input:not([type="checkbox"]):not([type="radio"]),
.request-filter-grid select {
  width: 100%;
  min-width: 0;
}

.request-filter-reset {
  min-height: 42px;
}

.toast-host {
  position: fixed;
  right: 18px;
  bottom: 18px;
  z-index: 90;
  display: grid;
  gap: 8px;
  width: min(360px, calc(100vw - 32px));
  pointer-events: none;
}

.toast {
  border: 1px solid #bcdcca;
  border-radius: 8px;
  padding: 14px 16px;
  background: #f2fbf5;
  color: #173d29;
  box-shadow: 0 18px 50px rgba(19, 38, 48, 0.18);
  font-weight: 800;
  opacity: 0;
  pointer-events: auto;
  transform: translateY(10px);
  transition: opacity 160ms ease, transform 160ms ease;
}

.toast.visible {
  animation: toastSlideIn 180ms ease;
  opacity: 1;
  transform: translateY(0);
}

.toast.error {
  border-color: #ecc2bd;
  background: #fff7f6;
  color: #74201a;
}

@keyframes toastSlideIn {
  from {
    opacity: 0;
    transform: translateY(10px);
  }

  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.segmented {
  display: inline-flex;
  overflow: hidden;
  border: 1px solid #b8c6d0;
  border-radius: 6px;
  background: #fff;
}

.segmented button {
  border: 0;
  border-radius: 0;
  background: transparent;
  color: #455764;
}

.segmented button.active {
  background: var(--brand);
  color: #fff;
}

.workspace {
  display: grid;
  gap: 14px;
}

.notice {
  display: grid;
  gap: 4px;
  margin-bottom: 12px;
  border: 1px solid #d3dde4;
  border-radius: 8px;
  padding: 12px 14px;
  background: #fff;
  color: #23343f;
  line-height: 1.42;
}

.notice strong {
  display: block;
  font-size: 14px;
  font-weight: 900;
}

.notice span {
  color: #455c6b;
  font-size: 13px;
  font-weight: 650;
}

.notice.error {
  border-color: #edc5bf;
  background: #fff8f6;
  color: #721e17;
}

.notice.error span {
  color: #79322b;
}

.notice.warn {
  border-color: #f0d9a8;
  background: #fff4df;
  color: #7a4a00;
}

.notice.warn span {
  color: #965c00;
}

/* CD-45: 메뉴 진입 재조회 중 한 줄. 옛 목록은 그대로 두므로 자리를 크게 차지하지 않는다. */
.list-reloading {
  margin: 0 0 8px;
  color: #455c6b;
  font-size: 13px;
  font-weight: 650;
}

/* 레인 수는 표시 정책에 따라 달라진다(78_: 승인대기·반려 숨김, 보류·취소 추가).
   고정 7열이면 빈 칸이 생기거나 잘리므로 항목 수에 맞춰 열을 만든다. */
.board {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(190px, 1fr);
  gap: 10px;
  overflow-x: auto;
}

.lane {
  min-height: 360px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #f8fafb;
}

.lane header,
.master-card header,
.qa-card header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  min-height: 44px;
  padding: 0 12px;
  border-bottom: 1px solid var(--line);
}

.dropzone {
  display: grid;
  gap: 8px;
  align-content: start;
  min-height: 300px;
  padding: 10px;
}

.work-card {
  display: grid;
  gap: 5px;
  border: 1px solid #dfe7ec;
  border-radius: 8px;
  padding: 11px;
  background: #fff;
  color: var(--ink);
  text-align: left;
}

.work-card:hover,
.work-card.selected {
  border-color: var(--brand);
  box-shadow: 0 0 0 3px rgba(0, 103, 166, 0.12);
}

.work-card span {
  color: var(--brand);
  font-family: "SFMono-Regular", Consolas, monospace;
  font-size: 12px;
  font-weight: 800;
  overflow-wrap: anywhere;
}

.work-card small {
  color: var(--muted);
  overflow-wrap: anywhere;
}

/* 252_ FU8: completion cards (CP.../CS... request numbers) are long,
   unbreakable codes that overran the fixed-width list card. */
.work-card strong {
  overflow-wrap: anywhere;
}

.badge {
  display: inline-flex;
  align-items: center;
  width: fit-content;
  min-height: 24px;
  border-radius: 999px;
  padding: 2px 9px;
  background: #e9eef2;
  color: #304451;
  font-size: 12px;
  font-weight: 800;
}

.badge.submitted,
.badge.assigned,
.badge.reported,
.badge.pending,
.badge.queued {
  background: #e8f1fb;
  color: #0b5d9c;
}

.badge.in-progress,
.badge.pending-approval,
.badge.confirmation-created,
.badge.blocked {
  background: #fff4df;
  color: var(--warn);
}

.badge.approved,
.badge.solution-provided,
.badge.closed,
.badge.confirmed,
.badge.active,
.badge.pass,
.badge.clean,
.badge.sent,
.badge.sent-mock {
  background: #e7f4ed;
  color: var(--good);
}

.badge.rejected,
.badge.inactive,
.badge.fail,
.badge.failed {
  background: #fae8e6;
  color: var(--bad);
}

.detail-panel {
  padding: 18px;
}

.detail-head {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  padding-bottom: 16px;
  border-bottom: 1px solid var(--line);
}

.detail-head p {
  margin-bottom: 0;
  color: var(--muted);
}

.detail-grid,
.action-grid,
.object-strip {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 10px;
  margin: 16px 0;
}

/* 272_ I: the completion-report modal is min(760px, 100%) wide, so four fixed
   columns leave ~151px of text per cell — emails and document numbers break
   character by character (252_ FU8's overflow-wrap only muted that symptom).
   Sizing the columns to the content gives three cells in the 760px modal and
   fewer as it narrows; the cap never exceeds the previous four at this width. */
.object-strip {
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}

/* F3: the customer signature renders as an image instead of its docUuid. */
.signature-preview-box {
  border: 1px solid #e0e7ec;
  border-radius: 8px;
  padding: 10px;
  background: #fff;
}

.signature-preview {
  display: block;
  max-width: 320px;
  max-height: 160px;
  background: #fff;
}

.action-grid {
  grid-template-columns: repeat(5, minmax(0, 1fr));
  align-items: end;
}

/* Round B: the assignment fields and the S/4 actions used to share one rigid
   5-column grid, so a sixth control wrapped alone onto the next line. They are
   now two purpose-built rows. */
.assign-row {
  display: flex;
  flex-wrap: wrap;
  align-items: end;
  gap: 12px;
  margin: 16px 0 10px;
}

.assign-row label {
  display: grid;
  gap: 5px;
  min-width: 200px;
  font-size: 12px;
  color: var(--muted);
}

/* 담당자 멀티(No.24·39). 칩 목록 + [+ 담당자 추가] 한 줄이고, 대표는 배지로 구분한다
   — 순서만으로 대표를 알리면 정렬이 바뀌는 순간 뜻이 사라진다. */
/* 라벨 한 줄 + 컨트롤 한 줄. 형제인 「처리단계」와 같은 두 줄 구조라야 assign-row 의
   align-items:end 에서 baseline 이 맞는다 — 칩을 세로로 쌓으면 옆 필드가 밀린다. */
.assign-row .assignee-field {
  display: grid;
  gap: 5px;
  min-width: 260px;
  font-size: 12px;
  color: var(--muted);
}

.assignee-control {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  min-height: 34px;
}

.assignee-control select {
  min-width: 150px;
}

.assignee-chips {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
}

.assignee-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 6px 4px 10px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--panel);
  color: var(--ink);
  font-size: 13px;
}

.assignee-chip.representative {
  border-color: var(--brand);
}

.assignee-chip-badge {
  padding: 1px 6px;
  border-radius: 999px;
  background: var(--brand);
  color: #fff;
  font-size: 11px;
}

.assignee-chip-remove {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--muted);
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
}

.assignee-chip-remove:hover,
.assignee-chip-remove:focus-visible {
  background: var(--page);
  color: var(--bad);
}

.assignee-chip-empty {
  color: var(--muted);
  font-size: 13px;
}

.action-toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 18px;
  margin: 0 0 16px;
}

.action-group {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #fbfcfd;
}

.action-group-label {
  font-size: 12px;
  font-weight: 750;
  color: var(--muted);
  letter-spacing: 0.02em;
}

.request-list-tools {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 8px 14px;
}

.request-check-cell {
  text-align: center;
  padding: 0;
}

/* 기본 .dialog-form 은 2열 그리드라 표가 반 폭으로 접힌다 — 통합 조회는 한 열이다. */
/* .modal-panel 의 760px 는 이 파일 뒤쪽에 있다 — 클래스 하나로는 못 이긴다. */
.modal-panel.rollup-panel {
  width: min(1180px, 100%);
}

.rollup-panel .dialog-form {
  grid-template-columns: 1fr;
}

.rollup-panel .button-row {
  justify-content: space-between;
  align-items: center;
  margin-top: 0;
}

.rollup-table tr[data-group-parity="0"] {
  background: var(--rollup-group-a);
}

.rollup-table tr[data-group-parity="1"] {
  background: var(--rollup-group-b);
}

.rollup-table .rollup-group-head td {
  border-top: 2px solid var(--line);
  font-weight: 700;
  color: var(--ink);
}

.rollup-table tr[data-rollup-empty] td {
  color: var(--muted);
}

/* CD-04 요청 상세 탭. 좁은 화면에서는 줄바꿈이 아니라 가로 스크롤이다 — 탭이
   두 줄로 접히면 그 아래 패널의 시작 위치가 탭마다 달라진다. */
.detail-tabs {
  display: flex;
  gap: 4px;
  overflow-x: auto;
  margin: 0 0 16px;
  padding-bottom: 1px;
  border-bottom: 1px solid var(--line);
  scrollbar-width: thin;
}

.detail-tab {
  flex: 0 0 auto;
  padding: 9px 16px;
  border: 1px solid transparent;
  border-bottom: none;
  border-radius: 8px 8px 0 0;
  background: none;
  font: inherit;
  font-size: 13px;
  font-weight: 650;
  color: var(--muted);
  cursor: pointer;
}

.detail-tab:hover {
  color: var(--ink);
  background: #f4f8fa;
}

.detail-tab.active {
  margin-bottom: -1px;
  border-color: var(--line);
  background: var(--panel);
  color: var(--brand-strong);
}

.detail-tab:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: -2px;
}

.recon-strip {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin: -6px 0 16px;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-left: 4px solid var(--muted);
  border-radius: 8px;
  background: #fbfcfd;
  font-size: 13px;
}

.recon-strip[data-state="ok"] {
  border-left-color: var(--good);
}

.recon-strip[data-state="warn"] {
  border-left-color: var(--warn);
}

/* The address is the longest field on the detail head, so it gets its own row
   instead of being squeezed into a quarter-width cell. */
.detail-wide {
  grid-column: 1 / -1;
}

/* 요청관리 화면은 정보 밀도가 높아 본문 글자를 한 단계 줄인다. */
#requestsView {
  font-size: 13px;
}

#requestsView .detail-grid strong,
#requestsView .object-strip strong {
  font-size: 13px;
}

#requestsView h2 {
  font-size: 20px;
}

#requestsView h3 {
  font-size: 15px;
}

#requestsView label,
#requestsView input,
#requestsView select {
  font-size: 13px;
}

/* 요청 목록을 표처럼 읽히게: 행 구분선·머리글 고정·교차 배경·행 강조. */
.request-table-wide thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: #eef3f6;
  border-bottom: 2px solid var(--line);
  font-size: 12px;
}

.request-table-wide tbody tr {
  border-bottom: 1px solid var(--line);
}

.request-table-wide tbody tr:nth-child(even) {
  background: #f7fafc;
}

.request-table-wide tbody tr:hover {
  background: #e8f2fb;
  cursor: pointer;
}

.request-table-wide td,
.request-table-wide th {
  border-right: 1px solid #eef2f5;
}

.request-table-wide td:last-child,
.request-table-wide th:last-child {
  border-right: 0;
}

/* Logged-in user in the top bar. The wrapper anchors the drop-down menu. */
.topbar-user {
  position: relative;
  color: #fff;
}

/* 칩은 아바타+이름만 — 디테일은 드롭다운에서 (통일 규격 2026-08-28). */
.topbar-user-chip {
  display: grid;
  grid-template-columns: 28px auto;
  align-items: center;
  gap: 8px;
  line-height: 1.25;
  padding: 4px 8px;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: inherit;
  cursor: pointer;
  font: inherit;
}

.topbar-user-avatar {
  width: 28px;
  aspect-ratio: 1;
  display: grid;
  place-items: center;
  color: #fff;
  background: #0877b3;
  border-radius: 50%;
  font-size: 12px;
  font-weight: 800;
}

.topbar-user-chip:hover,
.topbar-user-chip:focus-visible {
  background: rgba(255, 255, 255, 0.14);
}

.topbar-user-menu {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 40;
  display: grid;
  gap: 4px;
  justify-items: start;
  min-width: 200px;
  padding: 12px;
  border: 1px solid #d7dee8;
  border-radius: 8px;
  background: #fff;
  color: #1b2733;
  box-shadow: 0 8px 20px rgba(16, 32, 51, 0.18);
}

.topbar-user-menu > small {
  opacity: 0.75;
  word-break: break-all;
}

.topbar-user-menu > button {
  margin-top: 6px;
}

.topbar-user-name {
  font-weight: 750;
  font-size: 13px;
}

.topbar-user-role {
  font-size: 11px;
  opacity: 0.75;
}

/* Line-item cell that carries a value help button next to its input. */
.line-cell-vh {
  display: flex;
  gap: 6px;
  align-items: center;
}

.line-cell-vh input {
  flex: 1 1 auto;
  min-width: 0;
}

.line-cell-vh button {
  flex: 0 0 auto;
  min-height: 32px;
  padding: 0 10px;
  font-size: 12px;
}

/* C-13(G2): 라인 그리드는 요약 읽기전용이고 입력은 팝업에서 받는다.
   전용 wrap을 두는 이유 — .request-table-wrap은 @media(max-width:760px)에서
   overflow:visible로 덮이므로 12컬럼 표가 모바일에서 잘린다. */
.line-table-wrap {
  overflow-x: auto;
}

/* max-width와 overflow:hidden이 함께 있어야 ellipsis가 발동한다. */
.line-cell-text {
  display: inline-block;
  max-width: 220px;
  overflow: hidden;
  text-overflow: ellipsis;
  vertical-align: bottom;
}

/* CD-08: [확인]=저장. 방금 저장된 행을 잠시 밝혀 갱신된 목록에서 결과를 좇게 한다. */
.line-row-saved td {
  background: #f0f9f1;
  transition: background 0.6s ease;
}

.line-row-saved td:first-child {
  box-shadow: inset 3px 0 0 #2f9e44;
}

.line-row-actions {
  width: 1%;
  white-space: nowrap;
}

/* Value help dialog: the search row was a 2-column form grid, which stretched
   the button to the full row height. It is an inline search bar now. */
.value-help-body {
  display: grid;
  gap: 14px;
  padding: 18px;
}

.value-help-search {
  display: flex;
  gap: 10px;
}

.value-help-search input {
  flex: 1 1 auto;
  min-width: 0;
}

.value-help-search button {
  flex: 0 0 auto;
  min-width: 96px;
}

.value-help-count {
  margin: 0;
  font-size: 12px;
  color: var(--muted);
}

.value-help-result {
  min-height: 120px;
  max-height: 46vh;
  overflow: auto;
}

.value-help-options {
  display: grid;
  gap: 6px;
  margin: 8px 0 0;
  padding: 0;
  list-style: none;
}

.value-help-options button {
  display: grid;
  grid-template-columns: minmax(120px, 240px) minmax(0, 1fr);
  gap: 12px;
  width: 100%;
  min-height: 40px;
  padding: 8px 12px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: #fff;
  text-align: left;
  font-size: 13px;
  cursor: pointer;
}

.value-help-options button:hover {
  border-color: var(--brand);
  background: #f4f9fd;
}

/* CD-07: six columns do not fit the code+name list, so the equipment value help
   opens as a grid. Only dialogs that pass `columns` reach these rules. */
.value-help-grid-wrap {
  margin-top: 8px;
  overflow: auto;
}

.value-help-grid {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}

.value-help-grid th,
.value-help-grid td {
  padding: 6px 8px;
  border-bottom: 1px solid var(--line);
  text-align: left;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.value-help-grid thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: #f7f9fb;
  vertical-align: top;
}

.value-help-grid th .sort-btn {
  display: block;
  width: 100%;
  padding: 0 0 4px;
  border: 0;
  background: none;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
  white-space: nowrap;
}

.value-help-grid th .sort-btn.active {
  color: var(--brand);
}

.value-help-grid th .col-filter {
  width: 100%;
  min-width: 0;
  padding: 3px 6px;
  border: 1px solid var(--line);
  border-radius: 4px;
  font-size: 12px;
  font-weight: 400;
}

.value-help-grid th .col-filter:focus {
  border-color: var(--brand);
  outline: none;
}

.value-help-grid tbody tr {
  cursor: pointer;
}

.value-help-grid tbody tr:hover,
.value-help-grid tbody tr:focus {
  background: #f4f9fd;
  outline: none;
}

.detail-grid div,
.object-strip div {
  display: grid;
  gap: 5px;
  border: 1px solid #e1e8ed;
  border-radius: 8px;
  padding: 10px;
  background: #fbfcfd;
  min-width: 0;
}

.detail-grid span,
.object-strip span {
  color: var(--muted);
  font-size: 12px;
}

/* 252_ FU8: completion report modal packs 4 columns of long, unbreakable
   codes (완료보고번호/접수번호) and email addresses into a narrow grid item.
   Without this, grid's default min-width:auto blows the column out instead
   of letting the value wrap. */
.detail-grid strong,
.object-strip strong {
  overflow-wrap: anywhere;
}

.two-column {
  display: grid;
  grid-template-columns: 320px minmax(0, 1fr);
  gap: 14px;
}

.request-shell {
  grid-template-columns: 340px minmax(0, 1fr);
}

.request-list {
  max-height: calc(100vh - 280px);
  overflow: auto;
}

.request-list-workspace,
.request-detail-workspace {
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #fff;
  box-shadow: 0 14px 34px rgba(26, 43, 54, 0.06);
}

.request-list-workspace {
  gap: 0;
}

.request-list-head,
.request-detail-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 18px;
  padding: 16px 18px;
  border-bottom: 1px solid var(--line);
  background: #fff;
}

.request-list-head h2 {
  margin: 2px 0 4px;
  font-size: 21px;
}

.request-list-head p {
  margin: 0;
  color: var(--muted);
  font-size: 13px;
}

.request-list-head .eyebrow {
  color: var(--brand);
  font-family: "SFMono-Regular", Consolas, monospace;
  font-size: 11px;
  font-weight: 850;
  letter-spacing: 0.08em;
}

.request-result-count {
  flex: 0 0 auto;
  border: 1px solid #cfe0ea;
  border-radius: 999px;
  padding: 7px 11px;
  background: #f1f7fa;
  color: #264b60;
  font-size: 12px;
  white-space: nowrap;
}

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

.request-table {
  min-width: 1080px;
}

/* Round L2 (131_): fixed layout is what makes a dragged width stick. Under the
   default auto layout a <col> width is only a hint, so a long cell quietly
   overrides it and the drag reads as broken. */
.request-table-wide {
  table-layout: fixed;
}

/* Fixed columns clip. Say so with an ellipsis and put the whole value in the
   title, or a truncated address just looks like missing data. */
.request-table-wide tbody td {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.request-table-wide thead th {
  position: relative;
}

/* Label on one line, filter on the next. Both have to be block: left inline,
   the box sits beside the column name and squeezes it. */
.request-table-wide thead th .sort-btn {
  display: block;
  width: 100%;
  text-align: left;
}

.request-table-wide .col-filter {
  display: block;
  width: 100%;
  margin-top: 4px;
  padding: 2px 4px;
  border: 1px solid var(--line);
  border-radius: 3px;
  font-size: 11px;
  font-weight: 400;
  background: #fff;
}

.request-table-wide .col-filter:focus {
  outline: 2px solid var(--brand, #2f6f9f);
  outline-offset: -1px;
}

.request-table-wide .col-resize {
  position: absolute;
  top: 0;
  right: -3px;
  width: 6px;
  height: 100%;
  cursor: col-resize;
  touch-action: none; /* pointermove needs to win over scrolling */
  z-index: 2;
}

.request-table-wide .col-resize:hover {
  background: var(--brand, #2f6f9f);
  opacity: 0.35;
}

.request-table th {
  position: sticky;
  top: 0;
  z-index: 1;
  padding: 11px 12px;
  background: #f3f7f9;
  color: #536976;
  letter-spacing: 0.02em;
}

.request-table td {
  padding: 12px;
  vertical-align: middle;
}

.request-table tbody tr[data-request] {
  cursor: pointer;
  transition: background 120ms ease, box-shadow 120ms ease;
}

.request-table tbody tr[data-request]:hover {
  background: #f3f9fc;
}

.request-table tbody tr[data-request]:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: -2px;
  background: #eef7fb;
}

.request-table-wide {
  min-width: 1720px;
}

.request-table th .sort-btn {
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: inherit;
  letter-spacing: inherit;
  cursor: pointer;
  white-space: nowrap;
}

.request-table th .sort-btn.active {
  color: var(--brand);
}

.request-pager {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 12px;
  color: var(--muted);
}

.request-pager .pager-controls {
  display: flex;
  align-items: center;
  gap: 8px;
}

.request-pager .pager-controls button[disabled] {
  opacity: 0.4;
  cursor: default;
}

.request-pager .pager-size {
  display: flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
}

.request-table td strong,
.request-table td small {
  display: block;
}

.request-table td small {
  max-width: 190px;
  margin-top: 3px;
  overflow: hidden;
  color: var(--muted);
  text-overflow: ellipsis;
}

.request-number {
  color: var(--brand);
  font-family: "SFMono-Regular", Consolas, monospace;
  font-size: 12px;
  font-weight: 850;
}

.request-email {
  display: block;
  max-width: 210px;
  overflow: hidden;
  text-overflow: ellipsis;
}

.request-empty td {
  padding: 34px 18px;
  color: var(--muted);
  text-align: center;
}

.request-detail-workspace {
  padding: 0 18px 18px;
}

.request-detail-toolbar {
  position: sticky;
  top: 0;
  z-index: 8;
  margin: 0 -18px 18px;
  background: rgba(255, 255, 255, 0.96);
  backdrop-filter: blur(8px);
}

.request-detail-toolbar div {
  display: flex;
  align-items: baseline;
  gap: 9px;
  min-width: 0;
}

.request-detail-toolbar span {
  color: var(--muted);
  font-size: 12px;
}

.request-detail-toolbar strong {
  overflow: hidden;
  color: var(--brand);
  font-family: "SFMono-Regular", Consolas, monospace;
  font-size: 13px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.workflow-panel,
.work-detail-panel,
.email-log-panel,
.comment-panel,
.worklog-panel,
.solution-panel,
.template-editor-panel {
  display: grid;
  gap: 12px;
  margin: 16px 0;
  border: 1px solid #e1e8ed;
  border-radius: 8px;
  padding: 14px;
  background: #fbfcfd;
}

.workflow-panel header,
.section-head,
.template-preview header,
.timeline-item header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.workflow-panel h3,
.work-detail-panel h3,
.email-log-panel h3,
.comment-panel h3,
.worklog-panel h3 {
  margin-bottom: 0;
}

.worklog-downloads summary {
  cursor: pointer;
  color: var(--muted);
  font-size: 13px;
  padding: 6px 0;
}

.worklog-downloads[open] summary {
  margin-bottom: 4px;
}

.compact-head p {
  margin-bottom: 0;
  color: var(--muted);
  font-size: 12px;
}

.work-detail-form {
  display: grid;
  gap: 12px;
}

/* F8: 검색 버튼은 별줄이 아니라 입력칸 옆에 붙는다(.line-cell-vh). 라벨 행 수가
   칸마다 같아졌으므로 3행 격자 고정은 제거하고 상단 정렬만 유지한다. */
.work-detail-form .field-grid > label {
  align-content: start;
}

/* F8: 값도움에서 고른 명칭 병기 — 저장 필드는 코드뿐이라 표시 전용이다. */
.vh-picked-name {
  min-height: 1em;
  color: #4c5f6b;
  font-size: 12px;
}

.field-hint {
  color: #4c5f6b;
  font-size: 11px;
}

/* F-23: label 은 grid 컨테이너라 텍스트 노드와 <abbr> 이 각자 별도 grid item 이 되어
   줄바꿈된다(다음 행으로 밀림). 캡션+마커를 하나의 span(=하나의 grid item)으로 묶어
   한 줄에 붙인다. */
.field-label-text {
  display: inline-flex;
  align-items: baseline;
}

.required-so {
  text-decoration: none;
  border-bottom: 0;
  margin-left: 0.25rem;
  color: var(--bad);
  font-weight: 600;
  cursor: help;
}

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

.flow-rail {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(90px, 1fr);
  gap: 8px;
  overflow-x: auto;
}

/* 보류·취소는 진행 축이 아니라 분기라 레일 위에 별도로 알린다(78_). */
.flow-branch {
  margin-bottom: 10px;
  border-left: 3px solid #b8862b;
  border-radius: 4px;
  background: #fdf6e6;
  padding: 8px 10px;
  color: #6b4e12;
  font-size: 13px;
}

.flow-branch[data-status="CANCELLED"] {
  border-left-color: #9aa3ab;
  background: #f2f4f6;
  color: #4b555d;
}

.flow-step {
  display: grid;
  gap: 6px;
  align-content: start;
  min-height: 76px;
  border: 1px solid #e0e7ec;
  border-radius: 8px;
  padding: 10px;
  background: #fff;
}

.flow-step-number {
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border-radius: 999px;
  background: #e9eef2;
  color: #40515d;
  font-size: 12px;
  font-weight: 850;
}

.flow-rail .done .flow-step-number {
  background: var(--brand);
  color: #fff;
}

.flow-rail .current {
  border-color: var(--brand);
  box-shadow: 0 0 0 3px rgba(0, 103, 166, 0.12);
}

.stage-history {
  display: grid;
  gap: 6px;
  margin-top: 4px;
  padding-top: 7px;
  border-top: 1px solid #edf2f5;
}

.stage-history.empty {
  color: var(--muted);
  font-size: 11px;
}

.stage-history-item {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 6px;
  align-items: start;
  min-width: 0;
}

.stage-history-dot {
  width: 6px;
  height: 6px;
  margin-top: 5px;
  border-radius: 999px;
  background: var(--brand);
}

.stage-history-item div {
  display: grid;
  gap: 2px;
  min-width: 0;
}

.stage-history-item strong,
.stage-history-item span {
  min-width: 0;
  overflow: hidden;
  font-size: 11px;
  line-height: 1.35;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.stage-history-item strong {
  color: var(--ink);
  font-weight: 800;
}

.stage-history-item span {
  color: var(--muted);
}

.stage-history-actor {
  color: #516675;
  font-weight: 800;
}

.dashboard-panel {
  display: grid;
  gap: 14px;
}

.dashboard-head {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 14px;
  background: #fff;
}

.dashboard-head p {
  margin-bottom: 0;
  color: var(--muted);
}

.inline-check {
  display: inline-flex;
  align-items: center;
  width: fit-content;
  gap: 8px;
  font-weight: 700;
}

.inline-check input,
/* 252_ FU11-a: 라인 그리드 행 체크박스가 기본 input 크기(42px 정사각형)를 그대로
   물려받아 셀을 거의 채웠다 — 「내 담당만」류 체크박스와 같은 위계로 맞춘다.
   td 자체의 기본 패딩(9px 10px)이 여전히 클릭 여유를 준다. */
[data-line-check-cell] input {
  width: auto;
  min-height: auto;
}

.mine-filter {
  white-space: nowrap;
}

.gantt-panel {
  display: grid;
  gap: 10px;
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 14px;
  background: #fff;
}

.gantt-row {
  display: grid;
  grid-template-columns: 240px minmax(180px, 1fr) 120px;
  gap: 12px;
  align-items: center;
}

.gantt-row div:first-child {
  display: grid;
  gap: 4px;
}

.gantt-row span,
.gantt-row em {
  color: var(--muted);
  font-size: 13px;
  font-style: normal;
}

.gantt-track {
  height: 12px;
  border-radius: 999px;
  background: #e8eef2;
  overflow: hidden;
}

.gantt-track span {
  display: block;
  height: 100%;
  border-radius: inherit;
  background: var(--brand);
}

.analysis-form,
.comment-form,
.template-form {
  display: grid;
  gap: 12px;
}

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

.timeline-item {
  display: grid;
  gap: 8px;
  border: 1px solid #e0e7ec;
  border-radius: 8px;
  padding: 10px;
  background: #fff;
}

.timeline-item.compact p,
.timeline-item p,
.solution-panel p {
  margin-bottom: 0;
  color: var(--muted);
}

.timeline-item header span {
  color: var(--muted);
  font-size: 12px;
}

.email-log-list {
  display: grid;
  gap: 8px;
}

.email-log-row {
  display: grid;
  grid-template-columns: minmax(150px, 0.9fr) minmax(220px, 1.5fr) auto auto;
  gap: 12px;
  align-items: center;
  border: 1px solid #e1e8ed;
  border-radius: 8px;
  padding: 10px;
  background: #fff;
}

.email-log-row > div {
  display: grid;
  gap: 4px;
  min-width: 0;
}

.email-log-row strong,
.email-log-row span,
.email-log-row small {
  min-width: 0;
  overflow-wrap: anywhere;
}

.email-log-row span,
.email-log-row small {
  color: var(--muted);
  font-size: 12px;
}

.email-log-row .error-text {
  color: var(--bad);
}

.email-template-shell,
.email-log-shell {
  display: grid;
  grid-template-columns: 340px minmax(0, 1fr);
  gap: 14px;
}

.email-log-filter {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: none;
  white-space: nowrap;
  color: var(--muted);
  font-size: 13px;
}

.email-log-detail {
  display: grid;
  gap: 14px;
  align-content: start;
}

.mail-body {
  border-top: 1px solid var(--line);
  padding-top: 14px;
}

.mail-body-frame {
  width: 100%;
  min-height: 240px;
  border: 1px solid #c6d2da;
  border-radius: 8px;
  background: #fff;
}

.mail-body-plain {
  margin: 0;
  padding: 12px 14px;
  border: 1px solid #c6d2da;
  border-radius: 8px;
  background: #fff;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 13px;
  line-height: 1.6;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.email-resend {
  display: flex;
  align-items: flex-end;
  gap: 10px;
  flex-wrap: wrap;
  border-top: 1px solid var(--line);
  padding-top: 14px;
}

.email-resend label {
  flex: 1 1 260px;
  display: grid;
  gap: 6px;
  font-size: 13px;
  color: var(--muted);
}

.template-tools {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.template-tools button {
  min-height: 34px;
  border: 1px solid #b4c2cc;
  border-radius: 6px;
  background: #fff;
  color: var(--ink);
  font-weight: 750;
}

.wysiwyg-editor {
  min-height: 220px;
  overflow: auto;
  border: 1px solid #c6d2da;
  border-radius: 6px;
  padding: 12px;
  background: #fff;
  font-weight: 400;
  line-height: 1.5;
}

.comment-tabs {
  display: flex;
  gap: 18px;
  border-bottom: 1px solid var(--line);
  padding-bottom: 8px;
}

.comment-tabs label {
  display: inline-flex;
  align-items: center;
  width: fit-content;
}

.comment-tabs input {
  width: auto;
  min-height: auto;
}

.compact-tools {
  margin-top: 0;
}

.comment-editor:empty::before {
  content: attr(data-placeholder);
  color: var(--muted);
}

.comment-html {
  color: #2a3a45;
  line-height: 1.5;
}

.edited-mark {
  display: inline-grid;
  place-items: center;
  margin-left: 6px;
  border: 1px solid #c8d4dc;
  border-radius: 999px;
  padding: 1px 6px;
  color: var(--muted);
  font-size: 11px;
  font-style: normal;
  font-weight: 750;
}

.comment-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 10px;
}

.comment-actions .link-btn {
  min-height: 32px;
  padding: 0 10px;
  font-size: 13px;
}

.input-action {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 8px;
}

.address-results {
  display: grid;
  gap: 8px;
  max-height: 142px;
  overflow: auto;
}

.kakao-postcode {
  position: relative;
  min-height: 260px;
  height: clamp(260px, 38vh, 360px);
  border: 1px solid var(--line);
  border-radius: 8px;
  overflow: hidden;
  background: #fff;
}

.kakao-postcode[hidden] {
  display: none !important;
}

.kakao-postcode-loading {
  display: grid;
  height: 100%;
  min-height: 260px;
  place-items: center;
  color: var(--muted);
  font-size: 14px;
  font-weight: 750;
}

.address-modal .dialog-form {
  grid-template-columns: 1fr;
  gap: 12px;
}

.address-modal .wide {
  grid-column: 1;
}

.address-assist-panel {
  display: grid;
  gap: 10px;
  border: 1px solid #dce6ec;
  border-radius: 8px;
  padding: 12px;
  background: #f8fbfd;
}

.address-result {
  display: grid;
  gap: 3px;
  min-height: 42px;
  border: 1px solid #dbe4ea;
  border-radius: 8px;
  padding: 10px 12px;
  background: #fff;
  color: var(--ink);
  font-weight: 750;
  line-height: 1.35;
  text-align: left;
}

.address-fallback-actions {
  display: flex;
  justify-content: flex-end;
}

.address-selected-summary {
  display: grid;
  gap: 5px;
  border: 1px solid #b9d5e5;
  border-radius: 8px;
  padding: 11px 12px;
  background: #eef7fc;
  color: var(--ink);
}

.address-selected-summary[hidden] {
  display: none;
}

.address-selected-summary span {
  color: var(--brand);
  font-size: 12px;
  font-weight: 850;
}

.address-selected-summary strong {
  font-size: 16px;
  line-height: 1.35;
  overflow-wrap: anywhere;
}

.address-kakao-retry-btn {
  min-height: 40px;
}

.address-result-kicker {
  color: var(--brand);
  font-size: 12px;
  font-weight: 850;
}

.address-empty {
  border: 1px solid #e1e8ed;
  border-radius: 8px;
  padding: 11px 12px;
  background: #f8fafb;
}

.address-modal-detail {
  display: grid;
  gap: 10px;
  border-top: 1px solid #e1e8ed;
  padding-top: 10px;
}

.address-modal-detail label {
  display: grid;
  gap: 7px;
  color: var(--ink);
  font-size: 14px;
  font-weight: 800;
}

.address-kakao-active .kakao-postcode {
  order: 1;
}

.address-kakao-loading .kakao-postcode {
  background: #f8fbfd;
}

.address-kakao-active .address-assist-panel {
  order: 2;
  background: #f8fbfd;
}

.address-kakao-active .form-actions {
  order: 3;
}

.address-kakao-active #addressFallbackSearch,
.address-kakao-active .address-fallback-actions,
.address-kakao-active .address-results {
  display: none;
}

.address-kakao-active .address-modal-detail {
  border-top: 0;
  padding-top: 0;
}

.address-fallback-only .kakao-postcode {
  display: none;
}

.address-selected-mode .kakao-postcode {
  display: block;
}

.address-selected-mode .address-assist-panel {
  order: 2;
  grid-template-columns: minmax(0, 1fr);
  align-items: stretch;
  background: #f8fbfd;
}

.address-selected-mode .address-selected-summary,
.address-selected-mode .address-modal-detail {
  min-width: 0;
}

.address-selected-mode .address-results,
.address-selected-mode .address-fallback-actions {
  display: none;
}

.address-selected-mode .form-actions {
  order: 3;
}

.wysiwyg-editor:focus {
  border-color: var(--brand);
  box-shadow: 0 0 0 4px rgba(0, 103, 166, 0.18);
  outline: none;
}

.template-preview {
  display: grid;
  gap: 10px;
  border-top: 1px solid var(--line);
  padding-top: 14px;
}

.template-preview span {
  color: var(--muted);
  font-size: 13px;
}

.template-preview iframe {
  width: 100%;
  min-height: 260px;
  border: 1px solid #c6d2da;
  border-radius: 8px;
  background: #fff;
}

.work-card.inactive {
  opacity: 0.64;
}

.list-panel {
  display: grid;
  gap: 8px;
  align-content: start;
}

.master-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
}

.master-card,
.master-shell {
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #fff;
}

.table-scroll {
  overflow: auto;
  max-height: 300px;
}

.master-toolbar {
  display: flex;
  align-items: end;
  justify-content: space-between;
  gap: 14px;
  padding: 14px;
  border-bottom: 1px solid var(--line);
  background: #fff;
}

.master-toolbar label {
  width: min(360px, 100%);
}

.master-actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  justify-content: flex-end;
}

.master-grid-panel {
  overflow: auto;
  max-height: min(58vh, 620px);
}

.master-table tr {
  cursor: pointer;
}

.master-table tbody tr:hover,
.master-table tbody tr.selected {
  background: #eef7fc;
}

.master-table tbody tr.inactive {
  color: #81909a;
  background: #f7f9fa;
}

.master-help {
  margin: 0;
  padding: 12px 14px;
  color: var(--muted);
  border-top: 1px solid var(--line);
  font-size: 13px;
}

.modal-backdrop {
  position: fixed;
  inset: 0;
  z-index: 30;
  display: grid;
  place-items: center;
  padding: 18px;
  background: rgba(13, 31, 42, 0.44);
}

.modal-panel {
  width: min(760px, 100%);
  max-height: min(760px, calc(100vh - 36px));
  overflow: auto;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #fff;
  box-shadow: 0 24px 70px rgba(11, 29, 40, 0.28);
}

.modal-head {
  display: flex;
  justify-content: space-between;
  gap: 18px;
  padding: 18px;
  border-bottom: 1px solid var(--line);
}

/* 252_ FU10-2: 기본 h2(24px)는 대화상자 본문(13~17px) 대비 과했다 — 새 크기값을
   만들지 않고 이 리포가 이미 h3 위계로 쓰는 17px 을 재사용한다. 모든 모달 제목이
   같은 태그를 공유하므로 이 변경은 값도움뿐 아니라 전 대화상자에 일괄 적용된다. */
.modal-head h2 {
  margin: 4px 0 0;
  font-size: 17px;
}

.dialog-form {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
  padding: 18px;
}

.dialog-form .result,
.dialog-form .form-actions {
  grid-column: 1 / -1;
}

/* 2026-09-30: 라인 상세 모달. 전역 label 이 grid 라 같은 행의 짝(작업내용 textarea ·
   힌트 · 검색 버튼 줄)이 더 크면 입력칸이 늘어나 아래로 밀린다(실측 42px -> 54·83px).
   작업상세 폼(.work-detail-form .field-grid > label)과 같은 처방이다. */
.line-item-form > label {
  align-content: start;
}

/* 2026-09-30: 정렬Seq 는 자동 채번(readonly) — 입력칸처럼 보이면 고칠 수 있는 줄 안다. */
.line-item-form input[readonly] {
  background: #f3f6f8;
  color: #4c5f6b;
}

/* CD-37-A3 REQ-37-1: the completion report dialog shows the same document the
   customer page shows, at the same width. 730px is the customer .completion-doc
   (.public-page 780 - .work-form padding 2x24 - border 2); + .dialog-form padding
   2x18 + panel border 2 = 768. The backdrop scrolls instead of the panel, so a
   scrollbar never eats into that width (the width would then vary by platform). */
.completion-report-backdrop {
  overflow-y: auto;
  align-items: start;
}

.modal-panel.completion-report-panel {
  width: min(768px, 100%);
  max-height: none;
  overflow: visible;
}

.completion-report-panel [data-completion-report] {
  display: block;
}

/* A3 E-2: this dialog's footer sits directly in the panel, not inside a padded
   .dialog-form like the other dialogs, so it gets the same 18px here. */
.completion-report-panel > .form-actions {
  padding: 0 18px 18px;
}

.completion-console-facts {
  display: grid;
  gap: 10px;
  margin-top: 22px;
  padding-top: 16px;
  border-top: 1px solid var(--line);
}

.completion-console-facts h3 {
  margin: 0;
  font-size: 15px;
}

table {
  width: 100%;
  border-collapse: collapse;
}

th,
td {
  border-bottom: 1px solid #e5ebef;
  padding: 9px 10px;
  text-align: left;
  white-space: nowrap;
  font-size: 13px;
}

th {
  color: var(--muted);
  background: #f7f9fb;
  font-size: 12px;
  text-transform: uppercase;
}

.qa-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 12px;
}

.qa-head {
  align-items: flex-start;
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 14px 16px;
  background: #fff;
}

.qa-head h2 {
  margin: 0;
  font-size: 20px;
}

.qa-head p {
  margin: 6px 0 0;
  color: var(--muted);
  font-size: 13px;
}

.qa-card {
  padding-bottom: 12px;
}

.qa-card p {
  min-height: 42px;
  margin: 12px;
  color: var(--muted);
  font-size: 13px;
}

.qa-card .button-row {
  justify-content: flex-start;
  margin: 12px;
}

.qa-guide h3 {
  margin: 0;
}

.qa-guide p,
.qa-guide ul {
  margin: 0;
}

.qa-guide ul {
  display: grid;
  gap: 8px;
  padding-left: 18px;
}

.qa-guide li,
.muted-copy {
  color: var(--muted);
  font-size: 13px;
  line-height: 1.5;
}

.qa-guide strong {
  color: var(--ink);
}

@media (max-width: 980px) {
  .topbar {
    height: auto;
    min-height: 58px;
    gap: 8px;
    padding: 8px 10px;
  }

  .topbar-actions {
    gap: 8px;
  }

  .brand {
    min-width: 0;
    gap: 9px;
  }

  .brand-mark {
    width: 34px;
    height: 34px;
    flex: 0 0 auto;
  }

  .brand strong {
    display: block;
    max-width: 174px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 14px;
  }

  .brand small {
    display: none;
  }

  .menu-toggle {
    min-width: 72px;
    min-height: 42px;
    padding: 0 11px;
    font-size: 14px;
  }

  .topbar nav {
    gap: 5px;
  }

  .topbar a {
    min-height: 38px;
    padding: 0 8px;
    font-size: 13px;
  }

  .topbar nav {
    flex: 0 0 auto;
  }

  .desk-page {
    width: min(100% - 16px, 1440px);
    padding: 10px 0 28px;
  }

  .request-filter-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .field-grid,
  .field-grid.compact,
  .detail-grid,
  .object-strip,
  .review-meta,
  .master-grid,
  .dialog-form,
  .qa-grid,
  .two-column,
  .email-template-shell,
  .email-log-shell,
  .request-shell,
  .gantt-row {
    grid-template-columns: 1fr;
  }

  .desk-layout {
    grid-template-columns: 1fr;
  }

  .desk-layout.sidebar-collapsed {
    grid-template-columns: 1fr;
  }

  .desk-layout.sidebar-collapsed .desk-sidebar {
    display: grid;
  }

  .desk-sidebar {
    position: fixed;
    inset: 0 auto 0 0;
    z-index: 70;
    width: min(320px, calc(100vw - 44px));
    max-width: 100%;
    overflow: auto;
    border-radius: 0 8px 8px 0;
    transform: translateX(-110%);
    transition: transform 180ms ease;
  }

  .desk-layout.sidebar-open .desk-sidebar {
    transform: translateX(0);
  }

  .sidebar-head .icon-btn {
    display: grid;
  }

  .sidebar-backdrop {
    position: fixed;
    inset: 0;
    z-index: 60;
    display: none;
    border: 0;
    background: rgba(8, 20, 28, 0.42);
  }

  .desk-layout.sidebar-open .sidebar-backdrop {
    display: block;
  }

  .sidebar-group h2 {
    grid-column: auto;
  }

  /* CD-02: .mobile-collapse* 규칙은 전 폭 공통으로 승격되어 기본 스코프로 옮겼다. */

  .desk-toolbar {
    align-items: stretch;
    margin-bottom: 0;
    border: 0;
    padding: 0;
    grid-template-columns: 1fr;
    box-shadow: none;
  }

  .desk-toolbar select {
    max-width: none;
  }

  .summary-strip {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    margin-bottom: 0;
  }

  .summary-strip.compact-mobile {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 8px;
  }

  .summary-cell {
    min-height: 54px;
    padding: 9px 10px;
  }

  .summary-cell strong {
    margin-bottom: 2px;
    font-size: 18px;
  }

  .summary-cell span {
    font-size: 12px;
  }
}

@media (max-width: 760px) {
  .request-list-head,
  .request-detail-toolbar {
    align-items: flex-start;
  }

  .request-list-head {
    flex-direction: column;
  }

  .request-result-count {
    align-self: flex-start;
  }

  .request-table-wrap {
    overflow: visible;
    padding: 10px;
    background: #eef3f6;
  }

  .request-table,
  .request-table tbody {
    display: block;
    min-width: 0;
  }

  .request-table thead {
    display: none;
  }

  .request-table tbody tr[data-request] {
    display: grid;
    gap: 0;
    margin-bottom: 10px;
    overflow: hidden;
    border: 1px solid #d8e4ea;
    border-radius: 8px;
    background: #fff;
    box-shadow: 0 5px 14px rgba(26, 43, 54, 0.05);
  }

  .request-table tbody tr[data-request]:last-child {
    margin-bottom: 0;
  }

  .request-table td {
    display: grid;
    grid-template-columns: 88px minmax(0, 1fr);
    gap: 10px;
    align-items: start;
    border-bottom: 1px solid #edf1f4;
    padding: 9px 11px;
    white-space: normal;
  }

  .request-table td:last-child {
    border-bottom: 0;
  }

  .request-table td::before {
    content: attr(data-label);
    color: #697d89;
    font-size: 11px;
    font-weight: 800;
  }

  .request-table td small,
  .request-email {
    max-width: none;
    white-space: normal;
    overflow-wrap: anywhere;
  }

  .request-empty {
    display: table-row;
  }

  .request-detail-workspace {
    padding: 0 12px 12px;
  }

  .request-detail-toolbar {
    margin: 0 -12px 14px;
  }
}

@media (max-width: 420px) {
  .brand strong {
    max-width: 92px;
  }

  .topbar-actions {
    gap: 5px;
  }

  .topbar nav {
    gap: 2px;
  }

  .menu-toggle {
    min-width: 42px;
    padding: 0 10px;
  }

  .menu-toggle-label {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
  }

  .topbar a {
    padding: 0 6px;
    font-size: 12.5px;
  }
}

@media (max-width: 640px) {
  .request-filter-grid {
    grid-template-columns: 1fr;
  }

  .toast-host {
    right: 10px;
    bottom: 10px;
    left: 10px;
    width: auto;
  }

  .public-page,
  .intake-page {
    width: min(100% - 20px, 700px);
    padding-top: 14px;
  }

  .work-form {
    padding: 16px;
  }

  .intake-form {
    padding: 0;
  }

  h1 {
    font-size: 28px;
  }

  .phone-row,
  .file-row,
  .file-card,
  .email-log-row,
  .action-grid {
    grid-template-columns: 1fr;
  }

  .file-row,
  .file-card {
    align-items: start;
  }

  .address-search-row {
    grid-template-columns: minmax(0, 1fr) 72px;
  }

  .file-row {
    grid-template-columns: 48px minmax(0, 1fr) 38px;
  }

  .file-row select {
    width: 100%;
  }

  .file-row-content {
    grid-template-columns: 1fr;
    gap: 7px;
  }

  .file-row .file-meta {
    min-width: 0;
  }

  .file-row .icon-btn {
    align-self: center;
  }

  .drop-surface {
    min-height: 144px;
    padding: 18px 10px;
  }

  .upload-panel div:first-child,
  .signature-panel div:first-child,
  .completion-review > header,
  .dashboard-head,
  .detail-head {
    flex-direction: column;
    align-items: stretch;
  }

  .form-actions,
  .button-row,
  .workflow-actions,
  .master-actions {
    display: grid;
    grid-template-columns: 1fr;
  }

  .board {
    grid-auto-columns: minmax(170px, 82vw);
  }

  .flow-rail {
    grid-auto-columns: minmax(118px, 42vw);
  }

  .summary-strip {
    grid-template-columns: 1fr;
  }

  .desk-shell {
    padding: 10px;
  }

  .file-preview-dialog {
    padding: 10px;
  }
}

.global-spinner {
  position: fixed;
  inset: 0;
  z-index: 80;
  display: grid;
  place-items: center;
  pointer-events: auto;
  background: rgba(13, 31, 42, 0.28);
}

.global-spinner[hidden] {
  display: none;
}

.global-spinner-ring {
  width: 44px;
  height: 44px;
  border: 4px solid rgba(255, 255, 255, 0.45);
  border-top-color: var(--accent, #2b7de9);
  border-radius: 50%;
  animation: global-spinner-rotate 0.8s linear infinite;
}

@keyframes global-spinner-rotate {
  to { transform: rotate(360deg); }
}

/* 작업결과 첨부 (zcs002_doc). 접수 첨부(zcs001_doc)와 같은 file-card를 쓰되
   다운로드·삭제 두 버튼이 들어가므로 열 구성을 이 패널에서만 재정의한다. */
.work-doc-panel .file-list {
  display: grid;
  gap: 8px;
  margin-bottom: 12px;
}

.file-card-actions {
  display: flex;
  gap: 8px;
  align-items: center;
  justify-content: flex-end;
}

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

.work-doc-form label {
  display: grid;
  gap: 4px;
  min-width: 180px;
  font-size: 12px;
}

@media (max-width: 760px) {
  .work-doc-panel .file-card {
    grid-template-columns: minmax(0, 1fr);
  }

  .file-card-actions {
    justify-content: flex-start;
  }

  .work-doc-form label {
    min-width: 100%;
  }
}

/* G3d (92_ 4-5): PDF is browser print, not an ADS round trip. Every rule is
   scoped to .completion-print so the approval page - which shares .public-body
   and .public-page - keeps its own printing behaviour untouched (R4). */
@media print {
  /* Without an explicit margin the document runs to the sheet edge on the
     printers that default to zero, and the outer card borders get clipped. */
  @page {
    margin: 14mm;
  }

  .completion-print {
    background: #fff;
  }

  .completion-print .public-page {
    width: 100%;
    padding: 0;
  }

  .completion-print .work-form {
    border: 0;
    border-radius: 0;
    padding: 0;
    background: #fff;
    box-shadow: none;
  }

  /* The intro tells the reader to press a button that will not exist on paper,
     and the buttons themselves print as empty boxes. */
  .completion-print .print-hint,
  .completion-print .form-actions,
  .completion-print #clearSignatureBtn,
  .completion-print #result {
    display: none !important;
  }

  .completion-print .completion-doc {
    gap: 10px;
  }

  .completion-print .badge,
  .completion-print .doc-section,
  .completion-print .readonly-result,
  .completion-print .review-meta div,
  .completion-print .file-card,
  .completion-print .signature-panel {
    border: 1px solid #97a6b1;
    background: #fff;
    color: var(--ink);
    box-shadow: none;
    break-inside: avoid;
    page-break-inside: avoid;
  }

  .completion-print .quote-table {
    break-inside: avoid;
    page-break-inside: avoid;
  }

  /* The canvas keeps its 760x180 attribute size on screen; on paper it has to
     fit the sheet, and the border is what makes it read as a signature box. */
  .completion-print #signaturePad {
    width: 100%;
    height: auto;
    border: 1px solid #97a6b1;
    border-radius: 6px;
    background: #fff;
  }
}

/* CD-37-A2 REQ-37-2: the console completion report prints the same way the
   customer page does - browser print. manage.js puts .completion-report-printing
   on <body> only while printing, so no other console screen or dialog changes.
   The modal is fixed and scrolls inside a height cap on screen; printed as is,
   only the first screenful reaches the paper, so both are released here. */
@media print {
  .completion-report-printing > :not(.completion-report-backdrop) {
    display: none !important;
  }

  .completion-report-printing .completion-report-backdrop {
    position: static;
    display: block;
    overflow: visible;
    padding: 0;
    background: #fff;
  }

  .completion-report-printing .completion-report-backdrop .modal-panel {
    width: 100%;
    max-height: none;
    overflow: visible;
    border: 0;
    border-radius: 0;
    box-shadow: none;
  }

  .completion-report-printing .completion-report-backdrop .modal-head,
  .completion-report-printing .completion-report-backdrop .form-actions {
    display: none !important;
  }

  /* E-1: the report container is a two-column .dialog-form grid. The console-only
     facts (intro line + fact strip) live in .completion-console-facts since
     CD-37-A3 and the customer PDF has neither. The request-missing hint sits
     outside that section, so an incomplete report never prints as a complete one. */
  .completion-report-printing .completion-report-backdrop [data-completion-report] {
    display: block;
    padding: 0;
  }

  .completion-report-printing .completion-report-backdrop .completion-console-facts {
    display: none !important;
  }

  .completion-report-printing .completion-report-backdrop .badge,
  .completion-report-printing .completion-report-backdrop .doc-section,
  .completion-report-printing .completion-report-backdrop .readonly-result,
  .completion-report-printing .completion-report-backdrop .review-meta div,
  .completion-report-printing .completion-report-backdrop .file-card,
  .completion-report-printing .completion-report-backdrop .signature-panel {
    border: 1px solid #97a6b1;
    background: #fff;
    color: var(--ink);
    box-shadow: none;
    break-inside: avoid;
    page-break-inside: avoid;
  }

  .completion-report-printing .completion-report-backdrop .quote-table {
    break-inside: avoid;
    page-break-inside: avoid;
  }
}

/* F-M2 (110_): in-app confirm modal — same shell as the other dialogs so it
   stays inspectable and test-drivable, unlike a native confirm(). */
.confirm-panel {
  max-width: 420px;
}

.confirm-message {
  margin: 0;
  padding: 16px 20px;
  line-height: 1.6;
  white-space: pre-line;
}

.confirm-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  padding: 0 20px 18px;
}

/* F-M3 (110_): 처리결과 입력 — the only screen path that writes the solution. */
.solution-form {
  display: grid;
  gap: 12px;
}

.solution-form label {
  display: grid;
  gap: 6px;
  font-weight: 600;
}

.solution-form textarea {
  resize: vertical;
  min-height: 72px;
}

.solution-form .primary-btn {
  justify-self: end;
}

/* No.6: 진행상태 복수 선택 드롭다운 — 툴바 셀렉트와 같은 결의 요약 버튼 + 체크 목록 */
.status-filter {
  position: relative;
}

.status-filter > summary {
  list-style: none;
  cursor: pointer;
  border: 1px solid #d0d7e2;
  border-radius: 8px;
  padding: 8px 30px 8px 12px;
  background: #fff url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%23555' fill='none' stroke-width='1.5'/%3E%3C/svg%3E") no-repeat right 10px center;
  white-space: nowrap;
}

.status-filter > summary::-webkit-details-marker {
  display: none;
}

.status-filter[open] > .status-filter-menu {
  position: absolute;
  z-index: 40;
  min-width: 180px;
  margin-top: 4px;
  padding: 8px 10px;
  background: #fff;
  border: 1px solid #d0d7e2;
  border-radius: 8px;
  box-shadow: 0 8px 24px rgba(20, 40, 80, 0.14);
  display: grid;
  gap: 6px;
}

.status-filter-menu label {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.92rem;
  white-space: nowrap;
  cursor: pointer;
}

/* CD-39: 동의 화면(#intakeConsent). 체크박스는 .checkbox-field 를 그대로 쓰고,
   버튼 열은 .form-actions 를 그대로 써서 640px 이하 1열 그리드 규칙(3919_)을
   공짜로 받는다 - 375px 에서 버튼이 밀리지 않는 이유(REQ-39-8)가 그 규칙이다. */
.consent-block {
  padding-bottom: 18px;
  margin-bottom: 18px;
  border-bottom: 1px solid var(--line);
}

.consent-block:last-of-type {
  padding-bottom: 0;
  margin-bottom: 0;
  border-bottom: 0;
}

.consent-body {
  margin: 0 0 8px;
  color: #3a4a55;
  font-size: 13.5px;
  line-height: 1.55;
}

/* CD-51: S/4 전송 이력 — [이력 보기]가 가리킨 행, 부분채택 행, 오류 원문, 토스트 버튼. */
/* .work-detail-panel 은 grid 라 본문 칸이 표의 내용 폭만큼 늘어나 페이지를 가로로 밀었다
   (격자 항목의 기본 최소폭). 0 으로 풀어야 .line-table-wrap 이 제 안에서 스크롤한다. */
.ifact-history-body {
  min-width: 0;
}

.ifact-history-table tr.ifact-focus td {
  background: #fff4f3;
  box-shadow: inset 0 0 0 1px var(--bad);
}

.ifact-history-table tr.ifact-partial td {
  background: #fff8ec;
}

.ifact-error-text {
  white-space: pre-wrap;
  word-break: break-word;
}

/* CD-51 B: 시도 기록 하위 행. 전역 th, td 의 nowrap 을 풀어 긴 안내·원문이 표 폭을 밀지 않게 한다. */
.ifact-history-table tr.ifact-attempts td {
  white-space: normal;
  background: #fafbfc;
}

.ifact-attempt-list {
  margin: 6px 0 0;
  padding-left: 1.4em;
  display: grid;
  gap: 4px;
}

.ifact-attempt-list li {
  min-width: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px;
}

.toast .toast-action {
  margin-left: 8px;
}
