/* 탄스 화면 공통: 기본 부품(단추·입력·표·알림·표식)·셸(옆 막대·메뉴·탭 줄)·로그인·안내 화면
 *
 * 색·크기는 tokens.css 의 값만 쓴다. 사무 화면은 PC 우선, 현장·설치기사 화면은 폰·태블릿 우선이다.
 *
 * 2026-10-15 전면 개편(docs/design/ui.md 7절, 참고 전산의 화면 체계를 다시 써서 들임). 지난 배치와 달라진 것:
 *  · 메뉴: 여닫는 유리 서랍(761px 이상)을 걷고, 흰 위 막대에 메뉴를 늘 펼쳐 둔다. 어디로 갈 수 있는지가 늘 보인다.
 *    폰은 같은 메뉴가 아래 탭 막대가 된다. 화면 안의 작은 탭은 위 막대 둘째 줄(밑줄 탭)이다.
 *  · 모양: 알약 단추·알약 탭·그림자 카드를 걷었다. 단추·입력 4px, 표·칸 6px, 그림자는 떠 있는 것(대화 상자·펼친 메뉴)만.
 *  · 덩어리는 1px 선으로 나눈다. 표는 머리줄 옅은 띠 + 줄 사이 옅은 선, 칸 안 여백을 줄여 한 화면에 줄이 더 든다.
 *  · 짙은 면(위 막대·로그인 왼쪽 칸·안내 화면 머리)을 걷었다. 밝은 면 위에서 강조색이 보여 고른 것을 밑줄 하나로 가른다.
 * 화면 코드(JS)가 쓰는 클래스·data 속성·문구·칸 순서는 그대로다. 바뀐 마크업은 app.html·login.html·403.html·404.html 뿐이다.
 * 2026-10-17: 메뉴를 위 막대에서 왼쪽 옆 막대로 옮겼다(ui.md 9절, 아래 앱 셸 절). 작은 탭은 본문 위 탭 줄(.subbar)로 따로 섰다.
 * ⚠️ 줌을 막지 않는다(viewport 에 maximum-scale·user-scalable 을 적지 않는다).
 */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  margin: 0;
  min-height: 100vh;
  min-height: 100dvh;
  background: var(--t-bg);
  color: var(--t-text);
  font-family: var(--t-font);
  font-size: var(--t-fs);
  font-weight: var(--t-w-regular);
  line-height: 1.5;
  letter-spacing: 0;
  /* 한국어는 낱말(어절) 단위로 줄을 바꾼다. 폰에서 "없습/니다" 처럼 끊겼다(점검 C7). 아주 긴 영문·번호만 아무 데서나 끊는다 */
  word-break: keep-all;
  overflow-wrap: anywhere;
  -webkit-font-smoothing: antialiased;
}

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

h1,
h2,
h3 {
  font-weight: var(--t-w-medium);
}

strong {
  font-weight: var(--t-w-strong);
}

a {
  color: inherit;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}

:focus-visible {
  outline: 2px solid var(--t-focus);
  outline-offset: 2px;
}

[hidden] {
  display: none !important;
}

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

/* 숫자·번호·시각: 본문 글꼴 그대로 자릿수만 맞춘다. Pretendard 숫자는 기본이 비례폭이라 이것이 없으면 줄마다 자리가 흔들린다 */
.num {
  font-variant-numeric: tabular-nums;
  letter-spacing: 0;
}

.muted {
  color: var(--t-text-2);
}

/* 로고: 투명 여백을 잘라 낸 파일이라 높이가 곧 글자 높이다. 가로는 비율대로(1208:345) 따라오게 auto.
   ⚠️ 늘이기·기울이기·그림자·외곽선·다른 색 금지(브랜드 가이드). 어두운 테마는 <picture> 가 흰색판으로 바꾼다.
   <picture> 는 상자를 만들지 않게 두어 그림이 바로 부모의 flex·grid 칸이 되게 한다. */
.brand-mark {
  display: contents;
}

.brand-logo {
  display: block;
  width: auto;
  height: var(--t-logo-h);
  filter: var(--t-logo-filter);
}

/* ── 단추: 기본(흰 면 + 선) · 주요(강조색 채움) · 위험(주홍 글자와 선) 셋만 ─────────────────
   화면 하나에 주요 단추는 하나(많아도 둘)만 둔다. 채움 색이 여럿이면 무엇이 중요한지 읽히지 않는다.
   위험 단추는 채우지 않는다. 채운 붉은색은 화면에서 가장 먼저 눈에 띄어 잘못 누르기 쉽다.
   기본 단추는 홈페이지의 테두리 단추와 같은 말씨: 따뜻한 회색 선, 마우스를 올리면 글자색 테두리(2026-10-15 2차). */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--t-space-2);
  min-height: var(--t-control);
  padding: 0 12px;
  border: 1px solid var(--t-line-control);
  border-radius: var(--t-r);
  background: var(--t-surface);
  color: var(--t-text);
  font: inherit;
  font-size: var(--t-fs-ui);
  font-weight: var(--t-w-medium);
  line-height: 1.2;
  letter-spacing: 0;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color var(--t-dur), border-color var(--t-dur), color var(--t-dur);
}

.btn:hover {
  border-color: var(--t-text);
  background: var(--t-surface);
}

.btn:active {
  background: var(--t-sunk);
}

.btn:disabled {
  cursor: not-allowed;
  opacity: 0.45;
}

.btn:disabled:hover {
  border-color: var(--t-line-control);
  background: var(--t-surface);
}

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

.btn-primary:hover,
.btn-primary:active {
  border-color: var(--t-accent-hover);
  background: var(--t-accent-hover);
}

.btn-primary:disabled:hover {
  border-color: var(--t-accent);
  background: var(--t-accent);
}

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

.btn-danger:hover,
.btn-danger:active {
  border-color: var(--t-danger);
  background: var(--t-danger-bg);
}

.btn-sm {
  min-height: var(--t-control-sm);
  padding: 0 9px;
  font-size: var(--t-fs-sm);
}

.btn-block {
  width: 100%;
}

/* 세로로 쌓는 칸(stack·screen) 안의 버튼이 칸 폭만큼 늘어나지 않게. 가득 채울 때만 btn-block */
.stack > .btn:not(.btn-block),
.screen > .btn:not(.btn-block),
.stage > .btn:not(.btn-block) {
  justify-self: start;
  align-self: flex-start;
}

@media (pointer: coarse) {
  .btn {
    min-height: var(--t-touch);
  }

  .btn-sm {
    min-height: 40px;
  }
}

/* ── 입력 ─────────────────────────────────────────────────────────────── */
.field {
  display: grid;
  align-content: start;
  gap: 4px;
}

/* 칸 이름은 값보다 작고 흐리게. 이름이 값보다 크면 눈이 이름에 먼저 간다 */
.field-label {
  color: var(--t-text-2);
  font-size: var(--t-fs-sm);
  font-weight: var(--t-w-medium);
}

.input,
.select {
  width: 100%;
  height: var(--t-input-h);
  padding: 0 10px;
  border: 1px solid var(--t-line-strong);
  border-radius: var(--t-r);
  background: var(--t-surface);
  color: var(--t-text);
  font: inherit;
  font-size: var(--t-fs-input);
  letter-spacing: 0;
  transition: border-color var(--t-dur), box-shadow var(--t-dur);
}

/* 여러 줄 칸은 높이를 고정하지 않는다(rows 를 따른다) */
textarea.input {
  height: auto;
  min-height: 64px;
  padding: 7px 10px;
  line-height: 1.5;
  resize: vertical;
}

.input[type="search"] {
  -webkit-appearance: none;
  appearance: none;
}

.input::placeholder {
  color: var(--t-text-3);
}

.input:hover,
.select:hover {
  border-color: var(--t-text-3);
}

.input:focus,
.select:focus {
  border-color: var(--t-focus);
  box-shadow: 0 0 0 3px var(--t-focus-ring);
  outline: none;
}

.input:disabled,
.select:disabled {
  background: var(--t-sunk);
  color: var(--t-text-2);
  cursor: not-allowed;
}

.select {
  -webkit-appearance: none;
  appearance: none;
  padding-right: 28px;
  background-image: var(--t-select-arrow);
  background-repeat: no-repeat;
  background-position: right 10px center;
  background-size: 9px 6px;
}

/* 파일 고르기: 브라우저 기본 단추를 우리 버튼 모양으로 */
.input[type="file"] {
  height: auto;
  min-height: var(--t-input-h);
  padding: 4px;
  font-size: var(--t-fs-sm);
}

.input[type="file"]::file-selector-button {
  height: calc(var(--t-input-h) - 10px);
  margin-right: 8px;
  padding: 0 10px;
  border: 1px solid var(--t-line-control);
  border-radius: var(--t-r);
  background: var(--t-surface);
  color: var(--t-text);
  font: inherit;
  font-weight: var(--t-w-medium);
  cursor: pointer;
}

.input[type="file"]::file-selector-button:hover {
  border-color: var(--t-line-strong);
  background: var(--t-hover);
}

/* [파일 고르기] 단추 + 고른 파일 이름(dom.js fileField). 숨긴 input 에 초점이 가면 단추에 초점선을 그린다 */
.file-pick {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--t-space-3);
  min-width: 0;
}

.file-pick label:focus-within {
  outline: 2px solid var(--t-focus);
  outline-offset: 2px;
}

.file-pick-name {
  min-width: 0;
  color: var(--t-text-2);
  font-size: var(--t-fs-sm);
}

/* 접어 둔 자세한 내용(설정 > 수합의 설정 이름 등). 평소에는 필요 없는 값이라 접힌 채로 둔다 */
.more-detail {
  display: grid;
  gap: var(--t-space-3);
}

.more-detail > summary {
  justify-self: start;
  color: var(--t-text-2);
  font-size: var(--t-fs-sm);
  cursor: pointer;
}

.input-short {
  width: 80px;
}

input[type="checkbox"],
input[type="radio"] {
  accent-color: var(--t-accent);
}

.check {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: var(--t-control);
  font-size: var(--t-fs-sm);
}

.check input {
  width: 14px;
  height: 14px;
  margin: 0;
}

/* 손가락 기기: 작은 네모는 누르기 어려워 크게 */
@media (pointer: coarse) {
  .check input {
    width: 18px;
    height: 18px;
  }
}

.hint {
  color: var(--t-text-3);
  font-size: var(--t-fs-xs);
}

/* 칸이 옆 칸보다 짧아도 줄 사이가 벌어지지 않게 위로 붙인다(격자의 기본값은 늘이기다) */
.stack {
  display: grid;
  align-content: start;
  gap: 10px;
}

.row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--t-space-2);
}

.row-between {
  justify-content: space-between;
}

/* 안내 문구: 비어 있으면 자리를 차지하지 않는다. */
.form-message {
  font-size: var(--t-fs-sm);
}

.form-message:empty {
  display: none;
}

.form-message[data-state="error"] {
  color: var(--t-danger);
}

.form-message[data-state="ok"] {
  color: var(--t-ok);
}

/* ── 알림 띠·표식 ─────────────────────────────────────────────────────── */
/* 알림은 왼쪽 굵은 선으로 종류를 먼저 알리고, 바탕은 옅게 둔다. 기본 notice 는 경고(황토)다.
   뜻 없는 안내는 notice-info(안내 띠 색 + 회색 선). 강조색은 고른 것에만 쓰므로 안내 선에 쓰지 않는다. */
.notice {
  padding: 8px 12px;
  border-left: 3px solid var(--t-warn);
  border-radius: var(--t-r);
  background: var(--t-warn-bg);
  color: var(--t-text);
  font-size: var(--t-fs-sm);
}

.notice-info {
  border-left-color: var(--t-line-strong);
  background: var(--t-calm);
}

.notice-danger {
  border-left-color: var(--t-danger);
  background: var(--t-danger-bg);
}

.notice-ok {
  border-left-color: var(--t-ok);
  background: var(--t-ok-bg);
}

/* 작은 표식: 각진 작은 칸에 옅은 채움. 주문 상태·상품구분 색(.badge.status-*, .badge.kind-*)은 work.css.
   알약 모양을 걷었다(2026-10-15). 표 한 줄에 표식이 서넛 붙어도 덩어리로 뭉쳐 보이지 않게 크기도 줄였다. */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  height: 18px;
  padding: 0 6px;
  border-radius: var(--t-r-sm);
  background: var(--t-calm);
  color: var(--t-text-2);
  font-size: var(--t-fs-xs);
  font-weight: var(--t-w-medium);
  line-height: 1;
  letter-spacing: 0;
  vertical-align: middle;
  white-space: nowrap;
}

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

.badge-danger {
  background: var(--t-danger-bg);
  color: var(--t-danger);
}

.badge-ok {
  background: var(--t-ok-bg);
  color: var(--t-ok);
}

.badge-strong {
  background: var(--t-accent);
  color: var(--t-accent-text);
}

/* ── 표: 흰 면에 옅은 테두리, 머리줄은 옅은 띠, 줄 사이는 더 옅은 선 ───────────────────────
   줄무늬는 넣지 않는다. 상태 색 표시와 겹쳐 눈이 어지럽고, 마우스 올림 표시와도 헷갈린다.
   칸은 줄바꿈하지 않고 표가 넓으면 옆으로 민다(좁은 화면에서 글자가 한 자씩 세로로 쌓이지 않게).
   긴 글(접속기록의 대상, 엑셀 오류 이유)만 cell-wrap 으로 줄을 바꾼다.
   숫자는 표 전체에 자릿수 맞춤을 건다(날짜·번호·크기가 위아래로 줄을 맞춘다. 한글에는 영향이 없다). */
.table-wrap {
  overflow-x: auto;
  border: 1px solid var(--t-line);
  border-radius: var(--t-r-lg);
  background: var(--t-surface);
  -webkit-overflow-scrolling: touch;
}

.table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--t-fs-ui);
  font-variant-numeric: tabular-nums;
}

.table th,
.table td {
  padding: 7px 10px;
  border-bottom: 1px solid var(--t-line-soft);
  text-align: left;
  vertical-align: middle;
  white-space: nowrap;
}

/* 첫 칸·끝 칸은 표 모서리에서 조금 더 떨어뜨린다 */
.table th:first-child,
.table td:first-child {
  padding-left: 14px;
}

.table th:last-child,
.table td:last-child {
  padding-right: 14px;
}

/* 머리줄: 칸 이름이지 제목이 아니다. 작고 흐리게, 옅은 띠 위에 */
.table thead th {
  padding-top: 8px;
  padding-bottom: 8px;
  border-bottom-color: var(--t-line);
  background: var(--t-sunk);
  color: var(--t-text-2);
  font-size: var(--t-fs-sm);
  font-weight: var(--t-w-medium);
}

/* 줄 머리(가격표의 크기 이름 등)는 본문 칸과 같은 결에 굵기만 */
.table tbody th {
  font-weight: var(--t-w-medium);
}

/* 테두리 상자 안이라 마지막 줄의 밑선은 겹친다 */
.table tbody tr:last-child > td,
.table tbody tr:last-child > th {
  border-bottom: 0;
}

.table .cell-actions {
  white-space: nowrap;
}

/* 표 안의 작은 단추(수정 · 재고 확인 등)는 상태 고르기 칸(24px)과 같은 높이로. 줄 높이를 단추가 정하지 않게(PC 마우스만) */
@media (pointer: fine) {
  .table .btn-sm {
    min-height: 24px;
    padding: 0 8px;
  }
}

.table .cell-wrap {
  min-width: 112px;
  white-space: normal;
  word-break: break-all;
}

.table-empty {
  padding: 32px 8px;
  color: var(--t-text-3);
  text-align: center;
}

/* 폰에서 줄마다 카드(2026-10-11 점검 C2). 표가 옆으로만 밀려 상태·날짜가 첫 화면에 안 보였고, 밀 수 있는지도 몰랐다.
   표에 table-cards 를 더하고 칸마다 data-label(머리줄 이름)을 적으면 760px 이하에서 "이름 값" 두 줄 격자 카드가 된다.
   · cell-main: 카드 맨 위 한 줄 전체(번호·이름 같은 제목 칸). 라벨을 적지 않는다.
   · cell-full: 한 줄 전체를 쓰는 긴 칸(대상·메모·단추 묶음).
   · cell-hide-m: 폰 카드에서 뺄 칸(같은 값이 다른 칸에 있거나 상세에서 보는 값).
   PC 표는 그대로다. 머리줄은 화면 읽기 도구를 위해 남기되 보이지 않게 둔다.
   ⚠️ 줄 누르기(상세 열기)·고르기 칸은 칸의 내용이 그대로라 화면 쪽 코드는 바꾸지 않아도 된다. */
@media (max-width: 760px) {
  .table-wrap:has(> .table-cards) {
    overflow: visible;
    border: 0;
    background: none;
  }

  .table-cards,
  .table-cards tbody,
  .table-cards tr,
  .table-cards td {
    display: block;
  }

  .table-cards thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
  }

  .table-cards tbody {
    display: grid;
    gap: var(--t-space-2);
  }

  .table-cards tbody tr {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 6px 12px;
    padding: 10px 12px;
    border: 1px solid var(--t-line);
    border-radius: var(--t-r-lg);
    background: var(--t-surface);
  }

  .table-cards tbody td,
  .table-cards tbody td:first-child,
  .table-cards tbody td:last-child {
    display: block;
    min-width: 0;
    padding: 0;
    border: 0;
    font-size: var(--t-fs-ui);
    white-space: normal;
    overflow-wrap: anywhere;
  }

  /* 라벨은 칸 안 맨 위 한 줄. 칸은 block 이라 안의 번호·배지 같은 여러 글이 한 줄로 이어진다(grid 면 하나씩 세로로 쌓였다) */
  .table-cards tbody td[data-label]::before {
    content: attr(data-label);
    display: block;
    margin-bottom: 1px;
    color: var(--t-text-2);
    font-size: var(--t-fs-xs);
    font-weight: var(--t-w-medium);
  }

  .table-cards tbody td.cell-main {
    grid-column: 1 / -1;
    font-size: var(--t-fs-md);
    font-weight: var(--t-w-medium);
  }

  .table-cards tbody td.cell-full,
  .table-cards tbody td.table-empty {
    grid-column: 1 / -1;
  }

  .table-cards tbody td.cell-hide-m {
    display: none;
  }

  /* cell-pick: 고르기 네모 칸. 카드 오른쪽 위 모서리에 띄워 제목 줄과 한 줄에 둔다(혼자 한 칸을 차지하면 카드가 길어진다) */
  .table-cards tbody tr:has(> td.cell-pick) {
    position: relative;
    padding-right: 44px;
  }

  .table-cards tbody td.cell-pick {
    position: absolute;
    top: 4px;
    right: 4px;
    display: grid;
    place-items: center;
    width: 40px;
    height: 40px;
  }

  .table-cards tbody td.cell-pick:empty {
    display: none;
  }

  /* 빈 결과 줄은 카드 하나로 */
  .table-cards tbody td.table-empty {
    padding: 24px 8px;
    text-align: center;
  }
}

/* ── 로그인: 홈페이지 로그인(web/login.html)과 같은 짜임 ──────────────────────────────────
   넓은 화면(1020px 이상)은 왼쪽 반에 탄스 사진, 오른쪽 반에 로고 · 작은 머리말 · 큰 제목 · 입력. 폰은 입력만(사진은 받지도 않는다).
   2026-10-15 2차(ui.md 8절): 1차의 가운데 흰 칸을 홈페이지 짜임으로 바꿨다. 입력은 칸에 담지 않고 바탕 위에 바로 둔다(홈페이지와 같다).
   사진은 CSS 배경으로 넓은 화면에서만 부른다. <img> 로 두면 폰에서 숨겨도 내려받는다.
   ⚠️ 로그인 폼의 data-*·name·autocomplete 는 login.js 와 브라우저 비밀번호 저장이 쓴다. 모양만 바꾼다.
   ⚠️ 사진은 저장소 안의 파일만(/assets/img/, CSP img-src 'self'). 출처는 /assets/img/README.md. */
.page-login {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
}

.login-media {
  display: none;
}

.login-panel {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 48px 24px calc(48px + env(safe-area-inset-bottom));
}

/* 로그인 칸(첫 로그인 비밀번호 바꾸기도 같은 칸을 쓴다, app.js renderTempPassword) */
.login-card {
  width: 100%;
  max-width: 400px;
}

/* 로고(24px)의 보호 여백 12px 이상을 아래에 넉넉히 둔다 */
.login-brand {
  margin-bottom: 40px;
}

.login-brand .brand-logo {
  height: var(--t-logo-h-lg);
}

.login-eyebrow {
  color: var(--t-text-2);
  font-size: var(--t-fs-md);
}

.login-title {
  margin-top: var(--t-space-2);
  font-size: var(--t-fs-display);
  line-height: 1.3;
}

.login-lead {
  margin-top: var(--t-space-3);
  margin-bottom: var(--t-space-6);
  color: var(--t-text-2);
  font-size: var(--t-fs);
  line-height: 1.6;
}

/* 로그인 칸의 입력·단추는 홈페이지 회원 화면처럼 한 단계 크게(PC 44px, 손가락 기기는 원래 크기 이상) */
.login-card .input {
  height: max(44px, var(--t-input-h));
  font-size: max(15px, var(--t-fs-input));
}

.login-card .field-label {
  color: var(--t-text);
  font-size: var(--t-fs);
}

.login-card .btn-block {
  min-height: max(44px, var(--t-control));
  margin-top: var(--t-space-2);
  font-size: var(--t-fs-nav);
}

.login-help {
  margin-top: var(--t-space-3);
  padding-top: var(--t-space-5);
  border-top: 1px solid var(--t-rule);
  color: var(--t-text-2);
  font-size: var(--t-fs-sm);
}

@media (min-width: 1020px) {
  .page-login {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  }

  /* 사진: 칸을 꽉 채우고(잘라 맞춤) 책상·선반이 가운데 오게. 화면 높이에 붙여 둔다 */
  .login-media {
    position: sticky;
    top: 0;
    display: block;
    height: 100vh;
    height: 100dvh;
    background: var(--t-sunk) url("../img/hero-desk-shelf-workspace.jpg") 56% 50% / cover no-repeat;
  }
}

@media (max-width: 760px) {
  .login-panel {
    justify-content: flex-start;
    padding-top: calc(40px + env(safe-area-inset-top));
  }

  .login-brand {
    margin-bottom: 32px;
  }
}

/* ── 앱 셸: 왼쪽 옆 막대(메뉴)와 본문 위 탭 줄 ──────────────────────────────────
 * 2026-10-17 요청("메뉴를 왼쪽 사이드바 형식으로")으로 위 막대에 펼쳐 두던 메뉴를 왼쪽 옆 막대로 옮겼다(docs/design/ui.md 9절).
 * 2026-10-15 개편의 약속은 그대로다: 메뉴는 늘 보이고(여닫는 서랍을 두지 않는다), 흰 면과 구획 선, 각진 모양이다.
 *  · 1280px 이상(PC): 흰 옆 막대(--t-side). 위에서부터 로고 · 메뉴(그림 + 이름 한 줄) · 맨 아래 내 이름(이름 아래 역할).
 *    고른 메뉴는 표의 고른 줄(회원·문의)과 같은 말씨: 옅은 강조 바탕 + 왼쪽 강조색 막대 3px. 그림도 강조색이다.
 *  · 761~1279px(태블릿·좁은 창): 좁은 옆 막대(--t-rail). 폰 아래 탭 막대와 같은 칸(그림 위 + 이름 아래)을 세로로 쌓는다.
 *    넓은 막대보다 본문 폭을 120px 덜 먹는다. 넓은 막대를 1020px 부터 두었더니 1020~1279px(아이패드 가로 등)에서
 *    주문·작업지시서·문의 표가 옆으로 밀렸다(본문 773px 에 표 850~960px, 시연 데이터로 잼). 좁은 막대면 그 폭에서도 표가 든다.
 *  · 760px 이하(폰): 같은 header 가 맨 위 막대(로고 · 내 이름)가 되고, nav.menu 는 화면 아래 탭 막대로 그려진다(아래 폰 절, 전과 같다).
 *  · 화면 안의 작은 탭(dom.js setSubTabs)은 본문 위에 붙는 탭 줄(.subbar). 탭이 있는 화면에서만 보인다(.has-subtabs).
 *    긴 표를 내려도 탭이 보이고 화면마다 탭 자리가 같다(2026-10-11 T-31EBB914 의 약속을 그대로 지킨다).
 * HTML 은 app.html, 메뉴 칸은 app.js 가 서버 /api/me 로 a.menu-item[href="/app/<키>"][aria-current="page"] 꼴로 그린다.
 * ⚠️ header 에 backdrop-filter·transform·filter 를 걸지 않는다. 그 순간 header 가 position: fixed 의 기준이 되어
 *    폰 아래 탭 막대(같은 nav, position: fixed)가 화면 아래가 아니라 막대 안에 붙는다.
 * ⚠️ 옆 막대 전체에 overflow 를 걸지 않는다. 좁은 옆 막대의 내 메뉴(.me-panel)는 막대 오른쪽 밖으로 펼쳐지는데 그것이 잘린다.
 *    낮은 창에서 메뉴가 넘치면 nav.menu 만 세로로 민다.
 * ⚠️ 옆 막대는 position: fixed 라 흐름에서 빠지고 body 의 왼쪽 여백이 그 자리를 비워 둔다. 그래서 app.js 가 body 맨 앞에 넣는
 *    시연 띠와 탭 줄·수합 알림 띠·본문은 모두 옆 막대 오른쪽 칸에 그려진다(띠가 막대와 겹치지 않는다).
 * ⚠️ 수합 알림 띠(.collect-alert, orders.css 에서 sticky)는 app.js 가 본문 바로 앞(탭 줄 뒤)에 넣는다. 붙는 높이는 아래 .appbar ~ .collect-alert. */
.appbar {
  z-index: 15;
  background: var(--t-surface);
}

/* 위에 붙는 것(옆 칸·수합 알림 띠·내려 보낼 자리)이 그 아래에 붙는 높이. 화면마다 계산하지 않고 이 값 하나만 본다.
   옆 막대가 있는 폭에서 위에 붙는 것은 탭 줄뿐이라 탭이 없으면 0 이다. 폰은 위 막대 + 탭 줄(아래 폰 절).
   ⚠️ 0 이 아니라 0px 로 적는다. calc(var(--t-head) + 12px) 안에서 단위 없는 0 은 식 전체를 무효로 만든다. */
:root {
  --t-head: 0px;
}

:root:has(.subbar.has-subtabs) {
  --t-head: var(--t-subbar);
}

.appbar-brand {
  display: flex;
  flex: none;
  align-items: center;
  border-radius: var(--t-r);
}

.menu {
  display: flex;
  min-width: 0;
}

/* 메뉴 칸 공통. 칸 배치(그림 + 이름 한 줄 · 그림 위 이름 아래)와 고른 칸 표시는 폭마다 아래 절에서 정한다 */
.menu-item {
  position: relative;
  display: flex;
  flex: none;
  align-items: center;
  color: var(--t-text);
  text-decoration: none;
  white-space: nowrap;
  transition: background-color var(--t-dur), color var(--t-dur);
}

/* 메뉴 그림. 주소 끝으로 고른다(메뉴 키 = 주소 /app/<키>).
   ⚠️ 그림은 mask 로 글자색을 입힌다. filter 로 색을 바꾸지 않는다. */
.menu-item::before {
  content: "";
  flex: none;
  width: 22px;
  height: 22px;
  background-color: currentColor;
  -webkit-mask: var(--menu-icon, none) no-repeat center / contain;
  mask: var(--menu-icon, none) no-repeat center / contain;
}

.menu-item[href$="/app/today"] { --menu-icon: var(--t-icon-today); }
.menu-item[href$="/app/products"] { --menu-icon: var(--t-icon-products); }
.menu-item[href$="/app/orders"] { --menu-icon: var(--t-icon-orders); }
.menu-item[href$="/app/workorders"] { --menu-icon: var(--t-icon-workorders); }
.menu-item[href$="/app/field"] { --menu-icon: var(--t-icon-field); }
.menu-item[href$="/app/shipping"] { --menu-icon: var(--t-icon-shipping); }
.menu-item[href$="/app/inquiries"] { --menu-icon: var(--t-icon-inquiries); }
.menu-item[href$="/app/members"] { --menu-icon: var(--t-icon-members); }
.menu-item[href$="/app/settings"] { --menu-icon: var(--t-icon-settings); }
.menu-more { --menu-icon: var(--t-icon-more); }

/* 내 이름 · 역할. 펼치면 비밀번호 변경 · 로그아웃. 이름 앞에 사람 그림 하나(홈페이지 폰 머리글과 같은 그림) */
.me {
  position: relative;
}

.me > summary {
  display: flex;
  align-items: center;
  gap: var(--t-space-2);
  color: var(--t-text);
  list-style: none;
  cursor: pointer;
  transition: background-color var(--t-dur), border-color var(--t-dur);
}

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

.me > summary::before {
  content: "";
  flex: none;
  width: 18px;
  height: 18px;
  background-color: currentColor;
  -webkit-mask: var(--t-icon-person) no-repeat center / contain;
  mask: var(--t-icon-person) no-repeat center / contain;
}

.me > summary::after {
  content: "";
  flex: none;
  width: 8px;
  height: 6px;
  background: var(--t-select-arrow) no-repeat center / 8px 6px;
  transition: transform var(--t-dur);
}

.me[open] > summary::after {
  transform: rotate(180deg);
}

.me-text {
  display: flex;
  align-items: baseline;
  gap: var(--t-space-2);
  min-width: 0;
}

.me-text [data-me-name] {
  min-width: 0;
  max-width: 14em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.me-role {
  color: var(--t-text-2);
}

.me-panel {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  z-index: 20;
  display: grid;
  gap: 2px;
  min-width: 168px;
  padding: 4px;
  border: 1px solid var(--t-line);
  border-radius: var(--t-r-lg);
  background: var(--t-surface);
  box-shadow: var(--t-shadow);
}

.me-panel .btn {
  justify-content: flex-start;
  border-color: transparent;
  font-size: var(--t-fs-md);
  font-weight: var(--t-w-regular);
}

.me-panel .btn:hover {
  border-color: transparent;
  background: var(--t-hover);
}

/* 시연 띠: 홈페이지 맨 위 알림 띠와 같은 넓은 띠 한 줄(높이 32px, 가운데 작은 글자). 시연 데이터일 때만 app.js 가 넣는다 */
.page-app > .demo-banner {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 32px;
  padding: 4px var(--t-gutter);
  border: 0;
  background: var(--t-calm);
  color: var(--t-text);
  font-size: var(--t-fs-sm);
  font-weight: var(--t-w-regular);
  line-height: 1.4;
  text-align: center;
}

/* 본문 위 탭 줄: 화면 안의 작은 탭(dom.js setSubTabs). 탭이 없는 화면에서는 줄째 숨는다.
   안쪽은 본문(.stage)과 같은 최대 폭·여백이라 탭의 왼쪽 줄이 화면 제목과 맞는다 */
.subbar {
  position: sticky;
  top: 0;
  z-index: 14;
  display: none;
  border-bottom: 1px solid var(--t-rule);
  background: var(--t-surface);
}

.subbar.has-subtabs {
  display: block;
}

.subbar-tabs {
  display: flex;
  align-items: stretch;
  width: 100%;
  max-width: var(--t-maxw);
  height: var(--t-subbar);
  margin: 0 auto;
  padding: 0 var(--t-gutter);
}

/* 폰에서만 쓰는 탭 고르기 칸(아래 폰 절) */
.subtab-select {
  display: none;
}

/* 수합 알림 띠는 위에 붙은 것(탭 줄, 폰은 위 막대까지) 바로 아래에 붙는다(띠는 orders.css 에서 sticky) */
.appbar ~ .collect-alert {
  top: var(--t-head);
}

/* ── 옆 막대(761px 이상): 화면 높이에 붙은 흰 면 + 오른쪽 구획 선. 본문만 스크롤한다 ──────────────── */
@media (min-width: 761px) {
  .appbar {
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    border-right: 1px solid var(--t-rule);
  }

  .appbar-main {
    display: flex;
    flex-direction: column;
    height: 100%;
  }

  /* 로고 칸 높이는 폰 위 막대와 같은 --t-bar.
     ⚠️ 세로 flex 는 기본으로 가로를 늘인다. 로고 링크가 막대 폭만큼 늘지 않게 제 폭으로 둔다(초점선이 로고만 감싸게) */
  .appbar-brand {
    align-self: flex-start;
    height: var(--t-bar);
  }

  /* 메뉴 칸은 막대 폭을 다 쓴다. 낮은 창에서 넘치면 메뉴만 세로로 민다.
     밀림 상자에 바깥 초점선이 잘리므로 메뉴 칸의 초점선은 칸 안쪽에 그린다 */
  .menu {
    flex: 1 1 auto;
    flex-direction: column;
    gap: 2px;
    min-height: 0;
    padding-bottom: var(--t-space-3);
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-width: thin;
  }

  .menu-item:hover {
    background: var(--t-hover);
  }

  .menu-item:focus-visible {
    outline-offset: -2px;
  }

  .menu-item[aria-current="page"],
  .menu-item[aria-current="page"]:hover {
    background: var(--t-accent-soft);
    box-shadow: inset 3px 0 0 var(--t-accent);
  }

  .menu-item[aria-current="page"]::before {
    background-color: var(--t-accent);
  }

  /* 내 이름: 막대 맨 아래, 위에 옅은 선. 펼친 칸은 넓은 막대에서는 위로, 좁은 막대에서는 오른쪽으로 연다.
     ⚠️ 맨 아래 자리는 margin-top: auto 가 맡는다. 메뉴(flex: 1)가 밀어 내리는 것에 기대면, 메뉴를 숨기는 첫 로그인 비밀번호 바꾸기
     화면에서 내 이름이 로고 바로 밑으로 올라가고 위로 여는 칸이 화면 위 밖으로 나갔다 */
  .appbar-end {
    flex: none;
    margin-top: auto;
    padding: var(--t-space-2) var(--t-space-2) calc(var(--t-space-2) + env(safe-area-inset-bottom));
    border-top: 1px solid var(--t-line-soft);
  }

  .me > summary {
    border-radius: var(--t-r);
  }

  .me > summary:hover,
  .me[open] > summary {
    background: var(--t-hover);
  }

  .me-panel {
    top: auto;
  }

  /* 탭 줄 안쪽도 본문처럼 옆 막대 쪽(왼쪽)부터 채운다(아래 본문 절의 .stage 와 같은 까닭) */
  .subbar-tabs {
    margin-left: 0;
  }
}

/* 넓은 옆 막대(1280px 이상): 그림 + 이름 한 줄. 로고 · 메뉴 그림 · 사람 그림의 왼쪽 줄을 20px 에 맞춘다 */
@media (min-width: 1280px) {
  .page-app {
    padding-left: var(--t-side);
  }

  .appbar {
    width: var(--t-side);
  }

  .appbar-brand {
    margin-left: 20px;
  }

  .menu-item {
    gap: 12px;
    min-height: 40px;
    padding: 0 var(--t-space-5) 0 20px;
    font-size: var(--t-fs-nav);
  }

  .menu-item::before {
    width: 20px;
    height: 20px;
  }

  .me > summary {
    gap: 12px;
    min-height: 48px;
    padding: 6px 10px 6px 14px;
    font-size: var(--t-fs-md);
  }

  .me > summary::before {
    width: 20px;
    height: 20px;
  }

  /* 이름 아래에 역할(막대 폭이 정해져 있어 한 줄에 두면 이름이 잘린다). 이름이 길면 줄임표 */
  .me-text {
    display: grid;
    flex: 1 1 auto;
    gap: 0;
    line-height: 1.35;
  }

  .me-text [data-me-name] {
    max-width: none;
  }

  .me-role {
    font-size: var(--t-fs-sm);
  }

  /* 펼친 칸이 위로 열리므로 화살표도 처음에는 위를 본다 */
  .me > summary::after {
    transform: rotate(180deg);
  }

  .me[open] > summary::after {
    transform: none;
  }

  .me-panel {
    right: 0;
    bottom: calc(100% + 4px);
    left: 0;
    min-width: 0;
  }
}

/* 좁은 옆 막대(761~1279px, 태블릿·좁은 창): 폰 아래 탭 막대와 같은 칸(그림 22px 위 + 이름 12px 아래)을 세로로 쌓는다.
   손가락으로 누르는 칸이라 칸 높이(현장 큰 버튼과 같은 56px)를 줄이지 않는다. 메뉴 아홉 칸 + 로고 + 내 이름이 높이 660px 안에 든다 */
@media (min-width: 761px) and (max-width: 1279px) {
  .page-app {
    padding-left: var(--t-rail);
  }

  .appbar {
    width: var(--t-rail);
  }

  .appbar-brand {
    align-self: center;
  }

  .appbar-brand .brand-logo {
    height: var(--t-logo-h-rail);
  }

  .menu-item {
    flex-direction: column;
    justify-content: center;
    gap: 3px;
    min-height: var(--t-touch-lg);
    padding: 6px 4px;
    color: var(--t-text-2);
    font-size: var(--t-fs-tab);
    line-height: 1.3;
    text-align: center;
  }

  .menu-item:hover {
    color: var(--t-text);
  }

  .menu-item[aria-current="page"],
  .menu-item[aria-current="page"]:hover {
    color: var(--t-accent);
  }

  .me > summary {
    flex-direction: column;
    justify-content: center;
    gap: 3px;
    min-height: 56px;
    padding: 6px 2px;
    font-size: var(--t-fs-tab);
  }

  /* 좁은 막대에는 사람 그림과 이름만 둔다(역할까지 넣으면 이름이 두세 글자에서 잘린다) */
  .me > summary::after,
  .me-role {
    display: none;
  }

  .me-text {
    max-width: 100%;
  }

  .me-panel {
    right: auto;
    bottom: 0;
    left: calc(100% + 8px);
  }
}

/* ── 작은 탭(본문 위 탭 줄) ─────────────────────────────────────────────────
   홈페이지의 묶음 탭(제품 · 분류 탭)과 같은 말씨: 보조 글자색 글자, 고른 탭은 본문 글자색 + 글자 바로 아래 강조색 밑줄 2px.
   ⚠️ 묶음이 옆으로 밀리는 칸(overflow)이라 바깥 초점선은 잘린다. 탭 묶음을 탭 줄 높이만큼 늘여 위아래 자리를 둔다. */
.tabs {
  display: flex;
  align-items: center;
  gap: 0 var(--t-space-5);
  min-width: 0;
  max-width: 100%;
  overflow-x: auto;
  scrollbar-width: none;
}

.tabs::-webkit-scrollbar {
  display: none;
}

.tab {
  flex: none;
  min-height: 30px;
  padding: 0;
  border: 0;
  border-block: 2px solid transparent;
  border-radius: 0;
  background: none;
  color: var(--t-text-2);
  font: inherit;
  font-size: var(--t-fs-md);
  font-weight: var(--t-w-regular);
  white-space: nowrap;
  cursor: pointer;
  transition: color var(--t-dur), border-color var(--t-dur);
}

.tab:hover {
  color: var(--t-text);
}

.tab[aria-selected="true"],
.tab[aria-selected="true"]:hover {
  border-bottom-color: var(--t-accent);
  color: var(--t-text);
}

.subbar .tabs {
  align-self: stretch;
}

@media (pointer: coarse) {
  .tab {
    min-height: 40px;
  }
}

/* ── 본문 ──────────────────────────────────────────────────────────────── */
/* 화면의 큰 덩어리 사이는 같은 간격(stage 에 바로 붙는 화면과, 한 그릇 안에 그리는 화면 모두) */
.stage,
.screen {
  display: flex;
  flex-direction: column;
  gap: var(--t-space-5);
}

.stage {
  width: 100%;
  max-width: var(--t-maxw);
  margin: 0 auto;
  padding: var(--t-space-6) var(--t-gutter) 48px;
}

/* 옆 막대가 있는 폭에서는 본문을 막대 쪽(왼쪽)부터 채운다. 가운데에 두면 아주 넓은 화면에서 막대와 본문 사이가 벌어진다 */
@media (min-width: 761px) {
  .stage {
    margin-left: 0;
  }
}

/* 화면 제목: 홈페이지 제목처럼 크게, 굵기는 가볍게(500) */
.screen-title {
  font-size: var(--t-fs-xl);
  font-weight: var(--t-w-medium);
  line-height: 1.3;
}

/* 화면 머리 줄(제목 + 오른쪽 단추, 오늘 화면의 제목 + 날짜): 아래에 구획 선. 홈페이지의 제목 줄(문의하기 · 시공 사례)과 같은 말씨다.
   JS 가 그리는 첫 줄만 자리로 고른다(순서·문구는 그대로). 폼 안의 제목 줄(주문 등록)도 같다 */
:is(.stage, .screen, .field-list, form.stack) > :is(.screen-title, .row-between:has(.screen-title), .today-head):first-child {
  padding-bottom: var(--t-space-4);
  border-bottom: 1px solid var(--t-rule);
}

/* 상세·등록 화면 제목 앞의 "← 목록" 단추: 홈페이지 길잡이(처음 › 제품)처럼 테두리 없는 보조 글자 링크 모양.
   단추는 그대로(누르는 동작·글자는 화면 코드가 정한다). 제목 바로 앞 작은 단추만 자리로 고른다 */
.row:has(> .screen-title) > .btn-sm:first-child {
  min-height: 0;
  padding: 0;
  border-color: transparent;
  background: none;
  color: var(--t-text-2);
  font-size: var(--t-fs-md);
  font-weight: var(--t-w-regular);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.3em;
}

.row:has(> .screen-title) > .btn-sm:first-child:hover {
  border-color: transparent;
  background: none;
  color: var(--t-text);
}

.row:has(> .screen-title) > .btn-sm:first-child + .screen-title {
  margin-left: var(--t-space-3);
}

.section-title {
  font-size: var(--t-fs-lg);
  font-weight: var(--t-w-medium);
}

.empty {
  display: grid;
  gap: var(--t-space-3);
  padding: 48px 0;
}

.empty-text {
  color: var(--t-text-2);
  font-size: var(--t-fs-md);
}

@media (min-width: 1020px) {
  .screen-title {
    font-size: var(--t-fs-2xl);
  }
}

/* ── 폰(760px 이하): 같은 header 가 맨 위 막대(로고 · 내 이름), 메뉴는 화면 아래 흰 탭 막대(그림 위 + 이름 아래) ──────── */
@media (max-width: 760px) {
  :root {
    --t-head: var(--t-bar);
  }

  :root:has(.subbar.has-subtabs) {
    --t-head: calc(var(--t-bar) + var(--t-subbar));
  }

  .appbar {
    position: sticky;
    top: 0;
    border-bottom: 1px solid var(--t-rule);
  }

  /* 탭 줄이 있으면 위 막대와 탭 줄 사이는 옅은 선 하나로 둔다(두 줄이 한 막대로 읽히게) */
  .appbar:has(~ .subbar.has-subtabs) {
    border-bottom-color: var(--t-line-soft);
  }

  .appbar-main {
    display: flex;
    align-items: center;
    gap: var(--t-space-3);
    height: var(--t-bar);
    padding: 0 var(--t-gutter);
  }

  .appbar-end {
    display: flex;
    flex: none;
    align-items: center;
    margin-left: auto;
  }

  .menu {
    position: fixed;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: 10;
    display: grid;
    grid-auto-columns: minmax(0, 1fr);
    grid-auto-flow: column;
    gap: 0;
    height: calc(var(--t-tab) + env(safe-area-inset-bottom));
    padding-bottom: env(safe-area-inset-bottom);
    border-top: 1px solid var(--t-rule);
    background: var(--t-surface);
  }

  .menu-item {
    flex-direction: column;
    justify-content: center;
    gap: 3px;
    padding: 0 2px;
    color: var(--t-text-2);
    font-size: var(--t-fs-tab);
  }

  .menu-item:hover {
    background: var(--t-hover);
    color: var(--t-text);
  }

  /* 흰 탭 막대에서는 위쪽 강조색 막대 + 강조색 그림·글자로 고른 칸을 보인다(색만이 아니라 막대 모양으로도) */
  .menu-item[aria-current="page"],
  .menu-item[aria-current="page"]:hover {
    color: var(--t-accent);
    box-shadow: inset 0 2px 0 var(--t-accent);
  }

  /* 내 이름: 홈페이지 폰 머리글처럼 사람 그림 + 이름. 올리거나 펼치면 글자 바로 아래 밑줄 */
  .me > summary {
    min-height: 40px;
    border-block: 2px solid transparent;
    font-size: var(--t-fs-md);
  }

  .me > summary:hover,
  .me[open] > summary {
    border-bottom-color: var(--t-text);
  }

  .me-role {
    display: none;
  }

  .subbar {
    top: var(--t-bar);
  }

  .stage {
    gap: var(--t-space-4);
    padding: var(--t-space-5) 12px calc(var(--t-tab) + 32px + env(safe-area-inset-bottom));
  }

  .screen {
    gap: var(--t-space-4);
  }

  .page-app > .demo-banner {
    font-size: var(--t-fs-xs);
  }

  /* 탭이 많은 화면(설정)은 폰에서 탭 대신 고르기 칸 하나(dom.js setSubTabs asSelectOnPhone, 점검 S13).
     글자는 아이폰 확대를 막는 16px 그대로, 칸 높이만 줄 높이에 맞춘다 */
  .subtabs-as-select .tabs {
    display: none;
  }

  .subtabs-as-select .subtab-select {
    display: block;
    align-self: center;
    height: 36px;
  }
}

/* ── 칸·도구 줄·기록 목록 ──────────────────────────────────────────────── */
/* ⚠️ 칸 폭을 minmax(0, 1fr) 로 둔다. 기본(auto)이면 안의 넓은 표가 칸을 늘려, 폰(390px)에서 설정 탭 내용이
   화면 밖(561px)까지 밀렸다. 표는 제 칸(.table-wrap) 안에서 옆으로 민다. */
.panel {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-content: start;
  gap: var(--t-space-5);
}

.toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: end;
  gap: var(--t-space-2);
}

.toolbar .field {
  min-width: 100px;
}

.blocks {
  display: grid;
  gap: var(--t-space-2);
}

.block-item {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--t-space-2);
}

/* 기록 목록: 표와 같은 결(위에 선, 줄은 옅은 구분선) */
.activity-list {
  display: grid;
  margin: 0;
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--t-line);
}

.activity-item {
  display: grid;
  grid-template-columns: 140px 128px 104px 1fr;
  gap: var(--t-space-3);
  padding: 7px 0;
  border-bottom: 1px solid var(--t-line-soft);
  font-size: var(--t-fs-sm);
}

/* 주문 이력(시각 · 내용 · 누가) */
.activity-list-order .activity-item {
  grid-template-columns: 180px 1fr auto;
}

@media (max-width: 760px) {
  .activity-item,
  .activity-list-order .activity-item {
    grid-template-columns: 1fr;
    gap: 2px;
  }
}

/* ── 대화 상자 ────────────────────────────────────────────────────────── */
.modal {
  width: min(92vw, 380px);
  padding: 20px;
  border: 1px solid var(--t-line);
  border-radius: var(--t-r-lg);
  background: var(--t-surface);
  color: var(--t-text);
  box-shadow: var(--t-shadow);
}

.modal::backdrop {
  background: var(--t-scrim);
}

.modal-title {
  margin-bottom: var(--t-space-4);
  font-size: var(--t-fs-lg);
}

.modal-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: var(--t-space-2);
  margin-top: var(--t-space-3);
}

/* 임시 비밀번호: 헷갈리는 글자를 가르려고 여기만 고정폭 */
.secret {
  padding: 12px;
  border: 1px solid var(--t-line);
  border-radius: var(--t-r);
  background: var(--t-sunk);
  font-family: var(--t-mono);
  font-size: var(--t-fs-xl);
  font-weight: var(--t-w-strong);
  letter-spacing: 0.06em;
  text-align: center;
  user-select: all;
}

/* ── 권한 없음·찾을 수 없음 ───────────────────────────────────────────── */
/* 로그인과 같은 결(2026-10-15 2차): 밝은 바탕 가운데 로고, 그 아래 구획 선 · 제목 · 설명 · 단추. 칸에 담지 않는다 */
.page-message {
  display: grid;
  align-content: center;
  justify-items: center;
  gap: var(--t-space-6);
  min-height: 100vh;
  min-height: 100dvh;
  padding: 48px 24px;
}

.message-brand .brand-logo {
  height: var(--t-logo-h-md);
}

.message-card {
  display: grid;
  justify-items: center;
  gap: var(--t-space-4);
  width: 100%;
  max-width: 400px;
  padding-top: var(--t-space-6);
  border-top: 1px solid var(--t-rule);
  text-align: center;
}

.message-title {
  font-size: var(--t-fs-2xl);
  line-height: 1.35;
}

.message-text {
  color: var(--t-text-2);
}

/* ── 폰 탭 막대의 더보기(T-B95C2A71 s3) ──────────────────────────────────── */
/* 메뉴가 6칸을 넘으면 app.js 가 앞 5칸 + "더보기" 단추를 그린다. 폰(760px 이하)에서만 넘친 칸을 숨기고 더보기를 보인다.
   넓은 화면은 메뉴를 모두 펼쳐 두므로 더보기가 없다.
   ⚠️ 숨기는 것은 배치일 뿐이다. 열 수 있는지는 서버의 경로×역할 표가 정한다. */
.menu-more {
  display: none;
  border: 0;
  background: none;
  font-family: inherit;
  line-height: inherit; /* 단추 기본 줄 높이면 이름이 옆 칸(링크)보다 아래로 내려앉는다 */
  cursor: pointer;
}

.menu-more-list {
  display: grid;
  gap: var(--t-space-2);
  margin-top: var(--t-space-3);
}

@media (max-width: 760px) {
  .menu-item-overflow {
    display: none;
  }

  .menu-more {
    display: flex;
  }
}

/* ── 첫 로그인 비밀번호 바꾸기(app.js renderTempPassword) ─────────────────── */
/* 로그인 칸과 같은 모양으로 가운데 둔다. 이 상태에서는 다른 화면이 모두 막혀 메뉴를 숨긴다(점검 S20). */
.temp-password .menu {
  display: none;
}

.stage > .temp-password-card {
  align-self: center;
  margin-top: var(--t-space-6);
}

@media (max-width: 760px) {
  .stage > .temp-password-card {
    margin-top: 0;
  }
}

/* 메뉴가 하나(설치기사)면 폰 아래 탭 막대를 숨기고 그 자리만큼의 아래 여백도 거둔다(점검 S22) */
@media (max-width: 760px) {
  .single-menu .menu {
    display: none;
  }

  .single-menu .stage {
    padding-bottom: calc(32px + env(safe-area-inset-bottom));
  }
}
