/* ============================================================
   마이디비 — 컴포넌트
   ------------------------------------------------------------
   tokens.css 를 먼저 불러야 한다.

   ★ 규칙
     1. 여기서 색·크기를 직접 적지 않는다. 전부 var(--…) 만 쓴다.
     2. 화면(HTML)에서는 style="" 로 색을 넣지 않는다. 여기 클래스를 쓴다.
     3. 새 부품이 필요하면 여기에 추가하고 스타일 가이드에 예시를 남긴다.

   ★ 이름 규칙 — 짧고 뜻이 보이게
     레이아웃  app / topbar / gnb / col / head / body / panel
     부품      btn / fld / tbl / bdg / tier / prog / note / dlg / dim / tabs
     상태      is-on / is-sel / is-off / is-err / is-load
   ============================================================ */

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

/* ★★ 감추라고 했으면 감춘다.
   hidden 은 HTML 표준이지만 브라우저 «기본» 규칙이라, 여기서 .frm { display: flex }
   하나만 적어도 조용히 진다 — 오류도 경고도 없다.
   실제로 발주 패널의 「② 배정 일정」과 「② 불가일」이 동시에 보였다 (2026-09-04 대표).
   !important 를 쓰는 자리는 여기 하나뿐이다. 예외가 필요 없는 규칙이기 때문이다.
   검사 76 이 이 줄이 살아 있나를 본다. */
[hidden] { display: none !important; }

html, body { height: 100%; }
body {
  margin: 0;
  overflow: hidden;                     /* ★ 페이지는 스크롤되지 않는다 */
  background: var(--bg-app);
  color: var(--tx);
  font-family: var(--ff);
  font-size: var(--fs-13);
  line-height: var(--lh-n);
}
/* ★ 제목 태그만 «맑은 고딕»으로 남아 있었다 (2026-09-22 대표).
   테마는 그누보드 원본 css/default.css 를 «하나 더» 싣는데(head.sub.php 가 echo 한다)
   그 파일이 body · h1~h6 · input,button · textarea,select 넷에 글꼴을 직접 건다.
   폼 요소는 reset.css 의 font:inherit 이 덮고 body 는 위 줄이 덮는데
   «제목»은 reset 이 글꼴을 안 건드려 상속이 끊긴 채로 남았다.
   ★ 앱 셸에는 아무 영향이 없다 — 거기는 제목이 원래 상속만 받는다 */
h1, h2, h3, h4, h5, h6 { font-family: inherit; }

:focus-visible { outline: none; box-shadow: var(--focus); border-radius: var(--r-sm); }

/* ★ reset.css(gowsoft)가 h1~h6 에 line-height:1.3 을, a 에 text-decoration:none 을 준다.
   여기서 다시 적어 두는 이유 — reset 이 있든 없든 결과가 같아야 한다.
   값이 한쪽에만 있으면 「프로토타입에선 됐는데 서버에선 다르다」가 생긴다. */
h1, h2, h3, h4, h5, h6 { line-height: var(--lh-t); }
h1 { font-size: var(--fs-16); font-weight: var(--fw-b); margin: 0 0 var(--sp-1); }
h2 { font-size: var(--fs-14); font-weight: var(--fw-b); margin: var(--sp-8) 0 var(--sp-4); }
h3 { font-size: var(--fs-13); font-weight: var(--fw-b); margin: var(--sp-7) 0 var(--sp-3); }
p  { margin: 0 0 var(--sp-5); }
a  { color: var(--ac); text-decoration: none; }

/* ============================================================
   1. 앱 셸 — 스크롤은 «한 화면에 하나»
   ============================================================ */
.app  { height: 100vh; display: flex; flex-direction: column; }
.main { flex: 1; display: flex; min-height: 0; }
.col  { flex: 1; display: flex; flex-direction: column; min-width: 0; min-height: 0; }
.head { flex: none; padding: var(--sp-6) var(--sp-7) 0; }
.body { flex: 1; overflow: auto; padding: 0 var(--sp-7) var(--sp-8); }

/* 절 제목의 «무게» — 첫 절이 본 일이고 나머지는 곁이다.
   넷이 같은 크기면 「지금 해야 할 일」과 「지금」이 같은 무게로 읽힌다 */
h2.lead  { font-size: var(--fs-16); }
h2.minor { font-size: var(--fs-13); color: var(--tx-2); margin-top: var(--sp-7); }

/* 제목을 뺀 절 — 제목이 주던 사이 여백을 절이 스스로 갖는다 */
.goal + .dash, .dash + .sparks, .sparks + h2 { margin-top: var(--sp-7); }
.body.pad { padding-top: var(--sp-6); }

/* ---------- 목록 화면 — 스크롤하는 것이 «표»다 ----------
   .body 가 스크롤하면 표 머리가 함께 올라간다. 가로 스크롤이 걸린 표(.x)는
   «그 자체가» 스크롤 상자라 머리가 붙을 곳도 그 안이고, 높이가 안 잡혀 있으면
   세로로는 스크롤할 일이 없어 머리가 그냥 딸려 나간다.
   그래서 목록 화면에서는 .body 대신 표에 높이를 준다 — 머리는 붙고, 쪽 나누기는 늘 보인다. */
.body.list                  { display: flex; flex-direction: column; overflow: hidden;
                              padding-bottom: var(--sp-5); }
.body.list > .tblwrap       { flex: 1; min-height: 0; overflow: auto; }
.body.list > .row           { flex: 1; min-height: 0; height: auto; }
.body.list .pane            { display: flex; flex-direction: column; min-height: 0; }
.body.list .pane > .tblwrap { flex: 1; min-height: 0; overflow: auto; }
.body.list .scrolly         { overflow: auto; min-height: 0; }

/* ---------- 여러 절이 든 화면의 긴 표 ----------
   .tblwrap.x 는 overflow-x 때문에 «그 자체가» 스크롤 상자다. 그런데 높이가 없으면
   세로로는 스크롤할 일이 없어, .body 가 스크롤할 때 머리가 그냥 딸려 올라간다.
   목록 화면은 표에 높이를 줘서 풀었지만(.body.list), 절이 여럿인 화면은 그럴 수 없다 —
   표 위아래로 다른 것이 더 있다.
   그래서 «높이 상한»만 준다. 짧은 표는 아무 일도 안 일어나고,
   긴 표는 제 상자 안에서 스크롤하며 머리가 붙는다. */
.body:not(.list) .tblwrap.x { max-height: 70vh; overflow: auto; }

/* ---------- 아이콘 ----------
   ★ 이모지를 쓰지 않는다. 기기·글꼴마다 다르게 그려지고 크기·색·굵기를 맞출 수 없다.
   currentColor 라 글자색을 따라온다 — 다크가 저절로 맞는다. */
.ti     { width: 18px; height: 18px; flex: none; vertical-align: -3px; }
.ti.sm  { width: 15px; height: 15px; }
.ti.lg  { width: 22px; height: 22px; }

/* 상단바 — 밝은 톤. 선과 옅은 그림자로 띄운다
   왼쪽  햄버거 · 로고        오른쪽  앱 전환 · 알림 · 프로필 */
.topbar {
  flex: none; height: var(--topbar-h);
  display: flex; align-items: center; gap: var(--sp-4);
  padding: 0 var(--sp-5) 0 var(--sp-4);
  background: var(--sf-topbar);
  border-bottom: 1px solid var(--bd);
  box-shadow: var(--sh-top);
  z-index: 40;
}
.topbar .logo { font-weight: var(--fw-x); letter-spacing: -.2px; font-size: var(--fs-14);
                margin-right: var(--sp-3); color: var(--brand); }
/* 로고는 «화면 강조»가 아니라 브랜드 색이다 — 강조를 밝혀도 로고는 안 따라온다 */
.topbar .logo svg, .mo > .top .logo svg { color: var(--brand); }
.topbar .who  { color: var(--tx-2); font-size: var(--fs-12); }
.topbar .sp   { flex: 1; }
.topbar .meta { color: var(--tx-3); font-size: var(--fs-12); }

/* 아이콘 단추 — 상단바 오른쪽 3형제 */
.iconbtn {
  position: relative;
  width: 32px; height: 32px; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid transparent; border-radius: var(--r-md);
  background: transparent; color: var(--tx-2); cursor: pointer;
}
.iconbtn:hover { background: var(--sf-hover); color: var(--tx); }
.iconbtn.is-on { background: var(--ac-bg); color: var(--ac-tx); }
/* 읽지 않은 수 — 숫자가 정본이고 색은 보조다 */
.iconbtn .cnt {
  position: absolute; top: 1px; right: 1px;
  min-width: 15px; height: 15px; padding: 0 3px;
  display: flex; align-items: center; justify-content: center;
  background: var(--bd-c); color: #fff;
  border-radius: var(--r-pill); font-size: 10px; font-weight: var(--fw-b);
  font-variant-numeric: tabular-nums;
}

/* 이름 첫 글자 동그라미 — 그누보드 회원이미지를 켜고 올린 사람만 그림이 든다 (§487) */
.avatar {
  width: 26px; height: 26px; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--ac-bg); color: var(--ac-tx); overflow: hidden;
  border-radius: 50%; font-size: var(--fs-12); font-weight: var(--fw-b);
}
.avatar > img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* ---------- 팝오버 ----------
   모달(dlg)도 우측 패널(panel)도 아니다. 누른 단추 밑에 붙어 뜬다.
   ★ 하나를 열면 나머지는 닫힌다. 셋이 동시에 뜨면 어느 것을 눌렀는지 잃는다. */
.pops { position: relative; display: inline-flex; align-items: center; gap: var(--sp-2); }
.pop {
  display: none; position: absolute; top: calc(100% + 6px); right: 0; z-index: 60;
  min-width: 200px; max-width: 320px;
  background: var(--sf); border: 1px solid var(--bd); border-radius: var(--r-lg);
  box-shadow: var(--sh-2); padding: var(--sp-3);
}
.pop.is-on { display: block; }
.pop .hd { display: flex; align-items: center; justify-content: space-between;
           padding: var(--sp-3) var(--sp-4) var(--sp-4);
           font-size: var(--fs-12); font-weight: var(--fw-b); }
.pop .hd a { font-size: var(--fs-11); font-weight: var(--fw-n); color: var(--tx-3); }
.pop a.it, .pop button.it {
  display: flex; align-items: center; gap: var(--sp-4); width: 100%;
  padding: var(--sp-4); border: 0; background: transparent;
  border-radius: var(--r-md); color: var(--tx); font-size: var(--fs-12);
  text-align: left; text-decoration: none; cursor: pointer;
}
.pop .it:hover  { background: var(--sf-hover); }
.pop .it.is-on  { background: var(--ac-bg); color: var(--ac-tx); font-weight: var(--fw-b); }
.pop .it .ti    { color: var(--tx-3); }
.pop .it.is-on .ti { color: var(--ac-tx); }
.pop .sep { height: 1px; background: var(--bd-2); margin: var(--sp-3) 0; }
.pop .none { padding: var(--sp-8); text-align: center; color: var(--tx-3); font-size: var(--fs-12); }
/* 알림 한 줄 — 제목 · 본문 · 시각 */
/* ★ .it.noti 로 잡는다 — .pop a.it 의 «가운데 맞춤»이 이겨 알림 글이 가운데로 섰다 (§462) */
.pop .it.noti { flex-direction: column; align-items: flex-start; gap: 2px; }
.pop a.it.all { justify-content: center; color: var(--tx-2); }
/* 알림 전체 화면 (§462) — 안 읽은 것은 굵게 */
.tbl a.noti-go { color: var(--tx); }
.tbl a.noti-go.new { font-weight: var(--fw-b); }
.pop .noti .t { font-size: var(--fs-12); }
.pop .noti.new .t { font-weight: var(--fw-b); }
.pop .noti .m { font-size: var(--fs-11); color: var(--tx-2); }
.pop .noti .d { font-size: var(--fs-11); color: var(--tx-3); }

/* GNB */
.gnb {
  flex: none; width: var(--gnb-w);
  background: var(--sf-gnb); border-right: 1px solid var(--bd);
  display: flex; flex-direction: column; overflow: auto; padding: var(--sp-4) 0;
}
.gnb .grp { padding: var(--sp-5) var(--sp-6) var(--sp-2); font-size: var(--fs-11); color: var(--tx-3); }

/* ★ 묶음 제목 — 13개는 훑어서 못 찾는다 (2026-09-01).
   맨 위 역할 이름(.grp)보다 «한 단 아래»로 보여야 층이 읽힌다. */
.gnb .grp.sub2 {
  padding: var(--sp-6) var(--sp-6) var(--sp-2);
  letter-spacing: .06em; color: var(--tx-4);
}
.gnb .grp.sub2:first-of-type { padding-top: var(--sp-4); }

/* ★ 밀린 건수 — 0 이면 «아예 안 붙는다»(수를 안 들고 오면 안 그린다).
   숫자가 있는 것만 눈에 띄어야 한다. */
.gnb a .cnt {
  margin-left: auto; min-width: 18px; padding: 0 5px;
  font-size: var(--fs-11); font-weight: var(--fw-b); line-height: 17px;
  text-align: center; border-radius: 9px;
  background: var(--wn-bg); color: var(--wn);
}
.gnb a.is-on .cnt { background: var(--sf); color: var(--ac-tx); }

/* 접었을 때는 아이콘 위에 작게 얹는다 — 숨기면 「밀린 게 없다」로 읽힌다 */
.gnb.mini a { position: relative; }
/* ★ 탭에도 숫자를 붙인다 — 갈래 버튼의 배지와 «같은 일»을 한다.
   부품이 달라도 「몇 건인가」를 말하는 방식은 하나여야 한다 (2026-09-01). */
.tabs a .cnt {
  display: inline-block; margin-left: var(--sp-2);
  min-width: 17px; padding: 0 5px; border-radius: 9px;
  font-size: var(--fs-11); font-weight: var(--fw-b); line-height: 16px;
  text-align: center; background: var(--sf-sunken); color: var(--tx-3);
}
.tabs a.is-on .cnt { background: var(--ac-bg); color: var(--ac-tx); }

.gnb.mini a .cnt {
  position: absolute; top: 4px; right: 8px;
  margin: 0; min-width: 15px; padding: 0 4px; line-height: 15px;
  font-size: 10px;
}
.gnb a {
  display: flex; align-items: center; gap: var(--sp-4);
  padding: var(--sp-3) var(--sp-6);
  color: var(--tx-2); text-decoration: none; font-size: var(--fs-12);
  border-left: 3px solid transparent;
}
.gnb a:hover { background: var(--sf-hover); color: var(--tx); }
.gnb a.is-on {
  background: var(--ac-bg); color: var(--ac-tx);
  border-left-color: var(--ac); font-weight: var(--fw-b);
}
.gnb a .ti  { color: var(--tx-3); }
.gnb a.is-on .ti { color: var(--ac-tx); }
.gnb a .rt  { margin-left: auto; font-size: var(--fs-11); color: var(--tx-3); }
.gnb a.is-off { color: var(--tx-4); }
.gnb a.is-off .ti { color: var(--tx-4); }

/* ★ 미니 레일 — 접어도 이동할 수 있어야 한다.
   숨기지 않고 아이콘만 남기는 이유가 이것이다. 숨기면 갈 때마다 다시 펴야 한다.
   글자는 지우지 않고 감춘다 — 낭독기는 계속 읽는다. */
.gnb.mini { width: var(--gnb-mini); }
.gnb.mini .grp,
.gnb.mini a .rt { display: none; }
.gnb.mini a span:not(.rt) {
  position: absolute; width: 1px; height: 1px; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}
.gnb.mini a { justify-content: center; padding: var(--sp-4) 0; }

/* 우측 패널 — 모달이 아니라 패널이다. 목록을 보면서 작업한다 */
.panel {
  position: fixed; top: var(--topbar-h); right: 0; bottom: 0;
  width: var(--panel-w); z-index: 45;
  background: var(--sf); border-left: 1px solid var(--bd);
  box-shadow: var(--sh-3);
  display: flex; flex-direction: column;
  transform: translateX(100%); transition: transform .16s ease, width .16s ease;
}
.panel.is-on { transform: none; }

/* 넓은 패널 — 발주는 달력을, 구매자 고객 서랍은 상담을 «나란히» 본다 (2026-09-05 · §278).
   ★ 화면이 좁으면 «목록 320px 을 남기고» 줄어든다 — 1600 아래에서 곧장 560 으로 떨어지면
     1366 · 1440 노트북에서 넓은 서랍이 없는 것과 같았다 (§278).
   「목록을 보면서 작업한다」가 패널의 존재 이유다 — 1200 아래에서는 한 단 · 보통 폭이다 */
.panel.wide { width: min(var(--panel-w2), calc(100vw - 320px)); }
.two { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
       gap: var(--sp-8); align-items: start; }
/* 카드를 세로로 쌓는 단 — 설정의 두 단 (§286) */
.stack { display: flex; flex-direction: column; gap: var(--sp-6); min-width: 0; }
@media (max-width: 1200px) {
  .panel.wide { width: var(--panel-w); }
  .two { grid-template-columns: minmax(0, 1fr); }
}
/* 탭 하나가 넓은 것을 보는 동안(⑦ 구매자 서랍의 공급 내역 · §423) — 서랍이 메뉴 옆까지 덮고 늘어난 폭은 오른쪽 단이 다 갖는다.
   왼쪽 단은 «넓은 서랍일 때의 반»을 지켜 적던 상담 칸이 움직이지 않는다 */
.panel.wide.xwide { width: calc(100vw - var(--gnb-w)); }
:root:has(.gnb.mini) .panel.wide.xwide { width: calc(100vw - var(--gnb-mini)); }
@media (min-width: 1201px) {
  .panel.xwide .two {
    grid-template-columns: calc((min(var(--panel-w2), calc(100vw - 320px)) - var(--sp-6) * 2 - var(--sp-8)) / 2) minmax(0, 1fr);
  }
}
/* 실린 표는 제 상자에서 스크롤한다 — 머리가 붙고 가로 막대가 늘 보인다 */
[data-embed] > .tblwrap.x { max-height: max(240px, calc(100vh - var(--topbar-h) - 330px)); overflow: auto; }
.panel > header {
  flex: none; display: flex; align-items: center; gap: var(--sp-4);
  padding: var(--sp-5) var(--sp-6); border-bottom: 1px solid var(--bd-2);
}
.panel > header b { font-size: var(--fs-14); }
.panel > header .sp { flex: 1; }

/* 이전 · 다음 건 — 닫고 다시 여는 일이 없게.
   심사 4건 · 환불 4건은 «연달아» 본다. 서랍은 뒤를 안 덮으므로
   목록을 눌러 옮길 수도 있지만, 손이 키보드에 있을 때가 더 많다 */
.panel > header .cnt { font-size: var(--fs-11); color: var(--tx-3);
                       font-variant-numeric: tabular-nums; min-width: 40px; text-align: center; }
.panel > .scroll { flex: 1; min-height: 0; overflow: auto; padding: var(--sp-6); }
.panel > footer {
  flex: none; display: flex; align-items: center; gap: var(--sp-4);
  padding: var(--sp-5) var(--sp-6); border-top: 1px solid var(--bd-2);
}
/* ★ 푸터의 단추는 «다 같은 크기»다 (2026-09-23 대표: 「버튼 크기 확인해줘」).
   .btn.pri 는 높이를 안 정하므로 기본 30px 이라 .btn.sm(24px) 옆에서 6px 컸다 —
   한 줄에 두 크기가 섰고 푸터 스물하나가 «다» 그랬다.
   ★ 클래스를 손으로 붙이지 «않는다» — 열아홉에 sm 을 달면 스무째 서랍이 또 어긋난다.
     잣대는 「서랍을 덮는 줄의 단추는 24px」 하나이고 그것을 여기가 갖는다 (§123).
   ★ .btn.sm 보다 특이도가 높아 pri·dgr 에도 먹는다. 강조는 색이 이미 한다 */
.panel > footer .btn { height: 24px; padding: 0 var(--sp-4); }

/* ============================================================
   2. 면
   ============================================================ */
.card {
  background: var(--sf); border: 1px solid var(--bd);
  border-radius: var(--r-lg); box-shadow: var(--sh-1);
}
.card > .hd { display: flex; align-items: center; gap: var(--sp-4);
              padding: var(--sp-5) var(--sp-6); border-bottom: 1px solid var(--bd-2);
              font-size: var(--fs-13); font-weight: var(--fw-b); }
.card.flat { box-shadow: none; }
/* 첨부 여러 개 — 한 줄짜리 att 를 쌓는다 */
.atts { display: flex; flex-direction: column; gap: var(--sp-3); }
.card > .bd { padding: var(--sp-6); }

/* 툴바 — 표 위에 붙는다 */
.toolbar {
  display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap;
  padding: var(--sp-4) var(--sp-5);
  background: var(--sf); border: 1px solid var(--bd); border-radius: var(--r-lg);
}
.toolbar.top { border-radius: var(--r-lg) var(--r-lg) 0 0; border-bottom: 0; }
.toolbar.mid { border-radius: 0; border-bottom: 0; background: var(--sf-2); }
.toolbar .sp  { flex: 1; }
.toolbar .div { width: 1px; height: 18px; background: var(--bd); margin: 0 var(--sp-2); }
.toolbar .lb  { font-size: var(--fs-12); font-weight: var(--fw-b); color: var(--tx-2); }

/* 지표 */
/* 할 일 — 대시보드 첫 블록.
   지표(kpi)와 다르다. 지표는 「얼마인가」를 보고, 이건 「눌러서 그 화면으로」 간다.
   그래서 카드 전체가 링크다. 숫자만 크게 띄우고 나머지는 물러난다. */
/* ---------- 대시보드 열 칸 — 손댈 것 다섯 · 지켜볼 것 다섯 ----------
   ★ 이름이 .cards 가 아니다 — 그 이름은 «고르기 카드»(③ 공유)가 이미 쓰고 있고,
     뒤에 나오는 그쪽 규칙이 이겨서 넓은 화면에서 6열이 됐다.
   ★ 한 격자다. 넓으면 5×2, 폰에서는 2×5 — 열 칸이라 «늘 딱 맞는다».
     따로 두면 5칸이 2열에서 2×3 이 되어 마지막에 한 칸만 남았다. */
.dash { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: var(--sp-5); }

.card2 {
  display: flex; flex-direction: column; gap: var(--sp-2);
  min-height: 84px; padding: var(--sp-5) var(--sp-6);
  background: var(--sf); border: 1px solid var(--bd); border-radius: var(--r-lg);
  color: var(--tx); text-decoration: none;
}
.card2:hover { border-color: var(--ac); }
.card2 .hd { display: flex; align-items: baseline; gap: var(--sp-2); }
.card2 .t  { display: flex; align-items: center; gap: var(--sp-2); min-width: 0;
             font-size: var(--fs-12); color: var(--tx-2); }
.card2 .t > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.card2 .t .ti { color: var(--tx-3); flex: none; }
/* 숫자는 오른쪽 끝으로 밀고 한 단 크게 */
.card2 .v  { margin-left: auto; font-size: var(--fs-20); font-weight: var(--fw-x);
             font-variant-numeric: tabular-nums; line-height: 1; flex: none; }
.card2 .u  { font-size: var(--fs-11); color: var(--tx-3); font-weight: var(--fw-m); flex: none; }
.card2 .w  { margin-top: auto; font-size: var(--fs-11); color: var(--tx-3);
             line-height: var(--lh-n); }

/* 손댈 것 — 색이 붙고 살짝 떠 있다 */
.card2.do { box-shadow: var(--sh-1); }
.card2.do:hover { box-shadow: var(--sh-2); }
.card2.do.is-wn    .v { color: var(--wn); }
.card2.do.is-bad   .v { color: var(--bd-c); }
/* 지켜볼 것 — 흑백. 색이 없다는 것이 곧 「알고만 있으면 된다」다 */
.card2.see .v { color: var(--tx); }
.card2.is-clear .v { color: var(--tx-4); font-weight: var(--fw-m); }

@media (max-width: 1180px) { .dash { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width:  820px) { .dash { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
/* 한 줄에 다 선다 — 구매자 할 일은 다섯이나 여섯이라 5열 격자에서 빈칸이 남았다 */
.dash.fit { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
.dash.fit .card2 .w { min-height: calc(var(--fs-11) * var(--lh-n)); }

/* 묶음 면 — 구매자 대시보드의 고객 · 주문 · 발송 */
.cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
        gap: var(--sp-5); align-items: stretch; }
.cols.wide { grid-template-columns: repeat(auto-fit, minmax(440px, 1fr)); }
/* 셋이 한 줄 · 같은 높이. 좁으면 한 단 — auto-fit 로 두면 2+1 로 갈려 하나가 혼자 남았다 */
.cols.three { grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 1100px) { .cols.three { grid-template-columns: minmax(0, 1fr); } }
.cols .donut > svg { width: 112px; height: 112px; }
.cols > .card { display: flex; flex-direction: column; }
.cols > .card > .bd { flex: 1; display: flex; flex-direction: column; }
.cols > .card > .bd > .spark:last-child { margin-top: auto; padding-top: var(--sp-6); }
.card > .hd .mut { font-weight: var(--fw-m); font-size: var(--fs-12); }
.card > .tblwrap { border: 0; border-radius: 0 0 var(--r-lg) var(--r-lg); }
/* 나란히 선 두 표는 열이 같다(고객 · 상품 · 지역 · 날짜 · 진행) — 칸 폭을 고르게 나눠 두 표의 열이 한 줄로 선다 */
.cols.wide > .card > .tblwrap > .tbl { table-layout: fixed; }
.card .spark { border: 0; padding: 0; margin-top: var(--sp-6); }
.card .donut { margin-top: var(--sp-6); }
/* 발송 면 — 왼쪽 반은 월별 발송 · 오른쪽 반은 칸 둘을 위아래로 */
.half { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-5); align-items: stretch; }
.half > .spark { margin: 0; display: flex; flex-direction: column; }
.half > .spark .bars, .half > .spark .mbars { margin-top: auto; }
.half > .stats { grid-template-columns: minmax(0, 1fr); }
.stats { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1px;
         background: var(--bd-2); border: 1px solid var(--bd-2); border-radius: var(--r-md);
         overflow: hidden; }
.stats .st { display: flex; flex-direction: column; gap: var(--sp-1); min-width: 0;
             padding: var(--sp-4) var(--sp-5); background: var(--sf);
             color: var(--tx); text-decoration: none; }
.stats .st:hover { background: var(--sf-hover); }
.stats .st:last-child:nth-child(odd) { grid-column: 1 / -1; }
.stats .t { font-size: var(--fs-11); color: var(--tx-3); }
.stats .v { font-size: var(--fs-20); font-weight: var(--fw-x); line-height: 1.1;
            font-variant-numeric: tabular-nums; }
.stats .u { margin-left: 2px; font-size: var(--fs-11); font-weight: var(--fw-m); color: var(--tx-3); }
/* 곁값(오늘 · 지난달 …)은 수와 «한 줄»에 선다 — 칸이 늘 두 줄이라 높이가 저절로 맞는다 */
.stats .ln { display: flex; align-items: baseline; gap: var(--sp-3); min-width: 0; }
.stats .ln .v { flex: none; }
.stats .w { font-size: var(--fs-11); line-height: 1; color: var(--tx-3); min-width: 0;
            overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.stats .st.is-clear .v { color: var(--tx-4); font-weight: var(--fw-m); }
/* 할 일이 섞인 칸 — 1 이상이면 빨강 (대시보드 주문 면의 「불가일 미확정」 · §278) */
.stats .st.is-bad .v { color: var(--bd-c); }

/* 폰 — 이름과 숫자가 한 줄에 안 들어간다. 세로로 쌓되 2×5 는 지킨다 */
@media (max-width:  480px) {
  .card2 .hd { display: block; }
  .card2 .t  { margin-bottom: var(--sp-1); }
  .card2 .v  { margin-left: 0; display: inline-block; }
}

/* ---------- 목표 머리 — 왼쪽 숫자 · 오른쪽 가로 막대 ----------
   ★ 오른쪽을 SVG 로 두면 preserveAspectRatio 가 「비율을 지켜 안쪽에 맞추느라」
     폭이 남아도 안 늘어난다. 그래서 «격자»로 그린다 — 남는 폭이 생길 자리가 없다. */
.goal { display: grid; grid-template-columns: minmax(280px, 360px) minmax(0, 1fr);
        gap: var(--sp-7); align-items: center; padding: var(--sp-6);
        background: var(--sf); border: 1px solid var(--bd);
        border-radius: var(--r-lg); box-shadow: var(--sh-1); }
.goal > .txt { display: grid; gap: var(--sp-5); min-width: 0; }
.goal .trio { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
             gap: var(--sp-4); align-items: end; }
.goal .g   { display: flex; flex-direction: column; gap: var(--sp-1); min-width: 0; }
.goal .t   { font-size: var(--fs-11); color: var(--tx-3); white-space: nowrap; }
.goal .v   { font-size: var(--fs-20); font-weight: var(--fw-b); line-height: 1.1;
             font-variant-numeric: tabular-nums; }
.goal .v.big { font-size: var(--fs-28); font-weight: var(--fw-x); color: var(--ac); }
.goal .v.big.is-wn { color: var(--wn); }
.goal .u   { font-size: var(--fs-11); color: var(--tx-3); font-weight: var(--fw-m); }

/* 달성 막대 — 폭은 «목표 = 100%» 로 고정한다.
   ★ 100% 자리에 눈금을 세운다. 없으면 93% 와 103% 가 같아 보인다.
   ★ 넘친 만큼은 눈금 뒤로 이어 그린다 — 「초과 달성」이 지워지지 않게. */
/* ★ <span> 이라 display 를 안 주면 «인라인»이다 — 인라인에는 height 가 안 먹는다.
     앞서는 .goal 의 격자 칸이라 저절로 블록이 됐는데, .barwrap 안으로 들어오며 인라인이 됐다. */
.goal .bar { display: block; position: relative; height: 12px; border-radius: 999px;
             background: var(--sf-sunken); overflow: visible; }
.goal .bar .in { position: absolute; inset: 0; border-radius: 999px; overflow: hidden; }
.goal .bar i   { position: absolute; top: 0; bottom: 0; left: 0;
                 background: var(--ac); border-radius: 999px; }
.goal .bar i.is-wn  { background: var(--wn); }
.goal .bar i.over   { background: var(--ok); border-radius: 0 999px 999px 0; }
/* 목표선(진한 세로선)과 마감예상선(점선) — «글자는 없다».
   ★ 달성율 · 마감 달성율은 바로 옆 칸이 큰 글씨로 말한다. 막대가 두 번 말할 이유가 없다. */
/* ★ 막대 «안»에 딱 맞춘다 — 튀어나오면 눈에 거슬린다 (2026-09-03 대표).
   ★★ 다만 회색 심 하나로는 채움 위에서 사라진다 (--tx-3 대 --ac 대비 1.09).
      흰 테두리를 덧대 «어느 바닥에서도» 보이게 한다. */
.goal .bar u { position: absolute; top: 0; bottom: 0; width: 2px;
                       background: var(--tx-3);
                       box-shadow: 0 0 0 1px rgba(255,255,255,.9); }
.goal .bar.none { display: flex; align-items: center; justify-content: center; }
.goal .bar.none b { font-size: var(--fs-11); font-weight: var(--fw-m); color: var(--tx-3); }
/* 글자가 빠졌으므로 여백을 줄인다 — 선이 위아래로 4px 씩만 넘친다 */
.goal .barwrap { padding: var(--sp-4) 0 var(--sp-4); }

/* 오른쪽 — 최근 여섯 달, 가로 막대
   ★ 줄 이름은 «.mrow» 다. «.mo» 로 뒀더니 모바일 셸(.mo{height:100vh})과 부딪혀
     여섯 줄이 저마다 화면 높이만큼 늘어났다 — 그래프가 «안 그려진 것처럼» 보였다. */
.goal > .cht { min-width: 0; display: grid; gap: var(--sp-3); }
.goal .cht .key { display: flex; gap: var(--sp-5); font-size: var(--fs-11); color: var(--tx-3); }
.goal .cht .key i { display: inline-block; width: 9px; height: 9px; border-radius: 2px;
                    margin-right: var(--sp-2); vertical-align: -1px; background: var(--ac); }
.goal .cht .key span:nth-child(2) i { background: var(--a2); }
.goal .cht .key span:nth-child(3) i { background: var(--wn); }
.goal .cht .key span:nth-child(4) i { background: var(--ok); }
.goal .cht .mrow { display: grid; grid-template-columns: 40px minmax(0, 1fr) 92px 44px;
                 gap: var(--sp-3); align-items: center; font-size: var(--fs-11); }
.goal .cht .mrow .m  { color: var(--tx-3); font-variant-numeric: tabular-nums; }
.goal .cht .mrow .tr { display: block; position: relative; height: 12px;
                       border-radius: 3px; background: var(--a2); overflow: hidden; }
.goal .cht .mrow .tr.none { background: var(--sf-sunken); }
.goal .cht .mrow .tr i { position: absolute; inset: 0 auto 0 0; background: var(--ac);
                       border-radius: 3px; }
.goal .cht .mrow .tr i.is-wn { background: var(--wn); }
.goal .cht .mrow .tr i.over  { background: var(--ok); border-radius: 0 3px 3px 0; }
/* 100% 자리 — 넘친 달이 있으면 이 선이 안쪽으로 들어온다 */
.goal .cht .mrow .tr u { position: absolute; top: 0; bottom: 0; width: 1px;
                       background: var(--tx-3); box-shadow: 0 0 0 1px rgba(255,255,255,.9); }
.goal .cht .mrow .num { text-align: right; color: var(--tx-2);
                      font-variant-numeric: tabular-nums;
                      overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.goal .cht .mrow .pc  { text-align: right; font-weight: var(--fw-b);
                      font-variant-numeric: tabular-nums; }
.goal .cht .mrow .pc.is-wn { color: var(--wn); }
.goal .cht .mrow .pc.mut { font-weight: var(--fw-m); color: var(--tx-3); font-size: 10px; }
/* ★ 오른쪽이 없으면 두 단으로 «안» 나눈다 (§45 ⑦ 과 같은 자리) —
     안 그러면 머리가 왼쪽 360px 에 몰리고 오른쪽이 통째로 빈다.
     ⑳ 은 아래 표가 열두 달을 다 그리고, ⑥ 은 «세운 목표가 하나도 없는» 동안 그렇다
     (막대가 없는데 색 범례 넷만 서 있으면 그것은 값이 아니라 설명이다 · §5-101) */
.goal.solo { grid-template-columns: minmax(0, 1fr); }
@media (max-width: 900px) { .goal { grid-template-columns: minmax(0, 1fr); } }
@media (max-width: 520px) { .goal .cht .mrow { grid-template-columns: 36px minmax(0,1fr) 44px; }
  .goal .cht .mrow .num { display: none; } }

/* ---------- 도넛 — 라이브러리 없이 SVG ----------
   ★ 조각 안에는 글을 안 넣는다. 여덟 갈래에서 안 읽힌다 —
     이름·수·비율은 «범례»가 말하고, 아래 표가 다시 말한다. */
.donut { display: flex; align-items: center; gap: var(--sp-6); }
.donut > svg { width: 138px; height: 138px; flex: none; }
/* ★ 글자 크기가 «viewBox 단위»다 — SVG 는 CSS px 도 사용자 좌표로 읽는다.
   판이 0 0 42 42 이므로 17 을 주면 도넛(42)의 절반을 넘는 글자가 된다 */
.donut .hole { font-variant-numeric: tabular-nums; }
.donut .hole .n { font-size: 5.2px; font-weight: 700; fill: var(--tx); }
.donut .hole .t { font-size: 2.8px; fill: var(--tx-3); }
.donut .hole.long .n { font-size: 3.4px; }
.donut .lg { display: grid; gap: var(--sp-2); flex: 1; min-width: 0;
             font-size: var(--fs-11); }
.donut .lg > span { display: grid; grid-template-columns: 9px minmax(0, 1fr) auto auto;
                    gap: var(--sp-3); align-items: center; }
.donut .lg i  { width: 9px; height: 9px; border-radius: 2px; background: var(--s); }
/* 계열 색 여덟 — 조각과 범례가 «같은 이름»을 쓴다. 한 변수를 둘이 나눠 본다 */
.sl1 { --s: var(--c1); } .sl2 { --s: var(--c2); } .sl3 { --s: var(--c3); } .sl4 { --s: var(--c4); }
.sl5 { --s: var(--c5); } .sl6 { --s: var(--c6); } .sl7 { --s: var(--c7); } .sl8 { --s: var(--c8); }
.donut .sl { stroke: var(--s); }
.donut .lg em { font-style: normal; overflow: hidden;
                text-overflow: ellipsis; white-space: nowrap; color: var(--tx-2); }
.donut .lg b  { font-weight: var(--fw-b); font-variant-numeric: tabular-nums; }
.donut .lg u  { text-decoration: none; color: var(--tx-3);
                font-variant-numeric: tabular-nums; min-width: 38px; text-align: right; }
.donut + .rates { margin-top: var(--sp-5); padding-top: var(--sp-5);
                  border-top: 1px solid var(--bd); }
@media (max-width: 560px) { .donut { flex-direction: column; align-items: stretch; }
  .donut > svg { align-self: center; } }

/* ---------- 비율 목록 — 상품 · 지역 · 결제수단 ---------- */
.rates { display: grid; gap: var(--sp-2); }
.rates > div { display: grid; grid-template-columns: 1fr 56px 46px;
               align-items: center; gap: var(--sp-4); font-size: var(--fs-12); }
/* 돈은 자릿수가 길다 — 숫자 칸을 넓혀야 이름 칸을 안 밟는다 */
.rates.wide > div { grid-template-columns: 1fr 96px 46px; }
.rates .nm { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--tx-2); }
.rates .n  { text-align: right; font-weight: var(--fw-b);
             font-variant-numeric: tabular-nums; }
.rates .p  { text-align: right; font-size: var(--fs-11); color: var(--tx-3);
             font-variant-numeric: tabular-nums; }
.rates .bg { display: block; grid-column: 1 / -1; height: 4px; margin-top: -2px;
             background: var(--sf-sunken); border-radius: 999px; overflow: hidden; }
.rates .bg i { display: block; height: 100%; background: var(--a3); }

/* ---------- 여러 계열 꺾은선 — 전체 + 센터들 (⑫ 공급) ----------
   .trend 와 이름을 나눠 쓰지 않는다 — 한쪽을 고치면 다른 쪽이 조용히 바뀐다 */
.mline { background: var(--sf); border: 1px solid var(--bd); border-radius: var(--r-lg);
         padding: var(--sp-6); box-shadow: var(--sh-1); margin-bottom: var(--sp-6); }
.mline svg { display: block; max-width: 100%; }
.mline .gr { stroke: var(--bd-2); stroke-width: 1; }
.mline .gr.zero { stroke: var(--bd-strong); }   /* 음수 칸이 있을 때의 0 선 (§377) */
.mline .lb { font-size: 11px; fill: var(--tx-3); }
.mline .s  { fill: none; stroke-width: 1.5; stroke: var(--s, var(--ac)); }
.mline .s.all { stroke-width: 2.5; }
/* 색은 «계열 이름»이 갖는다 — .sl1~.sl8 이 --s 를 정한다 (규칙 6 · 인라인 금지) */
.mline .all { --s: var(--tx-2); }
.mline .key button { color: var(--s, var(--tx-2)); }
.mline .key { display: flex; flex-wrap: wrap; gap: var(--sp-3); margin-bottom: var(--sp-5); }
.mline .key button { display: inline-flex; align-items: center; gap: var(--sp-2);
                     border: 1px solid var(--bd); background: var(--sf);
                     border-radius: 999px; padding: 3px var(--sp-4);
                     font-size: var(--fs-11); cursor: pointer; }
.mline .key button i { display: inline-block; width: 12px; height: 3px;
                       border-radius: 2px; background: currentColor; }
.mline .key button b { color: var(--tx); font-variant-numeric: tabular-nums; }
.mline .key button.off { opacity: .4; }
.mline .key button.off b { color: var(--tx-3); }

/* ---------- 18개월 꺾은선 — 라이브러리 없이 SVG ---------- */
.trend { background: var(--sf); border: 1px solid var(--bd); border-radius: var(--r-lg);
         padding: var(--sp-6); box-shadow: var(--sh-1); }
/* ★ 늘리지 않는다. 폭은 그리는 쪽이 «픽셀로» 정한다 —
     확대하면 글자까지 커져 넓은 화면에서 본문보다 커졌다. */
.trend svg { display: block; max-width: 100%; }
.trend .am { fill: var(--a1); }                      /* 금액 막대 — 바탕이라 옅게 */
.trend .lb.r { text-anchor: start; }
.trend .key span.am i { background: var(--a2); height: 9px; border-radius: 2px; }
.trend .key span:nth-child(3) i { background: var(--bd-strong); }
.trend .ln  { fill: none; stroke: var(--ac); stroke-width: 2; }
.trend .ln2 { fill: none; stroke: var(--bd-strong); stroke-width: 2; stroke-dasharray: 4 3; }
.trend .gr  { stroke: var(--bd-2); stroke-width: 1; }
.trend .lb  { font-size: 11px; fill: var(--tx-3); }   /* 본문 각주와 «같은» 크기 */
.trend .key { display: flex; gap: var(--sp-5); margin-bottom: var(--sp-4);
              font-size: var(--fs-11); color: var(--tx-3); }
.trend .key b { color: var(--tx); font-variant-numeric: tabular-nums; }
.trend .key i { display: inline-block; width: 10px; height: 2px; margin-right: var(--sp-2);
                vertical-align: middle; background: var(--ac); }
.trend .key span:nth-child(2) i { background: var(--ac); }

/* 두 절을 나란히 */
.pair { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
        gap: var(--sp-5); }
.pair > section { background: var(--sf); border: 1px solid var(--bd);
                  border-radius: var(--r-lg); padding: var(--sp-6); box-shadow: var(--sh-1); }
.pair h3 { font-size: var(--fs-12); margin: 0 0 var(--sp-4); }

/* ---------- 흐름 막대 ----------
   숫자 하나로는 「멈췄다」가 안 보인다. 218 은 어제도 218 이었다.
   ★ 없는 것과 0 을 가른다 — 자료가 없는 날은 «점선 바닥», 0 인 날은 «회색 선».
     둘을 같게 그리면 「그날 공급이 없었다」와 「그날 자료가 없다」가 섞인다. */
.sparks { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: var(--sp-5); }
.spark  { background: var(--sf); border: 1px solid var(--bd); border-radius: var(--r-lg);
          padding: var(--sp-5) var(--sp-6) var(--sp-4); }
.spark .hd   { display: flex; align-items: baseline; gap: var(--sp-3); margin-bottom: var(--sp-4); }
.spark .hd .t { font-size: var(--fs-12); color: var(--tx-2); }
.spark .hd .v { margin-left: auto; font-size: var(--fs-20); font-weight: var(--fw-x);
                font-variant-numeric: tabular-nums; line-height: 1; }
.spark .hd .u { font-size: var(--fs-11); color: var(--tx-3); }

.spark .bars   { display: flex; align-items: flex-end; gap: 2px; height: 54px; }
.spark .bars i { flex: 1; display: block; min-height: 2px;
                 background: var(--ac); border-radius: 2px 2px 0 0; }
.spark .bars i.z  { background: var(--bd); height: 2px; }          /* 있었는데 0 */
.spark .bars i.na { background: none; height: 0; min-height: 0;    /* 자료가 없다 */
                    border-bottom: 2px dotted var(--bd); border-radius: 0; }
.spark .bars i.on { background: var(--tx); }                       /* 오늘 */

.spark .ax { display: flex; justify-content: space-between;
             margin-top: var(--sp-2); font-size: var(--fs-11); color: var(--tx-4); }
/* 숫자 붙은 막대 (구매자 대시보드 월별 · §286) — 막대마다 위에 수 · 아래에 달 */
.spark.num .mbars { display: flex; align-items: flex-end; gap: 3px; height: 88px; }
.spark.num .mb { flex: 1; min-width: 0; height: 100%; display: flex; flex-direction: column;
                 align-items: center; justify-content: flex-end; }
.spark.num .mb em { font-style: normal; font-size: 10px; line-height: 1; color: var(--tx-2);
                    font-variant-numeric: tabular-nums; margin-bottom: 3px; white-space: nowrap; }
.spark.num .mb i { display: block; width: 100%; min-height: 2px; background: var(--ac); border-radius: 2px 2px 0 0; }
.spark.num .mb i.z { background: var(--bd); height: 2px; }
.spark.num .mb i.on { background: var(--tx); }
.spark.num .mb small { font-size: 10px; line-height: 1; color: var(--tx-4); margin-top: 4px; white-space: nowrap; }

/* 수기 입력 지표 — 시스템 밖에서 오는 값 */
.hand { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--sp-5); }
.hand .h { background: var(--sf); border: 1px solid var(--bd); border-radius: var(--r-lg);
           padding: var(--sp-5) var(--sp-6); }
.hand .h .t { display: block; font-size: var(--fs-11); color: var(--tx-3); margin-bottom: var(--sp-3); }
.hand .h .in { display: flex; align-items: center; gap: var(--sp-3); }
.hand .h .fld { width: 100%; font-variant-numeric: tabular-nums; text-align: right; }
.hand .h .un { flex: none; font-size: var(--fs-11); color: var(--tx-3); }

.kpis { display: flex; gap: var(--sp-4); }
.kpi  { flex: 1; background: var(--sf); border: 1px solid var(--bd);
        border-radius: var(--r-lg); padding: var(--sp-4) var(--sp-5); box-shadow: var(--sh-1); }
.kpi .t { display: block; font-size: var(--fs-11); color: var(--tx-3); }
.kpi .v { font-size: var(--fs-20); font-weight: var(--fw-b); font-variant-numeric: tabular-nums; }
.kpi.big .v { font-size: var(--fs-28); font-weight: var(--fw-x); }
/* 기간이 섞인 절에서는 칸마다 «언제 것인지»를 단다 */
.kpi .when { display: block; margin-top: var(--sp-1);
             font-size: var(--fs-11); color: var(--tx-4); }
/* 넷 이상이면 줄바꿈한다 — flex:1 이면 칸 하나가 화면 절반이 된다.
   ★ 190 은 «돈과 날짜»가 정한 값이다 — 「지급액 12,345,678」이 134px,
   「마지막 주문 수집 2026-09-17 04:00」이 201px 를 요구한다. 낮추면 조용히 눌린다 */
.kpis.wrap { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }
/* 수량만 든 줄은 좁아도 된다 — 「A/S 공급 1,200」이 78px 다. 서랍 반폭에 넷이 한 줄로 선다 */
.kpis.wrap.qty { grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); }
/* 다섯이 한 줄 — 내 주문 서랍(배정 · 공급 · A/S 공급 · 잔량 · 진도). 120 이면 넷+하나로 갈렸다 */
.kpis.wrap.qty.one { grid-template-columns: repeat(auto-fit, minmax(84px, 1fr)); }

/* ============================================================
   3. 버튼
   ============================================================ */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-3);
  height: var(--ctl-h); padding: 0 var(--sp-6);
  font-family: inherit; font-size: var(--fs-12); font-weight: var(--fw-m);
  color: var(--tx); background: var(--sf);
  border: 1px solid var(--bd); border-radius: var(--r-md);
  cursor: pointer; white-space: nowrap; user-select: none;
}
.btn:hover  { border-color: var(--bd-strong); background: var(--sf-hover); }
.btn:active { background: var(--sf-sunken); }
.btn[disabled], .btn.is-off { opacity: .45; cursor: not-allowed; }
.btn[disabled]:hover, .btn.is-off:hover { border-color: var(--bd); background: var(--sf); }

.btn.pri   { background: var(--ac); border-color: var(--ac); color: var(--tx-on-ac); font-weight: var(--fw-b); }
.btn.pri:hover  { background: var(--ac-hover); border-color: var(--ac-hover); }
.btn.pri:active { background: var(--ac-press); border-color: var(--ac-press); }

.btn.dgr   { color: var(--bd-c); border-color: var(--bd-bd); }
.btn.dgr:hover { background: var(--bd-bg); border-color: var(--bd-c); }
.btn.dgr.solid { background: var(--bd-c); border-color: var(--bd-c); color: #fff; }

.btn.gho   { border-color: transparent; background: transparent; }
.btn.gho:hover { background: var(--sf-hover); border-color: transparent; }

.btn.sm    { height: 24px; padding: 0 var(--sp-4); font-size: var(--fs-12); }
.btn.lg    { height: 38px; padding: 0 var(--sp-8); font-size: var(--fs-13); }
.btn.blk   { display: flex; width: 100%; }
.btn.is-on { background: var(--ac); border-color: var(--ac); color: var(--tx-on-ac); font-weight: var(--fw-b); }

/* 뷰 전환 — 저장된 필터. 시트의 「필터 걸어 보기」를 대신한다 */
.views { display: inline-flex; gap: var(--sp-2); }

/* ============================================================
   4. 입력
   ============================================================ */
.fld {
  height: var(--ctl-h); padding: 0 var(--sp-4);
  font-family: inherit; font-size: var(--fs-12); color: var(--tx);
  background: var(--sf); border: 1px solid var(--bd); border-radius: var(--r-md);
}
.fld:hover { border-color: var(--bd-strong); }
.fld:focus { outline: none; border-color: var(--ac); box-shadow: var(--focus); }
.fld[disabled] { background: var(--sf-sunken); color: var(--tx-3); cursor: not-allowed; }
/* 고칠 수 없는 값 — 확인된 값(마이어시스트 회원 · §262)이나 아이디처럼 «보여 주기만» 하는 칸 */
.fld[readonly] { background: var(--sf-sunken); color: var(--tx-2); }
.fld[readonly]:hover { border-color: var(--bd); }
.fld[readonly]:focus { border-color: var(--bd); box-shadow: none; }
.fld.is-err { border-color: var(--bd-c); }
.fld.is-err:focus { box-shadow: 0 0 0 3px var(--bd-bg); }
.fld.sm { height: 26px; padding: 0 var(--sp-3); font-size: var(--fs-11); }
textarea.fld { height: auto; padding: var(--sp-3) var(--sp-4); line-height: var(--lh-r); resize: vertical; width: 100%; }
select.fld { padding-right: var(--sp-5); }
/* 상품 고르는 칸의 찾기 판 (§442) — select[data-pick] 앞에 서는 단추 · 누르면 body 에 판이 뜬다(서랍 45 · 드롭다운 60 위 · 띠 70 아래) */
.pick-btn { display: inline-flex; align-items: center; gap: var(--sp-3); text-align: left; cursor: pointer; }
.pick-btn .pick-t { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pick-btn .ti { flex: none; color: var(--tx-3); }
.pick-pan { position: fixed; z-index: 65; max-width: calc(100vw - 16px); padding: var(--sp-3);
            background: var(--sf); border: 1px solid var(--bd); border-radius: var(--r-md); box-shadow: var(--sh-2); }
.pick-pan .pick-q { width: 100%; margin-bottom: var(--sp-3); }
.pick-list { max-height: 320px; overflow: auto; }
.pick-it { padding: var(--sp-2) var(--sp-4); border-radius: var(--r-sm); font-size: var(--fs-12); cursor: pointer; white-space: nowrap; }
.pick-it.g  { font-weight: var(--fw-b); }
.pick-it.m  { padding-left: calc(var(--sp-4) + 14px); color: var(--tx-2); }
.pick-it.all { color: var(--tx-3); }
.pick-it.is-on { color: var(--ac-tx); }
.pick-it.is-act, .pick-it:hover { background: var(--ac-bg); }
.pick-it.no, .pick-it.no:hover { cursor: default; background: none; }
.pick-none { padding: var(--sp-3) var(--sp-4); font-size: var(--fs-12); color: var(--tx-3); }
.mo .pick-btn, .mo .pick-pan .pick-q { height: 40px; font-size: 16px; }
.fld.w-full { width: 100%; }
.fld.n { text-align: right; }
.fld.w-sm { width: 90px; } .fld.w-md { width: 160px; } .fld.w-lg { width: 240px; }

.chk { display: inline-flex; align-items: center; gap: var(--sp-3);
       font-size: var(--fs-12); cursor: pointer; user-select: none; }
.chk input { accent-color: var(--ac); width: 14px; height: 14px; }
/* 스위치 — 누르면 바로 저장되는 켬 · 끔 (§286 설정의 알림 · form[data-autosave]) */
.chk.sw input { appearance: none; -webkit-appearance: none; position: relative; margin: 0;
                width: 32px; height: 18px; border-radius: 9px; background: var(--bd); cursor: pointer;
                transition: background .15s; }
.chk.sw input::after { content: ''; position: absolute; top: 2px; left: 2px; width: 14px; height: 14px;
                       border-radius: 50%; background: #fff; transition: transform .15s; }
.chk.sw input:checked { background: var(--ac); }
.chk.sw input:checked::after { transform: translateX(14px); }
.chk.sw input:disabled { opacity: .5; cursor: default; }

/* 폼 줄 */
.frm     { display: flex; align-items: center; gap: var(--sp-4); margin-bottom: var(--sp-5); }
.frm.top { align-items: flex-start; }
.req { color: var(--bd-c); font-weight: var(--fw-b); }   /* 반드시 받는 칸 표시 */

.frm > label { flex: none; width: 92px; font-size: var(--fs-12); color: var(--tx-2); }
.frm > .v { flex: 1; min-width: 0; display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap; }
.frm .hint { width: 100%; font-size: var(--fs-11); color: var(--tx-3); }
.frm .err  { width: 100%; font-size: var(--fs-11); color: var(--bd-c); }
/* 고른 파일 목록 (§523) — mydb.js 가 파일 칸이 든 .v 끝에 붙인다 · 행마다 이름 · 크기 · [제외] */
.fsel { display: flex; flex-direction: column; gap: var(--sp-2); width: 100%; margin: 0; padding: 0; list-style: none; }
.fsel:empty { display: none; }
.fsel li { display: flex; align-items: center; gap: var(--sp-3); min-height: var(--ctl-h); padding: 0 var(--sp-2) 0 var(--sp-4);
           border: 1px solid var(--bd); border-radius: var(--r-md); background: var(--sf-sunken); font-size: var(--fs-12); }
.fsel .n { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fsel .s { flex: none; color: var(--tx-3); font-variant-numeric: tabular-nums; }
.frm:has(.fsel li) { align-items: flex-start; }

/* 읽기 전용 짝 */
.kv { display: grid; grid-template-columns: 92px 1fr; gap: var(--sp-2) var(--sp-4);
      font-size: var(--fs-12); margin: 0; }
.kv dt { color: var(--tx-2); }
.kv dd { margin: 0; }
/* 이름이 긴 짝 — 마이어시스트 옵션 · 주문서 입력 (§418) */
.kv.wide { grid-template-columns: minmax(92px, 38%) minmax(0, 1fr); }
.kv.wide dt, .kv.wide dd { overflow-wrap: anywhere; }
.kvh { margin: var(--sp-5) 0 var(--sp-2); font-size: var(--fs-12); color: var(--tx-3); font-weight: var(--fw-b); }

/* ============================================================
   5. 표 — 밀도가 이 제품의 승부처다
   ============================================================ */
.tblwrap { background: var(--sf); border: 1px solid var(--bd); border-radius: var(--r-lg); }
.tblwrap.x   { overflow-x: auto; }
.tblwrap.top { border-radius: 0 0 var(--r-lg) var(--r-lg); }

.tbl { width: 100%; border-collapse: collapse; font-size: var(--fs-12); }
.tbl th, .tbl td {
  height: var(--row-h); padding: 0 var(--sp-4);
  text-align: left; white-space: nowrap;
  border-bottom: 1px solid var(--bd-2);
}
/* ★ 머리 아래 선은 box-shadow 다 — border-collapse 에서 테두리는 «표»가 그리므로
   붙어 있는 동안 따라오지 않는다. */
.tbl thead th {
  position: sticky; top: 0; z-index: 2;
  background: var(--sf-sunken); color: var(--tx);
  font-size: var(--fs-11); font-weight: var(--fw-b);
  box-shadow: inset 0 -1px 0 var(--bd);
  user-select: none;
}
.tbl thead th.sortable { cursor: pointer; }
/* 머리의 링크는 «머리 색»을 그대로 쓴다 — a 의 강조색이 오면 머리 줄이 통째로 파래진다 */
.tbl thead th.sortable a { color: inherit; text-decoration: none; display: inline-block; }
.tbl thead th.sortable a:hover { color: var(--tx); }

/* 줄 끝의 작업 단추 — 몇 개든 «한 줄»로 선다.
   전에는 셋째 단추를 <div> 로 내려 줄 높이가 두 배가 됐다. 폭은 남아 있었다. */
.tbl td.acts     { white-space: nowrap; }
.tbl td.acts > * { vertical-align: middle; }
.tbl td.acts > * + * { margin-left: var(--sp-2); }
.tbl td.acts > form { display: inline-block; }
/* 합계도 «바닥에 붙는다» — 139줄을 훑는 동안 합계가 화면 밖으로 나가면 볼 수가 없다.
   ★ tfoot 이 «두 줄»일 수 있다 (㉑ 공급현황: 합계 + 센터별 진도).
     둘 다 bottom: 0 을 주면 겹쳐서 마지막 줄만 보인다 — 위 줄은 «한 줄 높이»만큼 띄운다.
   위 선은 머리와 같은 이유로 box-shadow 다 — border-collapse 에서 테두리는 «표»가
   그리므로 붙어 있는 동안 따라오지 않는다 (2026-09-05) */
.tbl tfoot td { position: sticky; z-index: 2; background: var(--sf-sunken); }
.tbl tfoot tr:last-child td        { bottom: 0; }
.tbl tfoot tr:nth-last-child(2) td { bottom: var(--row-h); }
.tbl.dense tfoot tr:nth-last-child(2) td,
.tblwrap.dense > .tbl tfoot tr:nth-last-child(2) td { bottom: var(--row-h-sm); }
.tbl tfoot tr:first-child td { box-shadow: inset 0 1px 0 var(--bd-strong); }
/* ★ 머리가 «두 줄»일 때 (㉑ 공급현황: 합계·센터 이름 / 요청·순입고·잔량).
   둘 다 top: 0 이면 같은 자리에 붙고, 나중에 그려지는 둘째 줄이 첫째 줄을 «덮는다» —
   그러면 요청·순입고가 어느 센터 것인지 알 수 없게 된다.
   위 줄에 rowspan="2" 로 걸친 칸은 첫 줄 소속이라 top: 0 이 맞다 (2026-09-05 대표) */
.tbl thead tr:nth-child(2) th       { top: var(--row-h); }
.tbl.dense thead tr:nth-child(2) th,
.tblwrap.dense > .tbl thead tr:nth-child(2) th { top: var(--row-h-sm); }

.tbl thead th.sortable:hover { background: var(--sf-hover); color: var(--tx); }
/* 지금 «고른» 줄 — 표 안에서 어디를 보고 있는지 짚어 준다.
   .is-on 은 패널·달력·단추가 이미 쓰는 이름이라 표에 또 얹지 않는다 (검사 64) */
.tbl tbody tr.here > td { background: var(--ac-bg); }
.tbl thead th .ar { color: var(--ac); }
.tbl tbody tr:hover { background: var(--sf-hover); }
.tbl tbody tr.is-sel { background: var(--ac-bg); }
.tbl tbody tr.clickable { cursor: pointer; }
/* 칸 하나가 서랍을 여는 격자 — ⑮ 매입단가 (§239) */
.tbl tbody td[data-row] { cursor: pointer; }
/* 끝난 주문 — 살아 있는 줄과 «섞여 보이면» 안 된다. 지우는 것이 아니라 뒤로 물린다 */
.tbl tbody tr.off > td { color: var(--tx-3); }
.tbl tbody tr.off > td b { font-weight: var(--fw-m); }
.tbl td.n, .tbl th.n { text-align: right; font-variant-numeric: tabular-nums; }
.tbl td.c, .tbl th.c { text-align: center; }
.tbl td.mut { color: var(--tx-3); }
/* 전화·번호처럼 «자릿수를 맞춰야» 읽히는 것 */
.mono { font-variant-numeric: tabular-nums; letter-spacing: -0.01em; }
/* ★ 감싸개로도 켠다 — mydb_table() 이 «감싸개 이름»만 받기 때문이다.
   이름을 나눠 쓰면 한쪽만 고쳐진다 (§75) */
.tbl.dense th, .tbl.dense td,
.tblwrap.dense > .tbl th, .tblwrap.dense > .tbl td { height: var(--row-h-sm); }
/* 칸이 많은 좁은 표 — 서랍(560px)의 A/S 표가 열 칸이 되어 옆으로 밀렸다 (§464) */
.tblwrap.tight > .tbl th, .tblwrap.tight > .tbl td { padding-left: 6px; padding-right: 6px; }
/* 수 칸에서 그 목록으로 가는 수 · 단골 색을 수 크기 그대로 (A/S 구매자 이력 · §465) */
.kpi a.go { color: inherit; text-decoration: none; }
.kpi a.go:hover { text-decoration: underline; }
.kpi .v .tier { font-size: inherit; line-height: 1.3; }

/* ---------- 교차표 — 가로 항목 × 세로 항목 (⑫ 공급 상세) ----------
   ★ 첫 칸이 «왼쪽에 붙는다». 가로로 밀면 무슨 줄인지 사라진다 —
     열이 열둘이라 좁은 화면에서는 반드시 밀린다.
   머리(top)와 첫 칸(left)이 만나는 자리는 «둘 다» 붙어야 하므로 z-index 를 더 올린다 */
.tbl.pivot th:first-child,
.tbl.pivot td:first-child { position: sticky; left: 0; z-index: 3;
                            background: var(--sf); min-width: 150px;
                            box-shadow: inset -1px 0 0 var(--bd); }
.tbl.pivot thead th:first-child { z-index: 5; background: var(--sf-sunken); }
.tbl.pivot tfoot td:first-child { z-index: 5; background: var(--sf-sunken); }
.tbl.pivot th.n, .tbl.pivot td.n { min-width: 62px; }

/* 교차표 칸 — 값이 클수록 바탕이 짙다. 넉 단이면 «어디가 몰렸나»가 한눈에 보인다.
   ★ 프로토타입은 인라인 style 이었다 — 규칙 6 이라 클래스로 옮겼다 (2026-09-16) */
.tbl.pivot td.bg1 { background: color-mix(in srgb, var(--ac) 6%,  transparent); }
.tbl.pivot td.bg2 { background: color-mix(in srgb, var(--ac) 11%, transparent); }
.tbl.pivot td.bg3 { background: color-mix(in srgb, var(--ac) 16%, transparent); }
.tbl.pivot td.bg4 { background: color-mix(in srgb, var(--ac) 22%, transparent); }
.tbl tbody tr:last-child td { border-bottom: 0; }

.empty { padding: var(--sp-10) var(--sp-8); text-align: center; color: var(--tx-3); font-size: var(--fs-12); }
.empty .big { display: block; font-size: var(--fs-14); color: var(--tx-2); margin-bottom: var(--sp-2); }

/* ============================================================
   6. 배지 · 태그 · 등급
   ============================================================ */
.bdg { display: inline-block; padding: 0 var(--sp-3); border-radius: var(--r-pill);
       font-size: var(--fs-11); line-height: 18px; white-space: nowrap; }
.bdg.gray { background: var(--sf-sunken); color: var(--tx-2); }
.bdg.ac   { background: var(--ac-bg); color: var(--ac-tx); }
.bdg.ok   { background: var(--ok-bg); color: var(--ok); }
.bdg.wn   { background: var(--wn-bg); color: var(--wn); }
.bdg.bad  { background: var(--bd-bg); color: var(--bd-c); }
.bdg.out  { background: transparent; border: 1px solid var(--bd); color: var(--tx-2); }

.tag { display: inline-block; padding: 0 var(--sp-3); border-radius: var(--r-sm);
       font-size: var(--fs-11); line-height: 18px; background: var(--sf-sunken); color: var(--tx-2); }
.tag.ac { background: var(--ac-bg); color: var(--ac-tx); }

/* 단골 등급 — 시트의 청록 히트스케일. 숫자가 정본, 색은 보조 (원칙 6) */
.tier { display: inline-block; min-width: 26px; text-align: center;
        padding: 0 var(--sp-3); border-radius: var(--r-sm);
        font-size: var(--fs-11); line-height: 18px; font-variant-numeric: tabular-nums; }
.tier.t1 { background: var(--tier1-b); color: var(--tier1-f); }
.tier.t2 { background: var(--tier2-b); color: var(--tier2-f); }
.tier.t3 { background: var(--tier3-b); color: var(--tier3-f); }
.tier.t4 { background: var(--tier4-b); color: var(--tier4-f); }
.tier.t5 { background: var(--tier5-b); color: var(--tier5-f); }

/* ============================================================
   7. 진도
   ============================================================ */
/* 막대 + 퍼센트 «한 덩이» — ⑪ 공유 「손댄 비율」.
   ★ 이름을 `.prog` 과 나눠 쓴다 — 두 벌이면 뒤엣것이 이겨 앞엣것이 조용히 진다.
     실제로 그랬다: 아래 `.prog`(56×6 · overflow:hidden)이 이 덩이를 통째로 잘랐다. */
.pbar { display: inline-flex; align-items: center; gap: var(--sp-3); }
.pbar .bar { position: relative; height: 14px; width: 62px;
             background: var(--sf-sunken); border-radius: 3px; overflow: hidden; }
.pbar .bar > i { display: block; height: 100%; background: var(--ac); }
.pbar.done .bar > i { background: var(--ok); }
/* 진도가 낮은 센터 — «주의»다. 빨강(위험)이 아니다 */
.pbar .bar.lo > i { background: var(--wn); }
.pbar.zero .bar { background: var(--bd-bg); }
.pbar .pct { font-size: var(--fs-11); width: 30px; text-align: right;
             font-variant-numeric: tabular-nums; color: var(--tx-2); }

/* 고르기 카드 — 「누구에게 줄까」처럼 «사람을 고르는» 자리.
   라디오를 숨기고 카드 전체를 누르게 한다. 목록보다 정보를 더 실을 수 있다 */
.cards { display: grid; gap: var(--sp-4);
         grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); }
.pick { display: flex; flex-direction: column; gap: var(--sp-2); cursor: pointer;
        padding: var(--sp-5); border: 1px solid var(--bd); border-radius: var(--r-lg);
        background: var(--sf); }
.pick:hover { border-color: var(--ac); }
.pick input { position: absolute; opacity: 0; pointer-events: none; }
.pick:has(input:checked) { border-color: var(--ac); background: var(--ac-bg);
                           box-shadow: inset 0 0 0 1px var(--ac); }
.pick.is-off { opacity: .55; cursor: default; }
.pick.is-off:hover { border-color: var(--bd); }
.pick .nm { font-weight: var(--fw-b); font-size: var(--fs-13); }
.pick .ds { font-size: var(--fs-12); color: var(--tx-2); }
/* 가입 유형 (§262) — 아이콘을 이름 앞에 */
.auth .pick .nm { display: flex; align-items: center; gap: var(--sp-3); font-size: var(--fs-14); }
.auth .pick .nm .ti { width: 18px; height: 18px; color: var(--ac); }

/* ============================================================
   8. 알림 · 검증
   ============================================================ */
.note { padding: var(--sp-4) var(--sp-5); border-radius: var(--r-md);
        font-size: var(--fs-12); line-height: var(--lh-n);
        background: var(--sf-sunken); border: 1px solid var(--bd); color: var(--tx-2); }
.note.ok  { background: var(--ok-bg); border-color: var(--ok-bd); color: var(--ok); }
.note.wn  { background: var(--wn-bg); border-color: var(--wn-bd); color: var(--wn); }
.note.bad { background: var(--bd-bg); border-color: var(--bd-bd); color: var(--bd-c); }
.note.ac  { background: var(--ac-bg); border-color: var(--ac-bd); color: var(--ac-tx); }
/* 테스트 서버 표시 (§511) — 운영에는 안 그린다. 상단 막대 높이는 그대로다(border-box) */
.topbar.is-test, .mo > .top.is-test { border-top: 3px solid var(--wn); }
.testmark { flex: none; padding: 2px var(--sp-3); border-radius: 999px; white-space: nowrap;
            font-size: var(--fs-12); font-weight: var(--fw-b); line-height: var(--lh-n);
            background: var(--wn-bg); color: var(--wn); border: 1px solid var(--wn-bd); }
.head h1 .testmark { margin-left: var(--sp-3); vertical-align: middle; }
.testmark.float { position: fixed; top: var(--sp-3); left: 50%; transform: translateX(-50%); z-index: 80; }
/* 한 줄에 하나 — 설치가 맞춘 것 (§510) */
.note.lst { display: flex; flex-direction: column; gap: var(--sp-1); }
.note.lst > b { display: flex; align-items: center; gap: var(--sp-2); margin-bottom: var(--sp-1); }

/* 확인 대화 */
.dlg { width: 420px; max-width: calc(100vw - 32px);
       background: var(--sf); border: 1px solid var(--bd);
       border-radius: var(--r-lg); box-shadow: var(--sh-2); overflow: hidden; }
.dlg > header { padding: var(--sp-6) var(--sp-7) 0; font-size: var(--fs-14); font-weight: var(--fw-b); }
.dlg > .bd { padding: var(--sp-4) var(--sp-7) var(--sp-6); font-size: var(--fs-12);
             color: var(--tx-2); line-height: var(--lh-r); }
.dlg > footer { display: flex; gap: var(--sp-4); justify-content: flex-end;
                padding: var(--sp-5) var(--sp-7); background: var(--sf-sunken);
                border-top: 1px solid var(--bd-2); }

/* 작은 진도 막대 — 표 칸 안 */
/* 작은 진도 막대 — 머리 막대와 «같은 규칙»이다.
   ★ 미달은 «주의(주황)»다. 빨강은 이 시스템에서 «위험»이라 목표 미달에 쓰지 않는다. */
.mbar { position: relative; display: block; width: 100px; height: 6px;
        border-radius: 999px; background: var(--sf-sunken); }
.mbar i { position: absolute; top: 0; bottom: 0; left: 0;
          background: var(--ac); border-radius: 999px; }
.mbar i.is-wn { background: var(--wn); }
.mbar i.over  { background: var(--ok); border-radius: 0 999px 999px 0; }
.mbar .in { position: absolute; inset: 0; border-radius: 999px; overflow: hidden; }
.mbar u { position: absolute; top: 0; bottom: 0; width: 1px; background: var(--tx-3);
          box-shadow: 0 0 0 1px rgba(255,255,255,.9); }
/* ★ 표 칸은 6px 이라 알약 안에 글자가 안 들어간다 — 막대를 걷고 «글자만» 남긴다.
     같은 마크업을 받되 «껍데기가 모양을 정한다» */
.mbar.none { display: inline; width: auto; height: auto; background: none; }
.mbar.none b { font-weight: var(--fw-m); color: var(--tx-3); }

/* 단추 줄 — 표 아래 */
.acts-row { display: flex; gap: var(--sp-4); margin-top: var(--sp-6); }

/* 잔량 현황 — 칸이 많은 격자 표.
   ★ 담당 밖 센터는 «회색»이다. 0 건(맡았는데 아직 안 옴)과 다른 상태다. */
.tbl.grid th, .tbl.grid td { padding: var(--sp-3) var(--sp-4); font-size: var(--fs-11); }
.tbl.grid th.grp  { border-left: 1px solid var(--bd); background: var(--sf-sunken);
                    font-size: var(--fs-11); }
.tbl.grid th.sub2,
/* ★ 묶음 머리 «안»의 부제 — ㉑ 이 센터 이름 밑에 담당 지역을 적는다 (2026-09-22).
   th.grp 가 11px 이라 전역 .sub(12px)를 쓰면 부제가 이름보다 커진다 */
.tbl.grid th.grp .sub2 { font-weight: var(--fw-m); color: var(--tx-3); font-size: 10px; }
.tbl.grid td.na   { background: var(--sf-sunken); }
.tbl tr.na > td   { color: var(--tx-3); }   /* 아직 안 온 단계 — 홀딩 서랍 「진행 단계」 (§403) */
/* 묶음이 바뀌는 자리 — ㉑ 은 상품이, ① 서랍의 A/S 는 고객이 바뀌는 줄에 건다.
   ★ .tbl.grid 로 좁혀 두었더니 «격자가 아닌» 표에서 조용히 안 먹었다 (§2 의 「.tbl.grid 를 안 걸었다」) */
.tbl tr.grpline > td { border-top: 1px solid var(--bd-strong); }
/* 공급 여러 줄 수정 (§482) — 등록 내역의 고르기 칸 · 화면을 덮는 창 · 엑셀 같은 표 */
.tbl th.fixsel, .tbl td.fixsel { width: 1%; white-space: nowrap; }
.fixdim { position: fixed; inset: 0; z-index: 70; display: flex; align-items: center; justify-content: center;
          padding: var(--sp-8); background: rgba(20,30,50,.35); }
.fixdlg { display: flex; flex-direction: column; width: 100%; max-width: 1600px; max-height: 100%;
          background: var(--sf); border-radius: var(--r-lg); box-shadow: var(--sh-3); }
.fixdlg > header, .fixdlg > footer { display: flex; align-items: center; gap: var(--sp-4); padding: var(--sp-5) var(--sp-7); }
.fixdlg > header { border-bottom: 1px solid var(--bd-2); }
.fixdlg > header .sp, .fixdlg > footer .sp { flex: 1; }
.fixdlg > footer { border-top: 1px solid var(--bd-2); }
.fixdlg > form { display: flex; flex-direction: column; min-height: 0; flex: 1; }
.fixdlg .fixgrid { flex: 1; min-height: 0; overflow: auto; border: 0; border-radius: 0; }
.fixdlg .fixgrid.pad { padding: var(--sp-6) var(--sp-7); }   /* 일괄 발주 (§616) — 옵션 · 미리보기 두 단 */
.fixdlg.nar { max-width: 640px; }   /* 주문 목록 [문자] (§633) — 칸 하나라 넓을 까닭이 없다 */
/* ★ 아래 .fixgrid .fld(일괄 수정 표 칸 · 높이 28)를 문자 창의 내용 칸에서는 푼다 (§635) — 한 줄로 굳었다 */
.fixdlg.nar textarea.fld { height: auto; }
/* 창(70) 안의 고르기 칸 — 찾기 판(65)이 창 뒤에 깔려 템플릿이 «없는» 것처럼 보였다 (§636). 판은 body 끝에 붙어 창 뒤 형제다 */
.fixdim ~ .pick-pan { z-index: 75; }
/* 본사 문자 템플릿 «불러오기» 창 (§664) — 문자 창(70) · 찾기 판(75) 위 · 저장 띠(toast 70)는 그 위로 올린다 */
.fixdim.tpl { z-index: 76; }
.fixdim.tpl ~ .toast { z-index: 77; }
.fixdlg.tplwin { max-width: 960px; height: min(720px, 100%); }
.tplwin .tw-bar { display: flex; align-items: center; gap: var(--sp-4); padding: var(--sp-4) var(--sp-7); border-bottom: 1px solid var(--bd-2); }
.tplwin .tw-body { flex: 1; min-height: 0; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
.tplwin .tw-list { overflow: auto; border-right: 1px solid var(--bd-2); }
.tplwin .tw-it { padding: var(--sp-4) var(--sp-7); border-bottom: 1px solid var(--bd-2); cursor: pointer; }
.tplwin .tw-it:hover { background: var(--sf-sunken); }
.tplwin .tw-it.is-on { background: var(--ac-bg); }
.tplwin .tw-h { display: flex; align-items: center; gap: var(--sp-3); }
.tplwin .tw-h b { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tplwin .tw-l { margin-top: 2px; font-size: var(--fs-12); color: var(--tx-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tplwin .tw-pv { overflow: auto; padding: var(--sp-6) var(--sp-7); background: var(--sf-sunken); }
.tplwin .tw-msg { max-width: 340px; margin-bottom: var(--sp-3); padding: var(--sp-5) var(--sp-6); border-radius: var(--r-lg);
                  background: var(--sf); box-shadow: var(--sh-1); white-space: pre-wrap; word-break: break-all; font-size: var(--fs-13); line-height: 1.6; }
.tplwin .tw-msg:empty { display: none; }
.tplwin .tw-act { display: flex; align-items: center; gap: var(--sp-3); margin-top: var(--sp-5); }
.tplwin .tw-act .sp { flex: 1; }
.tplwin .tw-pv textarea.fld { height: auto; }
.tplwin [hidden] { display: none; }   /* .tw-act · .empty 의 display 가 hidden 을 이기지 않게 — 맨 뒤에 둔다 */
@media (max-width: 720px) {
  .tplwin .tw-body { grid-template-columns: 1fr; grid-template-rows: minmax(0, 1fr) auto; }
  .tplwin .tw-list { border-right: 0; border-bottom: 1px solid var(--bd-2); }
}
.fixgrid .fld { width: 100%; min-width: 90px; height: 28px; }
.fixgrid textarea.fld { min-height: 28px; resize: vertical; padding-top: 4px; padding-bottom: 4px; }
.fixgrid .fld[data-col="cs_addr"], .fixgrid .fld[data-col="cs_memo"] { min-width: 200px; }
.fixgrid .fld[data-col="cs_age"], .fixgrid .fld[data-col="cs_sex"] { min-width: 52px; }
.fixgrid .fld[readonly] { background: var(--sf-sunken); color: var(--tx-2); }
/* 창(.fixgrid.pad — 일괄 발주 · 문자)의 옵션 칸은 제 폭을 쓴다 (2026-11-05 대표 · §669) — 위 .fixgrid .fld(공급 수정 표 칸 · 폭 100%)가 덮어
   일괄 발주 «회당» 칸이 줄 끝까지 늘고 «건»이 아랫줄로 밀렸다. 폭은 .fld.w-sm · w-md · w-lg 와 같다 */
.fixgrid.pad .fld.w-sm { width: 90px; min-width: 0; }
.fixgrid.pad .fld.w-md { width: 160px; min-width: 0; }
.fixgrid.pad .fld.w-lg { width: 240px; min-width: 0; }
.fixgrid tr.is-bad > td { background: var(--bd-bg); }
.fixgrid td.fixmsg { min-width: 220px; white-space: normal; color: var(--bd-c); font-size: var(--fs-11); }

/* 통계의 상품 묶음 (§480) — 묶음 줄은 굵게 · 묶인 상품은 들여 쓰고 옅게 */
.tbl tr.pdb > td:first-child { font-weight: var(--fw-b); }
.tbl tr.pdm > td { color: var(--tx-2); }
.tbl tr.pdm > td:first-child { padding-left: var(--sp-9); }
.tbl.grid td.rest { font-weight: var(--fw-b); }
.tbl.grid tfoot td { background: var(--sf-sunken);
                     font-variant-numeric: tabular-nums; }
/* 센터별 진도 — 합계 «아래에 붙는» 부속 줄이다. 위 선은 tfoot 첫 줄이 이미 그렸으므로
   여기서는 지운다. 둘이 한 덩이로 보여야 「합계와 그 내역」으로 읽힌다 */
.tbl.grid tfoot tr.pcrow td { box-shadow: none; }
.tbl.grid td.r { text-align: right; }
.mbar.sm { display: inline-block; width: 44px; height: 5px; vertical-align: middle; }
.pcs { margin-left: var(--sp-2); font-variant-numeric: tabular-nums; }

/* 다크에서는 흰 테두리가 튄다 — 바닥색으로 두른다 */
:root[data-theme="dark"] .goal .bar u,
:root[data-theme="dark"] .goal .cht .mrow .tr u,
:root[data-theme="dark"] .mbar u { box-shadow: 0 0 0 1px rgba(0,0,0,.55); }

/* 달력 — 구매자가 «못 받는 날»을 고른다 (방문지정) */
.cal { border: 1px solid var(--bd); border-radius: var(--r-lg); padding: var(--sp-5);
       background: var(--sf); }
.cal-hd, .cal-bd { display: grid; grid-template-columns: repeat(7, 1fr); gap: var(--sp-2); }
.cal-hd { margin-bottom: var(--sp-3); }
.cal-hd span { text-align: center; font-size: var(--fs-11); color: var(--tx-3); }
.cal-bd .pad { visibility: hidden; }
.cal-d { height: 30px; border: 1px solid var(--bd); border-radius: var(--r-md);
         background: var(--sf); color: var(--tx); font-size: var(--fs-12);
         font-variant-numeric: tabular-nums; cursor: pointer; }
.cal-d:hover { border-color: var(--bd-strong); background: var(--sf-hover); }
.cal-d.we { color: var(--tx-3); }
.cal-d.is-on { background: var(--wn); border-color: var(--wn); color: #fff; font-weight: var(--fw-b); }
.cal-d:focus-visible { outline: none; box-shadow: var(--focus); }

/* 배정 달력 — ㉒ 내 주문의 .cal 과 «구조는 같고 CSS 는 따로»다.
   .cal-d 에 얹으면 홑이름이 잡은 height: 30px 을 덮게 되어
   안 겹친 성질이 조용히 새어 든다 (검사 64 · .mo 가 그랬다) */
/* 걸친 달만큼 판을 그려 두고 «하나만» 보인다 — 넘기는 것은 보이는 판을 바꾸는 일이다.
   ★ [hidden] 을 «직접» 적는다 — 브라우저 기본 규칙은 display 를 준 이름에게 진다
     (2026-09 에 .frm{display:flex} 가 [hidden] 을 이겨 두 절이 함께 보였다) */
.acals { display: block; }
.acals > .acal[hidden] { display: none; }
.acal { border: 1px solid var(--bd); border-radius: var(--r-lg);
        padding: var(--sp-5); background: var(--sf); }
/* 달 넘기기 — 가운데 연월이 판마다 붙어 있어 누를 때 «글자를 고칠 일»이 없다.
   양 끝에서는 단추 자리를 빈 칸으로 둔다 — 아무 일도 안 하는 단추를 두지 않는다 (규칙 ⑨) */
.acal-nav { display: grid; grid-template-columns: 28px minmax(0, 1fr) 28px;
            align-items: center; margin-bottom: var(--sp-5); }
.acal-nav .ym { text-align: center; font-size: var(--fs-11); color: var(--tx-3);
                font-variant-numeric: tabular-nums; }
.acal-hd, .acal-bd { display: grid; grid-template-columns: repeat(7, 1fr); gap: var(--sp-3); }
.acal-hd { margin-bottom: var(--sp-3); }
.acal-hd span { text-align: center; font-size: var(--fs-11); color: var(--tx-3); }
.acal-bd .pad { visibility: hidden; }
.acal-d { min-height: 60px; display: flex; flex-direction: column; align-items: flex-start;
          gap: 1px; padding: var(--sp-3) var(--sp-4);
          border: 1px solid var(--bd); border-radius: var(--r-md);
          background: var(--sf); font-variant-numeric: tabular-nums; }
.acal-d .dd  { font-size: var(--fs-11); color: var(--tx-3); }
.acal-d .sup { font-size: var(--fs-12); font-weight: var(--fw-b); color: var(--ac); }
.acal-d .pln { font-size: var(--fs-11); color: var(--tx-3); }
/* 방문지정 방문 예정일 (§309) — 공급(받은 날)과 다른 날이라 색을 가른다 */
.acal-d .vs  { font-size: var(--fs-11); color: var(--ok); font-weight: var(--fw-b); }
/* A/S 신청이 들어온 날 — «주의»다. 빨강(위험)이 아니다 */
.acal-d .as  { font-size: var(--fs-11); color: var(--wn); font-weight: var(--fw-b); }
/* 발주일 — 처음 배정을 넣은 날 (§520). 공급과 견주는 기준이라 글자색 그대로 */
.acal-d .ord { font-size: var(--fs-11); color: var(--tx-1); font-weight: var(--fw-b); }
.acal-d.we .dd { color: var(--tx-4); }
.acal-d.no  { background: var(--bd-bg); border-color: var(--bd-bd); border-style: dashed; }
.acal-d.no .dd { color: var(--bd-c); }
.acal-d.od  { border-color: var(--ac); }
/* 그날 내역 (§495) — 수가 있는 날은 누른다 · 고른 날은 굵은 테두리 · 내역은 달력 바로 아래 칸에 펼친다 */
.acal-d.go { cursor: pointer; }
.acal-d.go:hover { border-color: var(--bd-strong); }
.acal-d.go.is-sel { border-color: var(--ac); box-shadow: 0 0 0 1px var(--ac); }
.cday { padding: var(--sp-5); border: 1px solid var(--bd); border-radius: var(--r-lg); background: var(--sf-sunken); }
.cday-hd { display: flex; align-items: center; gap: var(--sp-3); }
.cday .kvh:first-of-type { margin-top: var(--sp-3); }
.acal .lgd { display: flex; gap: var(--sp-5); flex-wrap: wrap;
             margin-top: var(--sp-4); font-size: var(--fs-11); color: var(--tx-3); }
.acal .lgd i { display: inline-block; width: 8px; height: 8px; border-radius: 2px;
               margin-right: var(--sp-2); vertical-align: middle; }
/* 범례 색 — 프로토타입은 인라인 style 로 두었다. 여기서는 규칙 6 을 지킨다 */
.acal .lgd i.sup { background: var(--ac); }
.acal .lgd i.pln { background: var(--tx-3); }
.acal .lgd i.vs  { background: var(--ok); }
.acal .lgd i.as  { background: var(--wn); }
.acal .lgd i.ord { background: var(--tx-1); }
/* 환불 — 거둔 수를 공급을 멈춘 날에 (§558) */
.acal-d .rf  { font-size: var(--fs-11); color: var(--bd-c); font-weight: var(--fw-b); }
.acal .lgd i.rf { background: var(--bd-c); }
.acal .lgd i.no  { background: var(--bd-bg); border: 1px dashed var(--bd-bd); }
/* 구매자 캘린더(§270) — 칸이 곧 그날로 가는 링크다. 재연락은 지나면 빨강 */
.acal-d .rc { font-size: var(--fs-11); color: var(--wn); font-weight: var(--fw-b); }
.acal-d .rc.late { color: var(--bd-c); }
.acal .lgd i.rc { background: var(--wn); }
/* 오늘 전의 예정은 아직 안 채워진 자리 — 「지연」 빨강 (§270-23) */
.acal-d .pln.late { color: var(--bd-c); font-weight: var(--fw-b); }
.acal .lgd i.late { background: var(--bd-c); }
.ucal a.acal-d { color: inherit; text-decoration: none; }
.ucal a.acal-d:hover { border-color: var(--bd-strong); }
.acal-d.on { background: var(--ac-bg); border-color: var(--ac); }
/* 구매자 캘린더 주 보기(§278) — 칸마다 그날의 고객 이름. 이름은 고객 서랍을 연다 */
.wcal { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: var(--sp-3); }
.wcal-d { min-height: 220px; display: flex; flex-direction: column; gap: 2px; padding: var(--sp-3);
          border: 1px solid var(--bd); border-radius: var(--r-md); background: var(--sf); min-width: 0; }
.wcal-d.od { border-color: var(--ac); }
.wcal-h { font-size: var(--fs-12); font-weight: var(--fw-b); color: var(--tx-2); text-decoration: none;
          margin-bottom: var(--sp-2); }
.wcal-h:hover { color: var(--ac); }
.wcal-d.we .wcal-h { color: var(--tx-4); }
.wcal-t { font-size: var(--fs-11); font-weight: var(--fw-b); margin-top: var(--sp-2); }
.wcal-t.rc { color: var(--wn); }
.wcal-t.sup { color: var(--ac); }
.wcal-t.pln { color: var(--tx-3); }
.wcal-t.vs { color: var(--ok); }
.wcal-t.late { color: var(--bd-c); }
.wcal .wi { display: block; width: 100%; text-align: left; font: inherit; font-size: var(--fs-12);
            color: var(--tx); background: none; border: 0; padding: 1px var(--sp-2); border-radius: var(--r-sm);
            white-space: nowrap; overflow: hidden; text-overflow: ellipsis; text-decoration: none; cursor: pointer; }
.wcal button.wi:hover { background: var(--sf-hover); }
.wcal .wi.more { color: var(--tx-3); font-size: var(--fs-11); }
.wcal .wi.pl, .wcal .wi.none { color: var(--tx-3); cursor: default; }
/* 상담(내가 쓴 상담 기록) · 불가(방문지정 확정 불가일) — §283. 불가 칸은 배정 달력의 .acal-d.no 와 같은 모양 */
.acal-d .ct { font-size: var(--fs-11); color: var(--ok); font-weight: var(--fw-b); }
.acal .lgd i.ct { background: var(--ok); }
.wcal-t.ct { color: var(--ok); }
.wcal-t.no { color: var(--bd-c); }
.wcal-d.no { background: var(--bd-bg); border-color: var(--bd-bd); border-style: dashed; }

/* 발주 설정 — 배정 방식 고르기 · 요일 · 센터 쪼개기 */
.segs { display: flex; gap: var(--sp-2); }
.days { display: flex; gap: var(--sp-2); }
.day  { position: relative; }
.day input { position: absolute; opacity: 0; width: 0; height: 0; }
.day span { display: grid; place-items: center; width: 30px; height: 28px;
            border: 1px solid var(--bd); border-radius: var(--r-md);
            font-size: var(--fs-12); color: var(--tx-2); cursor: pointer; background: var(--sf); }
.day input:checked + span { background: var(--ac); border-color: var(--ac);
                            color: var(--tx-on-ac); font-weight: var(--fw-b); }
.day input:focus-visible + span { box-shadow: var(--focus); }

.split { display: grid; gap: var(--sp-2); }
.split .row1 { display: grid; grid-template-columns: minmax(0, 1fr) 78px 18px 28px;
               gap: var(--sp-3); align-items: center; }
.split .row1 .u { font-size: var(--fs-11); color: var(--tx-3); }

/* 띠와 판 */
/* ★ 갈래를 «말의 성격»이 정한다 (2026-09-23 대표: 「스르륵 나왔다가
   스스륵 사라지는 정도의 알림이 적당하다」 · 「실패는 판」).
   ★ 자리는 화면 정가운데다 (2026-10-29 대표 · §623 — 전에는 상단 중앙이었다).
     띠 밑을 막지 않는다(pointer-events: none) — 3초 남짓 가운데의 표 · 칸 · 단추를 가리면 못 누른다.
   끝난 일은 띠가 받고 «사람이 무언가 해야 하는 일»은 판이 받는다 —
   §152 의 「가르는 물음은 «사람이 봐야 하나» 하나다」 그대로다.
   ★ §190 이 띠를 판으로 바꾼 까닭은 «사라짐»만이 아니었다 —
     그 띠는 화면 «맨 아래»(bottom:24)에 떴고 눈은 방금 누른 단추에 있었다.
     자리를 고치면 저절로 사라져도 읽힌다 (인계 §204).
   ★ 닫기 단추를 안 둔다 — 저절로 사라지는 것에 단추를 두면
     「안 누르면 안 사라지나」로 읽힌다 (규칙 ⑨).
   ★ z-index — 띠는 머리 띠(40)·서랍(45)·드롭다운(60) 위이고 판(80) 아래다.
   ★ 판은 «이미 있던» .dlg 다 — 새 이름은 어둠막 하나였다.
     화면검사는 .dlg 를 「안 쓰는 이름」으로 «안» 센다 —
     theme 의 동의 모달이 쓰는 JS 변수 `dlg` 가 글자로 걸려 가려 준다 (§190) */
.toast { position: fixed; top: 50%; left: 50%; z-index: 70; pointer-events: none; transform: translate(-50%, -50%);
         display: flex; align-items: center; gap: var(--sp-4);
         max-width: calc(100vw - 32px);
         padding: var(--sp-4) var(--sp-6); border-radius: var(--r-md);
         font-size: var(--fs-12); box-shadow: var(--sh-2);
         animation: toast-in .18s ease both; }
.toast.ok  { background: var(--ok-bg); color: var(--ok);   border: 1px solid var(--ok-bd); }
.toast.bad { background: var(--bd-bg); color: var(--bd-c); border: 1px solid var(--bd-bd); }
.toast.out { animation: toast-out .3s ease both; }
@keyframes toast-in  { from { transform: translate(-50%, calc(-50% + 8px)); opacity: 0; }
                       to   { transform: translate(-50%, -50%);             opacity: 1; } }
@keyframes toast-out { from { transform: translate(-50%, -50%); opacity: 1; }
                       to   { transform: translate(-50%, -50%); opacity: 0; } }
.dim { position: fixed; inset: 0; z-index: 80; padding: var(--sp-6);
       display: flex; align-items: center; justify-content: center;
       background: rgba(0, 0, 0, .45); }
.dlg.ok  > header .ti { color: var(--ok); }
.dlg.bad > header .ti { color: var(--bd-c); }

.prog { display: inline-block; vertical-align: middle; width: 56px; height: 6px;
        border-radius: 999px; background: var(--sf-sunken); overflow: hidden; }
.prog i { display: block; height: 100%; background: var(--ac); border-radius: 999px; width: 0; }
.prog.is-ok i { background: var(--ok); }
.prog-n { margin-left: var(--sp-3); font-variant-numeric: tabular-nums; }

.bflog { margin-top: var(--sp-5); max-height: 320px; overflow-y: auto;
         border: 1px solid var(--bd); border-radius: var(--r-md);
         background: var(--sf-sunken); padding: var(--sp-4); }
.bflog:empty { display: none; }
.bfline { font-size: var(--fs-11); color: var(--tx-2); font-variant-numeric: tabular-nums;
          padding: 2px 0; white-space: pre-wrap; }
.bfline.ok  { color: var(--ok); }
.bfline.bad { color: var(--bd-c); }
/* 올리는 줄 — 파일명 · 막대 · % (§446) */
.bfnow { display: flex; align-items: center; gap: var(--sp-4); margin-top: var(--sp-5);
         padding: var(--sp-4); border: 1px solid var(--bd); border-radius: var(--r-md);
         font-size: var(--fs-12); font-variant-numeric: tabular-nums; }
.bfnow[hidden] { display: none; }
.bfnow .t { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bfnow .prog { width: 160px; flex: none; }
.bfnow .prog[hidden], .bfnow .prog-n[hidden] { display: none; }
.bfnow .prog-n { margin-left: 0; color: var(--ac); font-weight: 600; }
.bfnow + .bflog { margin-top: var(--sp-3); }
/* 「올린다 · 취소」 — 읽은 것이 아직 안 들어간 자리다 (인계 §56) */
.bfline.ask { display: flex; gap: var(--sp-3); padding-top: var(--sp-4); }

/* ============================================================
   9. 탭
   ============================================================ */
/* ★ 아래 여백은 «탭이» 갖는다. `.head` 는 padding-bottom 이 0 이고 `.body` 는
   padding-top 이 0 이라(목록 화면에서 표가 붙어야 한다) 탭과 본문이 맞붙어 있었다.
   화면마다 인라인으로 주면 여덟 곳에서 따로 세게 된다 (2026-09-07 대표) */
.tabs { display: flex; gap: var(--sp-6); border-bottom: 1px solid var(--bd);
        margin-bottom: var(--sp-6); }
/* 탭이 이미 여백을 줬으므로 그 아래 `.body.pad` 는 더 얹지 않는다 — 두 배가 된다 */
.head:has(.tabs) + .body.pad { padding-top: 0; }
.tabs a { padding: var(--sp-4) 0 var(--sp-3); font-size: var(--fs-12); color: var(--tx-2);
          text-decoration: none; border-bottom: 2px solid transparent; margin-bottom: -1px; }
.tabs a:hover { color: var(--tx); }
.tabs a.is-on { color: var(--ac-tx); border-bottom-color: var(--ac); font-weight: var(--fw-b); }

/* ============================================================
   10. 기다림
   ============================================================ */
.skel { background: linear-gradient(90deg, var(--sf-sunken) 25%, var(--bd-2) 37%, var(--sf-sunken) 63%);
        background-size: 400% 100%; animation: skel 1.2s ease infinite;
        border-radius: var(--r-sm); height: 12px; }
@keyframes skel { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }
.spin { width: 15px; height: 15px; border: 2px solid var(--bd); border-top-color: var(--ac);
        border-radius: 50%; animation: spin .7s linear infinite; display: inline-block; }
@keyframes spin { to { transform: rotate(360deg); } }

/* ============================================================
   11. 이 프로젝트 전용
   ============================================================ */

/* 마스킹 — 개인정보. 목록은 가린 것이 기본이다
   이름 두 번째 글자 ㅇ · 전화 가운데 뒤 2자리 ㅇㅇ · 생년월일 대신 나이 */
/* 마스킹 — 목록은 가린 채로, 원본은 「눌러야」 보인다.
   ★ 누른 순간이 기록에 남는다. 그래서 무심코 열리면 안 되고 단추여야 한다. */
.mask { font-variant-numeric: tabular-nums; }
.mask .m { color: var(--tx-3); }
.mask.can { display: inline-flex; align-items: center; gap: var(--sp-3); }
.mask .open {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  padding: 0 var(--sp-3); height: 20px;
  border: 1px solid var(--bd); border-radius: var(--r-sm);
  background: var(--sf); color: var(--tx-3);
  font-size: var(--fs-11); font-family: inherit; cursor: pointer;
}
.mask .open:hover { border-color: var(--ac); color: var(--ac-tx); background: var(--ac-bg); }
.mask.is-open .open { display: none; }
.mask .raw { display: none; }
.mask.is-open .raw { display: inline; }
.mask.is-open .m,
.mask.is-open .masked { display: none; }

/* 밖에서 붙일 것 — 자리는 만들되 아직 안 붙었다고 알린다.
   ★ 되는 척하지 않는다. 개발이 「여기에 무엇을 붙여야 하는지」를 화면에서 본다. */
.btn.wait { border-style: dashed; color: var(--tx-3); }
.btn.wait:hover { border-color: var(--wn); color: var(--wn); background: var(--wn-bg); }

/* 가드 — 확정을 막는 조건을 「입력 중에」 보여준다.
   확정 눌렀을 때 처음 알면 늦다 */
.guard { display: flex; flex-direction: column; gap: 1px; }
.guard .g { display: flex; align-items: center; gap: var(--sp-4);
            padding: var(--sp-2) 0; font-size: var(--fs-12); color: var(--tx-3); }
.guard .g .mk { width: 16px; text-align: center; color: var(--tx-4); }
.guard .g.pass { color: var(--tx); }
.guard .g.pass .mk { color: var(--ok); }

/* ★ 「정해야 할 것」 — `.guard` 에서 갈랐다 (2026-09-01).
   `.guard` 는 «지금 상태»(검증 결과 · 막고 있는 것)를 말하고,
   `.asks` 는 «아직 안 정해진 것»을 말한다. 둘은 다른 일이다.
   ★ 질문은 «읽으라고» 있는 것이라 흐리게 두지 않는다 — .guard 보다 진하다. */

/* 첨부 · 녹취
   문서는 내려받고, 녹취는 스트리밍만 한다 — 파일이 밖으로 안 나간다 */
.att { display: flex; align-items: center; gap: var(--sp-4);
       padding: var(--sp-3) var(--sp-4); border: 1px solid var(--bd);
       border-radius: var(--r-md); font-size: var(--fs-12); background: var(--sf); }
.att .ic  { width: 22px; height: 22px; flex: none; display: grid; place-items: center;
            border-radius: var(--r-sm); background: var(--sf-sunken); font-size: 11px; }
.att .nm  { font-weight: var(--fw-m); }
.att .sub { color: var(--tx-3); font-size: var(--fs-11); }
.att .sp  { flex: 1; }
.att.rec .ic { background: var(--ac-bg); color: var(--ac-tx); }
/* 이력 한 건 — 상담 · 문자 (§216). .att 는 한 줄짜리라 여러 줄 글을 담으려면
   위로 붙이고 긴 낱말도 줄을 바꿔야 한다 — 안 그러면 좁은 단을 밀어낸다 */
.att.hist      { align-items: flex-start; }
.att.hist .bd  { flex: 1; min-width: 0; }
.att.hist .txt { line-height: 1.55; overflow-wrap: anywhere; }
/* 문의 대화(§279) — 본사가 쓴 줄은 왼쪽에 강조 선 · 두 쪽이 한눈에 갈린다 */
.att.hist.hq { border-left: 3px solid var(--ac); background: var(--ac-bg); }

/* 녹취는 «듣기»만 한다 — 내려받기 단추를 안 붙인다 (controlslist).
   재생기는 파일 이름 아래 한 줄을 다 쓴다 — 크롬은 폭이 300px 아래로 좁으면 재생 바를 줄이거나 숨긴다 */
.att.rec { flex-wrap: wrap; }
.att .pl { flex: 1 1 100%; min-width: 0; height: 32px; }

/* 상태 흐름 — 영업 6단계처럼 「어디까지 왔나」 */
.steps { display: flex; align-items: center; gap: var(--sp-2); font-size: var(--fs-11); }
.steps .s { padding: 0 var(--sp-3); border-radius: var(--r-sm); line-height: 18px;
            background: var(--sf-sunken); color: var(--tx-3); }
.steps .s.done { background: var(--ac-bg); color: var(--ac-tx); }
.steps .s.now  { background: var(--ac); color: var(--tx-on-ac); font-weight: var(--fw-b); }
.steps .ar { color: var(--tx-4); }

/* ============================================================
   12. 인증 — 로그인 · 비밀번호 찾기 · 2단계 인증
   앱 셸이 아니다. 별도 레이아웃이다.
   ============================================================ */
/* 보이는 높이 (§620) — 휴대폰 크롬은 100vh 를 «주소창이 숨은 높이»로 세어 폼이 주소창 절반만큼 내려가고 아래가 가렸다(§617 과 같은 자리) */
.auth { height: 100vh; height: 100dvh; display: flex; overflow: hidden; }

/* 왼쪽 — 브랜드 면. 로고는 위에 고정, 아래 덩이는 흐름의 끝에 선다.
   ★ 아래 덩이를 «흐름 안»에 둔다 — 바닥에 붙여 두면 그것이 자랄 때 가운데를 덮는다.
     0단계 값 셋이 들어오면 아래 덩이가 18px 에서 121px 이 되고 1366×768 에서 30px 겹쳤다.
     .mid 가 margin:auto 로 «남은 자리»에서 가운데에 서므로 가운데가 텅 비지 않는다. */
.auth .side {
  flex: 1; min-width: 0; position: relative; overflow: hidden; isolation: isolate;
  display: flex; flex-direction: column;
  padding: 110px 64px 44px;
  /* ★ 바탕을 --ac 에서 뗐다 — 다크에서 --ac 가 #a396f5 로 밝아져 흰 글자와 대비가 무너졌다.
     왼쪽 면은 «늘 어두운» 브랜드 면이라 판을 안 탄다 */
  background: radial-gradient(ellipse at 80% 76%, #8172e3 0%, transparent 55%),
              linear-gradient(145deg, #4940b3 0%, #6053ce 58%, #695bd4 100%);
  color: #fff;
}
/* 바탕의 결 — 면을 가로지르는 큰 원호 둘 */
.auth .side::before {
  content: ''; position: absolute; right: -330px; bottom: -350px;
  width: 620px; height: 620px; border-radius: 50%; z-index: -1;
  border: 1px solid #ffffff14; pointer-events: none;
}
.auth .side::after {
  content: ''; position: absolute; right: -390px; bottom: -420px;
  width: 760px; height: 760px; border-radius: 50%; z-index: -1;
  border: 1px solid #ffffff0d; pointer-events: none;
}
/* 로고 심볼을 크게 눕힌 것 (§169) — 세로로 비는 자리를 받는다.
   ★ 평소에는 안 그린다 — 그림(.brand-scene)이 그 자리를 채우고, 심볼이 네모라
     반투명 카드 뒤에서 «경계»가 드러난다. 그림이 접히는 낮은 화면에서만 돌아온다 */
.auth .side .deco {
  display: none;
  position: absolute; right: -14%; bottom: -22%; width: 78%;
  color: #fff; opacity: .09; pointer-events: none;
}
.auth .side .deco .mk { width: 100%; height: auto; }

.auth .side > * { position: relative; }
/* ★ 로그인 화면은 아무나 볼 수 있는 페이지다.
   범용 CRM 어휘만 쓴다 — 어느 회사나 하는 말이라 우리가 뭘 하는지는 알려 주지 않는다.
   「고객DB · TM센터 · 발주」 같은 사업 낱말은 여기 못 온다. */
.auth .side .mark { position: absolute; top: 48px; left: 0; right: 0; padding: 0 64px; }
.auth .side .mark > * { max-width: 460px; margin: 0 auto; color: #fff; }

.auth .side .mid { max-width: 460px; width: 100%; margin: auto; }
.auth .side .slogan {
  font-size: clamp(32px, 2.65vw, 40px); line-height: 1.4; letter-spacing: -1.35px;
  font-weight: var(--fw-m); margin: 0; word-break: keep-all;
}
.auth .side .slogan > span { display: block; white-space: nowrap; }
.auth .side .slogan strong { font-weight: 760; }   /* 가변 글꼴이라 700 과 800 사이가 있다 */

/* 그림 — 기록이 모여 오늘 할 일로 이어지는 모습.
   ★ 값이 아니라 «설명용 그래픽»이다 — 실제 고객 자료가 아니고 aria-hidden 이다 */
.auth .side .brand-scene { position: relative; height: 274px; margin-top: 42px; }
.auth .side .brand-scene svg {
  width: 24px; height: 24px; display: block; fill: none; stroke: currentColor;
  stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round;
}
.auth .side .scene-orbit {
  position: absolute; inset: -15px 20px 5px 65px;
  border: 1px solid #ffffff12; border-radius: 50%; transform: rotate(-24deg);
}
.auth .side .record-card {
  position: absolute; top: 0; left: 0; width: 350px; height: 192px; padding: 21px 24px;
  border: 1px solid #ffffff45; border-radius: 18px;
  background: linear-gradient(115deg, #ffffff20, #ffffff0c);
  box-shadow: 0 18px 48px #30277914;
}
.auth .side .record-heading {
  display: flex; align-items: center; gap: 10px;
  font-size: var(--fs-14); font-weight: var(--fw-b); letter-spacing: -.2px;
}
.auth .side .scene-icon { color: #e3ddff; }
.auth .side .scene-icon svg { width: 20px; height: 20px; }
.auth .side .record-dots { margin-left: auto; letter-spacing: 3px; font-size: var(--fs-11); color: #ded8ff; }
.auth .side .record-person { display: flex; align-items: center; gap: 12px; margin-top: 22px; }
.auth .side .person-avatar {
  display: grid; place-items: center; width: 40px; height: 40px; color: #eeeaff;
  background: #ffffff16; border: 1px solid #ffffff1a; border-radius: 13px;
}
.auth .side .person-avatar svg { width: 23px; height: 23px; }
.auth .side .record-line { display: block; height: 6px; border-radius: 4px; background: #e7e0ff80; }
.auth .side .line-long { width: 70px; }
.auth .side .line-short { width: 104px; height: 5px; margin-top: 10px; background: #e7e0ff35; }
.auth .side .status-pill {
  margin-left: auto; padding: 5px 9px; border-radius: 6px; white-space: nowrap;
  border: 1px solid #ffffff26; background: #ffffff0a; color: #eee9ff; font-size: var(--fs-11);
}
.auth .side .record-entry {
  display: flex; align-items: center; gap: 9px; margin-top: 20px;
  font-size: var(--fs-12); color: #e7e1ff;
}
.auth .side .entry-dot { width: 5px; height: 5px; border-radius: 50%; background: #d7cdfb; }
.auth .side .entry-check svg { width: 14px; height: 14px; }
.auth .side .today-card {
  position: absolute; top: 130px; right: 0; width: 272px; padding: 18px 20px 20px;
  border-radius: 15px; background: #fcfbff; color: #28253b;
  box-shadow: 0 18px 40px #2d216329;
}
.auth .side .today-heading {
  display: flex; align-items: center; gap: 7px;
  font-size: var(--fs-11); font-weight: var(--fw-b); color: #706987;
}
.auth .side .today-dot { width: 6px; height: 6px; border-radius: 50%; background: #5baf95; }
.auth .side .today-count { margin-left: auto; font-size: var(--fs-11); color: #91899f;
                           font-variant-numeric: tabular-nums; }
.auth .side .today-task { display: flex; align-items: center; gap: 10px; margin-top: 14px; }
.auth .side .task-check {
  display: grid; place-items: center; width: 32px; height: 32px; flex-shrink: 0;
  background: #e0f1eb; border-radius: 10px; color: #367f6b;
}
.auth .side .task-check svg { width: 20px; height: 20px; }
.auth .side .today-task strong { display: block; font-size: var(--fs-14);
                                 font-weight: var(--fw-x); letter-spacing: -.4px; }
.auth .side .today-task div > span { display: block; margin-top: 5px;
                                     font-size: var(--fs-11); color: #8a839b; }
.auth .side svg.task-arrow { width: 17px; height: 17px; margin-left: auto; color: #9b92b2; }

/* 아래 — 알려도 되는 것만 */
.auth .side .btm { margin-top: var(--sp-9); }
.auth .side .btm > div { max-width: 460px; margin: 0 auto; }
.auth .side .btm .info { display: flex; align-items: flex-end; gap: var(--sp-9);
                         font-size: var(--fs-12); }
.auth .side .btm .lb  { display: block; opacity: .5; font-size: var(--fs-11); margin-bottom: 2px; }
.auth .side .btm b    { font-size: var(--fs-13); font-weight: var(--fw-m); letter-spacing: -.1px; }
.auth .side .btm .ntc { opacity: .62; line-height: var(--lh-n); }

/* 약관 · 저작권 */
.auth .side .legal {
  display: flex; align-items: center; gap: var(--sp-5); flex-wrap: wrap;
  margin-top: var(--sp-7); padding-top: var(--sp-5);
  border-top: 1px solid rgba(255,255,255,.16);
  font-size: var(--fs-11);
}
.auth .side .legal a { color: #fff; opacity: .72; text-decoration: none; }
.auth .side .legal a:hover { opacity: 1; text-decoration: underline; }
.auth .side .legal a.strong { font-weight: var(--fw-b); opacity: .85; }
.auth .side .legal .dot { opacity: .32; }
.auth .side .legal .cr  { margin-left: auto; opacity: .42; }
/* 법정 표기 — 값이 있을 때만 그려진다. 한 줄이 넘치면 접힌다 */
.auth .side .biz { margin-top: var(--sp-4); opacity: .42; font-size: var(--fs-11);
                   line-height: var(--lh-n); display: flex; flex-wrap: wrap; gap: 0 var(--sp-4); }
.auth .side .biz .dot { opacity: .5; }

/* 폭이 좁으면 제목이 세 줄로 접힌다 — 한 줄씩 유지되는 크기로 내린다 */
@media (min-width: 1101px) and (max-width: 1240px) {
  .auth .side .slogan { font-size: 32px; }
}
/* 낮은 화면 — 덩이를 한 단계씩 줄인다 */
@media (min-width: 1101px) and (max-height: 840px) {
  .auth .side { padding-top: 90px; }
  .auth .side .mark { top: 28px; }
  .auth .side .slogan { font-size: 32px; line-height: 1.35; }
  .auth .side .brand-scene { margin-top: 26px; height: 234px; }
  .auth .side .record-card { height: 175px; padding-top: 18px; }
  .auth .side .record-person { margin-top: 15px; }
  .auth .side .record-entry { margin-top: 16px; }
  .auth .side .today-card { top: 106px; }
  .auth .side .btm { margin-top: var(--sp-7); }
}
/* ★ 더 낮으면 그림이 들어갈 자리가 없다 — 그림을 접고 «로고 결»이 그 자리를 받는다.
   아래 덩이(약관 · 법정 표기)는 잘리면 안 되는 것이라 그림이 먼저 물러난다.
   ★ 스크롤을 열지 않는다 — 바탕의 결과 원호가 음수 좌표라 늘 스크롤바가 생긴다 */
@media (min-width: 1101px) and (max-height: 730px) {
  .auth .side .brand-scene { display: none; }
  .auth .side .deco { display: block; }
}

/* 오른쪽 — 폼. 왼쪽과 1:1 */
.auth .form {
  flex: 1; min-width: 0;
  background: var(--sf); border-left: 1px solid var(--bd);
  display: flex; flex-direction: column; justify-content: flex-start;
  padding: 56px 64px; overflow: auto;
}
/* ★ 가운데는 위아래 빈 덩이로 선다 (§620) — justify-content: center 는 넘치면 위가 잘려 스크롤로도 안 닿았다(작은 휴대폰 · 가로 · 키보드).
     자리가 모자라면 둘 다 0 이 되어 위에서 시작한다 */
.auth .form::before, .auth .form::after { content: ''; flex: 1 0 0; }
.auth .form .top { display: none; width: 100%; max-width: 400px; margin: 0 auto var(--sp-8); color: var(--ac); }
.auth .box { width: 100%; max-width: 400px; margin: 0 auto; }
/* ★ 가운데로 옮겼다가(§259) 초라해 왼쪽으로 돌아왔다 — 왼쪽이면 칸 · 단추의 왼쪽 선과 제목이 한 줄로 이어진다 (§260) */
/* 제목 앞 아이콘 — 바탕 없이 강조색 선 아이콘만 (2026-09-28 대표 · §260) · 화면 이름이 h1 이다 (§306) */
.auth h1.ttl { display: flex; align-items: center; gap: 10px; margin: 0 0 28px; font-size: 26px; letter-spacing: -.3px; }
.auth h1.ttl .ti { width: 28px; height: 28px; margin-left: -2px; color: var(--ac); vertical-align: 0; }
.auth .lead { font-size: var(--fs-13); color: var(--tx-2); margin: -20px 0 28px;
              line-height: var(--lh-r); }

/* ★ 인증 화면만 라벨을 감춘다 (2026-08-31 대표).
   칸이 둘뿐이고 「아이디 · 비밀번호」는 누구나 아는 짝이라 라벨이 자리만 먹는다.
   ─ 다른 화면은 종전대로 라벨을 칸 위에 둔다. 칸이 많아지면
     자리표시글은 입력하는 순간 사라져서 「무슨 칸이었는지」를 잃는다.
   ─ 감추되 지우지 않는다. `.sr` 로 남겨 화면낭독기는 읽고 라벨 클릭도 살아 있다.
     (그누보드 코어의 `.sound_only` 와 같은 구실) */
/* ★ `.auth` 밖에서도 먹는다 (§165) — 가입 폼은 «정보 수정»과 한 파일이고
   수정 쪽은 그누보드 껍데기로 뜬다. `.auth` 안에 가두면 그 화면만 날것이 된다. */
.fset { display: flex; flex-direction: column; gap: var(--sp-5); }
.fset .f { display: flex; flex-direction: column; gap: var(--sp-3); }
.fset .lb { font-size: var(--fs-12); font-weight: var(--fw-m); color: var(--tx-2); }
.fset .fld { height: 46px; font-size: var(--fs-13); width: 100%; }
.fset .fld::placeholder { color: var(--tx-3); }
.auth .btn.lg { width: 100%; height: 46px; margin-top: 24px; font-size: var(--fs-13); }
/* 주 단추 아래 딸린 보조 단추 — 같은 폭 · 낮게 · 붙여서 (§546 마이어시스트 이메일 찾기 · §547 비밀번호 확인 [취소]).
   ★ 링크라 테마 default.css 의 a.btn(테두리 0 · 굵게 · 줄 높이 35px)이 특이도로 이긴다 — 다시 쥔다(§256 과 같은 자리) */
.auth .btn.lg.ext { height: 38px; margin-top: var(--sp-4); line-height: 1; font-weight: var(--fw-m); color: var(--tx);
                    border: 1px solid var(--bd); background: var(--sf); }
.auth .btn.lg.ext:hover { border-color: var(--bd-strong); background: var(--sf-hover); }
.auth .below { display: flex; align-items: center; justify-content: space-between;
               margin-top: var(--sp-6); font-size: var(--fs-12); }
.auth .below a { color: var(--tx-2); text-decoration: none; }
.auth .below a:hover { color: var(--ac); }
.auth .foot { margin-top: var(--sp-8); padding-top: var(--sp-6);
              border-top: 1px solid var(--bd-2);
              font-size: var(--fs-11); color: var(--tx-3); line-height: var(--lh-r); }

/* 회원가입 — 로그인과 무게를 다르게 둔다.
   여기서 강조색을 쓰면 「로그인」과 둘이 싸운다. 이미 계정이 있는 사람이 훨씬 많다. */
.auth .reg { display: flex; align-items: center; justify-content: center; gap: var(--sp-5);
             margin-top: var(--sp-8); padding-top: var(--sp-7);
             border-top: 1px solid var(--bd-2);
             font-size: var(--fs-13); color: var(--tx-3); }
/* ★ 테마가 싣는 그누보드 default.css 의 a.btn { border:0; font-weight:bold; font-size:1.4em } 이
   특이도로 .btn 을 이긴다 — 테두리가 지워지고 바탕이 폼과 같아 «여백만» 보였다 (§256 · §258).
   크기 · 테두리 · 굵기를 여기서 다시 쥔다 */
.auth .reg .btn { height: 34px; padding: 0 var(--sp-7); font-size: inherit; line-height: 1;
                  font-weight: var(--fw-m); color: var(--tx);
                  border: 1px solid var(--bd-strong); background: var(--sf); }
.auth .reg .btn:hover { border-color: var(--tx-3); background: var(--sf-hover); }
/* 정보 수정의 [마이어시스트 연결] (§262) — 같은 까닭으로 .btn 의 값을 다시 쥔다 */
.mydb-form .row > a.btn { height: var(--ctl-h); padding: 0 var(--sp-6); line-height: 1;
                          font-size: var(--fs-12); font-weight: var(--fw-m);
                          border: 1px solid var(--bd); text-decoration: none; }
.mydb-form .row > a.btn:hover { border-color: var(--bd-strong); }

/* 표 칸 안의 단추 하나짜리 폼 — 설정 > 발송 이력의 [다시 발송] (§297) */
form.inl { display: inline; margin-left: var(--sp-3); }

/* 문자 문구 (§295 · §296 · §514) — 받는 사람마다 큰 카드(.smsgc) · 문자마다 작은 카드(.smsev) · 모두 펼친다 */
.smsgc { margin-top: var(--sp-6); border: 1px solid var(--bd); border-radius: var(--r-lg); overflow: hidden; }
.smsgc > .hd { display: flex; align-items: center; gap: var(--sp-3); padding: var(--sp-4) var(--sp-5);
               background: var(--ac-bg); color: var(--ac-tx); font-size: var(--fs-14); }
.smsgc > .hd .n { font-size: var(--fs-12); }
.smsgc > .bd { display: flex; flex-direction: column; gap: var(--sp-4); padding: var(--sp-5); }
.smsev { padding: var(--sp-4) var(--sp-5); border: 1px solid var(--bd); border-radius: var(--r-md); background: var(--sf); }
.smsev .hd { display: flex; align-items: center; gap: var(--sp-3); margin-bottom: var(--sp-4); }
/* 세 칸 (§516) — 문자 입력 · 문자 예시 · 알림톡 미리보기 · 1200px 아래에서는 «입력 | 예시» 위 · 알림톡 아래 */
/* --sms-h 는 입력칸(textarea rows 4)의 높이 — 예시 · 알림톡 칸의 «최소» 높이다 · 넘치면 늘어난다 (§522) */
.smsev .cols { display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr) minmax(0, 1fr); gap: var(--sp-5); align-items: start;
               --sms-h: calc(var(--fs-12) * var(--lh-r) * 4 + var(--sp-3) * 2 + 2px); }
@media (max-width: 1200px) {
  .smsev .cols { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .smsev .cols > :last-child { grid-column: 1 / -1; }
}
.smsev .ttl { display: flex; align-items: center; gap: var(--sp-3); min-height: var(--ctl-h); margin-bottom: var(--sp-2);
              font-size: var(--fs-12); color: var(--tx-2); }
.smsev .ttl select { flex: 1; min-width: 0; }
.smsev .vars { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); margin-top: var(--sp-3); }
.smsev .vars .sp { flex: 1; }
.smsev .pv { white-space: pre-wrap; word-break: break-all; background: var(--sf-sunken); border-radius: var(--r-lg);
             padding: var(--sp-3) var(--sp-4); font-size: var(--fs-12); min-height: var(--sms-h); }
.smsev .meta { display: flex; align-items: center; gap: var(--sp-2); margin-top: var(--sp-2); font-size: var(--fs-12); color: var(--tx-2); }
.smsev .meta.bd-tx { color: var(--bd-c); }
/* 알림톡 미리보기 (§515) — 고른 템플릿의 제목 · 본문(예시 값) · 단추 · 채울 수 없는 값 · 고르지 않았으면 «미선택» */
.smsev .kk { min-height: var(--sms-h); padding: var(--sp-3) var(--sp-4); border-radius: var(--r-lg); background: var(--sf-sunken); font-size: var(--fs-12); color: var(--tx-1); }
.smsev .kk .kt { font-weight: var(--fw-b); }
.smsev .kk .kb { white-space: pre-wrap; word-break: break-all; }
.smsev .kk .kbt { margin-top: var(--sp-2); color: var(--tx-2); }
.smsev .kk .miss { margin-top: var(--sp-2); color: var(--bd-c); font-weight: var(--fw-b); }
.smsev .kk .kt:empty, .smsev .kk .kbt:empty, .smsev .kk .miss:empty { display: none; }
.smsev .kknone { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; min-height: var(--sms-h);
                 padding: var(--sp-5) var(--sp-4); border: 1px dashed var(--bd); border-radius: var(--r-lg);
                 text-align: center; font-size: var(--fs-12); color: var(--tx-3); }
.smsev .kknone .btn { margin-left: var(--sp-3); }
.smsev .alt { display: none; }
.smsev:has(.cols select option:checked:not([value=""])) .alt { display: inline-block; }
/* 켜짐 · 꺼짐 — 네모를 누르면 바로 바뀐다(저장은 [저장]) · 꺼진 문자는 점선과 흐린 글자 */
.smsev .st-off { display: none; }
.smsev:has(.hd .chk input:not(:checked)) { border-style: dashed; background: var(--sf-sunken); }
.smsev:has(.hd .chk input:not(:checked)) .st-on { display: none; }
.smsev:has(.hd .chk input:not(:checked)) .st-off { display: inline-block; }
.smsev:has(.hd .chk input:not(:checked)) .cols { opacity: .6; }

/* 알림톡 템플릿 단추 (§472) — 한 줄에 종류 · 이름 · 주소 · [삭제] */
.tpbtns { display: flex; flex-direction: column; gap: var(--sp-3); width: 100%; }
.tpbadd { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-3); width: 100%; }
.tpbadd + .tpbtns:not(:empty) { margin-top: var(--sp-3); }
.tpbtn { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-3); }

/* 알림톡 템플릿 등록 (§478) — 왼쪽 입력 · 오른쪽 미리보기(알리고 등록 화면과 같은 배치).
   ★ 미리보기는 카카오톡 모양을 그린 것이라 색을 토큰에서 안 받는다 — 판(밝음 · 어둠)을 타면 카카오톡처럼 안 보인다 */
.tplmk { display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: var(--sp-8); align-items: start; }
.tplmk-f { min-width: 0; }
.tplmk .cnt { display: block; width: 100%; text-align: right; }
.kkpv { position: sticky; top: var(--sp-4); padding: var(--sp-5) var(--sp-4); border: 1px solid var(--bd); border-radius: 28px; background: var(--sf); }
.kkpv-t { display: flex; align-items: center; justify-content: center; gap: var(--sp-2); margin-bottom: var(--sp-4); font-weight: var(--fw-b); }
.kkpv-scr { display: flex; flex-direction: column; min-height: 440px; padding: var(--sp-5) var(--sp-4) var(--sp-4); border-radius: var(--r-md); background: #abc1d1; }
.kkpv-msg { overflow: hidden; border-radius: 4px; background: #ffffff; color: #191919; font-size: 13px; }
.kkpv-hd { padding: 10px; background: #fee500; text-align: center; font-weight: 600; }
.kkpv-img { display: flex; align-items: center; justify-content: center; aspect-ratio: 2 / 1; background: #f4f4f4; color: #8a8a8a; }
.kkpv-img img { display: block; width: 100%; height: 100%; object-fit: cover; }
.kkpv-em { padding: 12px 14px 10px; border-bottom: 1px solid #eeeeee; }
.kkpv-st { font-size: 12px; color: #8a8a8a; }
.kkpv-tt { font-size: 20px; font-weight: 600; line-height: 1.3; white-space: pre-wrap; word-break: break-all; }
.kkpv-body { padding: 12px 14px; line-height: 1.55; white-space: pre-wrap; word-break: break-all; }
.kkpv-x, .kkpv-ad { padding: 0 14px 10px; font-size: 12px; color: #8a8a8a; white-space: pre-wrap; word-break: break-all; }
.kkpv-btns { display: flex; flex-direction: column; gap: 6px; padding: 0 14px 14px; }
.kkpv-btns:empty { display: none; }
.kkpv-btns .b { padding: 9px; border-radius: 4px; background: #f3f3f3; text-align: center; }
.kkpv-btns .b.ac { background: #fee500; font-weight: 600; }
.kkpv .ph { color: #b0b0b0; }
.kkpv-n { margin-top: auto; padding-top: var(--sp-4); text-align: right; font-size: 12px; color: #191919; }
@media (max-width: 1100px) {
  .tplmk { grid-template-columns: minmax(0, 1fr); }
  .kkpv { position: static; max-width: 360px; }
}

/* A/S 안내 (§448) — 설정 탭의 항목 칸 · 구매자 신청 칸 아래 상자 */
.qagset .imgs { display: flex; flex-wrap: wrap; gap: var(--sp-4); margin-top: var(--sp-4); }
.qagset .im { display: flex; flex-direction: column; align-items: flex-start; gap: var(--sp-2); }
.qagset .im img { display: block; height: 96px; width: auto; max-width: 160px; object-fit: cover;
                  border: 1px solid var(--bd); border-radius: var(--r-md); background: var(--sf-sunken); }
/* 구매자 신청 칸 — 칸 폭 그대로 · 위아래로 쌓는다 · 누르면 그림 팝업 (2026-10-20 대표 · §541) */
.qaguide .imgs { display: grid; gap: var(--sp-4); margin-top: var(--sp-4); }
.qaguide .imgs a { display: block; cursor: zoom-in; }
.qaguide .imgs img { display: block; width: 100%; height: auto;
                     border: 1px solid var(--bd); border-radius: var(--r-md); background: var(--sf-sunken); }

/* 그림 팝업 (§541 · mydb.js) — 화면 위에 띄운다 · 그림은 화면 안에 맞춘다 */
.imgpop { width: 100vw; height: 100vh; max-width: none; max-height: none; margin: 0; padding: 0;
          border: 0; background: transparent; }
.imgpop::backdrop { background: rgba(0, 0, 0, .72); }
.imgpop .in { display: flex; align-items: center; justify-content: center; width: 100%; height: 100%;
              padding: var(--sp-10) var(--sp-6); box-sizing: border-box; }
.imgpop .in img { max-width: 100%; max-height: 100%; object-fit: contain; border-radius: var(--r-md); background: #fff; }
.imgpop .x { position: fixed; top: var(--sp-6); right: var(--sp-6); }
.qaguide { margin: var(--sp-5) 0; padding: var(--sp-5); border: 1px solid var(--bd); border-radius: var(--r-md);
           background: var(--sf-sunken); font-size: var(--fs-12); }
.qaguide[hidden], .qaguide .g[hidden] { display: none; }
.qaguide .g > b { display: block; margin-bottom: var(--sp-3); }
.qaguide .g > p { margin: 0; color: var(--tx-2); white-space: normal; line-height: 1.6; }

/* 일반 회원이 마이디비로 오는 길 둘 (§290) — 내 계정(좁은 판)은 쌓고 · 마이디비 「접근 권한 없음」은 나란히 */
.jguide { display: grid; gap: var(--sp-5); margin: var(--sp-6) 0; }
.body .jguide { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); max-width: 880px; }
.jg { display: flex; flex-direction: column; padding: var(--sp-6);
      background: var(--sf); border: 1px solid var(--bd); border-radius: var(--r-lg); }
.jg h3 { margin: 0 0 var(--sp-4); font-size: var(--fs-14); font-weight: var(--fw-b); }
.jg ol { margin: 0; padding-left: 1.4em; list-style: decimal;
         font-size: var(--fs-13); line-height: 1.8; color: var(--tx-2); }
.jg .go { display: flex; justify-content: flex-end; margin-top: auto; padding-top: var(--sp-5); }
/* 테마의 default.css a.btn 이 특이도로 이긴다 — 크기 · 굵기 · 테두리를 다시 쥔다(§256 과 같은 자리) */
.jg .go a.btn { font-size: var(--fs-13); font-weight: var(--fw-m); line-height: 1;
                border: 1px solid var(--bd); text-decoration: none; }
.jg .go a.btn.pri { border-color: var(--ac); font-weight: var(--fw-b); }

/* ── 자동등록방지 (§261) ─────────────────────────────────────────────
   마크업은 extend/mydb_captcha.extend.php 가 낸다 — 바깥 id="captcha" 를 안 써
   default.css 의 #captcha 규칙(깨진 그림 · 박힌 색 · 40px)이 안 걸린다.
   ★ .auth 밖에도 둔다 — 정보 수정(.mydb-form)도 같은 폼을 쓴다 */
.cap { margin-top: var(--sp-5); }
.fgrp > .cap:first-child { margin-top: 0; }
.cap-row { display: flex; align-items: center; gap: var(--sp-3); }
.cap-row #captcha_img { flex: none; height: 46px; width: auto; border: 1px solid var(--bd); border-radius: var(--r-md); }
.cap-row .fld { flex: 1; min-width: 0; text-align: center; letter-spacing: 4px; font-variant-numeric: tabular-nums; }
/* 자리글 「숫자 6자리」는 벌리지 않는다 — 숫자만 벌린다 */
.cap-row .fld::placeholder { letter-spacing: 0; }
.cap-row .btn { flex: none; width: 46px; height: 46px; padding: 0; line-height: 1; }
.cap-row audio { display: none; }

/* 로고 → 홈 (§257) — 링크가 로고의 색과 자리를 그대로 받는다 */
.auth .side .mark a, .auth .form .top a { display: inline-block; vertical-align: top; color: inherit; }
.auth .below .links { display: inline-flex; align-items: center; gap: var(--sp-3); }
.auth .below .bar { color: var(--bd); }

/* ── 아이디 찾기 · 비밀번호 변경 (§257) ─────────────────────────────── */
.auth .find-tabs { margin-bottom: var(--sp-7); }
.auth .find-msg  { margin-bottom: var(--sp-6); }
/* 방법을 고르면 그 칸만 — 스크립트 없이 고른 라디오를 본다. :has 가 안 되는 브라우저는 둘 다 보인다(서버가 고른 쪽만 쓴다) */
.find-form:has(input[name=way][value=hp]:checked) [data-way=email],
.find-form:has(input[name=way][value=email]:checked) [data-way=hp] { display: none; }
.auth .find-acc { display: flex; align-items: baseline; justify-content: space-between;
                  padding: var(--sp-5) var(--sp-6); border: 1px solid var(--bd); border-radius: var(--r-md); }
.auth .find-acc b { font-size: var(--fs-14); }

/* ── 이용약관 · 개인정보처리방침 (§532) — 읽는 화면이라 상자 높이를 안 묶는다 ── */
.auth .tver { gap: var(--sp-3); margin-top: var(--sp-7); padding-top: var(--sp-5); border-top: 1px solid var(--bd); }
.auth .tver-ttl { margin: 0 0 var(--sp-5); font-size: var(--fs-14); font-weight: var(--fw-b); }
.auth .tview { color: var(--tx-2); font-size: var(--fs-13); line-height: var(--lh-r); word-break: keep-all; overflow-wrap: anywhere; }

/* ── 회원가입 (§165) ────────────────────────────────────────────────
   로그인과 두 자리가 다르다 — 칸이 마흔 남짓이라
   ㉮ 폼 면이 «위에서» 시작한다. 가운데로 맞추면 내용이 화면보다 길 때
      위쪽이 스크롤로 안 닿는다 (flex center + overflow 의 오래된 자리)
   ㉯ 상자가 넓다. 우편번호·본인확인은 칸 옆에 단추가 선다 */
.auth.wide .form { justify-content: flex-start; }
.auth.wide .form::before { display: none; }
.auth.wide .box,
.auth.wide .form .top { max-width: 560px; }
/* 단계 — `.steps` 는 ui.css 가 이미 갖고 있었다 (§95 의 「만들다 만 것」) */
.auth .steps { margin-bottom: var(--sp-6); }

/* 절 — 칸이 많아 덩이로 나눈다 */
.fgrp { margin-top: var(--sp-9); }
.fgrp:first-child { margin-top: 0; }
.fgrp > h3 { margin: 0 0 var(--sp-6); padding-bottom: var(--sp-4);
             border-bottom: 1px solid var(--bd-2);
             font-size: var(--fs-14); font-weight: var(--fw-b); }
.fgrp .tbl th, .fgrp .tbl td { white-space: normal; word-break: keep-all; }
/* 한 줄에 둘 — 비밀번호와 확인처럼 짝이 되는 칸 */
.fset .f2 { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-5); }
/* 칸 옆에 단추 */
.fset .row { display: flex; gap: var(--sp-4); align-items: center; flex-wrap: wrap; }
.fset .row .fld { flex: 1; min-width: 0; }
.fset .row .btn { height: 46px; white-space: nowrap; }
/* 칸 밑 한 줄 — 규격과 서버가 돌려준 답이 온다.
   ★ 도움말 아이콘을 안 쓴다 — 눌러야 보이는 규격은 안 본 것과 같다 (규칙 ⑩) */
.fset .hint { font-size: var(--fs-11); color: var(--tx-3); line-height: var(--lh-r); }
.fset .hint:empty { display: none; }

/* 약관 — 읽기만 한다 */
.terms { display: block; width: 100%; height: 148px; overflow: auto; resize: none;
         padding: var(--sp-5); border: 1px solid var(--bd); border-radius: var(--r-md);
         background: var(--sf-sunken); color: var(--tx-2);
         font-family: var(--ff); font-size: var(--fs-12); line-height: var(--lh-r); }
.terms + .chk { margin-top: var(--sp-4); }
/* 전체 동의 — 가입 유형 위 · 눈에 띄게 (2026-10-19 대표 · §538). 낱낱 동의는 오른쪽에 작게 둬 지나칠 수 있다 */
.agree-all { margin-top: var(--sp-9); padding: var(--sp-6) var(--sp-7);
             border: 1px solid var(--ac); border-radius: var(--r-lg); background: var(--ac-bg); }
.agree-all .chk { gap: var(--sp-4); font-size: var(--fs-16); font-weight: var(--fw-b); color: var(--tx); }
.agree-all .chk input { width: 20px; height: 20px; }
.agree-all .chk .mut { font-size: var(--fs-13); font-weight: var(--fw-n); }
.agree-one { display: flex; justify-content: flex-end; margin-top: var(--sp-3); }
.agree-one .chk { font-size: var(--fs-12); color: var(--tx-2); }
/* 선택 동의 — 한 줄씩 · 본문은 [전문] 창 */
.agree-line { display: flex; align-items: center; gap: var(--sp-4); padding: var(--sp-3) 0; }
.agree-line + .agree-line { border-top: 1px solid var(--bd-2); }
.agree-line .nm { flex: 1; min-width: 0; font-size: var(--fs-13); }
.agree-line .chk { font-size: var(--fs-12); color: var(--tx-2); white-space: nowrap; }
/* 정보 수정의 수신 설정 — 이름 아래 상태 일시 · 광고성 정보는 그 아래 매체 (§548) */
/* 홀딩 신청 칸의 멈춤 날 — 사유 칸 아래 묻히지 않게 크게 · 주황 (2026-10-20 대표 · §551) */
.stopat { display: inline-flex; align-items: center; gap: var(--sp-3); font-size: var(--fs-13); font-weight: var(--fw-b); color: var(--wn); }
.agree-line.edit { align-items: flex-start; }
.agree-line .st { display: block; margin-top: 2px; font-size: var(--fs-11); color: var(--tx-3); }
.agree-line .row.kid { display: flex; gap: var(--sp-5); margin-top: var(--sp-3); }
/* ★ 그누보드 상·하단을 걷은 화면은 «페이지»가 스크롤된다 (§168) —
   body 의 overflow:hidden 은 앱 셸(100vh 판)을 두고 건 것이라
   여기서는 아래 단추를 못 보게 만든다. `.auth` 는 스스로 100vh 라 영향이 없다 */
body.mydb-bare { overflow: auto; }

/* 정보 수정 — 그누보드 상·하단이 없어 폭과 나갈 길을 스스로 잡는다 (§165 · §166) */
.mydb-form { max-width: 560px; margin: 0 auto; padding: var(--sp-9) var(--sp-7); }
.mydb-form h2 { margin: 0 0 28px; font-size: 24px; letter-spacing: -.3px; }
.mydb-form .top { display: inline-block; margin-bottom: var(--sp-8); color: var(--ac); }
/* 묶음마다 흰 상자 · [저장]은 넓게 · 아래 링크는 양 끝 (2026-10-12 대표) — 가입(.auth)에만 걸려 있던 값을 여기도 준다 */
.mydb-form .fgrp { margin-top: var(--sp-6); padding: var(--sp-7);
                   background: var(--sf); border: 1px solid var(--bd); border-radius: var(--r-lg); box-shadow: var(--sh-1); }
.mydb-form .btn.lg { width: 100%; height: 46px; margin-top: var(--sp-7); font-size: var(--fs-13); }
.mydb-form .below { display: flex; align-items: center; justify-content: space-between;
                    margin-top: var(--sp-6); font-size: var(--fs-12); }
.mydb-form .below a { color: var(--tx-2); text-decoration: none; }
.mydb-form .below a:hover { color: var(--ac); }
.mydb-form .fset .f > b { font-size: var(--fs-13); font-weight: var(--fw-m); }
/* 칸 옆 단추(46px)와 달리 작은 단추는 제 높이 — 「전문」 · [비밀번호 변경] */
.mydb-form .fset .row .btn.sm { height: var(--ctl-h); }
/* 마이어시스트 연결 — 한 줄에 하나 · 대표 아닌 줄에 [대표 지정] (§487) */
.mydb-form .iwl { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2) var(--sp-3); min-height: var(--ctl-h); }
.mydb-form .iwl > b { font-size: var(--fs-13); font-weight: var(--fw-m); }
.mydb-form .iwl .btn.sm { margin-left: auto; }
/* 비밀번호 변경 — 눌러야 펼친다. [hidden] 은 .fset 의 display 에 진다 — 클래스로 연다 */
.pwbox .pwdots { color: var(--tx-3); letter-spacing: 2px; font-size: var(--fs-12); }
.pwbox .pwset { display: none; flex-direction: column; gap: var(--sp-5); margin-top: var(--sp-3);
                padding: var(--sp-6); background: var(--sf-sunken); border: 1px solid var(--bd-2); border-radius: var(--r-md); }
.pwbox.is-open .pwset { display: flex; }

/* 내 정보 (§486) — 왼쪽 요약 · 오른쪽 정보 수정 폼(테마 스킨을 그대로 싣는다). 좁으면 한 줄 */
.me { display: grid; grid-template-columns: 300px minmax(0, 1fr); gap: var(--sp-8); align-items: start; }
.me .who { display: flex; align-items: center; gap: var(--sp-5); margin-bottom: var(--sp-6); }
.me .who .col { flex: 1; gap: 2px; }
.me .who b { font-size: var(--fs-14); }
.me .avatar.lg { width: 44px; height: 44px; font-size: var(--fs-14); }
.me .mydb-form { max-width: none; margin: 0; padding: 0; }
.me .mydb-form .fgrp:first-of-type { margin-top: 0; }
.me .tdoc { margin-top: var(--sp-3); }
/* 동의 내역은 왼쪽 좁은 칸이라 이름 아래 값 · [전문]은 오른쪽 끝 (§548) */
.me .consent .frm { flex-direction: column; align-items: stretch; gap: var(--sp-2); }
.me .consent .frm > label { width: auto; }
.me .consent .frm > .v .tdoc { flex-basis: 100%; }
.me .consent .frm > .v > .tdoc:not([open]) { flex-basis: auto; margin: 0 0 0 auto; }
.me .leave { align-self: flex-start; padding: 0 var(--sp-2); font-size: var(--fs-11); color: var(--tx-3); text-decoration: none; }
.me .leave:hover { color: var(--tx-2); text-decoration: underline; }
.me .tdoc > summary { list-style: none; }
.me .tdoc > summary::-webkit-details-marker { display: none; }
.me .tdoc[open] > summary { margin-bottom: var(--sp-3); }
/* 오른쪽 폼은 설정 화면처럼 «라벨 왼쪽 · 칸 오른쪽» (2026-10-12 대표 「가」) — 폭은 다 쓰고 칸 길이는 맞춘다.
   바로 아래 .f 만 — 펼친 비밀번호 칸(.pwset 안)은 위아래 그대로. 라벨이 없는 줄(수신 설정)은 한 줄을 다 쓴다 */
.me .fset > .f { display: grid; grid-template-columns: 120px minmax(0, 480px); column-gap: var(--sp-5); row-gap: var(--sp-3); align-items: center; }
.me .fset > .f > * { grid-column: 2; }
.me .fset > .f > .lb { grid-column: 1; }
.me .fset > .f:not(:has(> .lb)) > * { grid-column: 1 / -1; }
.me .fset .fld { height: var(--ctl-h); font-size: var(--fs-12); }
.me .fset textarea.fld { height: auto; }
.me .fset .row .btn { height: var(--ctl-h); }
.me .mydb-form .btn.lg { display: flex; width: auto; min-width: 120px; height: var(--ctl-h); margin: var(--sp-6) 0 0 auto; font-size: var(--fs-12); }
@media (max-width: 1100px) { .me { grid-template-columns: minmax(0, 1fr); } }
@media (max-width: 640px) {
  .me .fset > .f { grid-template-columns: minmax(0, 1fr); }
  .me .fset > .f > *, .me .fset > .f > .lb { grid-column: 1; }
}

/* 워드마크 — 넣는 자리마다 크기를 픽셀로 받는다(viewBox 로 늘리면 글자까지 커진다) */
.mk { display: block; flex: none; }

.auth .side .btm .rt { margin-left: auto; text-align: right; }
.auth .fset .f b { font-size: var(--fs-13); font-weight: var(--fw-m); }

/* 좁을 때 — 브랜드 면을 접고 로고만 위로 */
@media (max-width: 1100px) {
  .auth .side { display: none; }
  .auth .form { flex: 1; width: auto; border-left: 0; padding: var(--sp-9) var(--sp-8); }
  /* ★ 휴대폰은 페이지 하나만 스크롤한다 (2026-10-29 대표 · §622) — 페이지(body.mydb-bare)와 폼 칸이 둘 다 스크롤 상자였다.
       페이지는 «주소창이 보일 때 높이»라 주소창이 숨으면 틀이 그만큼 길어져 스크롤이 두 개 · 밑에 빈 바탕이 드러났다 */
  .auth { height: auto; min-height: 100vh; min-height: 100dvh; overflow: visible; }
  .auth .form { overflow: visible; }
  /* ★ 그 «페이지»를 연다 (§630) — 가입 · 약관 · 찾기 · 로그인은 그누보드 상·하단을 안 거쳐 body.mydb-bare 가 없다.
       body 의 overflow:hidden 이 남아 첫 화면 아래가 잘렸다(아이폰은 끌면 회색 바탕만 출렁였다) */
  body:has(.auth) { overflow: auto; }
  .auth .form .top { display: block; }
  /* 로고는 가운데 · 화면 폭의 반 · 세로는 비율대로 (2026-10-29 대표 · §621) — 태블릿에서 커지지 않게 240px 에서 멈춘다 */
  .auth .form .top { text-align: center; }
  .auth .form .top .mk { width: min(50vw, 240px); height: auto; }
  /* 휴대폰 로그인 (2026-10-29 대표 · §627) — 폼은 위(키보드에 안 가린다) · 가입은 바닥 · 칸 52 · 글자 16(아이폰이 확대하지 않는다).
     ★ §620 의 위아래 빈 덩이를 로그인에서만 끈다 — 다른 인증 화면은 그대로 가운데다 */
  .auth.login .form { padding: 72px var(--sp-9) var(--sp-9); }
  .auth.login .form::before, .auth.login .form::after { display: none; }
  /* 로고 + 슬로건은 한 덩이(12) · 폼과는 띄운다(44) · 칸 사이 10 · 단추 위 14 (2026-10-30 대표 · §632) */
  .auth.login .form .top { margin-bottom: var(--sp-6); color: var(--brand); }
  .auth.login .box { flex: 1; display: flex; flex-direction: column; }
  /* 제목 자리에 슬로건 (2026-10-30 대표 · §631) — «로그인»은 화면낭독기 · 검색이 읽게 감추기만 한다.
     글자는 로고(화면 폭의 반 · 240 에서 멈춤)를 따라 커지고 줄어 로고 폭을 안 넘는다 */
  .auth.login h1.ttl { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
                       overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .auth.login .slg { display: block; margin: 0 0 44px; text-align: center; white-space: nowrap;
                     font-size: min(5.4vw, 25px); font-weight: var(--fw-x); line-height: 1.4; color: var(--tx); }
  .auth.login .fset { gap: var(--sp-5); }
  .auth.login .fset .fld { height: 52px; padding: 0 14px; font-size: var(--fs-16); border-radius: var(--r-lg); }
  .auth.login .btn.lg { height: 52px; margin-top: 14px; font-size: var(--fs-16); border-radius: var(--r-lg); }
  .auth.login .below { margin-top: var(--sp-7); font-size: var(--fs-14); }
  .auth.login .below .chk { min-height: 44px; gap: var(--sp-4); font-size: inherit; }
  .auth.login .below .chk input { width: 20px; height: 20px; margin: 0; }
  .auth.login .below a { display: inline-flex; align-items: center; min-height: 44px; }
  .auth.login .below .links { gap: var(--sp-5); }
  .auth.login .reg { flex-direction: column; gap: var(--sp-6); margin-top: auto; padding-top: var(--sp-9);
                     border-top: 0; font-size: var(--fs-14); }
  .auth.login .reg .btn { width: 100%; height: 48px; font-size: var(--fs-16); border-radius: var(--r-lg); }
  .auth.login .mfoot { display: flex; justify-content: center; align-items: center; gap: var(--sp-3);
                       margin-top: var(--sp-9); font-size: var(--fs-12); color: var(--tx-4); }
}
.auth .mfoot, .auth .slg { display: none; }
.auth .mfoot a { color: var(--tx-3); text-decoration: none; }
.auth .mfoot a.strong { color: var(--tx-2); font-weight: var(--fw-b); }
/* 짝이 되는 칸은 좁은 화면에서 한 칸씩 내려선다 (§165) */
@media (max-width: 520px) { .fset .f2 { grid-template-columns: minmax(0, 1fr); } }

/* 인증번호 6칸 */
.otp { display: flex; gap: var(--sp-3); justify-content: center; }
.otp input { width: 44px; height: 52px; text-align: center;
             font-size: 20px; font-weight: var(--fw-b); font-variant-numeric: tabular-nums;
             border: 1px solid var(--bd); border-radius: var(--r-md);
             background: var(--sf); color: var(--tx); font-family: inherit; }
.otp input:focus { outline: none; border-color: var(--ac); box-shadow: var(--focus); }
.otp input.is-err { border-color: var(--bd-c); }

/* ============================================================
   13. 잔손질
   ============================================================ */
/* ============================================================
   14. 모바일 — 구매자가 현장에서 쓴다
   ------------------------------------------------------------
   ★ 폰 그림 안에 그리지 않는다. 진짜 모바일 화면이다.
     실물은 앱 웹뷰로 뜬다 — 틀을 씌우면 실물과 달라진다.
   PC 는 앉아서 정리하고, 모바일은 서서 확인하고 전화한다.
   ============================================================ */
/* ★ 높이는 «보이는 높이»(dvh)다 (§617) — 휴대폰 크롬은 100vh 를 주소창이 숨은 높이로 세어, 페이지가 안 스크롤되는 이 셸에서
     아래 탭이 주소창만큼 화면 밖으로 밀렸다. dvh 를 모르는 브라우저는 앞의 100vh 를 쓴다 */
.mo { height: 100vh; height: 100dvh; display: flex; flex-direction: column;
      max-width: 520px; margin: 0 auto;
      background: var(--bg-app); border-left: 1px solid var(--bd); border-right: 1px solid var(--bd); }
.mo > .top { flex: none; height: 52px; display: flex; align-items: center; gap: var(--sp-4);
             padding: 0 var(--sp-6); background: var(--sf-topbar);
             border-bottom: 1px solid var(--bd); }
.mo > .top .logo { display: flex; align-items: center; height: 40px; color: var(--brand); }
.mo > .top .sp { flex: 1; }
.mo > .bd  { flex: 1; overflow: auto; padding: var(--sp-6); }   /* ★ 스크롤은 여기 하나 */
/* 아래 탭 — 엄지가 닿는 자리다 */
.mo > .tab { flex: none; display: flex; border-top: 1px solid var(--bd); background: var(--sf);
             padding-bottom: env(safe-area-inset-bottom); }   /* 아이폰 홈 막대 위로 (viewport-fit=cover) */
/* ★ 탭 단추만 잡는다 — 「메뉴」 시트(.pop) 안의 링크까지 먹으면 시트 항목이 탭처럼 그려진다 (§270) */
:is(.mo > .tab > a, .mo > .tab > button, .mo > .tab > .pops > button) {
                    flex: 1; display: flex; flex-direction: column; align-items: center;
                    position: relative; isolation: isolate;
                    gap: 7px; padding: 10px 0 6px;
                    border: 0; background: transparent; color: var(--tx-3);
                    text-decoration: none;
                    font-family: inherit; font-size: var(--fs-12); line-height: 16px; cursor: pointer; }
/* 아이콘 24 · 이름 12 · 높이 64 · 켜진 탭은 아이콘 뒤 옅은 보라 알약 (2026-10-30 대표 · §634) */
:is(.mo > .tab > a, .mo > .tab > button, .mo > .tab > .pops > button) > .ti { width: 24px; height: 24px; }
/* ★ 탭이 «링크»다 — 뒤로 가기가 살고 자바스크립트 없이도 넘어간다 */
:is(.mo > .tab > a.is-on, .mo > .tab > button.is-on, .mo > .tab > .pops > button.is-on) { color: var(--ac-tx); font-weight: var(--fw-b); }
:is(.mo > .tab > a.is-on, .mo > .tab > button.is-on, .mo > .tab > .pops > button.is-on)::before {
  content: ''; position: absolute; top: 7px; left: 50%; z-index: -1;
  width: 52px; height: 30px; margin-left: -26px; border-radius: 15px; background: var(--ac-bg);
}
/* 밀린 건수 — 탭은 아이콘 오른쪽 위에 얹고, 메뉴 시트는 줄 끝에 붙인다 (§388 · .gnb a .cnt 와 같은 색) */
.mo > .tab > a { position: relative; }
:is(.mo > .tab > a, .msheet .it) .cnt {
  min-width: 16px; padding: 0 4px; font-size: 10px; font-weight: var(--fw-b); line-height: 15px;
  text-align: center; border-radius: 8px; background: var(--wn-bg); color: var(--wn);
}
.mo > .tab > a .cnt { position: absolute; top: 5px; left: calc(50% + 8px); }
.msheet .it .cnt { margin-left: auto; }

/* 카드 한 장 = 고객 한 명. 표를 모바일에 우겨넣을 수 없다 */
.mo .c { background: var(--sf); border: 1px solid var(--bd); border-radius: var(--r-lg);
         padding: var(--sp-6); margin-bottom: var(--sp-5); box-shadow: var(--sh-1); }
.mo .c .t1 { display: flex; align-items: center; gap: var(--sp-4); }
.mo .c .t1 b { font-size: var(--fs-14); }
.mo .c .t1 .sp { flex: 1; }
.mo .c .t2 { margin-top: var(--sp-3); font-size: var(--fs-12); color: var(--tx-2);
             line-height: var(--lh-n); }
.mo .c .t3 { margin-top: var(--sp-5); display: flex; gap: var(--sp-4); }
/* ★ 손가락으로 누른다 — 40px 아래로 내리지 않는다. 글자는 14px (§286 · 44 · 48 은 글자에 비해 컸다) */
.mo .c .t3 .btn { flex: 1; height: 40px; font-size: var(--fs-14); }
.mo .t3 { display: flex; gap: var(--sp-4); }
.mo .t3 .btn { flex: 1; height: 40px; font-size: var(--fs-14); }
/* 상세의 칸 — 전화에서는 라벨과 값이 나란히 안 들어간다 */
.mo .frm { flex-direction: column; align-items: stretch; gap: var(--sp-2); }
.mo .frm > label { width: auto; }
.mo .fld.w-full, .mo .fld.w-lg, .mo .fld.w-md { width: 100%; max-width: 100%; }
.mo .btn.big { width: 100%; height: 40px; font-size: var(--fs-14); }
/* 꽉 찬 폭은 «그 화면의 주된 일»(저장 · 발송 · 신청)만 — 목록 위 [생성] 같은 곁 단추는 오른쪽에 제 폭으로 (§286) */
.mo .btn.big.side { width: auto; display: flex; margin-left: auto; padding: 0 var(--sp-6); }
.mo h2 { margin: var(--sp-8) 0 var(--sp-5); font-size: var(--fs-14); }
.mo h2:first-child { margin-top: 0; }

/* ── 모바일 판 부품 (2026-09-28 · §270) — 같은 메뉴 · 모바일 모양 ──
   머리(제목 · 건수) · 갈래 칩(가로로 민다) · 카드(.c) · [더 보기] · 아래 탭의 메뉴 시트 · 전체 화면 서랍 */
.mo .mhd { display: flex; align-items: baseline; gap: var(--sp-4); margin-bottom: var(--sp-5); }
.mo .mhd h1 { margin: 0; font-size: var(--fs-18); }
.chips { display: flex; gap: var(--sp-3); overflow-x: auto; margin: 0 0 var(--sp-6);
         padding-bottom: var(--sp-2); scrollbar-width: none; }
.chips::-webkit-scrollbar { display: none; }
.chip { flex: none; display: inline-flex; align-items: center; gap: var(--sp-2);
        height: 34px; padding: 0 var(--sp-6); border: 1px solid var(--bd); border-radius: 999px;
        background: var(--sf); color: var(--tx-2); font-size: var(--fs-12);
        text-decoration: none; white-space: nowrap; }
.chip.is-on { background: var(--ac-bg); color: var(--ac-tx); border-color: var(--ac); font-weight: var(--fw-b); }
/* 값 옆의 단추 하나짜리 폼 — ㉔ 구매자 서랍의 [채널 초기화] (§270-28) */
.kv dd > form { display: inline-block; margin-left: var(--sp-3); }
/* 마이어시스트 연결 여럿 — 한 줄에 하나 (§487) */
.kv .iwl + .iwl { margin-top: var(--sp-2); }
.kv .iwl > form { display: inline-block; margin-left: var(--sp-3); }
/* 발송 내용 미리보기 — 줄바꿈을 그대로 보인다(문자 · 알림톡 · §270-25) */
.pv { white-space: pre-wrap; word-break: break-all; }
/* 쓰기와 미리보기를 나란히 — 개인 발송 (§286). 오른쪽은 폰 화면 꼴이고 스크롤해도 따라온다 */
.compose { display: grid; grid-template-columns: minmax(0, 1fr) 340px; gap: var(--sp-8);
           align-items: start; max-width: 1120px; }
.compose > .cv { position: sticky; top: 0; }
@media (max-width: 1100px) { .compose { grid-template-columns: minmax(0, 1fr); } .compose > .cv { position: static; } }
.phone { background: var(--sf-2); border: 1px solid var(--bd); border-radius: 18px;
         padding: var(--sp-5) var(--sp-5) var(--sp-7); min-height: 220px; }
.phone .from { text-align: center; font-size: var(--fs-11); color: var(--tx-3); margin-bottom: var(--sp-5); min-height: 1em; }
.phone .bub { background: var(--sf); border: 1px solid var(--bd-2); border-radius: 14px 14px 14px 4px;
              padding: var(--sp-4) var(--sp-5); font-size: var(--fs-13); line-height: 1.6; max-width: 92%; }
.phone .bub:empty { display: none; }
.mo .phone { min-height: 0; }
/* 칩 줄 안의 «글자» — 누르는 것이 아니다(캘린더의 달 · §270-23) */
.chips .chip-t { flex: none; align-self: center; padding: 0 var(--sp-3); font-size: var(--fs-13); }
.mo .msrch { display: flex; gap: var(--sp-4); margin-bottom: var(--sp-5); }
.mo .msrch .fld { flex: 1; min-width: 0; height: 40px; }
.mo .msrch .btn { height: 40px; font-size: var(--fs-14); }
.mo .mmore { display: flex; width: 100%; height: 40px; justify-content: center; align-items: center; }
.mo .c[data-row] { cursor: pointer; }
.mo a.c { display: block; color: inherit; text-decoration: none; }
.mo .c.on { border-color: var(--ac); background: var(--ac-bg); }
.mo .c .t1 .chk { margin-right: var(--sp-2); }
/* 고르는 화면(공유)의 넘기기 줄 — 목록 아래에 붙어 바닥에 남는다 */
.mo .mbar { position: sticky; bottom: 0; z-index: 5; margin-top: var(--sp-5); }
.mo .mbar .toolbar { margin: 0; flex-wrap: wrap; box-shadow: var(--sh-2); border-radius: var(--r-lg); }
/* 아래 탭의 「메뉴」 — 누른 단추 «위»로 뜬다 */
.mo > .tab .pops { flex: 1; display: flex; }
.mo > .tab .pop { top: auto; bottom: calc(100% + 6px); right: var(--sp-3);
                  max-height: 70vh; overflow: auto; min-width: 240px; }
/* 서랍은 전화에서 «전체 화면 상세»다 */
.mo .panel, .mo .panel.wide { top: 0; left: 0; right: 0; width: auto; z-index: 70; }
/* 아직 모바일 모양이 없는 PC 덩이 — 본문 여백과 겹치지 않게 */
.mo .head, .mo .body { padding-left: 0; padding-right: 0; }
.mo .body.list { overflow: visible; }
.mo .toolbar { flex-wrap: wrap; }
/* ★ 모바일은 손가락으로 누른다 — 작은 단추 · 칸 · 체크도 40px 이다 (§303).
   글자는 16px — iOS 사파리는 16px 보다 작은 칸을 누르면 화면을 저절로 키운다 */
.mo .btn { height: 40px; }
.mo .btn.sm { height: 40px; padding: 0 var(--sp-5); font-size: var(--fs-13); }
/* 서랍 아래 줄도 손가락 크기 (2026-10-29 대표 · §624) — PC 의 24px 규칙(.panel > footer .btn)이 .mo .btn 을 이겨
   [닫기](btn sm)만 40px 이고 [생성] · [저장](btn pri)은 24px 였다. 그보다 세게 건다 */
.mo .panel > footer .btn { height: 40px; padding: 0 var(--sp-5); font-size: var(--fs-13); }
.mo > .top .iconbtn { width: 40px; height: 40px; }
.mo input.fld, .mo select.fld { height: 40px; font-size: 16px; }
.mo textarea.fld { font-size: 16px; }
.mo label.chk { min-height: 40px; }
.mo .chk:not(.sw) input { width: 20px; height: 20px; }
.mo .tabs a { min-height: 40px; display: inline-flex; align-items: center; }
/* 할 일 칩 — 오늘 할 일(모바일)의 카드를 한 줄로 가로로 민다 (§303) */
.mo .dash.mchips { display: flex; gap: var(--sp-3); overflow-x: auto; scrollbar-width: none; }
.mo .dash.mchips::-webkit-scrollbar { display: none; }
.mo .dash.mchips .card2 { flex: none; min-height: 40px; padding: 0 var(--sp-5); justify-content: center; }
.mo .dash.mchips .card2 .v { font-size: var(--fs-16); margin-left: var(--sp-3); }
.mo .dash.mchips .card2 .w { display: none; }
/* 수 칸 두 줄 — 충전 · 잔액의 넷이 한 줄에 하나씩 쌓여 화면 반을 썼다 (§303) */
.mo .kpis.wrap.two { grid-template-columns: repeat(2, minmax(0, 1fr)); }
/* 칸 안의 검색 — 개인 발송의 수신자 찾기가 폭의 절반에서 멈췄다 (§303) */
.mo .frm .v > .msrch { flex: 1 1 100%; width: 100%; margin-bottom: 0; }

/* 검색 — 조건을 여러 개 걸 수 있다.
   ★ 교차 검색이다. 조건을 더할수록 좁아진다 (전부 맞는 것만 남는다).
   더하기가 왼쪽에 있는 이유 — 첫 칸이 늘 같은 자리에 있어야 손이 기억한다. */
.srch { display: flex; align-items: center; gap: var(--sp-5); flex-wrap: wrap; }
.srch .s { display: flex; align-items: center; gap: var(--sp-3); }
.srch .s .fld { width: 210px; }
.srch .s:not(:first-child) .fld { width: 150px; }

/* 눈에는 안 보이고 화면낭독기에는 읽히는 글.
   라벨을 「지우는」 것과 「감추는」 것은 다르다 — 지우면 칸의 이름이 없어진다.
   그누보드 코어의 `.sound_only` 와 같은 구실이다. */
.sr { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
      overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }

.row  { display: flex; gap: var(--sp-6); }
.grow { flex: 1; min-width: 0; }
.sp   { flex: 1; }
.hr   { height: 1px; background: var(--bd-2); margin: var(--sp-6) 0; border: 0; }
.mut  { color: var(--tx-3); }
.sub  { color: var(--tx-2); font-size: var(--fs-12); }
.wn-tx { color: var(--wn); }
.ac-tx { color: var(--ac-tx); }
.ok-tx { color: var(--ok); }
.bd-tx { color: var(--bd-c); }
.small{ font-size: var(--fs-11); }
.num  { font-variant-numeric: tabular-nums; }

@media print { .topbar, .gnb, .panel { display: none; } body { overflow: visible; } }

/* ---------- 목록 쪽 나누기 ----------
   자리는 «표 바로 아래»다 — 좌우 2단이면 왼쪽 목록 아래.
   한 쪽이면 아무것도 안 그린다 (쪽.js 가 판단한다). */
.pager {
  display: flex; align-items: center; gap: var(--sp-4);
  padding: var(--sp-5) 0 var(--sp-3);
  font-size: var(--fs-12); color: var(--tx-3);
  flex-wrap: wrap;
}
.pager .cnt { font-variant-numeric: tabular-nums; }
.pager .cnt b { color: var(--tx); font-weight: var(--fw-b); }
.pager .sp { flex: 1; }
.pager .nums { display: flex; align-items: center; gap: 2px; }
.pager .nums .btn {
  min-width: 26px; height: 26px; padding: 0 var(--sp-3);
  justify-content: center; font-variant-numeric: tabular-nums;
}
.pager .nums .btn.is-on {
  background: var(--ac); border-color: var(--ac); color: #fff; font-weight: var(--fw-b);
}
.pager .nums .btn:disabled { opacity: .4; cursor: default; }
.pager .nums .gap { padding: 0 var(--sp-2); color: var(--tx-4); }

/* ============================================================
   마이디비 전용 — 2026-09-09
   프로토타입에서 인라인으로 쓰던 것을 여기로 옮겼다 (개발 규칙 6)
   ============================================================ */
#page { display: contents; }

.mt-2 { margin-top: var(--sp-2); }
.mt-3 { margin-top: var(--sp-3); }
.mt-4 { margin-top: var(--sp-4); }
.mt-5 { margin-top: var(--sp-5); }
.mt-6 { margin-top: var(--sp-6); }
.mb-5 { margin-bottom: var(--sp-5); }
.mb-6 { margin-bottom: var(--sp-6); }
.mb-7 { margin-bottom: var(--sp-7); }
.mt-0 { margin-top: 0; }

/* 긴 메모를 한 줄로 — 프로토타입이 인라인으로 두었던 세 줄이다 (규칙 6) */
.clip { display: inline-block; max-width: 280px; overflow: hidden;
        white-space: nowrap; text-overflow: ellipsis; vertical-align: bottom; }
.chk.wk { color: var(--bd-c); }

.chks { display: flex; flex-wrap: wrap; gap: var(--sp-3); }
/* 달 머리 — 두 달치 체크 칸을 달마다 끊는다 (내 주문 서랍의 상담 불가일) */
.chks-m { margin: var(--sp-5) 0 var(--sp-3); font-size: var(--fs-12); font-weight: var(--fw-b); color: var(--tx-2); }
.chks-m:first-of-type { margin-top: 0; }
/* 상담 불가일 달력 (§280 · 한 달씩 §285) — 요일을 맞춘 달 격자 한 장 · ‹ › 로 넘긴다 · 칸 전체가 누르는 자리 · 고른 날은 빨강.
   체크 칸은 숨기되 폼에는 그대로 실린다(숨은 달도) · «매주» 요일 단추 줄이 창 전체의 그 요일을 켠다 */
.bcal, .bcal-main, .bcal-ms, .bcal-m { min-width: 0; }
/* 두 단 (§287) — 왼쪽 달력 · 오른쪽 도구. 좁으면 도구가 위로 온다 */
.bcal.ed { display: grid; grid-template-columns: minmax(0, 1fr) 196px; gap: var(--sp-8); align-items: start; }
.bcal-side { display: flex; flex-direction: column; align-items: flex-start; gap: var(--sp-4); }
.bcal-side [data-bfrom] { width: 100%; }
.bcal-foot { display: flex; align-items: center; flex-wrap: wrap; gap: var(--sp-4); margin-top: var(--sp-5); }
.bcal-foot [data-bsum] { font-size: var(--fs-13); }
.bcal-from { margin-top: var(--sp-4); font-weight: var(--fw-b); }
.bcal-wd { display: grid; grid-template-columns: repeat(4, 40px); gap: var(--sp-2); }
@media (max-width: 1200px) {
  .bcal.ed { grid-template-columns: minmax(0, 1fr); }
  .bcal.ed > .bcal-side { order: -1; flex-direction: row; flex-wrap: wrap; align-items: center; }
  .bcal-wd { grid-template-columns: repeat(7, 40px); }
}
.mo .bcal.ed { grid-template-columns: minmax(0, 1fr); }
.mo .bcal.ed > .bcal-side { order: -1; flex-direction: row; flex-wrap: wrap; align-items: center; }
.mo .bcal-wd { grid-template-columns: repeat(7, minmax(0, 1fr)); width: 100%; }
/* 탭 머리의 상태 (§287 내 주문 서랍) */
.tabs a .bdg { margin-left: var(--sp-2); }
.bwd { min-width: 34px; justify-content: center; }
.bwd.is-on { background: var(--bd-bg); border-color: var(--bd-bd); color: var(--bd-c); font-weight: var(--fw-x); }
.bwd.is-part { border-color: var(--bd-bd); border-style: dashed; color: var(--bd-c); }
[data-brange].is-on { background: var(--ac-bg); border-color: var(--ac); color: var(--ac); }
.bcal-nav { display: grid; grid-template-columns: 32px minmax(0, 1fr) 32px; align-items: center; margin-bottom: var(--sp-3); }
.bcal-nav b { text-align: center; font-size: var(--fs-13); }
.bcal-nav button:disabled { visibility: hidden; }
.bcal-hd, .bcal-bd { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 3px; }
.bcal-hd > * { font-size: var(--fs-11); color: var(--tx-3); padding: var(--sp-2) 0; text-align: center; }
.bcal-hd .we { color: var(--bd-c); }
.bday { position: relative; display: grid; place-items: center; height: 40px; border-radius: var(--r-md);
        border: 1px solid transparent; font-size: var(--fs-13); font-variant-numeric: tabular-nums;
        cursor: pointer; user-select: none; }
.bday input { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.bday:hover { background: var(--sf-hover); }
.bday.we { color: var(--bd-c); }
.bday.is-on { background: var(--bd-bg); border-color: var(--bd-bd); color: var(--bd-c); font-weight: var(--fw-x); }
.bday.is-from { box-shadow: inset 0 0 0 2px var(--ac); }
.bday.off { color: var(--tx-4); cursor: default; background: none; }
.bday.pad { visibility: hidden; }
.bday:has(input:focus-visible) { box-shadow: var(--focus); }
.mo .bday { height: 44px; }
.frm-foot { display: flex; align-items: center; gap: var(--sp-5); margin-top: var(--sp-6); }

.tbl th.stick, .tbl td.stick { position: sticky; left: 0; z-index: 2; }
.tbl th.stick { background: var(--sf-sunken); z-index: 3; }
.tbl td.stick { background: var(--sf); }

.chk.mid { justify-content: center; }
.w-110 { width: 110px; }

.kpi .v .unit { font-size: var(--fs-13); font-weight: var(--fw-m); }
.frm .v .unit { font-size: var(--fs-11); color: var(--tx-3); }
.frm .v .lb   { font-size: var(--fs-11); color: var(--tx-3); }

.pop.wide { min-width: 280px; }
.pop .hd.col { flex-direction: column; align-items: flex-start; gap: 2px; }
.pop .hd .mut { font-weight: var(--fw-n); }

.iconbtn.named { width: auto; padding: 0 var(--sp-3); gap: var(--sp-3); }

/* ============================================================
   설정 화면 (2026-10-09 · §468 · §469) — 저장 단위마다 상자 하나 · 큰 탭 아래 작은 탭
   ============================================================ */
/* ★ 폭은 안 묶는다 (2026-10-10 대표: 「넓게」) — 760px 로 묶었더니 탭마다 폭이 달라 불편했다 */
.setw .kpis > .kpi, .kpis.line > .kpi { min-width: 0; }   /* 줄바꿈 없이 한 줄 — 카드가 좁아진다 */
/* 좁아져도 수와 단위가 갈라지지 않는다 — 본사 주문 상세는 카드가 일곱까지 선다 (§558) */
.kpis.line.qty > .kpi { padding: var(--sp-4); }
.kpis.line.qty > .kpi .t, .kpis.line.qty > .kpi .v { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.card.set { margin-bottom: var(--sp-6); }
.card.set > .bd > .frm:last-child, .card.set > .bd > form:last-child > .frm:last-child { margin-bottom: 0; }
.card.set h4 { margin: var(--sp-7) 0 var(--sp-3); font-size: var(--fs-12); font-weight: var(--fw-b); color: var(--tx-2); }
.card.set h4:first-of-type { margin-top: 0; }
.card.set > .bd > :first-child { margin-top: 0; }
.card.set .frm + h4:first-of-type { margin-top: var(--sp-7); }
/* 아래 여백(.body 의 padding)만큼 내려 화면 맨 아래에 붙인다 */
.card.set > .ft.stick { position: sticky; bottom: calc(var(--sp-8) * -1); z-index: 2; background: var(--sf); border-radius: 0 0 var(--r-lg) var(--r-lg); }
/* 폼이 상자 안에 있을 때 끝 단추 줄을 상자 아래 줄(.ft)과 같게 그린다 — 알림톡(본사) */
.card.set > .bd > .toolbar.mid:last-child,
.card.set > .bd > form:last-child > .toolbar.mid:last-child {
  margin: var(--sp-6) calc(var(--sp-6) * -1) calc(var(--sp-6) * -1); padding: var(--sp-4) var(--sp-6);
  border: 0; border-top: 1px solid var(--bd-2); border-radius: 0 0 var(--r-lg) var(--r-lg); background: var(--sf);
}
.card.set > .ft { display: flex; align-items: center; gap: var(--sp-4);
                  padding: var(--sp-4) var(--sp-6); border-top: 1px solid var(--bd-2); }
.card.set > .ft .sp { flex: 1; }
.subtabs { display: flex; flex-wrap: wrap; gap: var(--sp-3); margin: calc(var(--sp-3) - var(--sp-6)) 0 var(--sp-6); }
/* 수동 주문 수정 (§492) — 주문 서랍 안에서 누르면 펼친다 */
details.mform > summary { display: inline-flex; list-style: none; }
details.mform > summary::-webkit-details-marker { display: none; }
/* 정책 값 — 분야마다 표가 따로라 칸 폭을 맞춘다 (§468) */
.tblwrap.pol { margin-bottom: var(--sp-6); }
.tblwrap.pol > .tbl { table-layout: fixed; width: 100%; }
.tblwrap.pol > .tbl th:first-child { width: 30%; }
.tblwrap.pol > .tbl th:last-child { width: 110px; }
.tblwrap.pol > .tbl td { white-space: normal; }
/* TM센터 › 공급사 인계 (§557) — 인수 공급사 세 줄 · 줄마다 공급사와 비율 */
.tblwrap.mv { margin-bottom: var(--sp-6); }
.frm > .v.mvto { flex-direction: column; align-items: flex-start; gap: var(--sp-3); }
.mvto .row { display: flex; align-items: center; gap: var(--sp-3); }
/* 설정 › 기준 › 웹알림 (§556) — 발송 시점 · 내용은 길어 줄을 바꾼다 */
.tblwrap.nti { margin-bottom: var(--sp-6); }
.tblwrap.nti > .tbl { table-layout: fixed; width: 100%; }
.tblwrap.nti > .tbl th:nth-child(1) { width: 150px; }
.tblwrap.nti > .tbl th:nth-child(2) { width: 130px; }
.tblwrap.nti > .tbl th:nth-child(4) { width: 28%; }
.tblwrap.nti > .tbl th:last-child { width: 100px; }
.tblwrap.nti > .tbl td { white-space: normal; }

/* 고정 구매자 (§562) — 위쪽 단추 · 서랍 [고정]이 눌린 모양 · 새 창(buyer_view)은 메뉴 없이 상세만 */
.iconbtn.pin { color: var(--ac-tx); background: var(--ac-bg); font-size: var(--fs-13); font-weight: var(--fw-b); }
.iconbtn.pin .nm { max-width: 120px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.panel > header .btn[aria-pressed="true"] { color: var(--ac-tx); background: var(--ac-bg); border-color: var(--ac); }
:root:has(.panel.solo) .gnb { display: none; }
.panel.solo { position: static; transform: none; width: auto; height: calc(100vh - var(--topbar-h));
              border-left: 0; box-shadow: none; transition: none; }
.panel.solo:not(.is-on) { visibility: hidden; }
.panel.wide.solo.xwide { width: auto; }
