/* ============================================================
   헬프데스크 모듈 전용 스타일 — Blazor Common 으로 올리지 않는다.
   ============================================================ */

/* 표시 몇 개를 한 줄에 늘어놓는다. 조건줄(`jsini-toolbar`)과 섞지 않는다. */
.hd-stamps {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem;
  margin-bottom: 0.6rem;
}

.hd-subhead {
  margin: 1rem 0 0.6rem;
  font-size: var(--jsini-fs-lg);
  font-weight: 700;
}

/* ── 입력 폼 (요청 등록 · 파서) ─────────────────────────── */

/* 칸을 `minmax(0, 1fr)` 로 못박는다. auto 줄은 편집기 도구줄의 min-content 만큼 넓어져 폼 밖으로 넘친다.
   `.hd-field` 도 격자라 같이 적는다 — 바깥만 묶으면 안쪽 편집기가 다시 벌어진다. */
.hd-form {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 1rem;
  max-width: 46rem;
  margin-bottom: 1.25rem;
}

.hd-field {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 0.35rem;
  min-width: 0;
}

.hd-field__label {
  font-size: var(--jsini-fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--jsini-text-muted);
}

/* 곁단추 줄은 아래에 맞춘다(`flex-end`). 고른 파일 목록이 단추 위로 자라므로, 위에 맞추면 목록이 자랄 때 단추가 밀린다. */
.hd-tools {
  display: flex;
  align-items: flex-end;
  gap: 0.5rem;

  /* AI 판은 이 줄을 기준으로 선다. 단추를 기준으로 두면 375px 화면에서 판이 오른쪽으로 삐져나간다. */
  position: relative;
}

/* ── AI 도우미 ──────────────────────────────────────────────────── */
/* 판 안에 글과 목록이 함께 들어가 DevExpress 드롭다운(항목 목록)으로는 그릴 수 없어 손으로 그린다. */

/* 단추를 감싸는 통. 자리 기준은 여기 두지 않는다 — 펼친 판은 바깥 줄(`.hd-tools`)을 기준으로 선다. */
.hd-ai {
  display: inline-flex;
}

/* 곁단추 셋(첨부·AI·지우기)의 크기를 한 곳에서 정한다. 첨부 치수는 공용 부품(`.jsini-picker__pick`)을 따르므로 여기서 고치지 않는다 — 고치면 다른 화면의 첨부 단추가 함께 움직인다. */
.hd-tools .jsini-picker__pick,
.hd-tools .hd-tool-btn {
  min-width: 2.25rem;
  min-height: 2.25rem;
  padding-inline: 0;
}

/* 펼쳐 둔 동안 눌린 티를 낸다. */
.hd-tools .hd-ai__btn.is-on {
  border-color: var(--jsini-accent);
  color: var(--jsini-accent);
}

/* 펼친 판은 흐름 위에 띄운다 — 자리를 차지하면 열 때마다 편집기가 밀린다.
   위로 열고(`bottom: 100%`) 왼쪽에 맞춘다. 아래로 열면 화면 밖으로 나가고, 오른쪽에 맞추면 왼편으로 삐져나간다. */
.hd-ai__panel {
  position: absolute;
  z-index: 20;
  bottom: calc(100% + 0.35rem);
  left: 0;
  min-width: min(22rem, calc(100vw - 1rem));
  max-width: calc(100vw - 1rem);
  padding: 0.5rem;
  border: 1px solid var(--jsini-border);
  border-radius: var(--jsini-radius, 6px);
  background: var(--jsini-surface);
  box-shadow: 0 6px 20px rgb(0 0 0 / 15%);
}

.hd-ai__item,
.hd-ai__pick {
  display: block;
  width: 100%;
  padding: 0.5rem 0.6rem;
  border: 0;
  border-radius: 4px;
  background: transparent;
  color: var(--jsini-text);
  font-size: var(--jsini-fs-sm);
  text-align: left;
  cursor: pointer;
}

.hd-ai__item:hover,
.hd-ai__pick:hover {
  background: var(--jsini-surface-2, rgb(0 0 0 / 5%));
}

.hd-ai__wait {
  margin: 0;
  padding: 0.6rem;
  font-size: var(--jsini-fs-xs);
  color: var(--jsini-text-muted);
}

/* 이번 답을 만든 AI. **작게, 흐리게** — 고르는 값이 아니라 알려 주는 값이라
   후보보다 먼저 눈에 들면 안 된다. */
.hd-ai__model {
  margin: 0.35rem 0 0;
  padding: 0.35rem 0.6rem 0;
  border-top: 1px solid var(--jsini-border);
  font-size: var(--jsini-fs-xs);
  color: var(--jsini-text-muted);
  text-align: right;
}

.hd-ai__list {
  margin: 0;
  padding: 0;
  list-style: none;
}

/* 후보 사이의 가는 선. 첫 줄 위에는 긋지 않는다(`li + li`) — 판 머리에 선이 하나 더 생기면 테두리가 두 겹으로 보인다. */
.hd-ai__list li + li {
  border-top: 1px solid var(--jsini-border);
}

/* 제목 후보는 한 줄로 자르지 않고 접어서 다 보여 준다. 잘린 「…」 뒤에서는 후보끼리 구별되지 않는다. */
.hd-ai__pick {
  white-space: normal;
  word-break: break-word;
}

.hd-ai__foot {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.25rem;
  margin-top: 0.35rem;
  padding-top: 0.35rem;
  border-top: 1px solid var(--jsini-border);
}

/* 글자 없는 단추(다시 짓기). 네모로 세워 옆의 글자 단추와 높이를 맞춘다. */
.hd-ai__icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.75rem;
  min-height: 1.75rem;
  padding: 0;
  border: 0;
  border-radius: 4px;
  background: transparent;
  color: var(--jsini-text-muted);
  cursor: pointer;
}

.hd-ai__icon-btn:hover {
  background: var(--jsini-surface-2, rgb(0 0 0 / 5%));
  color: var(--jsini-text);
}

.hd-ai__plain {
  padding: 0.25rem 0.5rem;
  border: 0;
  background: transparent;
  color: var(--jsini-text-muted);
  font-size: var(--jsini-fs-xs);
  cursor: pointer;
}

.hd-ai__plain:hover {
  color: var(--jsini-text);
  text-decoration: underline;
}

/* 폼은 화면 높이에 맞고, 가운데 본문 편집기만 늘었다 줄었다 한다. `sticky` 로 띄우면 단추가 글 위에 겹쳐 글을 가린다.
   flex 칸의 최소 높이를 0 으로 내려야 편집기가 글만큼 자라 폼을 밀어내지 않는다. */
.hd-form.hd-form--wide {
  display: flex;
  flex-direction: column;

  /* 본문 통의 안쪽 높이를 그대로 쓴다. 통이 구르지 않으므로 폼이 화면을
     넘지 않고, 넘치는 글은 편집기 **안에서** 구른다. */
  height: 100%;
  min-height: 0;
}

.hd-form.hd-form--wide > .hd-content-field {
  flex: 1 1 auto;

  /* 본문 칸의 아래끝은 편집기가 아니라 칸이 건다. 편집기에 걸면 칸은 눌린 채 편집기가 단추 줄 위로 겹쳐 그려진다. */
  min-height: 12rem;

  /* 격자 대신 flex 로 둔다. 격자는 DevExpress 가 꽂은 `dxbl-resource-script` 셋(`display: block`)에도 줄을 나눠 줘서 제목과 본문 사이가 벌어진다. flex 에서는 그 빈 것들이 제 높이 0 만 차지한다. */
  display: flex;
  flex-direction: column;
}

/* 격자였을 때 `minmax(0, 1fr)` 이 하던 일을 여기서 한다. 없으면 편집기
   도구줄의 min-content 가 칸을 가로로 밀어 넓힌다(파일 위쪽 `.hd-form`
   주석의 그 일이 그대로 난다). */
.hd-form.hd-form--wide > .hd-content-field > * {
  min-width: 0;
}

.hd-form.hd-form--wide > .hd-content-field > .hd-content-editor {
  flex: 1 1 auto;
}

/* 편집기가 남는 칸을 채운다. 아래 요청 본문 편집기의 `min-height: 20rem` 은 여기서 걷어야 한다 — 남는 자리보다 크면 삐져나간다. */
.hd-form.hd-form--wide .hd-content-editor {
  height: 100%;
  min-height: 0;
}

/* 제목·곁단추·등록은 제 높이를 지킨다. 안 적으면 flex 가 이것들까지
   줄여서, 자리가 모자랄 때 단추가 납작해진다. */
.hd-form.hd-form--wide > .hd-title-field,
.hd-form.hd-form--wide > .hd-tools,
.hd-form.hd-form--wide > .hd-submit,
.hd-form.hd-form--wide > .hd-new-actions {
  flex: 0 0 auto;
}

.hd-new-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: flex-end;
  gap: 1rem;
}

/* 고른 파일 목록은 단추 위로 자란다. 세로 차례를 `column-reverse` 로 뒤집고 DOM 은 그대로 둔다 — 클립 단추가 부품과 묶여 있어 자리를 옮길 수 없다. 격자의 `justify-items` 가 하던 일은 `align-items` 가 맡는다. */
.hd-new-actions .jsini-picker {
  display: flex;
  flex-direction: column-reverse;
  align-items: flex-start;
}

/* 곁단추 줄은 제 높이를 지키는 칸이라 목록이 자라면 편집기가 그만큼 준다. 목록에 높이 상한(11rem)을 두어 세 번째 줄이 반쯤 걸치게 한다 — 더 있다는 신호다.
   이 화면의 줄에만 건다. 같은 고르개를 쓰는 다른 폼은 화면 높이에 묶여 있지 않다. */
.hd-new-actions .dxbl-upload-file-list-view {
  max-height: 11rem;
  overflow-y: auto;
}

/* 등록 줄은 휴대폰에서도 한 줄이다 — 왼쪽 곁단추, 오른쪽 등록. 등록이 줄을 통째로 쓰면 폼 끝이 두 층이 되어 본문 편집기 높이를 그만큼 빼앗는다.
   `pm-ask__bar` 와 같은 모양이다. 치수는 `DxButton` 의 뿌리 `.dxbl-btn` 에 건다 — 바깥 `div` 에 걸면 단추가 글자폭 그대로다.
   줄바꿈은 막는다(`nowrap`). 파일 이름이 길어도 등록이 아랫줄로 내려가지 않게 왼쪽이 줄고 단추는 제 크기를 지킨다. */
@media (width <= 767px) {
  .hd-new-actions {
    flex-wrap: nowrap;
  }

  .hd-tools {
    min-width: 0;
  }

  .hd-submit {
    flex: 0 0 auto;
  }

  .hd-submit .dxbl-btn {
    min-height: 2.75rem;
    padding-inline: 1.25rem;
    font-weight: 600;
  }
}

/* 제목 칸은 안쪽 `<input>` 에 여백을 준다. 바깥 칸에 걸면 테두리만 커지고 글자는 제자리라 위아래가 비어 보인다. */
.hd-title-field .dxbl-text-edit-input {
  padding-block: 0.75rem;
}

/* 데스크탑에서는 본문 폭을 쓴다. 뒤의 문의 접수 폼 칸이 같은 이름에 `max-width: 800px` 를 걸어 두므로, 이 폼은 `.hd-form.hd-form--wide` 로 겹쳐 적어야 이긴다. 제목 칸도 같이 늘려 편집기와 왼쪽 끝을 맞춘다. */
/* 바깥 상자(테두리·여백)를 두지 않는다 — 셸 본문에 이 폼 하나뿐이라 가르는 선이 아니고, 셸 여백이 얇은 지금은 상자가 자리를 더 먹는다. */
.hd-form.hd-form--wide {
  padding: 0;
  border: 0;
  margin: 0;
}

@media (width >= 768px) {
  .hd-form.hd-form--wide {
    max-width: none;
  }
}

/* 휴대폰에서는 「제목」·「내용」 이름표를 걷는다 — 같은 말이 칸 안 흐린 글자로 이미 있다.
   「요청자」·「첨부」는 남긴다. 「첨부」는 단추라 이름표를 걷으면 무엇을 고르는 단추인지 사라진다. */
@media (width <= 767px) {
  .hd-title-field > .hd-field__label,
  .hd-content-field > .hd-field__label {
    display: none;
  }

  /* 이름표를 감추면 칸 안 `gap`(0.35rem)만 남아 틈이 생기므로 칸 안쪽 틈을 0 으로 내린다. 칸 사이는 폼의 `gap` 이 맡는다. */
  .hd-title-field,
  .hd-content-field {
    gap: 0;
  }

  /* 칸 사이도 좁힌다. 1rem 은 이름표가 있던 시절의 값이다. */
  .hd-form.hd-form--wide {
    gap: 0.5rem;
  }

  /* 가상 키보드가 뜨면 보이는 높이가 줄어 본문 칸(12rem)이 등록 단추를 밀어낸다. 키보드가 열린 동안만 최소 높이를 3rem 으로 낮춘다. */
  html.jsini-kb-open .hd-form.hd-form--wide > .hd-content-field {
    min-height: 3rem;
  }
}

/* ── 요청 상세 ──────────────────────────────────────────── */

/* 요청 머릿값은 「이름 값」 한 줄씩 흘려 넣는다. 격자는 제일 긴 값에 맞춰 칸을 모두 넓히므로 쓰지 않는다.
   `dt` 가 `nowrap` 인 까닭: 이름이 두 글자뿐이라 접히면 줄 높이가 들쭉날쭉해진다. */

.hd-facts {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.2rem 1.15rem;
  margin: 0 0 0.6rem;
  padding: 0.4rem 0.7rem;
  border: 1px solid var(--jsini-border);
  font-size: var(--jsini-fs-sm);
}

/* 이름과 값이 한 덩이로 접힌다 — 묶지 않으면 좁은 화면에서 이름과 날짜가 다른 줄로 갈린다. */
.hd-fact {
  display: flex;
  align-items: baseline;
  gap: 0.3rem;
  min-width: 0;
}

.hd-facts dt {
  font-size: var(--jsini-fs-xs);
  color: var(--jsini-text-muted);
  white-space: nowrap;
}

.hd-facts dd {
  margin: 0;

  /* 「이순열(quristyle)」처럼 띄어쓰기 없는 덩이가 들어온다. 끊을 자리를 안 주면 좁은 칸에서 그대로 넘친다. */
  overflow-wrap: anywhere;
}

/* 본문. 줄바꿈을 살린다 — 폼에서 여러 줄로 쓴 글이라
   한 줄로 뭉개면 재현 방법을 읽을 수 없다. */
.hd-content {
  padding: 0.7rem 0.9rem;
  background: color-mix(in srgb, var(--jsini-text-muted) 8%, transparent);
  font-size: var(--jsini-fs-md);
  line-height: 1.7;
  white-space: pre-line;
}

/* 단추는 제목과 같은 줄 오른쪽 끝에 붙어 첫 화면에 늘 있다(`margin-left: auto`). 휴대폰에서는 머리가 접히며 단추 줄이 아래로 내려간다. */
.hd-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
  margin-left: auto;
}

.hd-actions a {
  text-decoration: none;
  padding: 0.2rem 0.7rem;
}

/* ── 현황 타일 ───────────────────────────────────────────────────── */
/* 상태 여섯을 한 줄에 늘어놓고, 좁으면 접히도록 `auto-fit` 을 쓴다. 고정 칸수는 태블릿에서 타일을 자른다. */

.hd-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 0.6rem;
}

/* ── 구역 제목 ───────────────────────────────────────────────────── */

.hd-section {
  margin: 1.4rem 0 0.5rem;
  font-size: var(--jsini-fs-lg);
  font-weight: 600;
}

/* ── 덧붙이는 말 ──────────────────────────────────────────────────── */
/* 배지 옆 짧은 설명. 배지와 같은 크기·색이면 둘 다 상태로 읽힌다. */

.hd-note {
  margin-left: 0.4rem;
  font-size: var(--jsini-fs-xs);
  color: var(--jsini-text-muted);
}

/* ── 차트 (D3) ─────────────────────────────────────────────────── */
/* `auto-fit` 이고, `min-width: 0` 이 없으면 차트 캔버스가 칸을 밀어 좁은 화면에서 가로 스크롤이 생긴다. */

.hd-charts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 1rem;
  margin: 0.75rem 0;
}

.hd-chart {
  min-width: 0;
  border: 1px solid var(--jsini-border);
  padding: 0.75rem 1rem 0.5rem;
}

.hd-chart__title {
  margin: 0 0 0.5rem;
  font-size: var(--jsini-fs-lg);
  font-weight: 600;
}

/* 가로축이 열두 칸(월별)·서른 칸(일별)인 차트는 `auto-fit` 으로 갈라 놓으면 축 라벨이 겹치므로 한 줄을 통째로 쓴다. */
.hd-chart--wide {
  grid-column: 1 / -1;
}

/* 차트 자리에 그릴 것이 없을 때. 판을 비워 두면 「망가졌나」로 읽힌다. */
.hd-chart__empty {
  margin: 0;
  padding: 2rem 0;
  text-align: center;
  color: var(--jsini-text-muted);
}

/* ── 눌리는 타일 ──────────────────────────────────────────────────── */
/* 타일 전체를 누르게 링크 한 장을 깐다(`hd-stat__hit`). 타일이 `relative` 여야 링크가 타일 안에 머문다 — 아니면 아무 데나 눌러도 목록이 열린다.
   초점 테두리는 `:focus-within` 으로 타일에 그린다. 깔린 링크는 속이 비어 있어 거기 테두리를 그리면 안 보인다. */

.hd-stat--link {
  position: relative;
  cursor: pointer;
  transition: border-color 0.12s ease, background-color 0.12s ease;
}

.hd-stat--link:hover {
  border-color: var(--jsini-accent);
  background-color: color-mix(in srgb, var(--jsini-accent) 8%, var(--jsini-surface));
}

.hd-stat--link:focus-within {
  outline: 2px solid var(--jsini-accent);
  outline-offset: 1px;
}

.hd-stat__hit {
  position: absolute;
  inset: 0;
  z-index: 1;
}

/* 깔아 둔 링크는 속이 비어 있다. 초점 테두리는 타일이 그리므로 여기서는 지운다 — 둘 다 그리면 테두리가 두 겹이 된다. */
.hd-stat__hit:focus,
.hd-stat__hit:focus-visible {
  outline: none;
}

/* ── 타일의 곁말 ──────────────────────────────────────────────────── */
/* 큰 숫자 아래 한 줄. 「지난달 23건 ▲ 12%」처럼 그 수를 어떻게 읽는지 적는다. 큰 숫자와 같은 크기면 값이 둘로 보인다. */

.hd-stat__note {
  font-size: var(--jsini-fs-xs);
  color: var(--jsini-text-muted);
  line-height: 1.3;
}

/* ── 고객사별 · 담당자별 카드 ──────────────────────────────────────────── */
/* 머리(이름·대푯값) · 띠(상태 분해, 도넛과 같은 팔레트) · 지표(흐린 이름 두 칸)로 나눈다.
   칸은 `auto-fill` 320px 다 — `auto-fit` 이면 카드 한 장이 화면을 가로질러 깨져 보인다. */

.hd-cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: 0.75rem;
}

.hd-my-comments {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 260px), 1fr));
  grid-auto-rows: 14rem;
  gap: 0.5rem;
}

.hd-my-comment {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  min-width: 0;
  height: 100%;
  box-sizing: border-box;
  margin-bottom: 0;
}

.hd-my-comment__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.5rem;
  min-width: 0;
  flex: 0 0 auto;
}

.hd-my-comment__request {
  min-width: 0;
  display: -webkit-box;
  overflow: hidden;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow-wrap: anywhere;
  font-weight: 600;
  color: var(--jsini-text);
  text-decoration: none;
}

.hd-my-comment__head .jsini-badge {
  flex: 0 0 auto;
}

.hd-my-comment__request:hover {
  text-decoration: underline;
}

.hd-my-comment__content {
  flex: 1 1 auto;
  overflow: auto;
  min-width: 0;
  min-height: 0;
  overflow-wrap: anywhere;
  padding-top: 0.5rem;
  border-top: 1px solid var(--jsini-border, #e0e0e0);
  /* `scrollbar-width: thin` 은 두지 않는다 — 크로미움에서 이 한 줄이 app.css 의 얇은 막대를 이 칸에서만 무시해 굵은 기본 막대가 선다. 얇게 하는 일은 app.css 가 한다. */
}

.hd-my-comment__content.hd-content img {
  display: inline-block;
  width: 4rem;
  height: 4rem;
  max-width: 100%;
  object-fit: cover;
  vertical-align: middle;
  margin: 0.125rem 0.25rem 0.125rem 0;
  border: 1px solid var(--jsini-border);
  border-radius: 4px;
  background: var(--jsini-surface);
}

.hd-my-comment__foot {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 0.75rem;
  padding-top: 0.5rem;
  border-top: 1px solid var(--jsini-border, #e0e0e0);
  font-size: var(--jsini-fs-sm);
  color: var(--jsini-text-muted);
  flex: 0 0 auto;
}

/* `jsini-card` 와 겹쳐 쓴다 — 테두리·바탕·그림자는 테마가 그리고, 여기서는 격자 칸의 몸가짐만 고친다. 아래 여백을 지우는 것은 `jsini-card` 의 1rem 이 칸 사이 간격에 겹쳐 아랫줄만 벌어지기 때문이다. */
.hd-card {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  min-width: 0;
  margin-bottom: 0;
}

/* 이름은 왼쪽, 대푯값은 오른쪽 끝. 이름이 길면 이름만 줄고
   숫자는 제자리를 지킨다(`flex-shrink: 0`). */
.hd-card__head {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  min-width: 0;
}

/* 담당자 얼굴 자리. 사진 주소를 화면에 들이지 않고 **이름 첫 글자**를
   쓴다 — 헬프데스크 사진은 아직 포털에서 꺼내 볼 길이 없어서,
   `img` 로 걸면 깨진 그림 아이콘이 카드마다 선다. */
.hd-card__avatar {
  --jsini-face-size: 2rem;
  --jsini-face-bg: var(--jsini-border, #e0e0e0);
  --jsini-face-ink: var(--jsini-text, inherit);
  --jsini-face-initial-size: var(--jsini-fs-sm);

  border: 1px solid var(--jsini-border, #e0e0e0);
}

.hd-card__name {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  font-size: var(--jsini-fs-lg);
  font-weight: 600;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 대푯값 — 카드에서 가장 굵은 한 곳. 「42건」의 「건」은 한 단 작게
   두어 숫자가 먼저 읽히게 한다. */
.hd-card__lead {
  flex: 0 0 auto;
  font-size: var(--jsini-fs-2xl);
  font-weight: 700;
  line-height: 1.1;
}

.hd-card__lead small {
  margin-left: 0.15rem;
  font-size: var(--jsini-fs-xs);
  font-weight: 500;
  color: var(--jsini-text-muted);
}

/* 상태 분해 띠. 조각 폭은 화면이 인라인 `width` 로 준다(비율이 자료다).
   `overflow: hidden` 이 있어야 조각이 둥근 모서리 밖으로 안 삐져나온다. */
.hd-bar {
  display: flex;
  overflow: hidden;
  width: 100%;
  height: 0.5rem;
  border-radius: 0.25rem;
  background: var(--jsini-border, #e0e0e0);
}

.hd-bar__seg {
  height: 100%;
}

/* 띠 아래 범례. 0 건인 상태는 화면에서 빼므로 여기 안 선다 —
   도넛에서 0 조각을 빼는 것과 같은 까닭이다. */
.hd-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 0.15rem 0.6rem;
  font-size: var(--jsini-fs-xs);
  color: var(--jsini-text-muted);
}

.hd-legend__item {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
}

.hd-legend__dot {
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
}

.hd-legend__count {
  font-weight: 600;
  color: var(--jsini-text);
}

/* 나머지 지표. 두 칸으로 접고 이름은 흐리게, 값만 굵게 둔다.
   `minmax(0, 1fr)` 이라야 긴 값(「2026-09-27」)이 칸을 밀지 않는다. */
.hd-card__facts {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.3rem 0.75rem;
  margin: 0;
  padding-top: 0.5rem;
  border-top: 1px solid var(--jsini-border, #e0e0e0);
  font-size: var(--jsini-fs-sm);
}

.hd-card__fact {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.35rem;
  min-width: 0;
}

.hd-card__fact dt {
  flex: 0 0 auto;
  color: var(--jsini-text-muted);
  font-weight: 400;
}

.hd-card__fact dd {
  margin: 0;
  overflow: hidden;
  font-weight: 600;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 카드가 한 장도 없을 때. 구역을 통째로 비우면 「안 불러왔나」로 읽힌다. */
.hd-cards__empty {
  margin: 0;
  padding: 1.5rem 0;
  text-align: center;
  color: var(--jsini-text-muted);
}

/* ── 문의 접수 폼 ─────────────────────────────────────────────────── */
/* 한 줄에 한 칸씩 쌓는 세로 폼. 폭을 묶는 것은 입력칸이 `width: 100%` 이기 때문이다 — 안 묶으면 와이드 모니터에서 한 줄짜리 칸이 화면 끝까지 늘어난다. */

.hd-form {
  max-width: 800px;
  margin: 0 auto;
  padding: 1.25rem 1.5rem;
  border: 1px solid var(--jsini-border);
}

.hd-form__title {
  margin: 0 0 1.25rem;
  font-size: 1.05rem;
  font-weight: 700;
}

.hd-form__field { margin-bottom: 1rem; }

.hd-form__field:last-of-type { margin-bottom: 1.5rem; }

.hd-form__label {
  display: block;
  margin-bottom: 0.3rem;
  font-weight: 600;
}

/* 보내기·비우기. 폼 끝이라 오른쪽으로 몬다. */
.hd-form__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  justify-content: flex-end;
}

/* 나란한 두 표(상태별·유형별). 좁으면 위아래로 쌓인다. */
.hd-two {
  display: grid;
  gap: 1rem;
  grid-template-columns: 1fr;
}

@media (width >= 1024px) {
  .hd-two { grid-template-columns: 1fr 1fr; }

  /* ── 나란한 자료 판이 본문 높이를 채운다 ────────────────────────────────────── */
  /* 판 높이 규칙(app.css)은 셸 본문의 직속 자식일 때만 걸린다. 나란히 앉히면 `.hd-two` 안에 들어가 빠지므로 여기서 한 번 더 건다(admin.css 의 `.ad-split` 과 같은 모양). */
  .jsini-shell__content:has(> .hd-two) {
    display: flex;
    flex-direction: column;
    overflow: hidden;
  }

  .jsini-shell__content > .hd-two {
    flex: 1;
    min-height: 0;

    /* 줄 높이를 내용이 정하지 않게 한다. 격자 줄의 기본은 `auto` 라서
       높이를 정해 줘도 줄이 자료만큼 늘어나 그대로 넘친다. */
    grid-template-rows: minmax(0, 1fr);
    align-items: stretch;
  }

  /* 격자 자식은 `min-height: auto` 라 내용보다 작아지지 않는다. */
  .hd-two > .commcont {
    min-height: 0;
  }

  .hd-two > .commcont > .commcont__body {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
  }
}

/* 위아래로 쌓인 자료 판 사이를 벌리는 공통 규칙은 나란히 앉힐 때 오른쪽
   판만 내려앉게 한다. 여기서 사이를 벌리는 일은 격자의 `gap` 이 한다. */
.hd-two > .commcont + .commcont {
  margin-top: 0;
}

/* ── 요청 본문 편집기 ───────────────────────────────────────────────── */
/* 생김새는 공지·메일의 `DxHtmlEditor` 가 그린다. 여기서는 높이만 정한다 — 기본이 세 줄쯤이라 칸 안에서 스크롤이 생기면 붙여넣은 그림이 화면 밖으로 밀린다. */

.hd-content-editor {
  min-height: 20rem;
}

/* ── 도구줄 글씨 ──────────────────────────────────────────────────── */
/* DevExpress 크기 단은 셋인데 포털 사다리는 여섯이다. 앞의 넷이 Small 하나로 접혀 도구줄 글씨만 제자리에 서므로, 도구줄이 읽는 변수를 우리 값으로 덮는다.
   굵기도 같이 돌린다: app.css 의 본문 단추 600 이 도구줄 묶음 이름표까지 진하게 만들어, 셋으로 적어 되돌린다. */

.hd-form .hd-content-editor .dxbl-toolbar {
  --dxbl-toolbar-font-size: var(--jsini-fs-base);
}

/* 도구줄 안의 고르개(글꼴·크기)와 단추 글씨도 같은 변수를 읽는다. 맞춰 주지 않으면 가장작게 단계에서 고르개만 12px 로 남는다. */
.hd-form .hd-content-editor .dxbl-text-edit {
  --dxbl-text-edit-font-size: var(--jsini-fs-base);
}

.hd-form .hd-content-editor .dxbl-btn {
  --dxbl-btn-font-size: var(--jsini-fs-base);
  font-weight: 400;
}

/* 도구줄 이름표는 `HtmlEditorKorean` 이 C# 에서 갈아 끼우지만, 글꼴·크기 두 칸의 빈칸 글자는 DevExpress 가 리소스에서 `placeholder` 로 박아 API 로 바꿀 자리가 없다. 그래서 그 글자를 투명하게 하고(`::placeholder`) 우리 글자를 `::after` 로 얹는다.
   콤보가 비었을 때 `field-text=""` 를 들고 있어 JS 없이 다시 맞는다. 초점이 들어오면 치운다(`:not(:focus-within)`) — 친 글자와 겹치기 때문이다. */
.hd-content-editor .dxbl-toolbar-combobox > input::placeholder {
  color: transparent;
}

.hd-content-editor .dxbl-toolbar-combobox[custom-placeholder="Font"][field-text=""]:not(:focus-within)::after,
.hd-content-editor .dxbl-toolbar-combobox[custom-placeholder="Size"][field-text=""]:not(:focus-within)::after {
  position: absolute;
  inset: 0 auto 0 0;
  display: flex;
  align-items: center;
  padding: 0 12px;
  color: var(--jsini-text-muted);
  pointer-events: none;
}

.hd-content-editor .dxbl-toolbar-combobox[custom-placeholder="Font"][field-text=""]:not(:focus-within)::after {
  content: "글꼴";
}

.hd-content-editor .dxbl-toolbar-combobox[custom-placeholder="Size"][field-text=""]:not(:focus-within)::after {
  content: "크기";
}

/* 편집기 안의 그림은 원본이 화면 캡처라 칸보다 넓은 것이 보통이다. 묶어 두지 않으면 편집기가 통째로 가로로 늘어난다. */
.hd-content-editor img {
  max-width: 100%;
  height: auto;
}

/* 그림 파일 칸은 사람에게 보이지 않는다 — `request-editor.js` 가 붙여넣기·끌어놓기와 「그림」 단추의 `click()` 으로 연다. `display: none` 으로 두면 사파리에서 열리지 않는 일이 있어 자리는 두고 화면에서만 치운다. */
.hd-paste-input {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  opacity: 0;
}

/* ── 요청 본문 (상세·수정에서 보는 쪽) ────────────────────────────────────── */
/* 본문이 HTML 이라 그림·표가 든다. 칸보다 넓은 것을 묶어 두지 않으면 본문이 쪽을 가로로 민다. */

.hd-content img {
  max-width: 100%;
  height: auto;
  display: block;
  margin: 0.5rem 0;
}

.hd-content table {
  border-collapse: collapse;
  max-width: 100%;
}

.hd-content td,
.hd-content th {
  border: 1px solid var(--jsini-border);
  padding: 0.25rem 0.5rem;
}

/* 편집기가 내놓는 글은 `<p>` 로 갈린다. 기본 여백을 두면 줄 사이가 지나치게 벌어진다. */
.hd-content p {
  margin: 0 0 0.5rem;
}

.hd-content p:last-child {
  margin-bottom: 0;
}

/* ── 요청 상세 머리 ────────────────────────────────────────────────── */
/* 이 화면은 탭으로 따로 선다 — 메뉴에 없는 주소라 사이드바 흔적과 브레드크럼이 없다. 알림으로 들어온 사람에게 첫 화면이므로 돌아갈 자리를 화면이 직접 둔다. */

/* 한 줄에 넷: 돌아갈 자리 · 제목 · 상태 배지 · 단추 줄. 상태는 값이 아니라 지금 상태이므로 제목 옆에 둔다.
   제목은 늘지 않고 줄기만 한다(`flex: 0 1 auto`). 늘면 배지가 단추 옆으로 밀려 나간다. 긴 제목은 제목만 접힌다. */
.hd-detail__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem 0.75rem;
  margin-bottom: 0.6rem;
}

.hd-detail__back {
  font-size: var(--jsini-fs-md);
  color: var(--jsini-text-muted);
  text-decoration: none;
  white-space: nowrap;
}

.hd-detail__back:hover {
  color: var(--jsini-text);
  text-decoration: underline;
}

.hd-detail__title {
  margin: 0;
  font-size: var(--jsini-fs-lg);
  font-weight: 700;

  /* 제목이 길면 줄이 접히는 대신 머리 전체가 가로로 늘어난다. */
  flex: 0 1 auto;
  min-width: 0;
  overflow-wrap: anywhere;
}

/* ── 댓글 나무 ───────────────────────────────────────────────────── */
/* `CommentThread` 가 자기를 다시 불러 그린다. 한 층 들여쓰는 폭과 층을 가르는 세로줄을 정한다. 깊이 제한이 없으므로 폭을 크게 잡으면 몇 층 만에 본문이 한 글자 폭이 된다. */

.hd-cmts {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.75rem;
}

.hd-cmt {
  padding: 0.75rem 1rem;
  border: 1px solid var(--jsini-border);
  border-radius: var(--jsini-radius, 6px);
  background: var(--jsini-surface);
  box-shadow: 0 1px 3px rgb(0 0 0 / 4%);
  min-width: 0;
}

.hd-cmt__head {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-bottom: 0.5rem;
}

/* 동그라미는 공용 부품(`UserAvatar` · app.css 의 `jsini-face`)이 그린다.
   여기서는 치수와 색만 덮는다. */
.hd-cmt__avatar {
  --jsini-face-size: 2rem;
  --jsini-face-bg: var(--jsini-border, #e0e0e0);
  --jsini-face-ink: var(--jsini-text, inherit);
  --jsini-face-initial-size: var(--jsini-fs-sm);

  border: 1px solid var(--jsini-border, #e0e0e0);
  user-select: none;
}

.hd-cmt__who {
  font-weight: 600;
  font-size: var(--jsini-fs-md);
}

.hd-cmt__when,
.hd-cmt__count {
  font-size: var(--jsini-fs-xs);
  color: var(--jsini-text-muted);
}

/* 앞의 것과 붙어 보이지 않게 한 칸 민다. */
.hd-cmt__count { margin-left: auto; }

.hd-cmt__body {
  font-size: var(--jsini-fs-md);
  line-height: 1.6;
  min-width: 0;
}

/* 지워진 댓글. 자리와 딸린 답글은 남기고 내용만 가린다 —
   줄째로 빼면 그 아래 답글이 부모를 잃는다. */
.hd-cmt__body--gone {
  color: var(--jsini-text-muted);
  font-style: italic;
}

/* 답글·삭제는 작은 회색 아이콘이고, 올렸을 때만 색이 선다. */
.hd-cmt__acts {
  display: inline-flex;
  align-items: center;
  gap: 0.125rem;
  margin-top: 0.2rem;
  --jsini-icon-size: 0.875rem;
}

.hd-cmt__acts .dxbl-btn.hd-cmt__act {
  padding: 0.2rem;
  min-height: 0;
  line-height: 1;
  color: var(--jsini-text-muted);
  border-radius: 999px;
}

.hd-cmt__acts .dxbl-btn.hd-cmt__act:hover {
  color: var(--tb-primary, currentColor);
  background: color-mix(in srgb, currentColor 10%, transparent);
}

.hd-cmt__acts .dxbl-btn.hd-cmt__act--del:hover {
  color: var(--bs-danger, #d63939);
}

.hd-cmt__write {
  margin-top: 0.5rem;
}

/* 한 층 들어간 답글들. 세로줄이 어느 말에 붙은 답인지를 보여 준다. */
.hd-cmt__kids {
  margin-top: 0.5rem;
  padding-left: 0.5rem;
}

@media (width <= 767px) {
  /* 360px 짜리 화면에서 네 층만 들어가도 본문이 사라진다. */
  .hd-cmt__kids {
    margin-left: 0.35rem;
    padding-left: 0.5rem;
  }
}

/* ── 댓글 쓰는 칸 ─────────────────────────────────────────────────── */
/* 생김새는 `DxHtmlEditor` 가 그린다. 여기서는 높이와 격자 안에서 벌어지지 않게 묶는 것을 정한다 — 까닭은 위 `.hd-form` 주석(도구줄 min-content)과 같다. */

.hd-cmt-write {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 0.35rem;
  min-width: 0;
}

.hd-cmt-root {
  margin-top: 1rem;
}

/* 뿌리 댓글 칸은 상세 맨 끝이라, 휴대폰에서 떠다니는 단추(✎) 자리에 선다. 그 자리에 「남기기」를 얹으므로 칸 오른쪽 아래를 한 칸 올려 비킨다. 값은 `.hd-manage-more--phone` 과 같다. */
@media (max-width: 767px) {
  .hd-cmt-root {
    margin-bottom: 4.25rem;
  }
}

/* 「남기기」를 칸 안에 얹으려고 기준점을 세운다. */
.hd-cmt-write {
  position: relative;
}

.hd-cmt-editor {
  /* 요청 본문(20rem)보다 낮다. 댓글은 대개 몇 줄이라, 높게 잡으면 답글 칸이 열릴 때마다 아래 글이 밀린다. */
  min-height: 9rem;

  /* 세로로 쌓는다. 도구줄을 접었을 때 글칸이 남는 높이를 받아야 칸 전체가 낮아지지 않는다 — 안 그러면 짚을 때마다 아래 글이 들썩인다. */
  display: flex;
  flex-direction: column;
}

/* 글칸(DevExpress 의 바깥 상자)이 남는 높이를 다 받는다. */
.hd-cmt-editor > .dxbl-widget-container {
  flex: 1 1 auto;
  min-height: 0;
}

/* ── 도구줄은 쓰는 동안만 선다 ──────────────────────────────────────────── */
/* 댓글 칸마다 서식 줄이 떠 있으면 글을 읽는 동안 쓸 일 없는 줄이 휴대폰에서 칸만큼 높다. `display: none` 으로 접는다 — `height: 0` 은 보이지 않은 채 눌리는 단추를 남긴다.
   펴는 조건은 화면이 `--writing` 클래스로 알린다. `:focus-within` 은 목록이 문서 끝에 그려져 고르는 순간 줄이 접히므로 쓰지 않는다. */
.hd-cmt-editor > .dxbl-ribbon__root {
  display: none;
}

.hd-cmt-write--writing .hd-cmt-editor > .dxbl-ribbon__root {
  display: block;
}

/* ── 「남기기」는 칸 안 오른쪽 아래에 얹는다 ──────────────────────────────────── */
/* 줄로 세우면 칸마다 단추 줄이 더해져 답글 몇 개만으로 읽을 글이 밀린다. 얹으면 칸 높이가 전부다. 글이 단추 밑으로 기어들지 않게 글칸 아래에 단추 높이만큼 여백을 둔다. */
.hd-cmt-write__run {
  position: absolute;
  right: 0.5rem;
  bottom: 0.5rem;
  z-index: 2;

  /* 얹은 자리에서는 아래 여백을 두지 않는다 — 칸 밖으로 민다. */
  margin-bottom: 0;
}

.hd-cmt-write__footer {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: 0.5rem;
  margin-top: 0.25rem;
}

.hd-cmt-write__footer .hd-cmt-write__run {
  position: static;
  margin-left: auto;
  flex-shrink: 0;
}

.hd-cmt-write__tools {
  min-width: 0;
}

.hd-cmt-write__tools .jsini-picker {
  display: flex;
  flex-direction: column-reverse;
  align-items: flex-start;
}

.hd-cmt-write__tools .dxbl-upload-file-list-view {
  max-height: 8rem;
  overflow-y: auto;
}

/* 단추가 가릴 만큼만 비워 둔다. DevExpress 글칸의 기본 여백 위에 더한다. */
.hd-cmt-editor .ql-editor {
  padding-bottom: 0.75rem;
}

/* 올리는 중이라는 말도 얹는다 — 줄로 세우면 그동안만 칸이 한 줄 높아져
   아래 글이 들썩인다. 단추와 반대쪽(왼쪽)이라 겹치지 않는다. */
.hd-cmt-write__busy {
  position: absolute;
  left: 0.6rem;
  bottom: 0.9rem;
  z-index: 2;
}

.hd-cmt-editor img {
  max-width: 100%;
  height: auto;
}

/* ── 댓글 첨부파일 목록 ── */
.hd-cmt__files,
.hd-my-comment__files {
  list-style: none;
  margin: 0.35rem 0 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
}

.hd-my-comment__files {
  flex: 0 0 auto;
}

.hd-cmt__file,
.hd-my-comment__file {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.2rem 0.5rem;
  border: 1px solid var(--jsini-border);
  border-radius: var(--jsini-radius, 4px);
  background: var(--jsini-surface, #f8f9fa);
  color: var(--jsini-text);
  font-size: var(--jsini-fs-sm, 0.85rem);
  text-decoration: none;
  max-width: 100%;
}

.hd-cmt__file:hover,
.hd-my-comment__file:hover {
  background: var(--jsini-hover, #e9ecef);
  text-decoration: underline;
}

.hd-cmt__file-name,
.hd-my-comment__file-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 14rem;
}

.hd-cmt__file-size,
.hd-my-comment__file-size {
  color: var(--jsini-text-muted);
  font-size: var(--jsini-fs-xs, 0.75rem);
  flex-shrink: 0;
}

/* ── 요청 처리 표의 「그림」 칸 ─────────────────────────────────────────── */
/* 파일 서버 그림은 150×150 이라 여기서 다시 줄여 건다. 높이는 줄 높이 안에서 잡는다 — 그림의 제 높이를 두면 그림 있는 줄과 없는 줄이 들쭉날쭉하다.
   `object-fit: cover` 라 가운데를 잘라 네모로 선다. `contain` 이면 줄마다 폭이 달라 칸이 흔들린다. */

.hd-row-thumb {
  width: 2rem;
  height: 2rem;
  object-fit: cover;
  border-radius: 3px;
  border: 1px solid var(--jsini-border);
  vertical-align: middle;
  background: var(--jsini-surface);

  /* 눌러서 크게 볼 수 있다는 표시. 줄 전체도 눌리는 자리라(상세로 간다)
     여기만 손가락이 아니라 **돋보기**여야 다른 일이 난다는 것이 보인다. */
  cursor: zoom-in;
}

/* ── 요청 처리 표 — 줄 하나가 80px 다 (`.hd-manage-grid`) ──────────────── */
/* 그림이 2rem 우표만 해서 알아볼 수 없었다. 높이는 그림이 아니라 줄(`td`)에 준다 — 그림에 주면 줄이 들쭉날쭉하다.
   그 높이가 두 줄을 내주므로 제목 칸이 제목 위에 상태·요청자·접수·경과를 얹는다. `CssClass` 값은 `DxGrid` 뿌리로 흘러가 `.commgrd` 가 아니라 표 자신에 붙는다. */

.hd-manage-grid .dxbl-grid-table > tbody > tr > td {
  height: 80px;
}

/* 「그림」 칸만 여백을 걷는다. DevExpress 가 `td` 여백을 자릿수로 그려 우리 선택자로는 못 이긴다. 테마가 다시 잡는 자리가 있어 `!important` 로 못 박는다. */
.hd-manage-grid .dxbl-grid-table > tbody > tr > td:has(> .hd-row-thumb) {
  padding: 0 !important;
}

/* 비율은 그대로 두고 가운데를 잘라 칸을 채운다(`cover`). `contain` 이면 줄마다 폭이 달라 칸이 흔들린다. 칸 폭이 80px 라 결과는 정사각이다. */
.hd-manage-grid .hd-row-thumb {
  display: block;
  width: 100%;
  height: 80px;
  border: 0;
  border-right: 1px solid var(--jsini-border);
  border-radius: 0;
}

/* ── 제목 칸 — 얹은 한 줄 + 제목 ──────────────────────────── */

.hd-req-cell {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.25rem;
  width: 100%;
  min-width: 0;
  text-align: left;
}

.hd-req-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.2rem 0.35rem;
  font-size: var(--jsini-fs-xs);
  line-height: 1.2;
  color: var(--jsini-text-muted);
}

.hd-req-meta__dot {
  opacity: 0.5;
}

/* 표가 `TextWrapEnabled="false"` 라 칸은 `nowrap` 이다. 제목만 두 줄까지 풀고 그 뒤는 … 로 자른다 — 안 자르면 긴 제목이 줄 높이를 밀어 80px 이 풀린다. */
.hd-req-title {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  white-space: normal;
  max-width: 100%;
  font-weight: 600;
  line-height: 1.35;
  color: var(--jsini-text);
}

/* ── 요청 처리 — 휴대폰의 카드 목록 (`RequestCards`) ─────────────────────── */
/* 휴대폰에는 표가 없다. 칸 머리줄이 없고 안에서 구르지 않는 목록은 DevExpress 표를 비틀어 얻을 수 없다(`RequestRowList` 머리말).
   줄은 `그림 | 글` 두 칸이고, 그림이 없어도 같은 자리를 비운다 — 안 비우면 글 시작선이 줄마다 어긋난다. 줄 높이는 못 박지 않는다. */

.hd-req-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

/* 줄은 테두리와 띠만 들고, 안의 상자(`__row`)가 글을 깐다. 갈라 둔 것은 글만 밀기 때문이다 — 띠는 줄에 붙어 제자리에 있어야 한다. */
.hd-req-list__item {
  position: relative;
  border-top: 1px solid var(--jsini-border);

  /* 민 글이 줄 밖으로 삐져나가 **쪽을 옆으로 굴리게** 하지 않는다. */
  overflow: hidden;
}

/* 판이 이미 테두리를 두르고 있어 첫 줄 위의 선은 두 겹이 된다. */
.hd-req-list__item:first-child {
  border-top: 0;
}

.hd-req-list__row {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  padding: 0.6rem 1rem;
  cursor: pointer;

  /* 누를 때 안드로이드 크롬이 칠하는 파란 네모를 걷는다. 줄 전체가 누르는
     자리라 그 네모가 카드만 하게 번쩍인다. */
  -webkit-tap-highlight-color: transparent;
}

.hd-req-list__row:active {
  background: var(--jsini-surface);
}

/* 56px 이다 — 표의 80px 보다 작다. 휴대폰에서는 글 폭이 아쉽고, 한 줄에 얹는 값이 다섯이라 그만큼 제목을 밀어낸다. 크게 보는 길은 그대로 있다. */
.hd-req-list__thumb {
  flex: 0 0 auto;
  width: 56px;
  height: 56px;
  object-fit: cover;
  border: 1px solid var(--jsini-border);
  border-radius: var(--jsini-radius-sm);
  background: var(--jsini-surface);

  /* 줄 전체도 눌리는 자리라(상세로 간다) 여기만 돋보기여야 다른 일이 난다는 것이 보인다. */
  cursor: zoom-in;
}

/* 그림이 없는 줄의 빈자리. 테두리를 두르지 않는다 — 빈 네모가 줄마다 서면
   그것이 「못 받은 그림」으로 읽힌다. 자리만 지킨다. */
.hd-req-list__thumb--none {
  border-color: transparent;
  background: transparent;
  cursor: default;
}

.hd-req-list__empty {
  margin: 0;
  padding: 1.5rem 1rem;
  text-align: center;
  color: var(--jsini-text-muted);
}

/* ── 「대기」는 밀어서 접수하고 지운다 ──────────────────────────────────────── */
/* 움직이는 값은 줄의 인라인 사용자 지정 속성으로 받는다. 클래스로 받으면 목록이 다시 그려질 때 Blazor 가 `class` 를 제 손으로 지워 손짓 중에 줄이 밀린 자리에 굳는다. 대는 쪽은 `js/request-swipe.js`.
   `--hd-swipe` 는 부호가 있다(양수 = 오른쪽 = 접수).
   띠를 줄 밑에 깔고 글로 덮지 않는다 — 글 바탕은 테마가 정해서 어긋난다. 띠가 민 만큼만 넓어지면 덮을 일이 없다. */

.hd-req-list__item[data-swipe] {
  --hd-swipe: 0px;
  --hd-swipe-ms: 0ms;
  --hd-swipe-ready: 0;
}

/* `touch-action: pan-y` 가 핵심 한 줄이다 — 세로 끌기는 브라우저 스크롤에 넘기고 가로 끌기만 우리에게 온다. 쪽이 통째로 구르는 자리라 세로를 막으면 목록을 못 넘긴다.
   띠는 `z-index` 로 글 위에 놓는다 — 절대 자리라 문서에서 뒤면 글을 덮는다. */
.hd-req-list__item[data-swipe] > .hd-req-list__row {
  position: relative;
  z-index: 2;
  touch-action: pan-y;
  transform: translateX(var(--hd-swipe));
  transition: transform var(--hd-swipe-ms) ease;
}

/* 가만히 있을 때 폭이 0 이다. 안쪽 여백을 주면 폭이 0 이어도 상자가 남아 가장자리에 색 실오라기가 선다 — 글자 여백은 안의 ✓·✕ 가 제 바깥 여백으로 한다.
   `max()` 로 한쪽 부호만 받아 두 띠가 함께 열리지 않게 한다(JS 도 방향을 한 번 가리면 바꾸지 않는다). */
.hd-req-swipe {
  position: absolute;
  inset-block: 0;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 0.25rem;
  overflow: hidden;
  color: #fff;
  font-size: var(--jsini-fs-2xs);
  white-space: nowrap;
  pointer-events: none;
  transition: width var(--hd-swipe-ms) ease;
}

/* 접수는 초록이다 — 공통 배지의 「완료·진행」 쪽 초록 그대로다. 이 화면만의
   색을 새로 만들면 같은 뜻이 자리마다 다른 초록이 된다. */
.hd-req-swipe--accept {
  left: 0;
  justify-content: flex-start;
  width: max(0px, var(--hd-swipe));
  background: #2e7d32;
}

/* 삭제는 빨강이고 **글자가 오른쪽 끝에 붙는다** — 손가락이 가는 쪽에서
   읽혀야 한다. */
.hd-req-swipe--remove {
  right: 0;
  justify-content: flex-end;
  width: max(0px, calc(-1 * var(--hd-swipe)));
  background: #d32f2f;
}

/* 문턱을 넘으면 표가 커지고 글자가 또렷해진다. **손을 떼기 전에**
   「놓으면 처리된다」를 알려 주는 것이 이 둘의 일이다 — 넘기 전에 놓으면
   줄은 제자리로 돌아간다. */
.hd-req-swipe__mark {
  flex: 0 0 auto;
  margin: 0 0.6rem;
  font-size: var(--jsini-fs-sm);
  line-height: 1;
  transform: scale(calc(0.7 + (0.3 * var(--hd-swipe-ready))));
  transition: transform 120ms ease;
}

.hd-req-swipe__text {
  opacity: calc(0.45 + (0.55 * var(--hd-swipe-ready)));
  transition: opacity 120ms ease;
}

/* 움직임을 줄여 달라고 한 사람에게는 **결과만** 준다. 띠는 열리지 않고 줄도
   따라 움직이지 않는다 — 처리됐다는 것은 줄이 목록에서 빠지거나(삭제) 상태
   딱지가 「진행」으로 바뀌는 것(접수)으로 이미 말한다. */
@media (prefers-reduced-motion: reduce) {
  .hd-req-list__item[data-swipe] > .hd-req-list__row,
  .hd-req-swipe,
  .hd-req-swipe__mark,
  .hd-req-swipe__text {
    transition: none;
  }
}

/* ── 그 목록이 실린 판은 쪽이 구른다 ──────────────────────────────────────── */
/* 셸 본문은 자료 판(`CommCont`)을 품으면 남은 높이를 판에 주고 넘치는 것을 자른다(app.css 의 `:has`). 표는 제 안에서 구르니 맞지만, 카드 목록은 줄이 전부 깔려 「더보기」가 잘린다.
   그래서 휴대폰에서만 붙는 이 클래스로 되돌린다. helpdesk.css 가 뒤에 실려 이긴다. */

.jsini-shell__content:has(> .hd-manage-cont--phone) {
  overflow: auto;
}

.jsini-shell__content:has(> .hd-manage-cont--phone) > .hd-manage-cont--phone {
  flex: 0 0 auto;
}

.jsini-shell__content:has(> .hd-manage-cont--phone) > .hd-manage-cont--phone > .commcont__body {
  display: block;
}

/* ── 요청 처리 — 목록 아래의 「더보기 · 더 읽기」 줄 ───────────────────────────── */
/* 데스크톱에서는 페이저 곁에, 휴대폰에서는 목록 맨 끝에 선다. 「더보기」는 다 보고 누르는 단추라 화면 아래에 붙박으면 손가락 밑에서 어른거린다. */

.hd-manage-more {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding-top: 0.4rem;
}

/* 데스크톱에만 선다. 페이저가 쪽을 말하므로 여기는 몇 건 중 몇 건을 받았는지만 적는다 — 그 수가 「더 읽기」를 누를 까닭이다. */
.hd-manage-more__note {
  margin-right: auto;
  font-size: var(--jsini-fs-xs);
  color: var(--jsini-text-muted);
}

/* 휴대폰에서는 단추를 띠 끝까지 늘린다 — 엄지가 닿는 자리에 놓이게.
   좌우 여백은 이 띠가 스스로 갖는다. 좁은 화면에서 판 안쪽 여백이 걷혀 있어(tabler.css) 안 주면 단추가 가장자리에 붙는다. 값은 카드 줄과 같은 1rem 이다. */
.hd-manage-more--phone {
  padding: 0.6rem 1rem 0;
}

.hd-manage-more--phone .hd-manage-more__go {
  width: 100%;
}

/* ── 떠다니는 단추를 피해 한 칸 올라선다 ────────────────────────────────────── */
/* 띠는 판 맨 아래, 즉 화면 바닥에 서고 거기가 떠다니는 단추(☰ · ✎) 자리라 양 끝이 가려진다. 폭을 줄여 비키는 쪽은 안 골랐다 — 단추 위치는 사람이 고르므로 위쪽을 고른 사람에게는 그냥 좁은 단추가 된다.
   `3.75rem` 은 단추(3rem)와 바닥 띄움(0.75rem)의 합이다 — `.jsini-shell__fab` 와 같은 수다. */
@media (max-width: 767px) {
  .hd-manage-more--phone {
    margin-bottom: 4.25rem;
  }
}

/* ── 다 깔고 나면 꺼진 채로 남는다 ───────────────────────────────────────── */
/* 끝을 알리는 꺼진 단추. DevExpress 의 꺼진 단추는 켜진 것보다 요란해 목록 아래서 먼저 눈에 든다 — 바탕을 걷고 점선 테두리만 남긴다(눌리지 않는다는 것도 함께 보인다).
   `!important` 는 테마가 `--dxbl-btn-*` 로 칠한 바탕을 덮는 값이다. 글자는 캡션의 `opacity: 0.5` 가 흐려서 되돌린다. */
.hd-manage-more--phone .hd-manage-more__go:disabled {
  background: transparent !important;
  border: 1px dashed var(--jsini-border) !important;
  color: var(--jsini-text-muted) !important;
  box-shadow: none !important;
}

.hd-manage-more--phone .hd-manage-more__go:disabled .dxbl-btn-caption {
  opacity: 1;
}

/* ── 눌리는 카드 ───────────────────────────────────────── */

.hd-card--link {
  position: relative;
  transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
}

.hd-card--link:hover {
  border-color: var(--jsini-accent);
  box-shadow: 0 4px 12px rgba(0,0,0,0.08);
}

.hd-card--link:focus-within {
  outline: 2px solid var(--jsini-accent);
  outline-offset: 1px;
}

.hd-card__hit {
  position: absolute;
  inset: 0;
  z-index: 1;
}

.hd-card__hit:focus,
.hd-card__hit:focus-visible {
  outline: none;
}

/* ── 끌어서 나누는 좌우 분할 (`hd-vsplit`) ─────────────────────────────── */
/* 프로시저 결과 화면이 쓴다. 폭은 사람이 정한다 — 격자 고정 비율은 이름이 긴 쪽과 결과가 많은 쪽이 서로 다른 폭을 바랐다.
   셸 사이드바와 같은 부품(`DxSplitter`)이라 규칙도 그쪽을 따른다(`.jsini-shell__split` 머리말). 모듈은 서로의 CSS 를 참조하지 않으므로 여기 한 벌을 둔다. 포털관리의 `ad-vsplit` 과 같은 일이다.
   `DxSplitter` 는 높이를 부모에게서 받는다 — 안 주면 판이 통째로 안 보이는, 오류 없는 고장이다.
   판 안에 `CommCont` 를 넣으므로 테두리·바탕은 그쪽이 그린다 — 여기서 덧그리면 선이 두 겹이 된다. */

@media (width >= 992px) {
  .jsini-shell__content:has(> .hd-vsplit) {
    display: flex;
    flex-direction: column;
    overflow: hidden;
  }

  .jsini-shell__content > .hd-vsplit {
    flex: 1;
    min-height: 0;
  }
}

/* 판 안쪽 여백을 걷어낸다. 규칙과 다투지 않고 그 규칙이 읽는 변수를 덮는다 — 크기 모드마다 값이 달라 자릿수를 넘겨야 세 모드에서 모두 걸린다. */
.jsini-shell .hd-vsplit.dxbl-splitter {
  --dxbl-splitter-pane-padding-x: 0;
  --dxbl-splitter-pane-padding-y: 0;
}

.hd-vsplit > .dxbl-splitter-pane > .dxbl-splitter-pane-content {
  min-width: 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

/* 판 하나(`CommCont`). 자기 안에서 구른다 — 판 밖으로 넘기면 셸 본문이 `overflow: hidden` 이라 잘린다. */
.hd-vsplit__pane {
  flex: 1;
  min-height: 0;
  overflow: hidden;
}

/* 구분선에 내용이 닿지 않게 띄운다. 붙어 있으면 어느 쪽 글자인지 헷갈린다. */
.hd-vsplit__pane--left { margin-right: 0.375rem; }
.hd-vsplit__pane--right { margin-left: 0.375rem; }

/* 머리줄은 제자리에 두고 안의 것만 구른다 — 통째로 구르면 「프로시저 52개」와 「실행」 단추가 함께 올라간다. */
.hd-vsplit__pane > .commcont__body {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

/* 구분선. **끌 수 있다는 것은 해 보기 전에는 보이지 않는다** — 마우스를
   올리면 강조색을 옅게 깔아 알린다(셸 구분선과 같은 뜻이다). */
.hd-vsplit > .dxbl-splitter-separator {
  background: var(--jsini-border);
}

.hd-vsplit > .dxbl-splitter-separator:hover {
  background: color-mix(in srgb, var(--jsini-accent) 55%, transparent);
}

/* 좁은 화면은 위아래로 쌓는다. 판을 지우지 않고 상자만 없앤다(`display: contents`) — 마크업을 갈아 끼우면 경계를 넘을 때 고른 프로시저와 실행 결과가 다시 만들어진다.
   DevExpress 가 판에 넣은 인라인 폭·좌표는 상자가 없으면 일을 하지 않는다. 구분선은 감춘다 — 끌 자리가 없다. */
@media (width < 992px) {
  .hd-vsplit,
  .hd-vsplit > .dxbl-splitter-pane,
  .hd-vsplit > .dxbl-splitter-pane > .dxbl-splitter-pane-content {
    display: contents;
  }

  .hd-vsplit > .dxbl-splitter-separator { display: none; }

  /* 쪽이 구르는 자리라 판이 스스로 높이를 묶으면 안 된다. */
  .hd-vsplit__pane {
    display: block;
    overflow: visible;
    margin: 0 0 1rem;
  }

  .hd-vsplit__pane > .commcont__body {
    display: block;
  }
}

/* ── 프로시저 목록 ─────────────────────────────────────────────────── */
/* 거르개는 거르는 것 바로 위에 붙박이고 목록만 구른다. 인자 칸과 「실행」은 판 아래에 붙박이로 남는다 — 판 전체가 구르면 고르자마자 단추가 화면 밖으로 밀려난다. */

.hd-procfilter {
  flex: 0 0 auto;
  width: 100%;
  margin-bottom: 0.5rem;
}

.hd-proclist {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;

  /* 좁은 화면은 판이 높이를 안 받으므로(미디어 질의 밖) 여기서 막는다. 안 막으면 프로시저 수십 개가 쪽을 통째로 늘린다. */
  max-height: 22rem;
  overflow-y: auto;
}

@media (width >= 992px) {
  .hd-proclist {
    flex: 1;
    min-height: 6rem;
    max-height: none;
  }
}

.hd-proclist__empty {
  margin: 0.4rem 0;
  font-size: var(--jsini-fs-sm);
  color: var(--jsini-text-muted);
}

/* 줄 하나. `<button>` 이라야 키보드로 닿는다 — 그 대신 단추의 기본 생김새를
   전부 걷어내야 한다. */
.hd-proc {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem;

  width: 100%;
  padding: 0.35rem 0.5rem;
  border: 0;
  border-radius: var(--jsini-radius-sm, 0.25rem);
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.hd-proc:hover {
  background: var(--jsini-surface);
}

.hd-proc:focus-visible {
  outline: 2px solid var(--jsini-accent);
  outline-offset: -2px;
}

/* 고른 줄은 **면으로** 칠한다. 테두리를 두르면 그 줄만 키가 커져 목록이
   들썩인다(테마 서랍의 고른 항목과 같은 규칙). */
.hd-proc.is-on {
  background: color-mix(in srgb, var(--jsini-accent) 14%, transparent);
}

.hd-proc__name {
  font-weight: 600;
  white-space: nowrap;
}

/* 설명은 곁말이라 줄을 늘리지 않는다. 이름이 길면 설명부터 줄어든다. */
.hd-proc__desc {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-align: right;
  font-size: var(--jsini-fs-xs);
  color: var(--jsini-text-muted);
}

/* ── 인자 칸 ────────────────────────────────────────────────────── */
/* 목록 바로 아래, 판 맨 밑에 붙는다. 한 줄에 「이름 · 칸 · 형」을 앉힌다 — 세로로 쌓으면 인자 하나가 세 줄을 먹어 목록이 그만큼 줄어든다.
   이름과 형은 글자만큼만 차지하고 남는 폭은 칸이 갖는다. 좁으면 둘 다 … 로 줄고 칸은 남는다. */

.hd-params {
  flex: 0 0 auto;
  margin-top: 0.75rem;
  padding-top: 0.75rem;
  border-top: 1px solid var(--jsini-border);
}

.hd-params__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  margin-bottom: 0.5rem;
}

.hd-params__title {
  font-size: var(--jsini-fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--jsini-text-muted);
}

.hd-params__fields {
  display: grid;
  grid-template-columns: minmax(0, max-content) minmax(0, 1fr) minmax(0, max-content);
  align-items: center;
  gap: 0.4rem 0.45rem;
  min-width: 0;
}

/* 줄 자신은 상자를 만들지 않는다 — 칸 셋이 바로 위 격자의 칸이 되어야
   줄마다 같은 세로줄에 선다. `<label>` 의 「눌러서 칸에 들어가기」는
   상자가 없어져도 그대로다. */
.hd-param {
  display: contents;
}

/* DevExpress 편집기는 제 내용만큼만 넓다. 격자 칸을 다 쓰게 한다 —
   안 그러면 판을 아무리 넓혀도 값 넣는 칸만 좁은 채로 남는다. */
.hd-params__fields .dxbl-text-edit,
.hd-params__fields .dxbl-date-edit {
  width: 100%;
  min-width: 0;
}

.hd-param__label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 600;
}

/* 설명·형·길이. **값을 막는 데 쓰지 않는다** — 화면이 형을 따지지 않는
   까닭은 화면 머리말에 있다. */
.hd-param__hint {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-align: right;
  font-size: var(--jsini-fs-xs);
  color: var(--jsini-text-muted);
}

/* ── 요청 처리의 「기간」 칸 (`.hd-period`) ────────────────────────────── */
/* 기준(접수·완료) 라디오와 날짜 둘을 한 덩어리로 세운다. 셋은 서로를 바꾸므로 흩어 놓으면 그 관계가 화면에 적히지 않는다.
   바탕은 판보다 한 톤 짙다(`--jsini-surface`). 조회 판이 흰 카드라 테두리만으로는 묻힌다. */

.hd-period {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.35rem 0.75rem;
  padding: 0.3rem 0.6rem;
  border: 1px solid var(--jsini-border);
  border-radius: var(--jsini-radius-sm);
  background: var(--jsini-surface);
  min-width: 0;
}

/* 라디오 묶음은 제 폭만 쓴다 — 자라면 날짜 쪽이 가져간 폭이 항목 사이 빈자리로 가서 한 묶음으로 안 보인다.
   항목 사이 간격은 DevExpress 가 준다(`.dxbl-radio-group` 에는 `gap` 이 없다). 그 안쪽 이름을 겨누지 않는다 — 테마를 올릴 때 조용히 어긋나는 자리다. */
.hd-period__basis {
  flex: 0 0 auto;
}

/* 날짜 둘과 「~」를 한 겹 더 묶는 까닭은 좁아질 때다 — 없으면 라디오·시작·물결표·끝이 제각기 흘러 「~」만 줄 끝에 남는다. */
.hd-period__range {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  flex: 1 1 auto;
  min-width: 0;
}

/* 195px 은 잰 값이다 — 지우개 48 · 달력 29 · 글상자 여백 24 를 빼도 「2026-09-28」(73px)이 들어가야 한다. 170 이면 「2026-09…」로 잘린다.
   인라인(`Style=`)이 아니라 여기 적는다. 인라인은 좁은 화면 규칙보다 세서 거기 두면 휴대폰에서 `!important` 가 붙는다. */
.hd-period__date {
  flex: 0 0 auto;
  width: 195px;
}

.hd-period__tilde {
  flex: 0 0 auto;
  color: var(--jsini-text-muted);
}

/* ── 넓은 화면 — 이 칸은 줄 전체를 쓴다 ───────────────────────────────────── */
/* 조건이 여섯을 넘는 판은 격자로 선다(app.css). 기둥 하나(17rem)에 이 묶음은 안 들어가 날짜가 잘리므로 줄을 통째로 쓴다(`1 / -1`).
   선택자는 app.css 규칙을 베껴 끝에 `.hd-period:last-child` 를 얹는다. 거기 `max-width: 14rem` 이 걸려 있어 자릿수가 모자라면 날짜와 물결표가 밖으로 밀린다. 베낀 덕에 저쪽 조건을 바꾸면 이쪽도 같이 꺼진다. */
@media (min-width: 768px) {
  .commsch:not(.commsch--stacked) .commsch__fields:has(> .commsch__item:nth-child(6)) > .commsch__item:has(> .hd-period) {
    grid-column: 1 / -1;
  }

  /* 기둥에 맞춰 14rem 에서 멈추게 한 규칙이 이 묶음에도 걸린다. 묶음은 제 내용만큼 넓어야 한다 — 줄을 통째로 쓰게 두면 오른쪽에 빈 테두리가 남아 빈 상자로 보인다. */
  .commsch:not(.commsch--stacked) .commsch__fields:has(> .commsch__item:nth-child(6)) .commsch__item > .hd-period:last-child {
    flex: 0 1 auto;
    max-width: none;
  }
}

/* ── 휴대폰 (≤767px) ────────────────────────────────────────────── */
/* 입력칸 폭이 `min(100%, 18rem)` 로 잘리는데 날짜 둘은 288px 에 안 든다(하나가 195px). 이 묶음만 폭 제한을 풀고(100%) 안에서 날짜를 세로로 세운다.
   물결표는 둘 사이 가운데에 남긴다 — 빼면 위아래 날짜가 무엇인지 알 수 없다. `!important` 는 app.css 가 달아 둔 값을 되돌린다. */
@media (max-width: 767px) {
  .commsch__item:has(> .hd-period) > .hd-period {
    width: 100% !important;
    max-width: none;
  }

  .hd-period__range {
    flex-direction: column;
    align-items: stretch;
    flex-basis: 100%;
    gap: 0.25rem;
  }

  .hd-period__date {
    width: 100%;
  }

  /* 날짜 사이에 가운데로 선다. 손가락 자리가 아니라 읽는 표시라 높이를 줄여 둔다 — 한 줄을 다 쓰면 칸 둘이 멀어져 묶은 모습이 풀린다. */
  .hd-period__tilde {
    align-self: center;
    line-height: 1;
    font-size: var(--jsini-fs-xs);
  }
}

@keyframes hd-cmt-blink {
  0% { background-color: transparent; }
  50% { background-color: color-mix(in srgb, var(--jsini-accent) 20%, transparent); }
  100% { background-color: transparent; }
}
.hd-cmt--highlight {
  animation: hd-cmt-blink 1s ease-in-out 3;
}

/* ── 한주운영시스템 모니터링 (`/helpdesk/hanju/system-monitoring`) ──────── */
/* 포털의 기본 테마에는 유틸리티 클래스가 없다(web/CLAUDE.md). 그래서 점수판 칸의 모양을 여기 이름 붙여 둔다. */

.hd-sysmon__bar {
  align-items: center;
}

.hd-sysmon__auto {
  margin-left: auto;
}

.hd-sysmon__head {
  display: flex;
  align-items: center;
  gap: 0.6rem;
}

.hd-sysmon__head > .jsini-subhead {
  margin-bottom: 0;
}

/* 네 칸은 `auto-fit` 이다 — 데스크톱에서 나란히, 휴대폰에서 아래로. 차트 묶음(`hd-charts`)과 같은 규칙이다. */
.hd-sysmon__cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 0.75rem;
  margin: 0.5rem 0 0.25rem;
}

.hd-sysmon__card {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  min-width: 0;
  padding: 0.75rem 0.9rem;
  border: 1px solid var(--jsini-border);
}

.hd-sysmon__card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.4rem;
}

.hd-sysmon__card-title {
  font-size: var(--jsini-fs-xs);
  font-weight: 700;
  color: var(--jsini-text-muted);
}

/* 큰 수 하나. 지표마다 색이 다른 것은 **아래 차트와 짝을 맞추기 위해서**다 —
   CPU 가 파랑이면 1H CPU 선도 파랑이라 눈이 따라간다. */
.hd-sysmon__value {
  font-size: var(--jsini-fs-2xl);
  font-weight: 800;
  line-height: 1.1;
}

.hd-sysmon__value--cpu { color: #1565c0; }
.hd-sysmon__value--io { color: #c62828; }
.hd-sysmon__value--ple { color: #2e7d32; }
.hd-sysmon__value--tps { color: #ef6c00; }

.hd-sysmon__unit {
  margin-left: 0.2rem;
  font-size: var(--jsini-fs-sm);
  font-weight: 600;
}

/* 기준 한 줄. 「표준: 70% 이하 유지」처럼 **숫자를 어떻게 읽는지**를 적는
   자리라 설명(아래)과 굵기로 갈라 둔다. */
.hd-sysmon__guide {
  font-size: var(--jsini-fs-xs);
  font-weight: 700;
  color: var(--jsini-accent);
}

.hd-sysmon__desc {
  margin: 0;
  font-size: var(--jsini-fs-xs);
  line-height: 1.35;
  color: var(--jsini-text-muted);
}

/* 한마디. 위에 가로선을 긋는 것은 **판정이 설명이 아니라는 표시**다. */
.hd-sysmon__advice {
  margin: 0.15rem 0 0;
  padding-top: 0.35rem;
  border-top: 1px solid var(--jsini-border);
  font-size: var(--jsini-fs-xs);
  font-weight: 700;
  font-style: italic;
}

/* 차트 여덟 장은 한 줄에 넷씩(1H 넷 · 24H 넷). 기본 300px 로는 사이드바를 편 상태에서 넷째가 혼자 내려가서 220px 로 줄인다 — 본문 930px 에서도 넷이 선다. */
.hd-charts--quad {
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}

/* ── 경량 SVG 모니터링 차트 (0ms JS 블로킹으로 부드러운 화면 전환) ── */
.hd-sysmon-chartbox {
  display: flex;
  flex-direction: column;
  width: 100%;
  position: relative;
}

.hd-sysmon-chart {
  display: block;
  width: 100%;
  flex: 1 1 auto;
  overflow: visible;
}

.hd-sysmon-legend {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  margin-bottom: 0.35rem;
  font-size: var(--jsini-fs-xs, 0.75rem);
}

.hd-sysmon-legend__item {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  color: var(--jsini-text, #333);
}

.hd-sysmon-legend__swatch {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 2px;
}

.hd-sysmon-legend__dash {
  display: inline-block;
  width: 14px;
  height: 0;
  border-top: 2px dashed currentColor;
}

.hd-sysmon-legend__name {
  font-weight: 500;
  white-space: nowrap;
}

.hd-sysmon-slice {
  cursor: crosshair;
  transition: fill 0.1s ease;
}

.hd-sysmon-slice:hover {
  fill: var(--jsini-hover-bg, rgba(0, 0, 0, 0.05));
}

/* 표에서 임계치를 넘긴 수 · 버틴 수. */
.hd-sysmon__over {
  font-weight: 700;
  color: #d32f2f;
}

.hd-sysmon__safe {
  color: #2e7d32;
}

/* 시간대별 로그 표는 높이 상한(58vh)을 풀어 줄을 모두 세운다. */
.hd-sysmon__log .commgrd {
  --commgrd-max-height: none;
}

/* 자료가 오기 전의 자리표시. 크기를 실제 값·차트와 맞춰 두어 자료가 들어와도 판이 들썩이지 않는다. */
.hd-skel {
  display: block;
  border-radius: 4px;
  background: linear-gradient(90deg,
      color-mix(in srgb, var(--jsini-text-muted) 12%, transparent) 25%,
      color-mix(in srgb, var(--jsini-text-muted) 22%, transparent) 50%,
      color-mix(in srgb, var(--jsini-text-muted) 12%, transparent) 75%);
  background-size: 200% 100%;
  animation: hd-skel-flow 1.4s ease-in-out infinite;
}

.hd-skel--badge {
  display: inline-block;
  width: 3rem;
  height: 1.25rem;
}

.hd-skel--value {
  width: 6rem;
  height: calc(var(--jsini-fs-2xl) * 1.1);
}

.hd-skel--line {
  width: 60%;
  height: 0.9em;
}

.hd-skel--chart {
  width: 100%;
}

@keyframes hd-skel-flow {
  from { background-position: 100% 0; }
  to { background-position: -100% 0; }
}

/* 자료가 들어온 칸은 스며들듯 나타난다 — 자리표시에서 값으로 툭 바뀌면 깜박임으로 읽힌다. */
.hd-sysmon__fade {
  animation: hd-sysmon-in 0.35s ease-out both;
}

@keyframes hd-sysmon-in {
  from { opacity: 0; transform: translateY(4px); }
  to { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .hd-skel,
  .hd-sysmon__fade {
    animation: none;
  }
}

/* ── 한주계량기 수집상태 (`/helpdesk/hanju/gauge-collection`) ─────────── */
/* 왼쪽은 계량기 나무, 오른쪽은 고른 하나의 상태와 이력이다. 좌우를 나누는 규칙은 위 `hd-vsplit` 에 있고, 여기는 판 안쪽만 적는다. */

/* 왼쪽 판의 거르개 셋. 좁은 판에 가로로 늘어서면 글자가 잘리므로 쌓는다. */
.hd-gauge__filters {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  margin-bottom: 0.4rem;
}

.hd-gauge__search {
  margin-bottom: 0.4rem;
}

/* 묶는 기준 셋. 한 줄을 셋이 고르게 나눠 쓴다 — 글자 길이가 달라도
   단추 폭이 같아야 고르개로 읽힌다. */
.hd-gauge__group {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.25rem;
  margin-bottom: 0.5rem;
}

/* 나무는 남은 높이를 다 쓰고 **제 안에서 구른다.** 높이를 값으로 주면
   아래 띠가 판 밖으로 밀려난다(web/CLAUDE.md). */
.hd-gauge__tree {
  flex: 1;
  min-height: 0;
}

/* 나무 줄 하나. 이름 · 곁말 · 설명이 한 줄에 서고, 설명만 줄어든다. */
.hd-gauge__node {
  display: flex;
  align-items: center;
  gap: 0.3rem;
  min-width: 0;
}

.hd-gauge__group-name {
  color: var(--jsini-accent);
}

.hd-gauge__count {
  font-size: var(--jsini-fs-xs);
  color: var(--jsini-text-muted);
}

.hd-gauge__node-dst {
  font-size: var(--jsini-fs-xs);
  color: var(--jsini-text-muted);
}

/* 설명은 남는 자리만 쓰고 넘치면 자른다. 이름이 먼저 읽혀야 한다. */
.hd-gauge__node-desc {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-align: right;
  font-size: var(--jsini-fs-xs);
  color: var(--jsini-text-muted);
}

/* 오른쪽 판은 제 안에서 구른다 — 표 둘이 쌓이면 판보다 길어진다. */
.hd-gauge__right > .commcont__body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
}

/* 액션 줄. 단추 일곱이 좁은 판에서는 다음 줄로 접힌다. */
.hd-gauge__bar {
  flex-wrap: wrap;
  align-items: center;
}

.hd-gauge__bar-right {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin-left: auto;
}

/* 지금 상태 넷(+에러). 타일과 같은 `auto-fit` 이라 좁아지면 접힌다. */
.hd-gauge__facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 0.5rem 1rem;
  margin: 0.5rem 0 0.75rem;
  padding-bottom: 0.6rem;
  border-bottom: 1px solid var(--jsini-border);
}

.hd-gauge__fact {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.hd-gauge__fact-label {
  font-size: var(--jsini-fs-xs);
  font-weight: 700;
  color: var(--jsini-text-muted);
}

.hd-gauge__fact-value {
  font-size: var(--jsini-fs-sm);
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 에러 줄은 한 줄로는 모자란다 — 두 칸을 쓴다. */
.hd-gauge__fact--error {
  grid-column: span 2;
}

.hd-gauge__fact--error .hd-gauge__fact-label,
.hd-gauge__fact--error .hd-gauge__fact-value {
  color: #d32f2f;
}

/* 지연이 있는 값 · 없는 값. 수집 이력 표의 색과 같은 쌍이다. */
.hd-gauge__over {
  color: #d32f2f;
}

.hd-gauge__safe {
  color: #2e7d32;
}

/* 복제 쪽 표는 본래 계량기의 것과 **구분되어야 한다** — 같은 칸 이름이
   두 번 나와서, 머리 색이 같으면 어느 쪽을 보고 있는지 헷갈린다. */
.hd-gauge__replica > .commcont__head > .commcont__title {
  color: #b26a00;
}

/* ── 접수 대시보드 (`/helpdesk/dashboard/reception`) ───────────────── */
/* 위가 나(상태 여섯 · 고리 둘 · 대기 목록), 아래가 남(고객사별 · 담당자별)이다. */

.hd-rcp__auto {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin-left: auto;
}

/* 위 세 덩이. 넓으면 나란히, 좁아지면 아래로 쌓인다 — 상태와 고리는
   좁아져도 읽히지만 대기 목록은 제목이 들어갈 폭이 필요해서 가장 크다. */
.hd-rcp__top {
  display: grid;
  grid-template-columns: minmax(190px, 0.8fr) minmax(260px, 1.2fr) minmax(280px, 1.6fr);
  gap: 0.75rem;
  margin-bottom: 1rem;
}

@media (max-width: 1199px) {
  .hd-rcp__top {
    grid-template-columns: 1fr 1fr;
  }

  /* 대기 목록은 줄이 길어 한 줄을 통째로 쓴다. */
  .hd-rcp__pending {
    grid-column: 1 / -1;
  }
}

@media (max-width: 767px) {
  .hd-rcp__top {
    grid-template-columns: 1fr;
  }
}

/* ── 상태 여섯 ──────────────────────────────────────────── */

.hd-rcp__states {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  min-width: 0;
}

/* 한 줄에 이름과 수. **누르면 그 목록이 열리므로 링크다** —
   `<div @onclick>` 으로 두면 탭으로 닿지 않는다. */
.hd-rcp__state {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  margin: 0;
  padding: 0.4rem 0.7rem;
  color: inherit;
  text-decoration: none;
}

.hd-rcp__state:hover {
  background: var(--jsini-surface-muted, rgba(127, 127, 127, 0.12));
}

.hd-rcp__state-name {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-size: var(--jsini-fs-sm);
  white-space: nowrap;
}

.hd-rcp__state-count {
  font-size: var(--jsini-fs-lg);
  font-weight: 700;
}

/* 괄호 안의 비율. 수보다 작고 흐리다 — 읽는 것은 수가 먼저다. */
.hd-rcp__state-count small {
  margin-left: 0.25rem;
  font-size: var(--jsini-fs-xs);
  font-weight: 400;
  color: var(--jsini-text-muted);
}

/* ── 고리 둘 ────────────────────────────────────────────── */

.hd-rcp__gauges {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.5rem;
  min-width: 0;
}

.hd-rcp__gauge {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.25rem;
  margin: 0;
  min-width: 0;
}

.hd-rcp__gauge-title {
  font-size: var(--jsini-fs-sm);
}

/* 고리와 그 가운데 글자. 글자를 고리 위에 얹어야 하므로 자리의 기준이 된다. */
.hd-rcp__gauge-ring {
  position: relative;
  display: inline-flex;
  color: inherit;
  text-decoration: none;
}

.hd-rcp__gauge-value {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;

  /* 고리 가운데라 **누름을 가로채면 안 된다** — 글자를 눌러도 링크가
     열려야 한다. */
  pointer-events: none;

  font-size: var(--jsini-fs-xl);
  font-weight: 700;
}

.hd-rcp__gauge-under {
  font-size: var(--jsini-fs-xs);
  color: var(--jsini-text-muted);
}

/* ── 대기 중인 요청 ─────────────────────────────────────── */

.hd-rcp__pending {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  min-width: 0;
  max-height: 22rem;
  overflow-y: auto;
}

.hd-rcp__pending-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem;
  margin: 0 0 0.25rem;
  font-size: var(--jsini-fs-sm);
  font-weight: 700;
}

.hd-rcp__more {
  font-size: var(--jsini-fs-xs);
  font-weight: 400;
}

/* 요청 한 줄 — 그림 · 제목 · 쓴 사람. 제목만 줄어든다. */
.hd-rcp__req {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.35rem 0.4rem;
  border-top: 1px solid var(--jsini-border);
  color: inherit;
  text-decoration: none;
  min-width: 0;
}

.hd-rcp__req:first-of-type {
  border-top: 0;
}

.hd-rcp__req:hover {
  background: var(--jsini-surface-muted, rgba(127, 127, 127, 0.12));
}

.hd-rcp__req-thumb {
  flex: 0 0 auto;
  width: 3.4rem;
  height: 2.4rem;
  object-fit: cover;
  border-radius: 2px;
}

/* 그림이 없는 줄도 **같은 자리를 먹는다** — 안 그러면 제목이 시작하는
   세로줄이 줄마다 어긋나 목록이 들쭉날쭉해진다. */
.hd-rcp__req-thumb--none {
  display: inline-block;
  background: var(--jsini-surface-muted, rgba(127, 127, 127, 0.12));
}

.hd-rcp__req-title {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: var(--jsini-fs-sm);
}

.hd-rcp__req-who {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  font-size: var(--jsini-fs-xs);
  color: var(--jsini-text-muted);
}

.hd-rcp__req-when {
  white-space: nowrap;
}

/* ── 고객사 · 담당자 카드 ───────────────────────────────── */

.hd-rcp__card {
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
  margin: 0;
  min-width: 0;
}

.hd-rcp__card-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem;
  min-width: 0;
}

/* 담당자 카드는 얼굴이 앞에 선다 — 글자가 아니라 얼굴로 찾는 자리다. */
.hd-rcp__card-head--who {
  align-items: center;
}

.hd-rcp__face {
  --jsini-face-size: 2rem;
}

.hd-rcp__card-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 700;
}

.hd-rcp__card-sub {
  flex: 0 0 auto;
  font-size: var(--jsini-fs-xs);
  color: var(--jsini-text-muted);
}

/* 비율 띠. 회사 카드와 담당자 카드가 함께 쓴다. */
.hd-rcp__bar-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  font-size: var(--jsini-fs-xs);
}

.hd-rcp__bar-track {
  display: block;
  height: 6px;
  margin-top: 0.15rem;
  background: var(--jsini-surface-muted, rgba(127, 127, 127, 0.18));
}

.hd-rcp__bar-fill {
  display: block;
  height: 100%;
}

.hd-rcp__counts {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.15rem 0.6rem;
}

.hd-rcp__count {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.15rem 0.25rem;
  color: inherit;
  text-decoration: none;
  min-width: 0;
}

.hd-rcp__count:hover {
  background: var(--jsini-surface-muted, rgba(127, 127, 127, 0.12));
}

.hd-rcp__count-label {
  font-size: var(--jsini-fs-sm);
  white-space: nowrap;
}

.hd-rcp__count-value {
  margin-left: auto;
}

.hd-rcp__admin-counts {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 0.2rem;
}

.hd-rcp__n {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 0.2rem 0;
  color: inherit;
  text-decoration: none;
}

.hd-rcp__n:hover {
  background: var(--jsini-surface-muted, rgba(127, 127, 127, 0.12));
}

.hd-rcp__n-value {
  font-size: var(--jsini-fs-sm);
  font-weight: 700;
}

.hd-rcp__n-label {
  font-size: var(--jsini-fs-2xs);
  color: var(--jsini-text-muted);
}

.hd-rcp__n--wait { color: #2563eb; }
.hd-rcp__n--run { color: #ea580c; }
.hd-rcp__n--done { color: #16a34a; }
.hd-rcp__n--talk { color: #9333ea; }
.hd-rcp__n--talk2 { color: #4f46e5; }

/* ── 유지보수 현황 (`/helpdesk/monitor/maintenance`) ───────────────── */
/* 년월 입력부를 눌러도 달력 다이얼로그가 뜨게 한다 — 드롭다운 단추의 `::after` 가 입력창 전체를 덮어, 입력부 클릭이 달력 단추 클릭과 같아진다. */
.hd-maintenance-period,
.hd-maintenance-period input {
  cursor: pointer;
}

.hd-maintenance-period button {
  position: static !important;
}

.hd-maintenance-period button::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 1;
  cursor: pointer;
}

@media (max-width: 767px), (pointer: coarse) {
  .hd-maintenance-period input {
    caret-color: transparent;
    -webkit-user-select: none;
    user-select: none;
  }
}

