/* --- common style --- */

/* ═══════════════════════════════════════════════════════════════
 * 페이지 hero · 모든 BPack 호스트(Shell · DataHub · MDM · GW · PMS · MES
 * · Inspector · BPack.Components.Docs)의 페이지 헤더 공통 스타일.
 *
 * 사용:
 *   <section class="bp-page-hero">
 *       <div class="bp-page-kicker">PMS · PROJECT MASTER</div>
 *       <h1>프로젝트 마스터</h1>
 *       <p class="bp-page-lede">설명 텍스트…</p>
 *   </section>
 *
 * 모듈/페이지 고유 스타일은 별도 클래스(예: bp-pms-project-…)로 작성.
 * 디자인 토큰 변경 시 이 한 곳만 수정하면 전 호스트에 반영된다.
 * ═══════════════════════════════════════════════════════════════ */
.bp-page-hero {
  margin-bottom: 24px;
}

.bp-page-kicker {
  color: var(--bp-text-brand);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  margin-bottom: 8px;
}

.bp-page-lede {
  color: var(--bp-text-secondary);
  margin-top: 8px;
  line-height: 1.5;
}

/* ═══════════════════════════════════════════════════════════════
 * 페이지 풀하이트 레이아웃 유틸 — 호스트 페이지의 `.bp-page` (flex column
 * container) 직속 자식 wrapper 용. BpCard 등 `flex:1 + min-height:0` 인
 * 컴포넌트가 부모 풀하이트를 채우도록 한다.
 *
 *   <div class="bp-page-full-height">
 *       <BpCard>...</BpCard>           // 카드가 페이지 가득 채움
 *   </div>
 *
 * 좌우 split 템플릿(MasterDetail · TreeGrid 등) 의 분할 영역 wrapper.
 *
 *   <div class="bp-page-full-height">
 *       <BpCard>
 *           <Content>
 *               <div class="bp-tpl-split">  // 좌우 패널 컨테이너
 *                   <BpSplitPanel>...</BpSplitPanel>
 *               </div>
 *           </Content>
 *       </BpCard>
 *   </div>
 * ═══════════════════════════════════════════════════════════════ */
.bp-page-full-height {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

.bp-tpl-split {
  flex: 1;
  min-height: 0;
  display: flex;
  overflow: hidden;
}

/* ── Form-grid 템플릿 (그리드 + 상세 폼) ─────────────────────────────
   EditForm 폼 영역: 라벨-입력 세로 필드를 auto-fit 그리드로 배치.
   Docs 데모 + 실제 앱(BPack) 공통 — 라이브러리 배포 CSS 단일 소스.
   (전엔 Docs app.css 에만 있어 실제 앱에서 폼 간격이 무효였음.)
   라이트/다크 양쪽 동일 가독성, --bp-* 토큰만. */
.bp-tpl-form-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: var(--bp-space-3) var(--bp-space-4);
  padding: var(--bp-space-2) 0 var(--bp-space-3);
}

.bp-tpl-form-field {
  display: flex;
  flex-direction: column;
  gap: var(--bp-space-1);
  min-width: 0;
}

.bp-tpl-form-field label {
  font-size: var(--bp-size-small);
  color: var(--bp-text-secondary);
  font-weight: var(--bp-weight-medium);
}

.bp-tpl-form-required {
  color: var(--bp-error-fg);
  margin-left: 2px;
}

.bp-tpl-form-input {
  width: 100%;
  height: var(--bp-h-md);
  padding: 0 var(--bp-space-3);
  background: var(--bp-bg-surface);
  color: var(--bp-text-primary);
  border: 1px solid var(--bp-border-default);
  border-radius: var(--bp-radius-md);
  font-size: var(--bp-size-body);
  transition: border-color var(--bp-duration-fast);
  min-width: 0;
}

.bp-tpl-form-input:focus,
.bp-tpl-form-input:focus-visible {
  outline: none;
  border-color: var(--bp-border-brand);
}

.bp-tpl-form-input.invalid {
  border-color: var(--bp-error);
}

.bp-tpl-form-error {
  font-size: var(--bp-size-xs);
  color: var(--bp-error-fg);
  min-height: 1em;
}

.bp-tpl-form-check {
  display: inline-flex;
  align-items: center;
  gap: var(--bp-space-2);
  height: var(--bp-h-md);
  color: var(--bp-text-primary);
}

.bp-tpl-form-actions {
  display: flex;
  gap: var(--bp-space-2);
  padding-top: var(--bp-space-2);
  border-top: 1px solid var(--bp-border-light);
  flex-wrap: wrap;
}

/* ── 헤더 계정 트리거 (BpHeader RightContent 안) ───────────────────────────
   Docs app.css 에만 있던 것을 라이브러리로 이동(F49 · 단일 소스).
   bp- 접두는 라이브러리 이름공간인데 호스트 파일에 있어, 다른 호스트가 **복사해야만**
   같은 모양을 낼 수 있었다 — 그래서 25개 호스트의 계정 자리가 다섯 갈래로 갈렸다.
   폭은 내용을 따른다(헤더 base 규칙이 가로를 더는 강제하지 않는다 — bp-layout.css 참조). */
.bp-header-user-trigger {
  display: inline-flex;
  align-items: center;
  gap: var(--bp-space-2);
  padding: var(--bp-space-1) var(--bp-space-2);
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--bp-radius-md);
  color: var(--bp-text-primary);
  cursor: pointer;
  transition: background-color var(--bp-duration-fast), border-color var(--bp-duration-fast);
}

.bp-header-user-trigger:hover {
  background: var(--bp-bg-muted);
  border-color: var(--bp-border-light);
}

.bp-header-user-meta {
  display: inline-flex;
  flex-direction: column;
  align-items: flex-start;
  line-height: var(--bp-line-tight);
  min-width: 0;
}

.bp-header-user-name {
  font-size: var(--bp-size-small);
  font-weight: var(--bp-weight-semibold);
  color: var(--bp-text-primary);
  max-width: 140px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.bp-header-user-role {
  font-size: var(--bp-size-2xs);
  color: var(--bp-text-tertiary);
  text-transform: uppercase;
  letter-spacing: var(--bp-tracking-wide);
}

.bp-header-user-chevron {
  font-size: 12px;
  color: var(--bp-text-tertiary);
}

/* 좁은 폭에서는 이름·역할을 숨기고 아바타+chevron 만 남긴다 — 드롭다운 안에 같은 정보가
   heading 으로 있으므로 손실이 없다. ⚠ @media 는 특이도를 올려 주지 않는다(error-prevention #26) —
   위 선언과 같은 (0,1,0)이고 **뒤에 오기 때문에** 이긴다. 순서를 바꾸지 않는다. */
@media (max-width: 720px) {
  .bp-header-user-meta {
    display: none;
  }
}

/* 헤더 버튼 안의 카운트 뱃지(알림 등) — .bp-btn 을 기준점으로 삼는다. */
.bp-header-icon-btn {
  position: relative;
}

.bp-header-badge {
  position: absolute;
  top: 2px;
  right: 2px;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: var(--bp-size-2xs);
  font-weight: var(--bp-weight-bold);
  line-height: 1;
  color: var(--bp-neutral-0, #fff);
  background: var(--bp-error);
  border-radius: var(--bp-radius-pill);
  pointer-events: none;
}

/* ── Dropdown 메뉴 항목 (헤더 사용자메뉴 · 사이드바 컨텍스트 스위처 공통) ──────
   Docs app.css 에만 있던 것을 라이브러리로 이동(단일 소스 — 실제 앱에도 배포). */
.bp-header-user-menu {
  display: flex;
  flex-direction: column;
  min-width: 180px;
  padding: var(--bp-space-1);
  /* elevated 배경 + 진한 테두리 + 큰 그림자로 사이드바/페이지 surface 위에 뜨게. */
  background: var(--bp-bg-elevated);
  border: 1px solid var(--bp-border-default);
  border-radius: var(--bp-radius-md);
  box-shadow: var(--bp-shadow-lg);
}

.bp-header-user-menu-item {
  display: flex;
  align-items: center;
  gap: var(--bp-space-2);
  padding: var(--bp-space-2) var(--bp-space-3);
  color: var(--bp-text-primary);
  text-decoration: none;
  font-size: var(--bp-size-small);
  border-radius: var(--bp-radius-sm);
  transition: background-color var(--bp-duration-fast);
}

.bp-header-user-menu-item:hover {
  background: var(--bp-bg-muted);
}

.bp-header-user-menu-item i {
  font-size: 14px;
  color: var(--bp-text-tertiary);
}

.bp-header-user-menu-divider {
  height: 1px;
  margin: var(--bp-space-1) 0;
  background: var(--bp-border-light);
}

/* ── 사이드바 하단 컨텍스트 스위처 트리거 (BpDropdown 트리거) ──────────────
   AppShell 사이드바 footer 의 컨텍스트/앱 스위처. Docs docs-appmenu-* 를 라이브러리 일반화. */
.bp-context-switcher-trigger {
  display: flex;
  align-items: center;
  gap: var(--bp-space-2);
  width: 100%;
  max-width: 100%;
  padding: var(--bp-space-1) var(--bp-space-2);
  border: 1px solid transparent;
  border-radius: var(--bp-radius-md);
  color: var(--bp-text-primary);
  cursor: pointer;
  transition: background-color var(--bp-duration-fast), border-color var(--bp-duration-fast);
}

.bp-context-switcher-trigger:hover {
  background: var(--bp-bg-muted);
  border-color: var(--bp-border-light);
}

.bp-context-switcher-mark {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: var(--bp-radius-md);
  background: var(--bp-bg-muted);
  color: var(--bp-text-brand);
}

.bp-context-switcher-meta {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  align-items: flex-start;
  line-height: var(--bp-line-tight);
  min-width: 0;
}

.bp-context-switcher-name {
  font-size: var(--bp-size-small);
  font-weight: var(--bp-weight-semibold);
  color: var(--bp-text-primary);
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.bp-context-switcher-sub {
  font-size: var(--bp-size-2xs);
  color: var(--bp-text-tertiary);
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.bp-context-switcher-chevron {
  flex: 0 0 auto;
  font-size: 12px;
  color: var(--bp-text-tertiary);
}

/* 메뉴 항목 중 button 형 — a 항목과 동일 외형 보장 */
.bp-context-switcher-list button.bp-header-user-menu-item {
  width: 100%;
  background: transparent;
  border: none;
  cursor: pointer;
  text-align: left;
  font: inherit;
}

/* SNB 접힘 상태 — 메타/세부 텍스트 숨기고 아이콘만 */
html[data-snb-collapsed="true"] .bp-context-switcher-meta,
html[data-snb-collapsed="true"] .bp-context-switcher-chevron {
  display: none;
}

/* card */
.bp-card {
  width: 100%;
  border-radius: var(--bp-radius-lg);
  background-color: var(--bp-bg-surface);
  color: var(--bp-text-primary);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
}

.bp-card .bp-card-header {
  width: 100%;
  height: 52px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 16px;
  background-color: var(--bp-bg-muted);
}

.bp-card.bp-border .bp-card-header {
  border-bottom: 1px solid var(--bp-border-light);
}

.bp-card .bp-card-header > div {
  display: flex;
  align-items: center;
}

.bp-card .bp-card-header > p {
  font-weight: var(--bp-weight-semibold);
  font-size: var(--bp-size-small);
  color: var(--bp-text-primary);
  margin: 0;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.bp-card .bp-card-header p.bp-xl {
  font-size: var(--bp-size-h3);
}

/* ── 헤더 우측 액션 영역 (HeaderActions) — BpCardGrid 툴바와 동일 톤 ── */
.bp-card .bp-card-header-actions {
  display: flex;
  align-items: center;
  gap: var(--bp-space-1);
  flex-shrink: 0;
}
/* 아이콘 전용 액션 버튼: 툴바와 동일한 28×28.
   .bp-card 접두로 specificity 를 (0,5,1) 로 올려 기본 sm 아이콘 규칙(.bp-btn.bp-sm:has(...)=(0,4,1), 32px)을 이긴다. */
.bp-card .bp-card-header-actions .bp-btn:has(i:first-child:last-child) {
  width: 28px;
  height: 28px;
  min-width: 28px;
  padding: 0;
}
.bp-card .bp-card-header-actions .bp-btn i {
  font-size: var(--bp-control-icon-sm);
}
/* Ghost(비-primary) 는 테두리로 가시성 확보 (툴바 동일) */
.bp-card .bp-card-header-actions .bp-btn:not(.bp-primary) {
  color: var(--bp-text-secondary);
  border: 1px solid var(--bp-border-default);
}
.bp-card .bp-card-header-actions .bp-btn:not(.bp-primary):hover {
  color: var(--bp-text-primary);
  background-color: var(--bp-bg-muted);
  border-color: var(--bp-border-strong);
}

.bp-card .bp-card-content {
  position: relative;
  width: 100%;
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  padding: 16px;
  background-color: var(--bp-bg-surface);
  color: var(--bp-text-primary);
}

.bp-card .bp-card-footer {
  width: 100%;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  padding: 0 16px;
  gap: 8px;
  background-color: var(--bp-bg-muted);
}

.bp-card.bp-border .bp-card-footer {
  border-top: 1px solid var(--bp-border-light);
}



/* loading — 오버레이/인라인 위치 지정 */
.bp-loading.overlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100vh;
  background: var(--bp-scrim-soft);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  z-index: 9999;
}

.bp-loading.inline {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: transparent;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  z-index: 10;
  border-radius: inherit;
}

/* toggle */
.bp-toggle-con {
  display: flex;
  align-items: center;
  gap: 12px;
}
.bp-toggle-con input{
  display: none;
}
.bp-toggle-label {
  position: relative;
  min-width: 46px;
  width: fit-content;
  height: 20px;
  border-radius: 16px;
  background: var(--bp-surface-track);
  font-size: 10px;
  font-weight: 700;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 6px 0 8px;
}
.bp-toggle-label::before {
  content: '';
  position: absolute;
  width: 16px;
  height: 16px;
  top: 2px;
  left: 2px;
  border-radius: 50%;
  background: var(--bp-bg-surface);
  transition: 0.3s;
  z-index: 2;
  filter: drop-shadow(0 2px 4px rgba(0, 35, 11, 0.2));
}
.bp-checkbox:checked + .bp-toggle-label::before {
  left: calc(100% - 18px);
}
.bp-toggle-label div {
  text-align: center;
  z-index: 1;
  color: var(--bp-text-disabled);
  display: flex;
  align-items: center;
}
.bp-toggle-label div:first-child {
  opacity: 0;
}
.bp-checkbox {
  display: none;
}
.bp-checkbox:checked + .bp-toggle-label {
  background-color: var(--bp-primary-500);
}
.bp-checkbox:checked + .bp-toggle-label div:first-child {
  color: var(--bp-neutral-0);
  transition: color 0.3s;
  opacity: 1;
}
.bp-checkbox:checked + .bp-toggle-label div:last-child {
  opacity: 0;
}

/* textfield & box*/
.bp-textfield-box{
  display: flex;
  flex-direction: column;
}

.bp-textfield-box > span{
  width: 100%;
  display: flex;
  justify-content: flex-start;
  margin-bottom: 4px;
  font-size: 14px;
  font-weight: 500;
  color: var(--bp-ink-max);
}

/* 테두리·radius·transition·3-state 는 파일 끝 "Input 3-state 표준" 블록이 소유. */
.bp-textfield {
  min-width: 0;
  width: fit-content;
  height: var(--bp-input-height);
  display: flex;
  align-items: center;
  padding: 0 12px;
  gap: 8px;
  margin-right: 4px;
  background-color: var(--bp-bg-surface);
  color: var(--bp-text-primary);
}

.bp-textfield-box:not(:has(i)) .bp-textfield {
  width: 100%;
}

.bp-textfield i{
  font-size: 20px;
  color: var(--bp-text-tertiary);
}

.bp-textfield input {
    width: 100%;
    color: var(--bp-text-primary);
    background-color: transparent;
}

.bp-textfield-box:has(i) .bp-textfield input{
  color: var(--bp-text-primary);
}

.bp-textfield input::placeholder{
  color: var(--bp-text-tertiary);
  opacity: 1;
}

/* disabled */
.bp-textfield:has(input:disabled) {
  background-color: var(--bp-bg-muted);
  border-color: var(--bp-border-light);
  cursor: not-allowed;
}

.bp-textfield input:disabled {
  color: var(--bp-text-disabled);
  cursor: not-allowed;
}

.bp-textfield:has(input:disabled) i {
  color: var(--bp-text-disabled);
}


/* datafield — 테두리·3-state 는 "Input 3-state 표준" 블록이 소유. */
.bp-datafield {
  min-width: 0;
  width: fit-content;
  height: var(--bp-input-height);
  display: flex;
  align-items: center;
  padding: 0 12px;
  gap: 8px;
  margin-right: 4px;
  background-color: var(--bp-bg-surface);
  color: var(--bp-text-primary);
}

.bp-datafield i {
  font-size: 20px;
  color: var(--bp-text-tertiary);
}

.bp-datafield input {
  width: 100%;
  color: var(--bp-text-primary);
  background-color: transparent;
}

.bp-datafield input::-webkit-calendar-picker-indicator {
    display: none;
    -webkit-appearance: none;
}

.bp-datafield input[type="date"] {
    cursor: pointer;
    position: relative;
}

/* Set datafield input as full clickable area */
.bp-datafield input[type="date"]:before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 1;
}

.bp-datafield input::placeholder {
    color: var(--bp-text-tertiary);
    opacity: 1;
}

/* search-area — 인풋+버튼 가로 배치 */
.bp-search-area {
  display: flex;
  gap: 8px;
  align-items: flex-end;
}

/* btn-group */
.bp-btn-group {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-right: 4px;
}

.bp-btn-group:has(button:only-child) {
  justify-content: flex-end;
}

.bp-btn-group.bp-no-gap{
  gap: 0;
}

/* checkbox */
.bp-checkbox {
  display: flex;
  align-items: center;
  gap: 8px;
}

.bp-checkbox > span {
  color: var(--bp-ink-body);
  font-size: 14px;
  font-weight: 400;
  cursor: pointer;
}

:where(.bp-checkbox, .bp-checklist, .bp-dcl, .bp-grid, .bp-tree) label:has(input[type='checkbox']) {
  display: block;
  width: 20px;
  height: 20px;
  position: relative;
  cursor: pointer;
}

:where(.bp-checkbox, .bp-checklist, .bp-dcl, .bp-grid, .bp-tree) label input[type='checkbox'] {
  appearance: none;
  position: absolute;
  top: 0;
  left: 0;
  width: 20px;
  height: 20px;
  margin: 0;
  border-radius: 5px;
  border: 2px solid var(--bp-border-default);
  background-color: var(--bp-bg-surface);
  cursor: pointer;
}

:where(.bp-checkbox, .bp-checklist, .bp-dcl, .bp-grid, .bp-tree) label input[type='checkbox'] + span {
  width: 20px;
  height: 20px;
  display: none;
  align-items: center;
  justify-content: center;
  position: absolute;
  top: 0;
  left: 0;
  pointer-events: none;
}

:where(.bp-checkbox, .bp-checklist, .bp-dcl, .bp-grid, .bp-tree) label input[type='checkbox'] + span > i {
  font-size: 16px;
  color: var(--bp-neutral-0);
  display: flex;
  align-items: center;
  justify-content: center;
}

:where(.bp-checkbox, .bp-checklist, .bp-dcl, .bp-grid, .bp-tree) label input[type='checkbox']:disabled {
  background-color: var(--bp-surface-sunken);
  border-color: var(--bp-surface-raised);
  cursor: not-allowed;
}

:where(.bp-checkbox, .bp-checklist, .bp-dcl, .bp-grid, .bp-tree) label input[type='checkbox']:disabled:checked {
  background-color: var(--bp-primary-300);
  border: none;
}

:where(.bp-checkbox, .bp-checklist, .bp-dcl, .bp-grid, .bp-tree) label:has(input[type='checkbox']:disabled) {
  cursor: not-allowed;
}

:where(.bp-checkbox, .bp-checklist, .bp-dcl, .bp-grid, .bp-tree) label input[type='checkbox']:checked {
  background-color: var(--bp-primary-500);
  border: none;
}

:where(.bp-checkbox, .bp-checklist, .bp-dcl, .bp-grid, .bp-tree) label input[type='checkbox']:checked + span {
  display: flex;
}

/* select-list */
.bp-select-list {
  min-width: 164px;
  width: 164px;
  padding: 8px;
  display: flex;
  flex-direction: column;
}

.bp-select-list .bp-title {
  width: 100%;
  height: 32px;
  color: var(--bp-ink-body);
  display: flex;
  align-items: center;
}

.bp-select-list ul {
  width: 100%;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
}

.bp-select-list ul > li {
  display: flex;
  align-items: center;
  min-height: 40px;
  padding: 0 8px;
  gap: 8px;
  border-radius: 4px;
  transition: 0.3s;
}

.bp-select-list ul > li:hover{
  background-color: var(--bp-overlay-hover);
}

.bp-select-list ul > li:active{
  background-color: var(--bp-overlay-active);
}

.bp-select-list ul > li > span {
  color: var(--bp-ink-strong);
}

/* radio-menu */
.bp-radio-btn{
  display: flex;
  gap: 12px;
}
.bp-radio-btn label{
  display: flex;
  align-items: center;
  cursor: pointer;
}

.bp-radio-btn input{
  display: none;
}

.bp-radio-btn label > div{
  width: 20px;
  height: 20px;
  border-radius: 50%;
  border: 2px solid var(--bp-surface-raised);
  position: relative;
  margin-right: 4px;
}

.bp-radio-btn input:checked + div{
  background-color: var(--bp-primary-500);
  border: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

.bp-radio-btn input:checked + div::after{
  content: '';
  width: 8px;
  height: 8px;
  background-color: var(--bp-neutral-0);
  border-radius: 50%;
}

.bp-radio-btn span{
  color: var(--bp-ink-strong);
  font-size: 14px;
  font-weight: 500;
}

/* radio disabled */
.bp-radio-btn input:disabled + div{
  border-color: var(--bp-surface-sunken);
  background-color: var(--bp-surface-sunken);
}

.bp-radio-btn input:disabled:checked + div{
  background-color: var(--bp-surface-track);
}

.bp-radio-btn label:has(input:disabled){
  cursor: not-allowed;
}

.bp-radio-btn label:has(input:disabled) span{
  color: var(--bp-text-disabled);
}

/* ═══════════════════════════════════════════════════════════════
 * BpTab · 탭 메뉴
 * 디자인 가이드 VI : 언더라인 스타일 (플랫 · 각진 모서리)
 *
 * ┌───────────────┐
 * │ Tab1 ┃ Tab2   │  ← 선택 탭 하단 2px Primary underline
 * │──────┸────────│  ← 하단 1px 구분선
 *
 * 선택 탭: 글자 Primary + 하단 Primary 2px
 * Hover: 배경 muted + 글자 primary
 * ═══════════════════════════════════════════════════════════════ */
.bp-tab-menu {
  display: inline-flex;
  color: var(--bp-text-secondary);
  font-size: var(--bp-control-font-md);
  font-weight: var(--bp-weight-medium);
  border-bottom: 1px solid var(--bp-border-light);
  gap: 2px;
  padding: 0;
  background: transparent;
}
.bp-tab-menu.bp-full-width {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  width: 100%;
}
.bp-tab-menu.bp-tab-width-auto {
  display: inline-flex;
}

.bp-tab-menu input[type="radio"] {
  display: none;
}

/* 기본 탭 item — 탭 버튼은 .bp-tab-menu 의 직계 자식 span 이다. 후손으로 쓰면 HeaderContent 안 span 까지 칠해진다(HR-MGT-004). */
.bp-tab-menu > span {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: var(--bp-h-md);
  padding: 0 var(--bp-control-pad-md);
  border-radius: var(--bp-radius-sm) var(--bp-radius-sm) 0 0;
  cursor: pointer;
  white-space: nowrap;
  transition: background-color var(--bp-duration-fast), color var(--bp-duration-fast);
  margin-bottom: -1px;           /* 하단 border 와 item underline 정렬 */
}

.bp-tab-menu > span:hover {
  color: var(--bp-text-primary);
  background: var(--bp-bg-muted);
}

.bp-tab-menu input[type="radio"]:checked + span {
  color: var(--bp-active-text);
  font-weight: var(--bp-weight-semibold);
}

/* Active 하단 2px primary underline */
.bp-tab-menu input[type="radio"]:checked + span::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 2px;
  background: var(--bp-active-accent);
  border-radius: var(--bp-radius-xs) var(--bp-radius-xs) 0 0;
}

.bp-tab-menu input[type="radio"]:checked + span:hover {
  background: var(--bp-bg-muted);
  color: var(--bp-active-text);
}

/* 탭 닫기(X) 버튼 — 헤더 텍스트 오른쪽에 표시 */
/* 닫기 버튼이 있으면 오른쪽 패딩을 제거해 X 를 헤더 끝까지 붙인다.
   .bp-tab-container 로 시작해 specificity 를 (0,3,1) 로 올려, 뒤에 오는
   사이즈별 `padding: 0 var(--bp-control-pad-*)` shorthand 보다 우선하게 한다. */
.bp-tab-container .bp-tab-menu > span:has(.bp-tab-close) {
  padding-right: 0;
}
.bp-tab-menu > span .bp-tab-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 1.5em;
  height: 1.5em;
  margin-left: var(--bp-space-2);
  border-radius: var(--bp-radius-circle);
  color: var(--bp-text-tertiary);
  cursor: pointer;
  transition: background-color var(--bp-duration-fast), color var(--bp-duration-fast);
}
.bp-tab-menu > span .bp-tab-close:hover {
  background: var(--bp-bg-muted);
  color: var(--bp-text-primary);
}
.bp-tab-menu > span .bp-tab-close .bi {
  font-size: 1.35em;
  line-height: 1;
}

/* Bar 모드 : 선택 탭이 필 형태로 도드라지는 variant (container 에 배경 필요) */
.bp-tab-bar .bp-tab-menu {
  border-bottom: 0;
}

/* 탭 메뉴 사이즈 (5-tier). 탭 상단 높이는 menu font-size, 아이템은 span height/padding. */
.bp-tab-menu.bp-xs { font-size: var(--bp-control-font-xs); }
.bp-tab-menu.bp-xs > span { height: var(--bp-h-xs); padding: 0 var(--bp-control-pad-xs); }

.bp-tab-menu.bp-sm { font-size: var(--bp-control-font-sm); }
.bp-tab-menu.bp-sm > span { height: var(--bp-h-sm); padding: 0 var(--bp-control-pad-sm); }

.bp-tab-menu.bp-md { font-size: var(--bp-control-font-md); }
.bp-tab-menu.bp-md > span { height: var(--bp-h-md); padding: 0 var(--bp-control-pad-md); }

.bp-tab-menu.bp-lg { font-size: var(--bp-control-font-lg); }
.bp-tab-menu.bp-lg > span { height: var(--bp-h-lg); padding: 0 var(--bp-control-pad-lg); }

.bp-tab-menu.bp-xl { font-size: var(--bp-control-font-xl); }
.bp-tab-menu.bp-xl > span { height: var(--bp-h-xl); padding: 0 var(--bp-control-pad-xl); }

/* select-box */
.bp-select-box{
  width: fit-content;
  position: relative;
  display: flex;
  align-items: center;
  gap: 8px;
  /* 포커스 링(.bp-select-box:focus-within box-shadow)이 이 요소에 걸리므로,
     안쪽 select 와 동일한 radius 를 줘야 링이 각지지 않고 라운드로 나온다. */
  border-radius: var(--bp-radius-sm);
}

.bp-textfield-box .bp-select-box{
  width: 100%;
}

.bp-textfield-box .bp-select-box select{
  width: 100%;
}

/* 테두리·radius·transition·3-state 는 "Input 3-state 표준" 블록이 소유.
   화살표 fill 은 data URI 라 var() 를 넣을 수 없다. #AFBACA 는 라이트에서
   --bp-neutral-400 · 다크에서 --bp-text-secondary 와 같은 값이라 양 테마 모두 읽힌다. */
.bp-select-box select{
  /* min-width 제거 — Width 파라미터로 외부 통제. 사이즈 룰에서 필요 시 재정의. */
  min-width: 0;
  height: var(--bp-input-height);
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  padding: 0 32px 0 8px;
  color: var(--bp-text-primary);
  background-color: var(--bp-bg-surface);
  background-image: url("data:image/svg+xml,%3Csvg width='20' height='20' viewBox='0 0 20 20' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M4.41205 6.91107C4.73748 6.58563 5.26512 6.58563 5.59056 6.91107L10.0013 11.3218L14.412 6.91107C14.7375 6.58563 15.2651 6.58563 15.5906 6.91107C15.916 7.23651 15.916 7.76414 15.5906 8.08958L10.5906 13.0896C10.2651 13.415 9.73748 13.415 9.41205 13.0896L4.41205 8.08958C4.08661 7.76414 4.08661 7.23651 4.41205 6.91107Z' fill='%23AFBACA'/%3E%3C/svg%3E");
  background-position: calc(100% - 8px) 50%;
  background-size: 18px;
  background-repeat: no-repeat;
  cursor: pointer;
  font-size: 14px;
}

/* 포커스 시 화살표를 밝은 녹색 상향 글리프로 바꾸던 규칙 삭제 —
   테두리(--bp-primary-500)와 색이 어긋났고, 다른 입력은 포커스에서
   아이콘을 바꾸지 않는다. 화살표는 전 상태 동일. */

/* 표준 사이즈 (BpSelect.razor.cs docstring: xs/sm/md/lg/xl) — BpButton/BpInput 과 동일 토큰 */
.bp-select-box.bp-xs select { height: var(--bp-h-xs); padding: 0 28px 0 var(--bp-control-pad-xs); font-size: var(--bp-control-font-xs); }
.bp-select-box.bp-sm select { height: var(--bp-h-sm); padding: 0 28px 0 var(--bp-control-pad-sm); font-size: var(--bp-control-font-sm); }
.bp-select-box.bp-md select { height: var(--bp-h-md); padding: 0 32px 0 var(--bp-control-pad-md); font-size: var(--bp-control-font-md); }
.bp-select-box.bp-lg select { height: var(--bp-h-lg); padding: 0 32px 0 var(--bp-control-pad-lg); font-size: var(--bp-control-font-lg); }
.bp-select-box.bp-xl select { height: var(--bp-h-xl); padding: 0 36px 0 var(--bp-control-pad-xl); font-size: var(--bp-control-font-xl); }

/* modal */
.bp-modal-container{
  width: 100%;
  height: 100vh;
  position: fixed;
  top: 0;
  left: 0;
  background: var(--bp-scrim-soft);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
}

/* 모달리스 모드: backdrop 투명 + 포인터 이벤트 통과, 다이얼로그 본체만 입력 수신 */
.bp-modal-container.bp-non-modal{
  background: transparent;
  pointer-events: none;
}

.bp-modal-container.bp-non-modal .bp-modal{
  pointer-events: auto;
  box-shadow: var(--bp-shadow-lg);
}

.bp-modal{
  /* 크기·레이아웃을 전부 **컨테이너가 준 변수**로 받는다.
     ⚠️ error-prevention #21 — Blazor 와 JS 가 같은 요소의 style 이나 class 를 나눠 쓰면
     재렌더가 상대의 값을 지운다. 그래서 Blazor 는 이 요소의 style·class 를 **쓰지 않는다**:
       · Blazor → .bp-modal-container 의 CSS 변수만
       · JS     → .bp-modal 의 style(left/top/width/height/position)과 class(bp-modal-resized)
     display 까지 변수로 받는 이유가 그것이다 — 클래스로 주면 JS 가 붙인 클래스가 지워진다. */
  width: var(--bp-modal-w, 350px);
  height: var(--bp-modal-h, auto);
  /* ⚠️ fallback 이 축마다 다르다. 0.2.8 의 **계산값**에 맞춘 것이지 초기값이 아니다.

     · min-width  → 0    : bp-variables.css 의 `.bp-modal-container > * { min-width: 0 }`
                           containment 규칙이 이미 0 으로 정해 뒀다. 이 파일이 뒤에 로드되고
                           특이도가 같아(둘 다 0,1,0) 여기서 auto 를 쓰면 그 규칙을 **덮는다**.
                           실제로 덮었다 — viewport 800 에서 창이 940px·left -70 으로 나가
                           닫기 버튼과 리사이즈 손잡이가 화면 밖에 놓였고, 컨테이너가
                           position: fixed 라 스크롤로도 닿지 않았다(독립 Review R2 실측).
     · min-height → auto : min-height 에는 그런 containment 규칙이 없어 0.2.8 계산값이 auto 다.
                           행 방향 flex item 이라 주축이 아니어서 실질 0 과 같다.

     ⚠️ R1 은 0.2.8 을 실제 파일이 아니라 `.old .bp-modal { min-width: auto }` 로 흉내 냈고,
     그 셀렉터가 (0,2,0) 이라 containment 규칙까지 함께 덮여 반대 결론이 나왔다
     (error-prevention #26 — 특이도를 안 맞춘 재현). 재현본이 아니라 **실제 파일**로 잰다.

     창이 0 으로 찌그러지는 것은 bp-common.js 의 리사이즈 바닥값이 막는다. */
  min-width: var(--bp-modal-min-w, 0);
  min-height: var(--bp-modal-min-h, auto);
  display: var(--bp-modal-display, block);
  flex-direction: column;
  padding: 20px;
  border-radius: 12px;
  background-color: var(--bp-bg-surface);
  position: relative;
}

.bp-modal-top{
  width: 100%;
}

/* 상단 이동 핸들 — 아이콘 없이 드래그 영역만 유지(cursor: move). */
.bp-modal-drag-bar{
  height: 24px;
  margin: -20px -20px 0;
  cursor: move;
  border-radius: 12px 12px 0 0;
}

/* 리사이즈 핸들 — 우측하단 코너에서 너비·높이 동시 조절 (nwse) */
.bp-modal-resize-handle{
  position: absolute;
  right: 0;
  bottom: 0;
  width: 20px;
  height: 20px;
  cursor: nwse-resize;
  z-index: 1;
}

.bp-modal-resize-handle::after{
  content: '';
  position: absolute;
  right: 4px;
  bottom: 4px;
  width: 9px;
  height: 9px;
  border-right: 2px solid var(--bp-border-strong);
  border-bottom: 2px solid var(--bp-border-strong);
  border-bottom-right-radius: 3px;
  transition: border-color 0.15s;
}

.bp-modal-resize-handle:hover::after{
  border-color: var(--bp-text-secondary);
}

/* ── 가장자리 리사이즈 (F35) ──────────────────────────────────
   오른쪽 모서리는 가로만, 아래 모서리는 세로만 바꾼다. 꼭지점(위 규칙)은 그대로 둘 다 바꾼다.
   ⚠️ 두께를 키우면 가장자리 가까운 버튼·입력의 클릭을 먹는다. 6px 을 유지한다.
   꼭지점 핸들(20px)과 겹치지 않게 양쪽 끝을 그만큼 비운다. */
.bp-modal-resize-e{
  position: absolute;
  /* 위 24px 은 비운다 — .bp-modal-drag-bar(height 24px)가 거기 있다.
     덮으면 그 6px 으로는 창을 옮길 수 없다. */
  top: 24px;
  right: 0;
  bottom: 20px;
  width: 6px;
  cursor: ew-resize;
  z-index: 1;
}

.bp-modal-resize-s{
  position: absolute;
  left: 0;
  right: 20px;
  bottom: 0;
  height: 6px;
  cursor: ns-resize;
  z-index: 1;
}

/* 코너 리사이즈로 크기 조절된 모달 — 늘어난 높이를 본문이 채우고, 넘치면 스크롤.
   리사이즈 전 기본 모달(내용 크기)에는 미적용 → 회귀 없음. */
/* 높이가 정해진 창 — 본문이 남은 높이를 쓰고 넘치면 스크롤해야 한다. 안 그러면 내용이
   창 밖에 그려지고, 비모달에서는 그 영역이 pointer-events 를 물려받아 뒤 화면 클릭까지 막는다.

   두 경로가 있다:
     · 리사이즈 드래그  → JS 가 .bp-modal-resized 를 붙인다
     · Height 파라미터 → Blazor 가 컨테이너에 --bp-modal-display:flex 를 준다
   Blazor 쪽을 클래스로 주지 않는 이유는 위 #21 주석과 같다. */
.bp-modal.bp-modal-resized{
  display: flex;
}

.bp-modal.bp-modal-resized .bp-modal-content{
  flex: 1 1 auto;
  min-height: 0;
  overflow: auto;
}

.bp-modal-content{
  flex: 1 1 auto;
  min-height: 0;
  overflow: var(--bp-modal-content-overflow, visible);
}

/* ── 리사이즈 대응 다이얼로그 레이아웃 헬퍼 (호스트 프로젝트 재사용용) ──
   편집 다이얼로그처럼 "코너 리사이즈로 세로로 늘리면 본문 컨트롤이 늘고 버튼은 하단에 붙는"
   데스크톱(WinForms Dock/Anchor) 동작을 만든다. 다이얼로그 루트를 .bp-dialog-fill 로 감싸고,
   늘어나는 본문을 .bp-dialog-fill-body, 버튼줄을 .bp-modal-footer 로 둔다.
   .bp-dialog-fill-body 안의 "늘어날 컨트롤"에 채움 옵션을 준다(예: BpTextArea Fill="true").
   ⚠️ 늘어날 컨트롤이 없다면 이 레이아웃 대신 Resizable 을 끄거나 너비 위주로 쓴다
      (세로로 늘려도 여백만 생기므로). */
.bp-dialog-fill{
  display: flex;
  flex-direction: column;
  height: 100%;
  min-height: 0;
}

.bp-dialog-fill-body{
  flex: 1 1 auto;
  min-height: 0;
  overflow: auto;
}

.bp-modal-top > div{
  width: 52px;
  height: 52px;
  background-color: var(--bp-surface-sunken);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  margin-bottom: 16px;
}

.bp-modal-top > div i{
  font-size: 26px;
  color: var(--bp-text-secondary);
}

.bp-modal-top button{
  position: absolute;
  top: 8px;
  right: 8px;
}

.bp-modal-header{
  width: 100%;
  margin-bottom: 20px;
}

.bp-modal-header p{
  color: var(--bp-ink-max);
  font-size: 20px;
}

.bp-modal-content{
  width: 100%;
}

.bp-modal-content p{
  font-size: 14px;
  color: var(--bp-ink-body);
  line-height: 140%;
}

/* 폼 컨트롤 세로 스택 — 명시 opt-in 유틸. 다이얼로그 본문이나 페이지 폼에서
   BpInput/BpSelect/BpTextArea 등을 쌓을 때 wrapper 에 추가하면 16px 간격을 자동 부여.
   기존 .bp-modal-content / .bp-con / .bp-con-content 규칙은 손대지 않으므로 호스트 회귀 없음. */
.bp-form-stack{
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.bp-modal-footer{
  width: 100%;
  display: flex;
  justify-content: space-between;
  margin-top: 24px;
  gap: 8px;
}

.bp-modal-footer button{
  width: 50%;
}

/* 단일 버튼 다이얼로그(Alert · 안내 등) — 가운데 정렬 + 내용 크기 버튼.
   2 개 이상 버튼은 위의 space-between + 50% 너비 규칙 유지 (Confirm · 3-button).
   BpConfirmDialog 의 razor.css 가 같은 정렬을 시도하지만 dynamic render 환경
   에서 scope marker 매칭이 보장되지 않아 글로벌 :has 셀렉터로 fallback. */
.bp-modal-footer:has(> button:only-child) {
  justify-content: center;
}

.bp-modal-footer:has(> button:only-child) button {
  width: auto;
  min-width: 120px;
  padding: 0 24px;
}

.bp-modal-footer button:focus-visible{
  outline: none;
  box-shadow: 0 0 0 2px var(--bp-bg-surface), 0 0 0 4px var(--bp-primary-500);
}

/* modal Edit  */
.bp-modal-container.bp-edit .bp-modal{
  width: 548px;
}

.bp-modal-container.bp-edit .bp-modal-top > div{
  background-color: var(--bp-primary-50);
}

.bp-modal-container.bp-edit .bp-modal-top > div i{
  font-size: 32px;
  color: var(--bp-primary-fg);
}

.bp-modal-container.bp-edit .bp-con{
    margin-top: 16px;
}

.bp-modal-container.bp-edit .bp-con .bp-con-header{
  width: 100%;
  height: 48px;
  padding: 0 12px;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.bp-modal-container.bp-edit .bp-con .bp-con-header p{
  color: var(--bp-text-primary);
  font-size: 14px;
  font-weight: 500;
}

.bp-modal-container.bp-edit .bp-con .bp-con-header > div:has(label){
  display: flex;
  align-items: center;
  gap: 4px;
}

.bp-modal-container.bp-edit .bp-con .bp-con-header > div:has(label) > span{
  color: var(--bp-primary-fg);
  font-size: 12px;
  font-weight: 400;
}

.bp-modal-container.bp-edit .bp-con .bp-con-content{
  width: 100%;
}

/* grid help modal */
/* 모달보다 본문이 길면 본문만 스크롤한다 — 스크롤 영역이 없어 1280×800 에서 제목·닫기 버튼이 화면 위로 나갔다(F22 R3 Minor-11). */
.bp-grid-help{
  max-height: calc(100vh - 160px);
  overflow-y: auto;
}

.bp-grid-help h4{
  font-size: 14px;
  font-weight: 600;
  color: var(--bp-text-primary);
  margin: 0 0 8px 0;
}

.bp-grid-help h4:not(:first-child){
  margin-top: 16px;
}

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

.bp-grid-help-table td{
  padding: 4px 8px;
  border-bottom: 1px solid var(--bp-surface-sunken);
  color: var(--bp-ink-secondary);
}

.bp-grid-help-table td:first-child{
  width: 140px;
}

.bp-grid-help-key{
  font-weight: 500;
  color: var(--bp-text-primary);
}

/* ── 비밀번호 보기/숨기기 토글 ──
   모양은 여기가 단독으로 소유한다(css-standards 「같은 클래스를 두 곳에 분산 금지」).
   자리는 문맥이 정한다 — BpInput 안에서는 .bp-textfield 의 flex item,
   정적 SSR 폼에서는 .bp-password-field 안의 absolute. */
.bp-password-toggle {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: none;
  background: none;
  color: var(--bp-text-tertiary);
  cursor: pointer;
}

.bp-password-toggle:hover:not(:disabled) {
  color: var(--bp-text-secondary);
}

.bp-password-toggle:disabled {
  color: var(--bp-text-disabled);
  cursor: not-allowed;
}

/* 정적 SSR 폼(로그인 등)에서 input 안쪽 오른쪽에 얹는다 — 상호작용 없이 bp-input.js 위임 처리기가 움직인다. */
.bp-password-field {
  position: relative;
}

.bp-password-field .bp-password-toggle {
  position: absolute;
  right: var(--bp-space-2);
  top: 50%;
  transform: translateY(-50%);
  font-size: var(--bp-control-icon-md);
}

/* 글자가 버튼 밑으로 들어가지 않게 — 아이콘(20px) + 좌우 여백.
   직계 input 만 잡는다 — 래퍼 안에 다른 입력이 들어와도 번지지 않게(R1 Minor-4). */
.bp-password-field > input {
  padding-right: 36px;
}

/* toast — 위치(top/bottom·left/right)는 BpToastProvider 가 Position/OffsetX/OffsetY 로 인라인 지정.
   기본은 top-center · OffsetY 5px(헤더 띠 안).
   align-items: center 는 **폭이 서로 다른 토스트가 쌓일 때** 각자 가운데로 오게 한다 —
   없으면 컨테이너 왼쪽에 붙어 최대 60px 넘게 어긋난다(F29 R1 Minor). */
.bp-toast-container {
  position: fixed;
  z-index: 9999;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  pointer-events: none;
}

.bp-toast{
  /* height: 46px; */
  min-height: 46px;
  /* position: fixed; */
  /* top: 60px; */
  /* right: 60px; */
  max-width: 400px;
  width: max-content;
  border-radius: 8px;
  background-color: var(--bp-toast-bg);
  box-shadow: var(--bp-shadow-lg);
  color: var(--bp-text-on-fill);
  display: flex;
  align-items: center;
  padding: 0 16px;
  user-select: none;
  pointer-events: auto;
  cursor: pointer;
}

.bp-toast i:nth-child(1){
  font-size: 24px;
  color: var(--bp-error-fg);
  margin-right: 12px;
}

.bp-toast.bp-check i:nth-child(1){
  color: var(--bp-success-fg);
}

.bp-toast.bp-warning i:nth-child(1){
  color: var(--bp-warning-fg);
}

.bp-toast.bp-info i:nth-child(1){
  color: var(--bp-primary-fg);
}

.bp-toast span{
  color: var(--bp-text-on-fill);
  flex: 1;
}


.bp-toast i:nth-child(3){
  font-size: 16px;
  margin-left: 8px;
  cursor: pointer;
}

/* divider */
.bp-divider {
  width: 1px;
  height: 34px;
  background-color: var(--bp-surface-sunken);
  margin: 0 12px;
}

/* pagination */
.bp-pagination {
  width: 100%;
  height: 58px;
  min-height: 58px;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  padding: 0 12px;
  border-top: 1px solid var(--bp-surface-sunken);
}

/* CustomPaginator ���� ��ġ ��Ÿ�� */
.bp-custom-paginator {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 16px;
    flex-wrap: wrap;
}

    .bp-custom-paginator .bp-pagination-summary {
        font-size: 14px;
        color: var(--bp-text-tertiary);
        white-space: nowrap;
    }

    .bp-custom-paginator .bp-select-box {
        flex-shrink: 0;
    }

    .bp-custom-paginator .bp-pagination-controls {
        display: flex;
        align-items: center;
        gap: 4px;
        flex-shrink: 0;
    }

    .bp-custom-paginator .bp-btn-pagination {
        min-width: 30px;
        width: 30px;
        height: 30px;
        border: 1px solid var(--bp-surface-track);
        background: var(--bp-bg-surface);
        color: var(--bp-ink-strong);
        border-radius: 4px;
        cursor: pointer;
        display: flex;
        align-items: center;
        justify-content: center;
        transition: all 0.2s ease;
    }

.bp-btn-pagination:nth-child(n+3):nth-last-child(n+3){
    border: 0;
}

.bp-btn-pagination i{
    width: 10px;
    font-size: 20px;
}

.bp-btn-pagination:nth-child(-n+2):hover,
.bp-btn-pagination:nth-last-child(-n+2):hover {
    background: var(--bp-surface-raised);
}


.bp-btn-pagination:nth-child(n+3):nth-last-child(n+3):hover:not(:disabled) {
    background: var(--bp-surface-raised);
}

    .bp-btn-pagination:nth-child(n+3):nth-last-child(n+3).bp-active {
        background: var(--bp-primary-500);
        color: var(--bp-text-on-fill);
    }
        .bp-btn-pagination:nth-child(n+3):nth-last-child(n+3).bp-active:hover {
            background: var(--bp-primary-600);
        }

        .bp-custom-paginator .bp-btn-pagination:disabled {
            background: var(--bp-surface-sunken);
            border-color: var(--bp-surface-raised);
            color: var(--bp-text-disabled);
            cursor: not-allowed;
        }

/* ── 그리드/트리 셀 내부 입력 컴포넌트 적응 ──
   td padding 유지 + input border: none → 컬럼 폭 변동 없는 인라인 편집
   편집 가능/불가 셀은 배경색 차이로 구분 */

/* 셀 내부 라벨 숨김 — 컬럼 헤더가 라벨 역할 */
.bp-grid-cell-edit .bp-textfield-box > span,
.bp-tree-cell-edit .bp-textfield-box > span {
    display: none;
}

.bp-grid-cell-edit .bp-textfield-box,
.bp-tree-cell-edit .bp-textfield-box {
    width: 100%;
}

.bp-grid-cell-edit .bp-textfield,
.bp-tree-cell-edit .bp-textfield {
    min-width: 0;
    width: 100%;
    height: auto;
    padding: 0;
    gap: 4px;
    margin-right: 0;
    border: none;
    border-radius: 0;
    background-color: transparent;
}

.bp-grid-cell-edit .bp-datafield,
.bp-tree-cell-edit .bp-datafield {
    min-width: 0;
    width: 100%;
    height: auto;
    padding: 0;
    gap: 4px;
    margin-right: 0;
    border: none;
    border-radius: 0;
    background-color: transparent;
}

.bp-grid-cell-edit .bp-select-box,
.bp-tree-cell-edit .bp-select-box {
    width: 100%;
}

.bp-grid-cell-edit .bp-select-box select,
.bp-tree-cell-edit .bp-select-box select {
    min-width: 0;
    width: 100%;
    height: auto;
    padding: 0;
    font-size: inherit;
    border: none;
    background-color: var(--bp-bg-surface);
}

.bp-grid-cell-edit .bp-select-list,
.bp-tree-cell-edit .bp-select-list {
    min-width: 0;
    width: 100%;
}

.bp-grid-cell-edit .bp-date-input-wrapper,
.bp-tree-cell-edit .bp-date-input-wrapper {
    min-width: 0;
    width: 100%;
    height: auto;
    padding: 0;
    margin-right: 0;
    border: none;
    border-radius: 0;
    background-color: transparent;
}

.bp-grid-cell-edit .bp-checklist,
.bp-tree-cell-edit .bp-checklist {
    min-width: 0;
    width: 100%;
}

.bp-grid-cell-edit .bp-dcl,
.bp-tree-cell-edit .bp-dcl {
    min-width: 0;
    width: 100%;
}

.bp-grid-cell-edit .bp-dcl-trigger,
.bp-tree-cell-edit .bp-dcl-trigger {
    min-width: 0;
    height: auto;
    border: none;
    border-radius: 0;
    background-color: transparent;
}

.bp-grid-cell-edit .bp-toggle-con,
.bp-tree-cell-edit .bp-toggle-con {
    gap: 6px;
}

/* 셀 내부 Lookup */
.bp-grid-cell-edit .bp-lookup-label,
.bp-tree-cell-edit .bp-lookup-label {
    display: none;
}

.bp-grid-cell-edit .bp-lookup,
.bp-tree-cell-edit .bp-lookup {
    gap: 0;
}

.bp-grid-cell-edit .bp-lookup-input-wrapper,
.bp-tree-cell-edit .bp-lookup-input-wrapper {
    height: auto;
    border: none;
    border-radius: 0;
    background-color: transparent;
}


/* ═══════════════════════════════════════════════════════════════
 * Dark-theme overrides · BpGrid/BpTree · global (scoped CSS 는
 * [data-theme] 이 html 에 있어 매칭 안되는 한계 회피)
 *
 * 실제 색상은 --bp-active-bg/-text/-accent · --bp-row-active-* 시맨틱
 * 토큰으로 주입. 톤 조정은 bp-variables.css 의 다크 블록 한 군데.
 * Grid·Tree 행 active 는 --bp-row-active-* (Amber) 공용.
 * ═══════════════════════════════════════════════════════════════ */

/* BpGrid · active = Accent(Amber), Tree 와 동일.
   active 룰은 `.bp-grid-row.bp-grid-row-active` 더블 클래스로 hover spec 보다 우선. */
[data-theme="dark"] .bp-grid .bp-grid-row:hover {
    background-color: var(--bp-active-bg-soft);
}
[data-theme="dark"] .bp-grid .bp-grid-row.bp-grid-row-active,
[data-theme="dark"] .bp-grid .bp-grid-row.bp-grid-row-active:hover {
    background-color: var(--bp-row-active-bg);
    color: var(--bp-row-active-text);
}
[data-theme="dark"] .bp-grid .bp-grid-row.bp-grid-row-active td:first-child {
    box-shadow: inset 3px 0 0 var(--bp-row-active-accent), inset 0 -1px 0 var(--bp-border-light);
}
[data-theme="dark"] .bp-grid .bp-grid-row.bp-grid-row-active .bp-grid-frozen {
    background-color: var(--bp-row-active-bg);
}
[data-theme="dark"] .bp-grid .bp-grid-row-selected {
    background-color: var(--bp-active-bg-soft) !important;
}
[data-theme="dark"] .bp-grid .bp-grid-row-selected .bp-grid-frozen {
    background-color: var(--bp-active-bg-soft);
}
/* row-editing 은 다크에서도 scoped CSS 의 --bp-bg-muted / --bp-bg-surface 를 그대로 사용 (BpTree 와 동일) */

/* BpTree · active = Accent(Amber), Grid 와 동일.
   다크 hover 도 BpGrid 와 동일하게 --bp-active-bg-soft 사용 (라이트의 --bp-bg-muted 가
   다크에선 surface 와 거의 같아 hover 효과가 거의 안 보이는 문제 회피). */
[data-theme="dark"] .bp-tree .bp-tree-row:hover {
    background-color: var(--bp-active-bg-soft);
}
[data-theme="dark"] .bp-tree .bp-tree-row.bp-tree-row-active,
[data-theme="dark"] .bp-tree .bp-tree-row.bp-tree-row-active:hover {
    background-color: var(--bp-row-active-bg);
    color: var(--bp-row-active-text);
}
[data-theme="dark"] .bp-tree .bp-tree-row.bp-tree-row-active td:first-child {
    box-shadow: inset 3px 0 0 var(--bp-row-active-accent);
}
/* BpTreeMenu 노드 — NavMenu 와 동일 패턴.
   라이트 hover 는 scoped CSS 의 --bp-bg-muted 사용 (NavMenu 와 동일).
   다크 hover 는 --bp-active-bg-soft (NavMenu 와 통일).
   active 는 --bp-row-active-* 토큰이 자동 테마 적응 — 단 다크 hover spec 을
   이기도록 명시 룰 추가. */
[data-theme="dark"] .bp-tree-menu .bp-tree-row:hover {
    background: var(--bp-active-bg-soft);
    color: var(--bp-text-primary);
}
[data-theme="dark"] .bp-tree-menu .bp-tree-row.is-active,
[data-theme="dark"] .bp-tree-menu .bp-tree-row.is-active:hover {
    background: var(--bp-row-active-bg);
    color: var(--bp-row-active-text);
}

[data-theme="dark"] .bp-tree .bp-tree-row-selected {
    background-color: var(--bp-active-bg-soft) !important;
}

/* ═══════════════════════════════════════════════════════════════
 * BpLoading · mark variant · 글로벌 (스코프드 바깥에서 사용 가능)
 * BpReconnectModal 등 scoped 경계를 넘어가는 곳에서 쓴다.
 * ═══════════════════════════════════════════════════════════════ */
.bp-loading-anim.bp-loading-mark {
    display: grid;
    place-items: center;
    position: relative;
}
.bp-loading-anim.bp-loading-mark svg {
    width: 100%;
    height: 100%;
}
.bp-loading-mark.bp-sm { width: 32px; height: 32px; }
.bp-loading-mark.bp-md { width: 56px; height: 56px; }
.bp-loading-mark.bp-lg { width: 88px; height: 88px; }

.bp-loading-mark .bp-loading-square {
    fill: var(--bp-primary-fg);
    transform-origin: 50% 50%;
    animation: bp-loading-square-rotate 2.4s cubic-bezier(0.65, 0, 0.35, 1) infinite;
}
.bp-loading-mark .bp-loading-letter {
    stroke: var(--bp-neutral-0);
    stroke-dasharray: 80 80;
    stroke-dashoffset: 80;
    animation: bp-loading-letter-draw 2.4s ease-in-out infinite;
}
.bp-loading-mark .bp-loading-dot-svg {
    fill: var(--bp-accent-fg);
    transform-origin: 30px 6px;
    animation: bp-loading-dot-pulse 1.2s ease-in-out infinite;
}

@keyframes bp-loading-square-rotate {
    0%, 100% { transform: rotate(0deg); }
    25%      { transform: rotate(90deg); }
    50%      { transform: rotate(180deg); }
    75%      { transform: rotate(270deg); }
}
@keyframes bp-loading-letter-draw {
    0%   { stroke-dashoffset: 80;  opacity: 0; }
    25%  { stroke-dashoffset: 0;   opacity: 1; }
    75%  { stroke-dashoffset: 0;   opacity: 1; }
    100% { stroke-dashoffset: -80; opacity: 0; }
}
@keyframes bp-loading-dot-pulse {
    0%, 100% { transform: scale(1);   opacity: 1; }
    50%      { transform: scale(1.4); opacity: 0.5; }
}

/* ═══════════════════════════════════════════════════════════════
 * Input / Select / Tab 5단계 사이즈 alias (xs/sm/md/lg/xl)
 * .bp-btn 은 bp-variables.css Phase 2 alias 에 이미 추가됨.
 * 여기서는 .bp-textfield / .bp-datafield / .bp-select-box / .bp-tab-menu
 * 가 공통 컨트롤 토큰 (--bp-h-*, --bp-control-*) 에 연결되도록.
 * ═══════════════════════════════════════════════════════════════ */

/* textfield */
.bp-textfield.bp-xs { height: var(--bp-h-xs); padding: 0 var(--bp-control-pad-xs); font-size: var(--bp-control-font-xs); }
.bp-textfield.bp-sm { height: var(--bp-h-sm); padding: 0 var(--bp-control-pad-sm); font-size: var(--bp-control-font-sm); }
.bp-textfield.bp-md { height: var(--bp-h-md); padding: 0 var(--bp-control-pad-md); font-size: var(--bp-control-font-md); }
.bp-textfield.bp-lg { height: var(--bp-h-lg); padding: 0 var(--bp-control-pad-lg); font-size: var(--bp-control-font-lg); }
.bp-textfield.bp-xl { height: var(--bp-h-xl); padding: 0 var(--bp-control-pad-xl); font-size: var(--bp-control-font-xl); }
.bp-textfield.bp-xs i { font-size: var(--bp-control-icon-xs); }
.bp-textfield.bp-sm i { font-size: var(--bp-control-icon-sm); }
.bp-textfield.bp-md i { font-size: var(--bp-control-icon-md); }
.bp-textfield.bp-lg i { font-size: var(--bp-control-icon-lg); }
.bp-textfield.bp-xl i { font-size: var(--bp-control-icon-xl); }

/* datafield */
.bp-datafield.bp-xs { height: var(--bp-h-xs); padding: 0 var(--bp-control-pad-xs); font-size: var(--bp-control-font-xs); }
.bp-datafield.bp-sm { height: var(--bp-h-sm); padding: 0 var(--bp-control-pad-sm); font-size: var(--bp-control-font-sm); }
.bp-datafield.bp-md { height: var(--bp-h-md); padding: 0 var(--bp-control-pad-md); font-size: var(--bp-control-font-md); }
.bp-datafield.bp-lg { height: var(--bp-h-lg); padding: 0 var(--bp-control-pad-lg); font-size: var(--bp-control-font-lg); }
.bp-datafield.bp-xl { height: var(--bp-h-xl); padding: 0 var(--bp-control-pad-xl); font-size: var(--bp-control-font-xl); }

/* select-box select */
.bp-select-box.bp-xs select { height: var(--bp-h-xs); padding: 0 28px 0 var(--bp-control-pad-xs); font-size: var(--bp-control-font-xs); }
.bp-select-box.bp-sm select { height: var(--bp-h-sm); padding: 0 28px 0 var(--bp-control-pad-sm); font-size: var(--bp-control-font-sm); }
.bp-select-box.bp-md select { height: var(--bp-h-md); padding: 0 32px 0 var(--bp-control-pad-md); font-size: var(--bp-control-font-md); }
.bp-select-box.bp-lg select { height: var(--bp-h-lg); padding: 0 36px 0 var(--bp-control-pad-lg); font-size: var(--bp-control-font-lg); }
.bp-select-box.bp-xl select { height: var(--bp-h-xl); padding: 0 40px 0 var(--bp-control-pad-xl); font-size: var(--bp-control-font-xl); }

/* tab-menu · 탭 탑 bar height */
.bp-tab-menu.bp-xs { height: var(--bp-h-xs); }
.bp-tab-menu.bp-sm { height: var(--bp-h-sm); }
.bp-tab-menu.bp-md { height: var(--bp-h-md); }
.bp-tab-menu.bp-lg { height: var(--bp-h-lg); }
.bp-tab-menu.bp-xl { height: var(--bp-h-xl); }
.bp-tab-menu.bp-xs > span { font-size: var(--bp-control-font-xs); padding: 0 var(--bp-control-pad-xs); }
.bp-tab-menu.bp-sm > span { font-size: var(--bp-control-font-sm); padding: 0 var(--bp-control-pad-sm); }
.bp-tab-menu.bp-md > span { font-size: var(--bp-control-font-md); padding: 0 var(--bp-control-pad-md); }
.bp-tab-menu.bp-lg > span { font-size: var(--bp-control-font-lg); padding: 0 var(--bp-control-pad-lg); }
.bp-tab-menu.bp-xl > span { font-size: var(--bp-control-font-xl); padding: 0 var(--bp-control-pad-xl); }

/* Textarea — 인풋과 동일 배경 토큰 (높이는 rows 로 조정되므로 size 미적용).
   테두리·3-state 는 아래 "Input 3-state 표준" 블록이 소유. */
.bp-textarea {
    background-color: var(--bp-bg-surface);
    color: var(--bp-text-primary);
    padding: 8px 12px;
    font-family: inherit;
    font-size: var(--bp-control-font-md);
}
.bp-textarea::placeholder {
    color: var(--bp-text-tertiary);
    opacity: 1;
}

/* ═══════════════════════════════════════════════════════════════
 * Input 3-state 표준 — 전 입력 계열의 테두리를 여기 한 곳에서 소유
 *
 *   idle  : 1px solid var(--bp-border-default) · var(--bp-radius-sm)
 *   hover : var(--bp-text-tertiary)   — focus/열림/disabled 면 무반응
 *   focus : var(--bp-primary-500) + var(--bp-focus-ring)
 *
 * 계열별 .razor.css 에 border/radius/focus 를 다시 쓰지 않는다. scoped CSS 는
 * 속성 셀렉터가 하나 더 붙어(`::deep` 없으면 `.bp-*[b-xxx]`, 있으면 `[b-xxx] .bp-*`)
 * 여기보다 명시도가 높아 조용히 이 표준을 덮는다.
 * 각 컴포넌트 CSS 는 높이·패딩·배경만 갖는다.
 *
 * 이 블록은 파일 끝에 둔다 — 위 계열 기본 규칙과 명시도가 같으므로
 * 순서로 이긴다. 그리드/트리 셀 편집(.bp-grid-cell-edit 등)은 명시도가
 * 한 단계 높아 여전히 border:none 을 유지한다.
 * ═══════════════════════════════════════════════════════════════ */

/* (a) idle — 테두리를 그리는 요소 */
.bp-textfield,
.bp-datafield,
.bp-textarea,
.bp-select-box select,
.bp-date-input-wrapper,
.bp-grid-filter-input,
.bp-tree-filter-input,
.bp-grid-paginator-size select,
.bp-lookup-input-wrapper,
.bp-dcl-trigger,
.bp-checklist-container {
    border: 1px solid var(--bp-border-default);
    border-radius: var(--bp-radius-sm);
    transition: border-color var(--bp-duration-fast),
                box-shadow var(--bp-duration-fast),
                background-color var(--bp-duration-fast);
}

/* (b) hover — 중간 단계. focus·열림·disabled 면 반응하지 않는다 */
.bp-textfield:hover:not(:focus-within):not(:has(:disabled)),
.bp-datafield:hover:not(:focus-within):not(:has(:disabled)),
.bp-textarea:hover:not(:focus):not(:disabled),
.bp-select-box select:hover:not(:focus):not(:disabled),
.bp-date-input-wrapper:hover:not(:focus-within):not(:has(:disabled)),
.bp-grid-filter-input:hover:not(:focus):not(:disabled),
.bp-tree-filter-input:hover:not(:focus):not(:disabled),
.bp-grid-paginator-size select:hover:not(:focus):not(:disabled),
.bp-lookup-input-wrapper:hover:not(:focus-within):not(.active),
.bp-dcl-trigger:hover:not(.active),
.bp-checklist-container:not(.bp-disabled):hover:not(:focus-within) {
    border-color: var(--bp-text-tertiary);
}

/* (c) focus · 열림(active) */
.bp-textfield:focus-within,
.bp-datafield:focus-within,
.bp-textarea:focus,
.bp-select-box:focus-within,
.bp-date-input-wrapper:focus-within,
.bp-grid-filter-input:focus,
.bp-tree-filter-input:focus,
.bp-grid-paginator-size select:focus,
.bp-lookup-input-wrapper:focus-within,
.bp-lookup-input-wrapper.active,
.bp-dcl-trigger.active,
.bp-checklist-container:focus-within {
    border-color: var(--bp-primary-500);
    box-shadow: var(--bp-focus-ring);
    outline: none;
}

/* select 만 예외 — 테두리는 안쪽 select, 링은 래퍼(.bp-select-box)에 걸린다.
   두 사각형이 같은 radius 를 쓰므로 시각적으로 한 겹으로 보인다.

   outline: none 이 필수다. bp-reset 의 `input:focus-visible { outline: none }` 은
   <input> 만 잡아서 <select> 에는 전역 `:focus-visible { outline: 2px solid
   var(--bp-primary-500); outline-offset: 4px }` 가 그대로 걸린다 → 보더(녹색) +
   래퍼 링 + 바깥 2px 아웃라인으로 테두리가 이중으로 보인다.
   포커스 표시는 보더+링이 이미 담당하므로(WCAG 2.4.7) 아웃라인은 끈다.
   .bp-grid-paginator-size select 는 자기 규칙에 outline: none 을 갖고 있다. */
.bp-select-box:focus-within select,
.bp-select-box select:focus,
.bp-select-box select:focus-visible {
    border-color: var(--bp-primary-500);
    outline: none;
}
