/* ===========================================================================
   console.css — 사내 운영 콘솔(태양광 EPC 통합 SaaS) 공통 껍데기

   고객용 페이지와 성격이 다르다. 여기는 업무 화면이라 밀도가 높고,
   사이드바 · 상단바 · 카드 그리드가 모든 화면에서 같다.
   색·글꼴은 tokens.css 를 그대로 쓴다(같은 브랜드).
   =========================================================================== */

:root {
  --w-side: 240px;          /* 좌측 메뉴 */
  --h-topbar: 64px;         /* 상단 바 */
  --c-console-bg: var(--c-g75);  /* 업무 화면 바탕 — 카드를 흰색으로 띄우기 위해 회색 */
}

body.console {
  background: var(--c-console-bg);
  font-size: var(--fs-xs);
}

/* ── 레이아웃 ─────────────────────────────────────────────────────────── */
.shell { display: flex; min-height: 100vh; }

.shell__main {
  flex: 1;
  min-width: 0;               /* 없으면 표가 넓어질 때 사이드바를 밀어낸다 */
  display: flex;
  flex-direction: column;
}

.shell__body { padding: 24px; flex: 1; }

/* ── 사이드바 ─────────────────────────────────────────────────────────── */
.side {
  width: var(--w-side);
  flex: none;
  background: #fff;
  border-right: 1px solid var(--c-line);
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
}

.side__head {
  height: var(--h-topbar);
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 20px;
  border-bottom: 1px solid var(--c-line);
  flex: none;
}

/* 제품 워드마크 — 고객용 사이트와 다른 브랜드다(시공사에게 파는 제품) */
.plogo { display: flex; align-items: center; gap: 9px; }

.plogo__mark {
  width: 30px; height: 30px;
  border-radius: 8px;
  background: var(--g-cta);
  color: #fff;
  display: grid;
  place-items: center;
  flex: none;
}

.plogo__mark svg { width: 18px; height: 18px; }
.plogo__name { display: block; font-size: var(--fs-base); font-weight: 800; color: var(--c-navy-deep); letter-spacing: -.02em; }
.plogo__sub { display: block; font-size: 10px; color: var(--c-muted); }

.side__nav { padding: 12px 0; flex: 1; }

.side__group {
  padding: 16px 20px 8px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .04em;
  color: var(--c-muted);
}

.side__link {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 20px;
  font-size: var(--fs-xs);
  color: var(--c-navy-deep);
  border-left: 3px solid transparent;
}

.side__link:hover { background: var(--c-console-bg); }

.side__link svg { width: 18px; height: 18px; flex: none; color: var(--c-muted); }

/* 현재 화면 — 각 페이지의 <body data-cpage="..."> 가 정한다 */
.side__link.is-on {
  background: var(--c-sky-pale);
  border-left-color: var(--c-blue);
  color: var(--c-blue);
  font-weight: 700;
}

.side__link.is-on svg { color: var(--c-blue); }

.side__foot {
  margin: auto 12px 16px;
  padding: 14px;
  border-radius: 8px;
  background: var(--c-console-bg);
  font-size: 11px;
  color: var(--c-subtle);
  line-height: 1.6;
}

.side__foot b { display: block; font-size: var(--fs-xs); color: var(--c-navy-deep); }

/* ── 상단 바 ──────────────────────────────────────────────────────────── */
.topbar {
  height: var(--h-topbar);
  flex: none;
  background: #fff;
  border-bottom: 1px solid var(--c-line);
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 0 24px;
  position: sticky;
  top: 0;
  /* ⚠️ 알림 창(.ntpanel)이 이 안에 있어 이 값에 갇힌다 — 응대 화면 신원 줄(30)·메모 독(40)보다 위,
     문안 팝업(.cmodal 60)보다 아래(2026-10-22 사장님 — 「종을 누르면 플로팅 창 아래로 숨어」) */
  z-index: 45;
}

.crumb { display: flex; align-items: center; gap: 8px; font-size: var(--fs-xs); color: var(--c-muted); }
.crumb b { color: var(--c-navy-deep); font-weight: 700; }
.crumb span { color: var(--c-muted); }

.topbar__search {
  margin-left: auto;
  width: 260px;
  height: 36px;
  padding: 0 14px;
  border: 1px solid var(--c-line);
  border-radius: 8px;
  font-family: inherit;
  font-size: var(--fs-xs);
}

.topbar__icons { display: flex; align-items: center; gap: 6px; }

.iconbtn {
  position: relative;
  width: 36px; height: 36px;
  display: grid;
  place-items: center;
  border-radius: 8px;
  color: var(--c-subtle);
}

.iconbtn:hover { background: var(--c-console-bg); }
.iconbtn svg { width: 20px; height: 20px; }

.iconbtn__dot {
  position: absolute;
  top: 4px; right: 4px;
  min-width: 16px; height: 16px;
  padding: 0 4px;
  border-radius: 8px;
  background: var(--c-coral);
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  display: grid;
  place-items: center;
}
.iconbtn__dot[hidden] { display: none; }

/* ★★ 알림 목록(2026-10-03) — 종 아이콘 아래로 편다 */
.ntwrap { position: relative; }
.ntpanel {
  position: absolute; top: 44px; right: 0; z-index: 50;
  width: min(380px, calc(100vw - 32px)); max-height: 70vh; overflow-y: auto;
  background: #fff; border: 1px solid var(--c-line); border-radius: 10px;
  box-shadow: 0 10px 30px rgb(0 0 0 / 12%);
}
.ntpanel[hidden] { display: none; }
.ntpanel__h { display: flex; justify-content: space-between; align-items: center;
  padding: 10px 14px; border-bottom: 1px solid var(--c-line); font-size: var(--fs-xs); }
.ntpanel__h b { font-size: var(--fs-sm); }
.ntitem { display: block; width: 100%; text-align: left; padding: 10px 14px;
  border-bottom: 1px solid var(--c-line); font-size: var(--fs-xs); line-height: 1.5; color: var(--c-text); }
.ntitem:hover { background: var(--c-console-bg); }
.ntitem.is-new { background: var(--c-sky-pale); }
.ntitem__t { display: block; color: var(--c-subtle); margin-top: 2px; }
.ntempty { padding: 18px 14px; font-size: var(--fs-xs); color: var(--c-subtle); }


.me { display: flex; align-items: center; gap: 8px; padding-left: 10px; margin-left: 4px; border-left: 1px solid var(--c-line); }

.me__avatar {
  width: 32px; height: 32px;
  border-radius: 50%;
  background: var(--c-navy);
  color: #fff;
  display: grid;
  place-items: center;
  font-size: var(--fs-xs);
  font-weight: 700;
}

.me__name { font-size: var(--fs-xs); font-weight: 700; color: var(--c-navy-deep); line-height: 1.3; }
.me__role { font-size: 11px; color: var(--c-muted); }

/* ── 페이지 머리 ──────────────────────────────────────────────────────── */
.phead {
  display: flex;
  align-items: flex-start;
  gap: 16px;
  margin-bottom: 20px;
}

.phead__title { font-size: 22px; font-weight: 700; color: var(--c-navy-deep); }
.phead__sub { margin-top: 6px; font-size: var(--fs-xs); color: var(--c-subtle); }
.phead__actions { margin-left: auto; display: flex; gap: 8px; flex: none; }

/* ── 단계 표시 ────────────────────────────────────────────────────────── */
.steps5 {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 14px 18px;
  margin-bottom: 16px;
  background: #fff;
  border: 1px solid var(--c-line);
  border-radius: 10px;
  overflow-x: auto;
}

.steps5__item {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: var(--fs-xs);
  color: var(--c-muted);
  white-space: nowrap;
}

.steps5__num {
  width: 22px; height: 22px;
  border-radius: 50%;
  background: var(--c-console-bg);
  color: var(--c-muted);
  font-size: 11px;
  font-weight: 700;
  display: grid;
  place-items: center;
  flex: none;
}

.steps5__item.is-on { color: var(--c-blue); font-weight: 700; }
.steps5__item.is-on .steps5__num { background: var(--c-blue); color: #fff; }
.steps5__item.is-done .steps5__num { background: var(--c-mint); color: #fff; }

.steps5__bar { flex: 1; height: 1px; background: var(--c-line); min-width: 20px; }

/* ── 카드 ─────────────────────────────────────────────────────────────── */
.grid { display: grid; gap: 16px; }
.grid--3 { grid-template-columns: repeat(3, 1fr); }
.grid--2 { grid-template-columns: 1fr 1fr; }
.grid--4 { grid-template-columns: repeat(4, 1fr); }
.grid--sidebar { grid-template-columns: 1fr 340px; }

.panel {
  background: #fff;
  border: 1px solid var(--c-line);
  border-radius: 10px;
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.panel__head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 16px 18px;
  border-bottom: 1px solid var(--c-line);
}

.panel__title { font-size: var(--fs-base); font-weight: 700; color: var(--c-navy-deep); }
.panel__more { margin-left: auto; font-size: 11px; color: var(--c-muted); }
/* ⚠️⚠️ **정의가 없었다** — `js/talk.js`·`js/account.js`·`console/stock.html` 아홉 곳이
   쓰는데 CSS 에 없어 **본문 크기 그대로** 찍혔다(제목과 구별이 안 됐다).
   `panel__more` 와 달리 오른쪽으로 밀지 않는다 — 제목 바로 옆에 붙는 부제다. */
.panel__sub { font-size: 11px; color: var(--c-muted); line-height: 1.5; }
.panel__body { padding: 18px; flex: 1; }
.panel__body--flush { padding: 0; }

/* ── 지표 타일 ────────────────────────────────────────────────────────── */
.kpi {
  background: #fff;
  border: 1px solid var(--c-line);
  border-radius: 10px;
  padding: 16px 18px;
}

/* ⚠️ 셋 다 span·b 라 inline 이면 margin-top 이 죽고 한 줄로 붙어 버린다
   (입지검토 KPI 에서 "2,529㎡도형 2,558㎡" 로 붙어 나왔다). block 으로 못 박는다. */
.kpi__label { display: block; font-size: 11px; color: var(--c-muted); }
.kpi__value { display: block; margin-top: 6px; font-size: 24px; font-weight: 700; color: var(--c-navy-deep); }
.kpi__value small { font-size: var(--fs-xs); font-weight: 500; margin-left: 2px; }
.kpi__delta { display: block; margin-top: 4px; font-size: 11px; color: var(--c-muted); }
.kpi__delta.up { color: var(--c-mint); }
.kpi__delta.down { color: var(--c-coral); }

/* ── 표 ───────────────────────────────────────────────────────────────── */
.ctable { width: 100%; border-collapse: collapse; font-size: var(--fs-xs); }

.ctable th,
.ctable td {
  padding: 12px 14px;
  text-align: left;
  border-bottom: 1px solid var(--c-line);
  white-space: nowrap;
}

.ctable thead th {
  background: var(--c-g50);
  font-weight: 700;
  color: var(--c-subtle);
  font-size: 11px;
}

.ctable tbody tr:hover { background: var(--c-g50); }
.ctable td.num { text-align: right; font-variant-numeric: tabular-nums; }
.ctable .wrap { white-space: normal; }

.tablewrap { overflow-x: auto; }

/* ── 정의형 목록(라벨-값) ─────────────────────────────────────────────── */
.dl { display: grid; grid-template-columns: 92px 1fr; row-gap: 10px; font-size: var(--fs-xs); }
.dl dt { color: var(--c-muted); }
.dl dd { color: var(--c-navy-deep); font-weight: 500; }

/* ── 상태 뱃지 ────────────────────────────────────────────────────────── */
.tag {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 9px;
  border-radius: 5px;
  font-size: 11px;
  font-weight: 700;
  white-space: nowrap;
}

.tag--blue { background: var(--c-sky-pale); color: var(--c-blue); }
.tag--green { background: var(--c-mint-pale); color: var(--c-mint); }
.tag--orange { background: var(--c-cream); color: var(--c-orange-ink); }
.tag--red { background: var(--c-coral-pale); color: var(--c-coral); }
.tag--gray { background: var(--c-console-bg); color: var(--c-subtle); }
.tag--navy { background: var(--c-navy); color: #fff; }

/* ── 버튼 (콘솔용, 작게) ─────────────────────────────────────────────── */
.cbtn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  height: 36px;
  padding: 0 14px;
  border-radius: 8px;
  border: 1px solid var(--c-line);
  background: #fff;
  font-size: var(--fs-xs);
  font-weight: 500;
  color: var(--c-navy-deep);
  white-space: nowrap;
}

.cbtn:hover { background: var(--c-console-bg); }
.cbtn svg { width: 16px; height: 16px; }

.cbtn--primary { background: var(--c-blue); border-color: var(--c-blue); color: #fff; font-weight: 700; }
.cbtn--primary:hover { filter: brightness(1.06); background: var(--c-blue); }
.cbtn--navy { background: var(--c-navy); border-color: var(--c-navy); color: #fff; font-weight: 700; }
.cbtn--navy:hover { background: var(--c-navy); filter: brightness(1.12); }
.cbtn--green { background: var(--c-mint); border-color: var(--c-mint); color: #fff; font-weight: 700; }
.cbtn--green:hover { background: var(--c-mint); filter: brightness(1.06); }
/* 눌리길 바라지 않는 버튼(끊기 등) — 옆의 주된 버튼보다 뒤로 물러난다.
   ★ `.cbtn--*` 식구를 두 파일로 가르지 않으려고 여기 둔다(지금은 한 화면만 쓴다). */
.cbtn--quiet { color: var(--c-muted); border-color: transparent; background: none; }
.cbtn--quiet:hover { color: var(--c-text); border-color: var(--c-line); }
.cbtn--lg { height: 44px; padding: 0 20px; font-size: var(--fs-base); }
.cbtn--block { width: 100%; }

/* ── 입력 ─────────────────────────────────────────────────────────────── */
.cfield { display: grid; grid-template-columns: 92px 1fr; align-items: center; gap: 12px; }
.cfield + .cfield { margin-top: 10px; }
.cfield__label { font-size: var(--fs-xs); color: var(--c-muted); }
/* 입력칸 아래 설명 — ⚠️ .cfield 는 2열 그리드라 그냥 두면 라벨 칸으로 떨어진다 */
.cfield__help { grid-column: 2; margin: 4px 0 0; font-size: var(--fs-xs);
  line-height: 1.5; color: var(--c-muted); }
.cfield__help b { color: var(--c-text); font-weight: 600; }

.cinput {
  width: 100%;
  height: 38px;
  padding: 0 12px;
  border: 1px solid var(--c-line);
  border-radius: 8px;
  background: #fff;
  font-family: inherit;
  font-size: var(--fs-xs);
  color: var(--c-navy-deep);
}

.cinput:focus { outline: none; border-color: var(--c-blue); }
textarea.cinput { height: auto; padding: 10px 12px; line-height: 1.6; resize: vertical; }

select.cinput {
  appearance: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238c959c' stroke-width='2' stroke-linecap='round'><path d='M6 9.5l6 6 6-6'/></svg>");
  background-repeat: no-repeat;
  background-position: right 10px center;
  background-size: 16px;
  padding-right: 30px;
}

/* ── 타임라인 ─────────────────────────────────────────────────────────── */
.tl { display: flex; flex-direction: column; }

.tl__item {
  position: relative;
  padding: 0 0 20px 26px;
  border-left: 2px solid var(--c-line);
}

.tl__item:last-child { border-left-color: transparent; padding-bottom: 0; }

.tl__dot {
  position: absolute;
  left: -8px; top: 1px;
  width: 14px; height: 14px;
  border-radius: 50%;
  background: #fff;
  border: 2px solid var(--c-line);
}

.tl__item.is-done .tl__dot { background: var(--c-mint); border-color: var(--c-mint); }
.tl__item.is-on .tl__dot { background: var(--c-blue); border-color: var(--c-blue); box-shadow: 0 0 0 4px var(--c-sky-pale); }

.tl__title { font-size: var(--fs-xs); font-weight: 700; color: var(--c-navy-deep); }
.tl__meta { margin-top: 3px; font-size: 11px; color: var(--c-muted); }
.tl__note { margin-top: 8px; padding: 10px 12px; border-radius: 8px; background: var(--c-console-bg); font-size: 11px; color: var(--c-subtle); }

/* ── 진행 막대 ────────────────────────────────────────────────────────
   <span> 으로 쓰는 자리가 많다. display:block 이 없으면 inline 이라 height 가 무시된다. */
.bar { display: block; height: 8px; border-radius: 4px; background: var(--c-line); overflow: hidden; }
/* ⚠️ 채움도 span 이다 — display:block 이 없으면 height:100% 가 무시돼
   막대가 통째로 안 보인다(입지검토 민가 막대가 그랬다). */
.bar__fill { display: block; height: 100%; border-radius: 4px; background: var(--c-blue); }
.bar__fill--green { background: var(--c-mint); }
.bar__fill--orange { background: var(--c-orange); }

/* ── 목록 행 ──────────────────────────────────────────────────────────── */
.rows { display: flex; flex-direction: column; }

.row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 18px;
  border-bottom: 1px solid var(--c-line);
  font-size: var(--fs-xs);
}

.row:last-child { border-bottom: 0; }
.row:hover { background: var(--c-g50); }
.row.is-on { background: var(--c-sky-pale); }
.row__main { min-width: 0; flex: 1; }
/* ⚠️ 둘 다 span 으로 쓰인다 — inline 이면 `margin-top` 이 죽고 제목과 부연이
   한 줄에 붙는다(`.kpi` 와 같은 사고다). `.row` 의 직계 자식일 때는
   flex 아이템이라 어차피 블록이므로 이 선언이 그쪽을 바꾸지 않는다. */
.row__title { display: block; font-weight: 700; color: var(--c-navy-deep); }
.row__meta { display: block; margin-top: 3px; font-size: 11px; color: var(--c-muted); }
.row__right { margin-left: auto; text-align: right; flex: none; }

/* ── 안내 배너 ────────────────────────────────────────────────────────── */
.note {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 12px 14px;
  border-radius: 8px;
  font-size: var(--fs-xs);
  line-height: 1.6;
}

.note--blue { background: var(--c-sky-pale); color: var(--c-navy); }
.note--green { background: var(--c-mint-pale); color: var(--c-mint-ink); }
.note--orange { background: var(--c-cream); color: var(--c-coral-ink); }
.note svg { width: 18px; height: 18px; flex: none; margin-top: 1px; }

/* ── 파일 카드 ────────────────────────────────────────────────────────── */
.files { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }

.file {
  border: 1px solid var(--c-line);
  border-radius: 8px;
  overflow: hidden;
  text-align: center;
}

.file__thumb {
  height: 96px;
  display: grid;
  place-items: center;
  background: var(--c-console-bg);
  color: var(--c-muted);
  font-size: 11px;
}

.file__name { padding: 10px 8px 4px; font-size: 11px; font-weight: 700; color: var(--c-navy-deep); }
.file__ext { padding-bottom: 10px; }

/* ── 아이콘 기본 크기 ─────────────────────────────────────────────────
   <use> 로 참조하는 svg 는 크기를 안 주면 300×150 이 된다.
   태그 선택자로 둔다 — svg[class] 로 두면 클래스 지정을 이겨버린다. */
svg { width: 1em; height: 1em; fill: none; }

/* ── 아직 없는 기능 + 토스트 (ui.js 가 쓴다) ─────────────────────────── */
/* ⚠️⚠️ **콘솔에서는 `.is-off` 가 시각적으로 안 죽고 있었다** (2026-09-01).
   회색 처리는 `components.css` 에만 있는데 콘솔은 그 파일을 안 부른다 —
   「회색으로 죽여 두고 누르면 이유를 말한다」의 **앞 절반이 콘솔에서만 빠져** 있었다.
   회색으로만 두면 고장난 것처럼 보이고, 멀쩡해 보이면 왜 안 되는지 모른다. */
.is-off { cursor: not-allowed; opacity: .5; filter: grayscale(1); }
.is-off:hover { opacity: .5; }

.toast {
  position: fixed;
  left: 50%;
  bottom: 32px;
  translate: -50% 8px;
  z-index: 100;
  max-width: min(90vw, 520px);
  padding: 12px 20px;
  border-radius: 8px;
  background: rgb(0 14 30 / 92%);
  color: #fff;
  font-size: var(--fs-xs);
  text-align: center;
  opacity: 0;
  visibility: hidden;
  transition: opacity .18s ease, translate .18s ease, visibility .18s;
}

.toast.is-on { opacity: 1; visibility: visible; translate: -50% 0; }

/* ── 시안 표시 ────────────────────────────────────────────────────────
   콘솔은 화면만 있고 서버가 없다. 화면이 진짜처럼 보일수록 명시가 필요하다. */
.mock {
  margin: 24px;
  padding: 10px 14px;
  border-radius: 8px;
  background: var(--c-amber-pale);
  border: 1px solid var(--c-amber-line);
  color: var(--c-amber-ink);
  font-size: 11px;
  text-align: center;
}

/* 사이드바 구역 제목 (개발 등) */
.side__sec{
  margin:18px 0 6px; padding:0 16px;
  font-size:10.5px; font-weight:700; letter-spacing:.04em;
  color:var(--c-g500); text-transform:uppercase;
}

/* ═══════════════════════════════════════════════════════════════════
   반응형 — 콘솔 껍데기
   ═══════════════════════════════════════════════════════════════════

   ⚠️ 이 파일에는 원래 미디어 쿼리가 **하나도 없었다.** 데스크톱 전용으로
      만들어져 375px 에서 문서가 717px 로 넘쳤다. 콘솔은 데스크톱 업무 도구지만
      가로로 넘치는 화면은 그 자체로 고장으로 보인다.

   ★ **메뉴 구성을 바꾸지 않는다.** 넘침을 없애는 것뿐이다 — 좁아지면 격자를
      한 줄로, 더 좁아지면 사이드바를 상단 레일로. 내비게이션 재설계는 별건이다.

   중단점 — 1200 검색 축소 · 1000 격자 한 줄 · 900 사이드바를 상단으로

   ⚠️⚠️ 가로 스크롤을 거는 자리에는 **반드시 `min-width: 0`** 을 준다.
      없으면 flex 아이템이 내용 폭만큼 버텨서, 스크롤이 생기는 대신 그 줄이
      늘어나 **페이지 전체가 가로로 넘친다**(형제 프로젝트에서 겪었다).

   ⚠️ 여기서 못 고치는 것이 있다 — `console-pages.css` 가 **뒤에 로드**되므로
      거기 정의된 선택자는 같은 특이도면 그쪽이 이긴다(미디어 쿼리는 특이도를
      안 올린다). `.crmgrid` 가 그래서 저 파일에 있다. */

@media (max-width: 1200px) {
  .topbar__search { width: 180px; }
}

/* ── 1000 이하 — 격자를 한 줄로, 검색은 감춘다 ─────────────────
   ⚠️ 처음엔 사이드바를 58px 아이콘 레일로 접으려 했는데, 메뉴 **라벨이
      `<span>` 이 아니라 맨 텍스트 노드**라 CSS 로 접을 수가 없었다.
      마크업을 건드리는 대신 사이드바는 그대로 두고 900 에서 상단으로 넘긴다. */
@media (max-width: 1000px) {
  .grid--sidebar,
  .grid--3,
  .grid--4 { grid-template-columns: 1fr; }

  .topbar__search { display: none; }
  .shell__body { padding: 16px; }

  /* 시안 화면의 고정 폭 컴포넌트 — 좁아지면 접는다.
     ⚠️ 아직 시안이라 구조가 바뀔 수 있다. 지금은 **넘침만** 막는다. */
  .projhead { flex-direction: column; }         /* 프로젝트 헤더 (site) */
  .projhead__side { width: 100%; }
  .projhead__thumb { width: 100%; height: 120px; }
  .payline { flex-wrap: wrap; }                 /* 결제 라인 (finance) */
  .payline__step { flex: 1 1 140px; }
  .row { flex-wrap: wrap; }                     /* 목록 한 줄 (crm) */
  .row__right { margin-left: 0; text-align: left; }

  /* 단계 표시는 **접지 않는다** — 1→2→3 이 줄바꿈되면 순서가 안 읽힌다.
     자기 안에서 옆으로 밀리게 한다. */
  .steps5 { overflow-x: auto; min-width: 0; }
  .steps5__item { flex: none; }

  /* ⚠️ 표는 **카드 안에서만** 옆으로 밀린다. 카드가 스크롤을 안 가지면
     표 폭(자재표 369px)이 그대로 문서 폭이 되어 페이지가 통째로 넘친다. */
  .tablewrap,
  .panel__body--flush { overflow-x: auto; min-width: 0; }
}

/* ── 900 이하 — 사이드바를 상단 가로 레일로 ───────────────────
   ⚠️ 720 으로 뒀다가 768px 에서 넘쳤다. 사이드바가 240px 를 먹으면
      본문에 528px 밖에 안 남아 시안 화면들이 안 들어간다. */
@media (max-width: 900px) {
  .shell { flex-direction: column; }

  .side {
    width: 100%;
    height: auto;
    position: static;
    flex-direction: row;
    align-items: center;
    border-right: 0;
    border-bottom: 1px solid var(--c-line);
    overflow-x: auto;                /* 메뉴는 옆으로 밀어 본다 */
    min-width: 0;                    /* ⚠️ 없으면 페이지가 통째로 넘친다 */
  }
  .side__head { border-bottom: 0; border-right: 1px solid var(--c-line); flex: none; }
  .side__nav { display: flex; padding: 0; min-width: 0; }
  .side__group, .side__foot { display: none; }   /* 그룹 제목·연락처는 접는다 */
  .side__link { padding: 12px 14px; white-space: nowrap; }

  .grid--2 { grid-template-columns: 1fr; }

  .topbar { padding: 0 12px; gap: 8px; }
  .me__name, .me__role { display: none; }
  .crumb { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

  /* 화면 제목줄 — 버튼이 밑으로 내려온다 */
  .phead { flex-direction: column; align-items: flex-start; gap: 12px; }
  .phead__actions { flex-wrap: wrap; }

  .shell__body { padding: 12px; }
}

/* ── 모달 ───────────────────────────────────────────────────────────────
   ★ 2026-09-03 — 「담당 건」에만 있던 것을 올렸다(입찰 화면이 같이 쓴다).
   ⚠️ `.dlmodal*` 이던 이름이다 — 두 화면 이상이 쓰면 여기로 온다는 규칙. */
.cmodal { position: fixed; inset: 0; z-index: 60; display: flex;
           align-items: center; justify-content: center; }
.cmodal__back { position: absolute; inset: 0; background: rgba(15,23,42,.45); }
.cmodal__box { position: relative; width: min(720px, 92vw); max-height: 86vh;
                overflow: auto; background: #fff; border-radius: 14px;
                box-shadow: 0 18px 48px rgba(15,23,42,.28); }
.cmodal__head { display: flex; align-items: center; justify-content: space-between;
                 padding: 16px 20px; border-bottom: 1px solid var(--c-line); }
.cmodal__head h2 { font-size: 16px; }
.cmodal__body { padding: 18px 20px 22px; }
/* 표가 들어가는 모달은 넓게 */
.cmodal__box--wide { width: min(980px, 94vw); }

/* ── 두 세계 (2026-09-04) ─────────────────────────────────────────────────
   ⚠️ `is-off` 는 **JS 가 칠한다** — 마크업에는 아무것도 숨겨져 있지 않아
      JS 가 죽어도 모든 화면에 갈 수 있다.
   ⚠️⚠️ **사이드바는 흰 배경이다**(`.side { background:#fff }`). 어두운 줄 알고
      흰 글씨를 썼다가 버튼이 통째로 안 보였다 — `.btn--primary` 때와 같은 실수다.
      ★ **색을 짐작하지 말고 잰다.** */
/* ★★ 2026-10-04 — 세계 전환 버튼을 없앴다. `is-off` 는 이제 고객 모드(통화 중)에서만 쓴다 */
.side__nav .is-off { display: none; }
/* ★ 참고 자료(엔지니어링) — 맨 아래에 접어 둔다. 글씨를 한 단 낮춰 「일하는 메뉴가 아니다」가 보이게 */
.side__ref { margin-top: 14px; border-top: 1px solid var(--c-line); padding-top: 6px; }
.side__refsum { list-style: none; cursor: pointer; padding: 12px 20px 8px; font-size: 11px; font-weight: 700;
                letter-spacing: .04em; color: var(--c-muted); display: flex; align-items: center; gap: 6px; }
.side__refsum::-webkit-details-marker { display: none; }
.side__refsum { list-style: none; }  /* ⚠️ 요즘 Safari 는 ::marker 로 그린다 — 이게 없으면 화살표가 둘(2026-10-22) */
.side__refsum::before { content: '▸'; font-size: 10px; transition: transform .15s; }
.side__ref[open] > .side__refsum::before { transform: rotate(90deg); }
.side__ref .side__group { padding-top: 10px; font-weight: 600; }
.side__ref .side__link { color: var(--c-muted); }
.side__ref .side__link.is-on { color: var(--c-navy-deep); }
/* 인허가 계정 — 남의 화면에 「보기만 합니다」 */
.pro-note { margin-bottom: 14px; }

/* ⚠️ 이 화면이 **어디에 있는 것인지** — 방향 전환(2026-09-03) 뒤 성격이 바뀐
   화면들이 스스로 적는다. 안 적으면 시공용 도면으로 오해한다. */
.pwhere { display: flex; flex-wrap: wrap; gap: 4px 8px; align-items: baseline;
          margin: 0 0 14px; padding: 11px 14px; border-radius: 10px;
          background: var(--c-coral-wash); border: 1px solid var(--c-coral-line);
          font-size: 12.5px; line-height: 1.75; word-break: keep-all; }
.pwhere > b { color: var(--c-coral-ink); }
.pwhere > span { color: var(--c-muted); }

/* ── 고객 모드 사이드바 (2026-09-04) ──────────────────────────────────────
   전화가 와서 고객이 특정되면 사이드바가 **그 고객의 공정**이 된다.
   ⚠️ `is-off` 는 JS 가 칠한다 — 죽으면 평소 메뉴가 그대로 보인다. */
.sided { padding: 0 0 10px; border-bottom: 1px solid var(--c-line); margin-bottom: 6px; }
.sided__who { padding: 4px 14px 10px; }
.sided__who b { display: block; font-size: 14px; color: var(--c-navy-deep); }
.sided__who span { display: block; margin-top: 2px; font-size: 11px; color: var(--c-muted);
                   overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sided__off { margin-top: 7px; padding: 3px 9px; border: 1px solid var(--c-line);
              border-radius: 999px; background: none; cursor: pointer;
              font-size: 11px; color: var(--c-muted); font-family: inherit; }
.sided__off:hover { color: var(--c-text); border-color: var(--c-muted); }

/* 전체 일정 막대 — ⚠️ 단계 수 기준이지 공사량이 아니다(title 로 적는다) */
.sided__bar { height: 6px; margin: 0 14px; border-radius: 999px;
              background: var(--c-console-bg, var(--c-g100)); overflow: hidden; }
.sided__bar span { display: block; height: 100%; border-radius: 999px;
                   background: linear-gradient(90deg, #38bdf8, var(--c-blue)); }
.sided__pct { padding: 6px 14px 2px; font-size: 11px; color: var(--c-muted); }

.sided__g { padding: 11px 14px 4px; font-size: 10.5px; font-weight: 700;
            letter-spacing: .03em; color: var(--c-muted); }
.sided__s { display: flex; align-items: flex-start; gap: 8px; padding: 6px 14px;
            text-decoration: none; }
.sided__n { flex: none; width: 18px; height: 18px; margin-top: 1px; border-radius: 50%;
            display: inline-flex; align-items: center; justify-content: center;
            font-size: 9.5px; font-weight: 700;
            background: var(--c-console-bg, var(--c-g100)); color: var(--c-muted); }
.sided__t { flex: 1 1 auto; min-width: 0; font-size: 12px; color: var(--c-muted);
            line-height: 1.4; }
.sided__d { display: block; margin-top: 1px; font-size: 10px; color: var(--c-muted);
            opacity: .85; }
.sided__s:hover .sided__t { color: var(--c-text); }
/* ⚠️ 색만으로 알리지 않는다 — 번호 모양과 굵기가 함께 말한다 */
.sided__s.is-done .sided__n { background: var(--c-mint-pale); color: var(--c-mint-ink); }
.sided__s.is-done .sided__t { color: var(--c-text); }
.sided__s.is-now { background: var(--c-sky-wash); box-shadow: inset 2px 0 0 var(--c-blue); }
.sided__s.is-now .sided__n { background: var(--c-blue); color: #fff; }
.sided__s.is-now .sided__t { color: var(--c-navy-deep); font-weight: 700; }

/* ★★★ 응대 화면 — **보고 있는 단계**와 **지금 단계**가 갈린다 (2026-09-15).
   ⚠️⚠️ 탭(`stpnav`)과 **같은 말**을 쓴다 — 둘이 다른 말을 하면 다시 어긋나 보인다:
        보고 있는 단계 = 줄 바탕 + 채운 번호   ·   지금 단계 = 점(●) + 왼쪽 띠
   ⚠️ `.has-view` 일 때만 이 규칙이 산다 — 다른 화면에는 「보고 있는 단계」가 없어
      줄 강조가 곧 지금 단계다(평소 모습 그대로). `js/console.js` 의 `applyViewing`. */
.sided__dot { display: none; }
.sided.has-view .sided__s.is-now .sided__dot {
  display: inline; margin-left: 4px; font-style: normal; font-size: 9px;
  color: var(--c-blue); vertical-align: 1px; }
.sided.has-view .sided__s.is-now:not(.is-view) { background: transparent; }
.sided.has-view .sided__s.is-now:not(.is-view) .sided__n {
  background: var(--c-console-bg, var(--c-g100)); color: var(--c-muted); }
.sided.has-view .sided__s.is-now:not(.is-view) .sided__t { font-weight: 500; color: var(--c-text); }
.sided.has-view .sided__s.is-view { background: var(--c-sky-pale); }
.sided.has-view .sided__s.is-view .sided__n { background: var(--c-blue); color: #fff; }
.sided.has-view .sided__s.is-view .sided__t { color: var(--c-navy-deep); font-weight: 700; }

.sided__sub { padding: 4px 14px 8px 40px; }
.sided__sub span { display: block; padding: 2px 0; font-size: 11px; color: var(--c-muted); }
.sided__sub span::before { content: '· '; }
.sided__sub em { display: block; margin-top: 5px; font-size: 10px; font-style: normal;
                 color: var(--c-muted); line-height: 1.5; word-break: keep-all; }
/* ⚠️ 앞뒤가 안 맞는 날짜 — 목록에서도 보여야 한다(고치지 않고 짚는다) */
.sided__s.is-bad .sided__d { color: var(--c-coral-ink); }
.sided__s.is-bad .sided__d::before { content: '⚠️ '; }

/* ★★ 아직 안 된 것의 개수 — 그 단계를 열 때마다 눈에 들어와야 한다.
   ⚠️ **경고색(코랄)을 안 쓴다.** 고장이 아니라 **남은 일**이다 — 코랄로 칠하면
      열여덟 칸 중 열한 칸이 붉어져 진짜 경고(is-bad)가 안 보인다.
   ⚠️ `flex: none` — 이름이 길면 배지가 눌려 사라진다. */
.sided__gap { flex: none; min-width: 16px; height: 16px; margin-top: 2px; padding: 0 4px;
              border-radius: 999px; display: inline-flex; align-items: center;
              justify-content: center; font-size: 9.5px; font-weight: 700;
              background: var(--c-amber-pale); color: var(--c-amber-ink); }

/* ★★★ 전화가 오면 뜬다 — CTI 수신 알림 (2026-09-24)
   ⚠️ **오른쪽 아래**에 둔다. 가운데(`.toast`)는 지나가는 알림 자리이고, 이건
      **사람이 닫을 때까지 남아야** 한다 — 전화를 놓치면 안 된다.
   ⚠️ `z-index` 는 모달(`.cmodal` 60)보다 위다 — 문안 팝업을 열어 둔 채로
      전화가 올 수 있고, 그때 가려지면 없는 것과 같다.
   ⚠️ 좁은 화면에서는 가로를 꽉 쓴다(전화는 밖에서도 받는다). */
.ctipop { position: fixed; right: 20px; bottom: 20px; z-index: 80;
          display: flex; flex-direction: column; gap: 10px;
          width: min(340px, calc(100vw - 32px)); pointer-events: none; }
.ctipop__c { position: relative; pointer-events: auto;
             padding: 14px 16px 16px; border-radius: 12px;
             border: 1px solid var(--c-line); border-left: 4px solid var(--c-mint);
             background: #fff; box-shadow: 0 10px 30px rgb(15 23 42 / 18%); }
/* ⚠️⚠️ **흉내 낸 것은 다르게 보인다** — 실물과 섞이면 데모에서 무너진다 */
.ctipop__c.is-sim { border-left-color: var(--c-subtle); background: var(--c-console-bg); }
.ctipop__x { position: absolute; top: 8px; right: 8px; width: 24px; height: 24px;
             border: 0; background: none; color: var(--c-subtle); cursor: pointer;
             font-size: 13px; line-height: 1; }
.ctipop__k { display: flex; align-items: center; gap: 6px; margin-bottom: 6px; padding-right: 28px; /* ✕ 자리 */ }
.ctipop__in { font-size: 12px; color: var(--c-subtle); }
/* 받은 시각 — ⚠️ 돌아왔을 때 옛 알림을 지금 울리는 전화로 읽지 않게 */
/* ★ 누구 고객인가 · 담당자가 통화 중인가 — 동료가 대신 받을지 정하는 줄 */
.ctipop__o { margin: 6px 0 0; font-size: 13px; line-height: 1.45; color: var(--c-text); }
.ctipop__o.is-busy { padding: 6px 8px; border-radius: 6px; background: var(--c-coral-wash);
                     color: var(--c-coral-ink); }
.ctipop__age { margin-left: auto; font-size: 12px; color: var(--c-subtle); font-variant-numeric: tabular-nums; }
.ctipop__no { font-size: 19px; font-weight: 800; letter-spacing: -.01em;
              font-variant-numeric: tabular-nums; }
.ctipop__who { margin-top: 2px; font-size: var(--fs-sm); font-weight: 700; }
.ctipop__d { margin-top: 2px; font-size: var(--fs-xs); color: var(--c-muted);
             line-height: 1.5; }
.ctipop__msg { margin-top: 6px; padding: 6px 8px; border-radius: 6px;
               background: var(--c-console-bg); font-size: var(--fs-xs); }
.ctipop__warn { margin-top: 6px; font-size: 12px; color: var(--c-amber-ink); }
.ctipop__go { margin-top: 10px; width: 100%; justify-content: center; }
/* ★ 다른 사람이 받은 카드 — 버튼 대신 한 줄. 흐리게 두어 「지금 울리는 전화」와 갈린다 */
.ctipop__c.is-taken { opacity: .78; }
.ctipop__taken { margin-top: 10px; padding: 8px 10px; border-radius: 6px; font-size: 13px;
  line-height: 1.45; background: var(--c-mint-wash); color: var(--c-mint-ink); }

/* ★ 사이드바 — 회사 로고가 있으면 해 아이콘 자리에 선다(2026-09-27) */
.plogo__mark.has-img { background: none; padding: 0; overflow: hidden; }
.plogo__img { width: 100%; height: 100%; object-fit: contain; }

/* ★★ 내 영역 칠하기(2026-10-17 사장님 — *"인허가라면 자신이 속한 영역에 별도의 색으로"*) — 영업은 1~7, 인허가는 맡은 단계.
   ⚠️ 지금 단계·보고 있는 단계 표시를 덮지 않는다(그 둘이 위에서 이긴다) */
.sided__s.is-mine { background: var(--c-violet-wash); box-shadow: inset 3px 0 0 var(--c-violet-line); }
.sided__s.is-mine .sided__t { color: var(--c-violet-ink); }
.sided__s.is-mine.is-done .sided__t { color: var(--c-text); }
.sided__s.is-mine.is-now, .sided__s.is-mine.is-view { box-shadow: inset 3px 0 0 var(--c-blue); }
.sided__legend { display: flex; align-items: center; gap: 5px; flex-wrap: wrap; padding: 10px 14px 12px; font-size: 10.5px; color: var(--c-muted); }
.sided__legend .sided__dot { display: inline; font-style: normal; color: var(--c-blue); }
.sided__mine-sw { display: inline-block; width: 12px; height: 10px; border-radius: 3px; background: var(--c-violet-wash); box-shadow: inset 3px 0 0 var(--c-violet-line); }
.sided.is-page .sided__s.is-view { background: var(--c-sky-pale); }
.sided.is-page .sided__s.is-view .sided__n { background: var(--c-blue); color: #fff; }
.sided.is-page .sided__s.is-view .sided__t { color: var(--c-navy-deep); font-weight: 700; }

/* ★★ 진행판 위 팝업(js/ptrack.js) · 팝업 안 화면(?embed=1 · js/console.js) — 2026-10-17 */
html.is-embed .side, html.is-embed .topbar, html.is-embed .pdw, html.is-embed .ctipop, html.is-embed .thbar,
html.is-embed .stengr__back { display: none !important; }
html.is-embed .shell__body { padding: 16px; }
.ptmodal { position: fixed; inset: 0; z-index: 70; background: rgb(13 20 48 / 45%); display: grid; place-items: center; padding: 20px; }
.ptmodal__box { width: min(1200px, 100%); height: min(92vh, 1100px); background: var(--c-bg); border-radius: 16px; overflow: hidden;
                display: flex; flex-direction: column; box-shadow: 0 30px 80px rgb(13 20 48 / 35%); }
.ptmodal__head { display: flex; align-items: center; gap: 10px; padding: 12px 16px; border-bottom: 1px solid var(--c-line); background: var(--c-sky-wash); }
.ptmodal__where { flex: 1; min-width: 0; font-size: 14px; color: var(--c-g700); }
.ptmodal__where b { color: var(--c-heading); }
.ptmodal__frame { flex: 1; width: 100%; border: 0; background: var(--c-g50); }
body.has-ptmodal { overflow: hidden; }
@media (max-width: 720px) { .ptmodal { padding: 0; } .ptmodal__box { height: 100vh; border-radius: 0; } .ptmodal__head { flex-wrap: wrap; } }

/* ═══ 웹 상담 요청 — 깜빡이는 카드 (2026-10-20 사장님 「역방향」) ═══════════════
   오른쪽 **위**에 둔다 — 아래는 전화 알림(.ctipop) 자리다. 둘이 같이 와도 안 겹친다.
   ⚠️ 깜빡임은 **아무도 안 맡은 요청**에만 · 느리게(2.4초) · 움직임 줄이기면 멈춘다. */
.leadpop { position: fixed; right: 20px; top: 72px; z-index: 79;
           display: flex; flex-direction: column; gap: 8px;
           width: min(340px, calc(100vw - 32px)); pointer-events: none; }
.leadpop[hidden] { display: none; }
.leadpop > * { pointer-events: auto; }
.leadpop__h { display: flex; align-items: center; gap: 8px; padding: 8px 10px 8px 14px;
              border-radius: 10px; background: var(--c-navy); color: #fff;
              box-shadow: 0 8px 22px rgb(15 23 42 / 22%); font-size: 13px; }
.leadpop__h span { opacity: .8; font-size: 12px; }
.leadpop__x { margin-left: auto; width: 26px; height: 26px; border: 0; border-radius: 6px;
              background: rgb(255 255 255 / 14%); color: #fff; cursor: pointer; font-size: 14px; line-height: 1; }
.leadpop__c { position: relative; padding: 12px 14px 14px; border-radius: 12px;
              border: 1px solid var(--c-line); border-left: 4px solid var(--c-blue);
              background: #fff; box-shadow: 0 10px 30px rgb(15 23 42 / 18%); }
.leadpop__c.is-mine { border-left-color: var(--c-mint); }
.leadpop__c.is-late { border-left-color: var(--c-coral); }
.leadpop__k { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-bottom: 6px; }
.leadpop__age { margin-left: auto; font-size: 12px; color: var(--c-subtle); }
.leadpop__c.is-late .leadpop__age { color: var(--c-coral-ink); font-weight: 600; }
.leadpop__who { font-size: 16px; font-weight: 700; color: var(--c-text); }
.leadpop__no { margin-left: 4px; font-size: 14px; font-weight: 600; color: var(--c-blue); }
.leadpop__d, .leadpop__o { margin-top: 2px; font-size: 12.5px; color: var(--c-muted); }
.leadpop__m { margin-top: 6px; padding: 6px 8px; border-radius: 6px; background: var(--c-sky-pale);
              font-size: 12.5px; color: var(--c-text); white-space: pre-line;
              max-height: 4.8em; overflow: hidden; }
.leadpop__a { display: flex; gap: 6px; margin-top: 10px; }
.leadpop__a .cbtn { flex: 1; justify-content: center; text-decoration: none; }
.leadpop__more { display: block; padding: 6px 10px; border-radius: 8px; background: #fff;
                 border: 1px solid var(--c-line); font-size: 12.5px; text-align: center; }
.leadpop__pill { align-self: flex-end; padding: 8px 14px; border: 0; border-radius: 999px;
                 background: var(--c-navy); color: #fff; font-size: 13px; cursor: pointer;
                 box-shadow: 0 8px 22px rgb(15 23 42 / 22%); }
@keyframes leadblink {
  0%, 100% { box-shadow: 0 8px 22px rgb(15 23 42 / 22%), 0 0 0 0 rgb(47 107 240 / 0%); }
  50%      { box-shadow: 0 8px 22px rgb(15 23 42 / 22%), 0 0 0 6px rgb(47 107 240 / 45%); }
}
.leadpop__h.is-blink, .leadpop__pill.is-blink { animation: leadblink 2.4s ease-in-out infinite; }
.side__leadn { margin-left: auto; min-width: 20px; padding: 1px 6px; border-radius: 999px;
               background: var(--c-blue); color: #fff; font-size: 11px; font-weight: 700; text-align: center;
               animation: leadblinkdot 2.4s ease-in-out infinite; }
@keyframes leadblinkdot { 50% { opacity: .35; } }
@media (prefers-reduced-motion: reduce) {
  .leadpop__h.is-blink, .leadpop__pill.is-blink, .side__leadn { animation: none; }
}
@media print { .leadpop { display: none !important; } }

/* 응대 화면 — 웹 상담 요청 줄(먼저 전화 거세요) */
.tklead { margin-bottom: 12px; padding: 12px 14px; border-radius: 12px;
          border: 1px solid var(--c-line); border-left: 4px solid var(--c-blue); background: var(--c-sky-pale); }
.tklead.is-late { border-left-color: var(--c-coral); }
.tklead__h { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; font-size: 13px; }
.tklead__h b { font-size: 14px; }
.tklead__m { margin-top: 6px; font-size: 13px; white-space: pre-line; color: var(--c-text); }
.tklead__a { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; align-items: center; }
.tklead__a .cbtn { text-decoration: none; }
.tklead__s { font-size: 12px; color: var(--c-muted); }
/* 담당 건 목록 — 아직 통화가 안 된 웹 상담 요청 줄 */
@keyframes leadrow { 50% { background: var(--c-sky-pale); } }
.ctable tr.is-lead td { animation: leadrow 2.4s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) { .ctable tr.is-lead td { animation: none; background: var(--c-sky-pale); } }
