/* OmniFlow 디폴트 앱 템플릿 — Design Tokens & Base Styles.
 * 출처: OmniFlow-Hub(hub_v2) '정밀 계기판' 마스터 팔레트를 StockPlan이 이식한 버전을 재사용.
 * 라이트 기본 + [data-theme="dark"] 미러 + 토글(localStorage hub_theme, base.html 담당).
 * 새 앱을 만들 때 색만 바꾸고 싶으면 :root / [data-theme="dark"] 블록의 값만 바꾸면 된다
 * (클래스명은 여러 앱이 공유하는 구조이니 그대로 두는 걸 권장).
 */
:root {
  --bg:               #F5F4F0;
  /* 크롬(사이드바·상단바·레일)은 **흰색**이다 — 허브와 같은 배치
     (허브: 캔버스 #F3F5F8 / 표면 #FFFFFF). 예전엔 #F7F6F2 라 캔버스(#F5F4F0)와
     **차이가 2**밖에 안 나 사이드바 경계가 안 보였다(2026-09-05 캡처 대조).
     다크는 이미 표면과 같은 값이라 그대로 둔다. */
  --bg-elevated:      #FFFFFF;
  --surface:          #FFFFFF;
  --surface-strong:   #EFEDE7;
  --border:           #E3E1DA;
  --border-strong:    #C9C6BC;
  --text:             #191C22;
  --text-muted:       #5B6068;
  --text-subtle:      #9A9C9F;

  --accent:           #2D5FA9;
  --accent-light:     #4E86D8;   /* 브랜드 마크 그라디언트용 (허브 로고와 같은 결) */
  --accent-hover:     #234F92;
  --accent-soft:      #E9F0FA;
  --on-accent:        #FFFFFF;

  --ok:               #25755A;
  --danger:           #C03B33;
  --danger-strong:    #A8322B;
  --warn:             #B96A00;

  --radius:             8px;
  --radius-sm:          4px;
  --radius-lg:         12px;
  --shadow-card:      0 1px 2px rgba(25,28,34,0.04), 0 8px 24px -16px rgba(25,28,34,0.18);
  --shadow-elev:      0 24px 48px -18px rgba(25,28,34,0.28);
  --font:             "Pretendard","Noto Sans KR", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-mono:        "IBM Plex Mono","JetBrains Mono","Consolas",ui-monospace, monospace;
}

/* ── 어드민 팔레트 = 허브 값 (2026-09-05) ─────────────────────────────
 * 캡처로 나란히 놓고 보니 치수·구조·아이콘은 같은데 **바탕색 계열**이 달랐다 —
 * 허브는 차가운 회청색(#F3F5F8), 우리는 따뜻한 베이지(#F5F4F0).
 *
 * 값은 `OmniFlow-Hub/src/hub/page.py` 의 `:root` 에서 그대로 가져왔다.
 * 강조색(--accent)은 KGI 네이비를 남긴다 — 앱을 구별하는 유일한 색이다.
 *
 * **어드민에만** 입힌다(`body:not(.shop)`). 고객 화면(`body.shop`)은 같은 토큰을
 * 쓰지만 별도 브랜드 면이고, 이번 지시는 백엔드에 관한 것이었다.
 * `body` 에 선언하는 이유는 `:root` 보다 안쪽이라 고객 화면을 안 건드리기 때문이다. */
body:not(.shop) {
  --bg:               #F3F5F8;
  --bg-elevated:      #FFFFFF;
  --surface:          #FFFFFF;
  --surface-strong:   #F1F5F9;
  --border:           #E5E7EB;
  --border-strong:    #CBD5E1;
  --text:             #1F2937;
  --text-muted:       #6B7280;
  --text-subtle:      #9CA3AF;
}
[data-theme="dark"] body:not(.shop) {
  --bg:               #0D0E10;
  --bg-elevated:      #161719;   /* 허브 사이드바는 `--bg-surface` 를 쓴다 */
  --surface:          #161719;
  --surface-strong:   #1C1F24;
  --border:           #26282C;
  --border-strong:    #34373C;
  --text:             #F2F3F5;
  --text-muted:       #9BA1A9;
  --text-subtle:      #6B7178;
}

[data-theme="dark"] {
  --bg:               #0B0C0E;
  --bg-elevated:      #121316;
  --surface:          #121316;
  --surface-strong:   #202329;
  --border:           #26292F;
  --border-strong:    #363A42;
  --text:             #ECEDEF;
  --text-muted:       #9CA1A8;
  --text-subtle:      #62666E;

  --accent:           #7E8BDB;
  --accent-light:     #9AA5E8;
  --accent-hover:     #8E9AE4;
  --accent-soft:      #1D2030;
  --on-accent:        #0B0C0E;

  --ok:               #58BD8F;
  --danger:           #E25A52;
  --danger-strong:    #EF6E66;
  --warn:             #E3A23C;

  --shadow-card:      0 1px 2px rgba(0,0,0,0.4), 0 10px 28px -18px rgba(0,0,0,0.7);
  --shadow-elev:      0 24px 48px -18px rgba(0,0,0,0.7);
}

/* --- Reset --- */
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  background-color: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: var(--fs-6);
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
  min-height: 100dvh;
  /* 어드민 셸은 허브 셸 키트(.wp-shell 그리드, hub-shell.css — 2026-10-17)라 body 에 배치를 두지 않는다. */
}


a { color: inherit; text-decoration: none; }
/* 허브는 Quasar 가 button 을 리셋해 준다. 우리는 그 프레임워크가 없으므로
   같은 리셋이 필요하다 — 없으면 브라우저 기본(테두리 2px · 회색 배경 · 패딩)이
   남아 `.shell-icon-btn` 같은 허브 규칙이 제 모양을 못 낸다.
   **`hub-shell.css` 보다 먼저** 와야 한다 — 뒤에 두면 허브 규칙을 덮는다.
   `.btn` 은 자기 배경·테두리·패딩을 직접 정하므로 영향 없다. */
button { font: inherit; color: inherit; cursor: pointer;
         appearance: none; background: none; border: 0; padding: 0;
         text-align: inherit; }
input, select, textarea { font: inherit; color: inherit; }
code { font-family: var(--font-mono); font-size: 0.92em; background: var(--surface-strong); padding: 2px 6px; border-radius: var(--radius-sm); }
.hidden { display: none !important; }
.text-muted { color: var(--text-muted); }

/* 사이드바·상단바·우측 레일은 `hub-shell.css`(허브 소스에서 자동 생성) 담당.
   여기에 다시 쓰지 말 것 — 두 벌이 되면 어느 쪽이 이기는지 아무도 모른다. */

/* --- Main / Cards --- */
.page-grid-single { max-width: 720px; margin: 0 auto; }
/* `.card` · `.btn` · `.tbl` 의 **생김새는 `hub-components.css`** 가 정한다
   (허브 `shell.py` 에서 잘라 온 것). 여기에 다시 쓰면 두 벌이 된다. */
/* 15px 은 스케일에 없는 값이었다. */
.card-title { margin: 0 0 4px; font-size: var(--fs-5); font-weight: 700;
              color: var(--accent); letter-spacing: -0.01em; }
/* 카드 안의 **작은 제목**(h3). 13px 이라 본문과 같아서 제목으로 안 보였다. */
h3.card-sub { color: var(--text); font-size: var(--fs-6); font-weight: 700;
              margin: 18px 0 8px; }
.card-sub { color: var(--text-muted); font-size: var(--fs-7); margin: 0 0 14px; }
.card-section { margin-top: 14px; }
.card-section + .card-section { padding-top: 12px; border-top: 1px solid var(--border); }

.stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 10px; }
.stat-card { background: var(--surface-strong); border: 1px solid var(--border); border-radius: var(--radius); padding: 12px 14px; display: grid; gap: 4px; }
.stat-label { font-size: var(--fs-9); color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.04em; }
.stat-value { font-size: var(--fs-1); font-weight: 700; font-variant-numeric: tabular-nums; }

/* --- Buttons --- */
/* 버튼 생김새도 `hub-components.css`. 여기엔 **허브에 없는 것만** 남긴다. */
.btn:active { transform: translateY(1px); }
.btn-ok { background: var(--ok); border-color: var(--ok); color: var(--on-accent); }

/* --- Forms / kv --- */
.kv-grid { display: grid; grid-template-columns: max-content 1fr; column-gap: 18px; row-gap: 8px; margin: 0; }
.kv-grid dt { color: var(--text-muted); font-size: var(--fs-7); }
.kv-grid dd { margin: 0; color: var(--text); font-size: var(--fs-7); }
.form-grid { display: grid; grid-template-columns: max-content 1fr; column-gap: 12px; row-gap: 8px; align-items: center; }
.form-grid label { color: var(--text-muted); font-size: var(--fs-7); }
.form-row { display: flex; align-items: center; gap: 8px; }
.text-input {
  background: var(--bg-elevated); color: var(--text);
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: 6px 10px; font-size: var(--fs-7); width: 100%;
}
.text-input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-soft); }
.checkbox { display: inline-flex; align-items: center; gap: 6px; color: var(--text-muted); font-size: var(--fs-7); }
.checkbox input { accent-color: var(--accent); }

/* ── 메인 화면 관리 (/admin/promo) ─────────────────────────────────
   이 화면의 핵심은 **미리보기**다. 배경 사진 위에 흰 글자를 얹는 판단은 눈으로만
   할 수 있어서, 저장하고 고객 화면을 새로고침하는 왕복을 없앤다.
   무대(stage)는 고객 화면과 **같은 겹침 순서**로 그린다 — 사진 → 어둡게 → 글자. */
.promo-tabs { display: flex; gap: 6px; margin: 0 0 14px; }
.promo-tab { padding: 8px 16px; border: 1px solid var(--border); border-radius: var(--radius-sm);
             color: var(--text-muted); text-decoration: none; font-size: var(--fs-7); }
.promo-tab.is-on { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.promo-count { opacity: .75; font-size: var(--fs-9); margin-left: 4px; }

.promo-grid { list-style: none; margin: 0 0 12px; padding: 0; display: grid;
              grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 12px; }
.promo-card { border: 1px solid var(--border); border-radius: var(--radius);
              overflow: hidden; background: var(--surface); cursor: grab; }
.promo-card.is-live { border-color: var(--accent); }
.promo-card.is-drag { opacity: .45; }
/* 비율은 고객 메인 히어로와 같게 — 데스크톱 1440×435(실측). 16/7 이면 사진의 위아래가
   더 보여서 고객이 보는 크롭과 달랐다. 사진 배치(object-fit: cover, 가운데)도 같다. */
.promo-thumb { position: relative; aspect-ratio: 1440 / 435; background: var(--surface-strong);
               display: flex; align-items: center; justify-content: center; overflow: hidden; }
.promo-thumb img { width: 100%; height: 100%; object-fit: cover; }
.promo-thumb.is-popup { aspect-ratio: 4 / 3; }
.promo-noimg { color: var(--text-subtle); font-size: var(--fs-8); padding: 8px; text-align: center; }
.promo-veil { position: absolute; inset: 0; background: #0B1B2B; }
.promo-text { position: absolute; inset: 0; padding: 10px 12px; color: #fff;
              display: flex; flex-direction: column; justify-content: center; gap: 2px; }
.promo-thumb.is-center .promo-text { text-align: center; }
.promo-thumb.is-right .promo-text { text-align: right; }
.promo-text em { font-style: normal; font-size: var(--fs-9); opacity: .8; }
.promo-text b { font-size: var(--fs-5); line-height: 1.25; }
.promo-text i { font-style: normal; font-size: var(--fs-9); opacity: .9;
                border: 1px solid rgba(255,255,255,.6); border-radius: 3px;
                padding: 1px 6px; align-self: flex-start; margin-top: 4px; }
.promo-thumb.is-center .promo-text i { align-self: center; }
.promo-thumb.is-right .promo-text i { align-self: flex-end; }
.promo-meta { padding: 10px 12px; display: flex; flex-direction: column; gap: 4px; }
.promo-meta b { font-size: var(--fs-7); }
.promo-badge { align-self: flex-start; font-size: var(--fs-9); padding: 1px 8px;
               border-radius: 10px; }
.promo-badge.ok { background: var(--accent-soft); color: var(--accent); }
.promo-badge.off { background: var(--surface-strong); color: var(--text-subtle); }

.promo-editor { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 420px), 1fr));
                gap: 20px; align-items: start; }
.promo-editor .form-grid { grid-template-columns: max-content minmax(0, 1fr); }
.promo-editor .form-grid > * { min-width: 0; }
.promo-editor input[type="file"] { max-width: 100%; box-sizing: border-box; }
.promo-editor small[role="status"] { display: block; overflow-wrap: anywhere; }
.promo-preview { position: sticky; top: 76px; align-self: start; }
.promo-preview-head { display: flex; align-items: center; justify-content: space-between;
                      margin-bottom: 6px; font-size: var(--fs-7); font-weight: 600; }
.promo-vp { display: flex; gap: 4px; }
.promo-vp .is-on { background: var(--accent); border-color: var(--accent);
                   color: var(--on-accent); }
.promo-stage { position: relative; overflow: hidden; border-radius: var(--radius);
               border: 1px solid var(--border); background: var(--shop-navy-deep, #16283C);
               aspect-ratio: 1440 / 435; transition: max-width .2s ease; }  /* 고객 히어로 실측 비율 */
.promo-stage.is-mo { max-width: 240px; aspect-ratio: 390 / 380; margin: 0 auto; }  /* 폰 390×380 실측 */
.promo-stage-bg { position: absolute; inset: 0; background-size: cover;
                  background-position: center; }
.promo-stage-veil { position: absolute; inset: 0; background: #0B1B2B; opacity: .35; }
.promo-stage-body { position: absolute; inset: 0; padding: 18px 20px; color: #fff;
                    display: flex; flex-direction: column; justify-content: center; gap: 4px; }
.promo-stage-body.is-center { text-align: center; align-items: center; }
.promo-stage-body.is-right { text-align: right; align-items: flex-end; }
.pv-eyebrow { margin: 0; font-size: var(--fs-9); opacity: .82; }
.promo-stage-body h2 { margin: 0; font-size: var(--fs-2); line-height: 1.2;
                       text-shadow: 0 2px 10px rgba(0,0,0,.35); }
.pv-sub { margin: 0; font-size: var(--fs-8); opacity: .85; line-height: 1.6; }
.pv-cta { margin-top: 6px; background: var(--accent); color: var(--on-accent);
          padding: 5px 12px; border-radius: var(--radius-sm); font-size: var(--fs-8); }

/* 카테고리 대표사진 — 목록 안이라 작게. 없으면 "자동" 이라고 알린다. */
.cat-img-cell { white-space: nowrap; }
.cat-img { display: inline-flex; align-items: center; justify-content: center;
           width: 46px; height: 46px; border-radius: var(--radius-sm);
           border: 1px solid var(--border); object-fit: cover; background: var(--surface-strong);
           vertical-align: middle; }
.cat-img.is-auto { font-size: var(--fs-9); color: var(--text-muted); }
.cat-img-form { display: inline-flex; align-items: center; gap: 4px; margin-left: 6px; }
.cat-img-form input[type=file] { max-width: 180px; padding: 4px; }

/* 자동 넘김 간격 — 목록 위에 한 줄로 앉힌다(설정이 하나뿐이라 카드를 따로 안 만든다). */
.promo-autoplay { display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
                  margin: 0 0 14px; padding: 10px 12px; border: 1px solid var(--border);
                  border-radius: var(--radius); background: var(--surface-strong); }
.promo-autoplay label { font-weight: 600; font-size: var(--fs-8); }

/* 무대에서 전환 효과를 그대로 돌려 본다 (`is-play` 를 붙였다 뗀다).
   고객 화면과 **같은 이름·같은 곡선**을 쓴다 — 여기서 본 것과 실제가 다르면
   미리보기가 아니라 다른 화면이다. */
@keyframes pvSlide { from { transform: translateX(9%); } to { transform: none; } }
@keyframes pvKen   { from { transform: scale(1); } to { transform: scale(1.12); } }
@keyframes pvFocus { from { filter: blur(12px); transform: scale(1.06); }
                     to   { filter: blur(0); transform: none; } }
@keyframes pvRise  { from { opacity: 0; transform: translateY(12px); }
                     to   { opacity: 1; transform: none; } }
@keyframes pvFade  { from { opacity: 0; } to { opacity: 1; } }

.promo-stage.is-play.fx-fade  .promo-stage-bg { animation: pvFade .6s ease both; }
.promo-stage.is-play.fx-slide .promo-stage-bg {
  animation: pvSlide .85s cubic-bezier(.16, .84, .28, 1) both; }
.promo-stage.is-play.fx-zoom  .promo-stage-bg {
  animation: pvKen 11s cubic-bezier(.33, 0, .67, 1) both; }
.promo-stage.is-play.fx-blur  .promo-stage-bg {
  animation: pvFocus 1s cubic-bezier(.16, .84, .28, 1) both; }

.promo-stage.is-play .promo-stage-body > * {
  animation: pvRise .62s cubic-bezier(.16, .84, .28, 1) both; }
.promo-stage.is-play .promo-stage-body > *:nth-child(1) { animation-delay: .10s; }
.promo-stage.is-play .promo-stage-body > *:nth-child(2) { animation-delay: .18s; }
.promo-stage.is-play .promo-stage-body > *:nth-child(3) { animation-delay: .26s; }
.promo-stage.is-play .promo-stage-body > *:nth-child(4) { animation-delay: .34s; }

@media (prefers-reduced-motion: reduce) {
  .promo-stage.is-play .promo-stage-bg,
  .promo-stage.is-play .promo-stage-body > * { animation: none !important; }
}

/* 팝업 미리보기 — 실제 위치대로 무대 안에 놓는다. */
.promo-stage-popup { background: var(--surface-strong); aspect-ratio: 16 / 10; }
.promo-popup-mock { position: absolute; background: var(--surface);
                    border: 1px solid var(--border); border-radius: var(--radius);
                    box-shadow: 0 8px 24px rgba(0,0,0,.2); overflow: hidden;
                    font-size: var(--fs-9); }
.promo-popup-mock.is-center { top: 50%; left: 50%; transform: translate(-50%, -50%); }
.promo-popup-mock.is-left-bottom { left: 10px; bottom: 10px; }
.promo-popup-mock.is-right-bottom { right: 10px; bottom: 10px; }
.pv-pop-title { padding: 6px 8px; font-weight: 700; border-bottom: 1px solid var(--border); }
.pv-pop-img { height: 70px; background-size: cover; background-position: center; }
.pv-pop-body { padding: 6px 8px; color: var(--text-muted); white-space: pre-wrap; }
.pv-pop-foot { display: flex; justify-content: space-between; padding: 5px 8px;
               background: var(--surface-strong); color: var(--text-subtle); }

@media (max-width: 1100px) {
  .promo-editor { grid-template-columns: 1fr; }
  .promo-preview { position: static; }
}

/* --- Responsive --- */
/* 쉘(사이드바·상단바·레일)의 반응형은 `shell-overrides.css` 에 있다.
   여기에는 **본문 안쪽**만 둔다. */
@media (max-width: 880px) {
  .card { padding: 12px 14px; }
  .stat-grid { grid-template-columns: repeat(2, 1fr); }
}

/* --- A11y --- */
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) {
  * { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}

/* ─────────────────────────────────────────────────────────────
 * KGI Store 추가 — 어드민 페이지/테이블 유틸 (토큰만 사용, raw hex 금지)
 * ───────────────────────────────────────────────────────────── */

/* 레이아웃 폭 — 한 곳에서 정한다. 화면마다 다른 값을 박으면 어느 화면이
   왜 좁은지 추적할 수 없다. `scripts/probe_responsive.py` 가 지킨다. */
:root {
  /* 글자 크기 9단. 예전엔 11·12·12.5·13·13.5·14·15·16·17·20·22 **열한 가지**를
     쓰고 있었다 — 반계단(12.5·13.5)이 섞인 건 스케일이 아니라 임기응변이고,
     그래서 "제목인지 본문인지" 가 눈에 안 들어왔다.
     허브 쉘(OmniFlow-Hub/src/hub/shell.py)과 같은 9단으로 맞춘다. */
  --fs-1: 22px;   /* 페이지 제목 · 큰 숫자 */
  --fs-2: 20px;   /* 예비(더 큰 제목이 필요할 때) */
  --fs-3: 18px;   /* 섹션 제목 */
  --fs-4: 17px;   /* 브랜드 */
  --fs-5: 16px;   /* 카드 제목 */
  --fs-6: 14px;   /* 본문 · 메뉴 · 버튼 */
  --fs-7: 13px;   /* 표 · 보조 설명 */
  --fs-8: 12px;   /* 메타 · 작은 버튼 */
  --fs-9: 11px;   /* 라벨 · 캡션 */

  --page-max: 1920px;   /* 어드민 본문 상한 — 표 중심이라 넓을수록 이득 */
  --page-pad: 24px;
  --read-max: 900px;    /* 읽는 글(문단·안내문)의 상한 — 한 줄이 길면 못 읽는다 */
  --kv-max:   1200px;   /* 키-값 표 — 라벨과 값이 멀어지면 짝을 못 찾는다 */
}

/* `margin: 0 auto` 가 없어서 와이드 모니터에서 본문이 **왼쪽에 붙어** 있었다.
   2560px 에서 오른쪽 1,024px 가 통째로 비었다(2026-09-04 실측). */
.page { padding: 20px var(--page-pad); max-width: var(--page-max); margin: 0 auto; }
/* 페이지 제목이 카드 제목(15px)과 5px 차이라 위계가 약했다. 22 로 올린다. */
.page-title { margin: 0 0 4px; font-size: var(--fs-1); font-weight: 700;
              letter-spacing: -0.015em; line-height: 1.3; }
/* 본문 상한을 1,920 으로 넓히면서 생긴 대가 — 안내 문단이 한 줄로 1,900px 를
   가로지르면 눈이 다음 줄을 못 찾는다. **읽는 글만** 따로 좁힌다.
   표·카드는 넓을수록 이득이므로 건드리지 않는다. */
.page-sub { margin: 0 0 20px; color: var(--text-muted); font-size: var(--fs-7);
            max-width: var(--read-max); }
.card > p.text-muted, .card > .page-sub { max-width: var(--read-max); }

/* 표 생김새도 `hub-components.css`. 여기엔 우리만의 것만. */
/* **키-값 표는 넓히면 안 된다.** 머리글 줄(thead)이 없고 `th` 가 각 줄 왼쪽에
   오는 표는 "상품명 ─ 값 ─ 별칭 ─ 값" 짝이므로, 1,878px 로 늘리면 라벨과 값이
   700px 떨어져 눈이 짝을 못 찾는다(본문 상한을 1,920 으로 넓히며 실제로 그랬다).
   thead 가 있는 **데이터 표는 넓을수록 이득**이라 건드리지 않는다. */
.tbl:not(:has(thead)) { max-width: var(--kv-max); }
/* 머리글이 데이터와 같은 크기면 표 안에서 구분이 안 된다 — 허브도 한 단 낮춘다
   (`--text-caption-size` 12px). 자간만 우리 것을 더한다. */
.tbl thead th { letter-spacing: 0.02em; }
.tbl .num { text-align: right; font-family: var(--font-mono); }

.ok { color: var(--ok); }
.err { color: var(--danger); }
/* 토큰(--warn)은 있었는데 쓰는 클래스가 없어, warn 을 붙여도 색이 안 나왔다 */
.warn { color: var(--warn); }
code { font-family: var(--font-mono); font-size: var(--fs-8); color: var(--text-muted); }

/* 상품 이미지 관리 */
.admin-imgs { display: flex; flex-wrap: wrap; gap: 14px; margin-bottom: 16px; }
.admin-imgs figure { width: 150px; margin: 0; padding: 8px; border: 1px solid var(--border);
                     border-radius: var(--radius); }
.admin-imgs figure.is-main { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-soft); }
.admin-imgs img { width: 100%; height: 110px; object-fit: contain; background: var(--surface-strong);
                  border-radius: var(--radius-sm); }
.admin-imgs figcaption { display: flex; justify-content: space-between; align-items: center;
                         margin-top: 6px; font-size: var(--fs-9); }
.admin-imgs figcaption b { color: var(--accent); }
.admin-img-actions { display: flex; gap: 4px; margin-top: 6px; }
.admin-img-actions form { flex: 1; }
.admin-img-actions button { width: 100%; }
textarea.text-input { width: 100%; font-family: var(--font); resize: vertical; }
.admin-post-body { padding: 14px 16px; background: var(--surface-strong); border-radius: var(--radius);
                   white-space: pre-wrap; line-height: 1.7; font-size: var(--fs-7); }

/* 가격 — 등급표는 열이 20개라 가로 스크롤이 필요하다 */
.tbl-scroll { overflow-x: auto; }
.tbl-scroll .tbl { min-width: 1400px; }
/* STD 열 강조 — 존재하지 않는 토큰(--surface-2)에 라이트 색을 폴백으로 박아 두었더니
   다크모드에서 흰 배경 + 흰 글자가 됐다. 실제 토큰을 쓴다. */
.grade-std { background: var(--surface-strong); font-weight: 600; }

/* 주문 — 필터가 많아 레이블이 세로로 쪼개진다 */
/* 시안 15: 상태 탭 + 건수. 탭 줄 안에서만 가로로 밀린다. */
.order-tabs { display: flex; flex-wrap: wrap; gap: 2px; min-width: 0; overflow-x: auto;
              border-bottom: 1px solid var(--border); }
.order-tabs a { flex: none; padding: 9px 14px; white-space: nowrap; font-size: var(--fs-7);
                color: var(--text-muted); text-decoration: none;
                border-bottom: 2px solid transparent; }
.order-tabs a b { font-weight: 700; }
.order-tabs a:hover { color: var(--text); }
.order-tabs a.is-on { color: var(--brand, #1b3a6b); font-weight: 700;
                      border-bottom-color: currentColor; }
.order-tabs a.is-warn b { color: #c0392b; }
.quick-range { display: inline-flex; gap: 4px; }
.quick-range .btn-quiet { padding: 6px 10px; font-size: var(--fs-8); cursor: pointer;
                          border: 1px solid var(--border); border-radius: 6px;
                          background: var(--surface); color: var(--text-muted); }
.quick-range .btn-quiet:hover { border-color: var(--brand, #1b3a6b);
                                color: var(--brand, #1b3a6b); }
[data-page="admin-order-detail"] .tbl .form-row { flex-wrap: nowrap; }
[data-page="admin-order-detail"] .form-row .btn { white-space: nowrap; }

/* 좁은 화면에서 넓은 표 — 카드마다 따로 가로 스크롤한다.
   이 규칙이 없으면 main 전체가 밀려서 검색 필터·제목까지 같이 사라진다.
   (2026-08-26 UI 재점검: 모바일에서 어드민 표 7개가 그 상태였다) */
@media (max-width: 900px) {
  .page .card { overflow-x: auto; }
}

/* 버튼·레이블·표 머리글은 줄바꿈하지 않는다.
   좁은 화면에서 "검 색" 처럼 글자가 갈라지던 것을 페이지마다 막다가 한 곳으로 모았다. */
.page .btn,
.page .form-row > label,
.page .form-row > span,
.page .tbl th { white-space: nowrap; }
[data-page="admin-prices"] .tbl td { white-space: nowrap; }

/* 재고 수량 범위 입력 — 나란히 두 칸이라 좁게 (시안 11) */
.qty-range { width: 90px; }

/* 상품 편집 탭 (시안 백엔드 1) — 섹션이 일곱이라 한 화면에 다 펴면 너무 길다 */
.edit-tabs { display: flex; flex-wrap: wrap; gap: 2px; min-width: 0; overflow-x: auto;
             margin: 0 0 16px; border-bottom: 1px solid var(--border); }
.edit-tabs button { flex: none; padding: 9px 14px; white-space: nowrap; cursor: pointer;
                    border: 0; border-bottom: 2px solid transparent; background: none;
                    color: var(--text-muted); font: inherit; font-size: var(--fs-7); }
.edit-tabs button:hover { color: var(--text); }
.edit-tabs button.is-on { color: var(--brand, #1b3a6b); font-weight: 700;
                          border-bottom-color: currentColor; }
/* 마크업에는 hidden 을 넣지 않는다 — JS 가 죽으면 일곱 섹션이 전부 감춰져
   화면이 통째로 비어 버린다. 감추는 일은 JS 가 하고, JS 가 없으면 다 보인다. */

/* 줄 끝에 몰린 짧은 링크가 폭이 모자라 **한 글자씩 세로로** 쪼개지는 일이 있었다.
   가로 밀림이 아니라 감사가 못 잡는다 — 줄바꿈 자체를 막는다. */
.nowrap { white-space: nowrap; }

/* 기준가 대비 표시 (시안 29) — 인상은 붉게, 인하는 푸르게 */
.pct-up { color: #c0392b; }
.pct-down { color: #1f6feb; }

/* 연령표 합계 줄 (시안 35) */
.row-total td { border-top: 2px solid var(--border-strong, var(--border)); font-weight: 700; }

/* ── 상품 한 화면 편집기 (2026-09-17) ────────────────────────────────
   탭 대신 한 화면: 왼쪽(기본정보·옵션) / 오른쪽(상품그룹·이미지), 아래는 접힌 부가 영역. */
.pe-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; flex-wrap: wrap; }
.pe-badges { display: flex; gap: 6px; flex-wrap: wrap; padding-top: 6px; }
.pe-badge { font-size: var(--fs-8); padding: 3px 9px; border-radius: 999px;
            background: var(--surface-strong); color: var(--text-muted); }
.pe-badge.ok { background: var(--accent-soft); color: var(--accent); }
.pe-badge.off { background: var(--surface-strong); color: var(--text-subtle); }
.pe-grid { display: grid; grid-template-columns: minmax(0, 3fr) minmax(280px, 2fr); gap: 16px; align-items: start; }
.pe-main, .pe-side { display: grid; gap: 16px; min-width: 0; }
.pe-form { display: grid; gap: 12px; }
.pe-form label { display: grid; gap: 4px; font-size: var(--fs-7); color: var(--text-muted); min-width: 0; }
.pe-form label small { font-weight: 400; }
.pe-form .text-input { width: 100%; }
.pe-form .checkbox { display: flex; align-items: center; gap: 6px; min-height: 36px; color: var(--text); }
.pe-row2 { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.pe-row3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
.pe-actions { align-items: end; }
.pe-submit { display: flex; align-items: end; justify-content: flex-end; }
.pe-opt .text-input { width: 100%; }
.pe-opt-btns { display: flex; gap: 4px; align-items: center; white-space: nowrap; }
.pe-opt-btns form { display: inline; }
.pe-opt-new td { background: var(--accent-soft); }
.pe-more { margin-top: 0; }
.pe-more > summary { cursor: pointer; font-weight: 700; padding: 4px 0; }
.pe-more[open] > summary { margin-bottom: 10px; }
#pe-group-values { display: grid; gap: 8px; }
#pe-group-values label { display: grid; gap: 4px; font-size: var(--fs-7); color: var(--text-muted); }
#pe-group-new { display: grid; gap: 8px; }
.pe-img-main { position: relative; aspect-ratio: 1 / 1; border: 1px solid var(--border);
               border-radius: var(--radius); overflow: hidden; background: var(--surface-strong);
               display: flex; align-items: center; justify-content: center; }
.pe-img-main img { width: 100%; height: 100%; object-fit: contain; }
.pe-img-empty { text-align: center; color: var(--text-subtle); font-size: var(--fs-7); line-height: 1.5; }
.pe-img-tag { position: absolute; left: 8px; top: 8px; font-size: var(--fs-8); padding: 2px 8px;
              border-radius: 999px; background: var(--accent); color: #fff; }
.pe-upload { margin: 8px 0 14px; }
.pe-upload label { cursor: pointer; }
.pe-img-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); gap: 8px; margin-bottom: 10px; }
.pe-img-grid figure { margin: 0; border: 1px solid var(--border); border-radius: var(--radius-sm, 6px);
                      overflow: hidden; background: var(--surface-strong); }
.pe-img-grid img { width: 100%; aspect-ratio: 1 / 1; object-fit: contain; display: block; }
.pe-img-actions { display: flex; gap: 2px; padding: 4px; justify-content: center; }
.pe-img-actions form { display: inline; }
.pe-img-add label { display: flex; flex-direction: column; align-items: center; justify-content: center;
                    aspect-ratio: 1 / 1; border: 1px dashed var(--border-strong); border-radius: var(--radius-sm, 6px);
                    cursor: pointer; color: var(--text-muted); font-size: var(--fs-7); text-align: center; }
.pe-img-add label:hover { border-color: var(--accent); color: var(--accent); }
@media (max-width: 960px) {
  .pe-grid { grid-template-columns: 1fr; }
  .pe-row3 { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 640px) {
  .pe-row2, .pe-row3 { grid-template-columns: 1fr; }
}

/* ── 상품 등록 화면 (2026-09-18, 시안 docs/itemregister.png) ──────────────
   번호 붙은 카드 4개(기본정보 · 이미지 · 카테고리/그룹 · 옵션 · 추가정보),
   오른쪽 위 [목록으로] [저장하기]. 위쪽 규칙(2026-09-17)에 덧붙인다. */
.pe-head { flex-wrap: nowrap; margin-bottom: 16px; }
.pe-head-title { flex: 1 1 auto; min-width: 0; }
.pe-crumb { margin: 0 0 2px; font-size: var(--fs-8); color: var(--text-muted); }
.pe-crumb a { color: var(--text-muted); }
.pe-crumb span { margin: 0 4px; }
.pe-head .page-sub { margin-bottom: 8px; }
.pe-head-actions { display: flex; flex: 0 0 auto; align-items: center; gap: 8px;
                   margin-left: auto; padding-top: 4px; white-space: nowrap; }
/* `#pe-group-new { display: grid }` 가 [hidden] 을 이겨서 새 그룹 칸이 늘 펼쳐져 있었다 */
#pe-group-new[hidden] { display: none; }
/* 카드 제목 앞 번호 — 어디부터 채우면 되는지 눈으로 따라가게 */
.pe-step { display: inline-flex; align-items: center; justify-content: center;
           width: 22px; height: 22px; margin-right: 6px; border-radius: 999px;
           background: var(--accent); color: #fff; font-size: var(--fs-8); font-weight: 700; }
.pe-req { display: inline-block; padding: 1px 7px; border-radius: var(--radius-sm);
          background: var(--danger); color: #fff; font-size: var(--fs-9); font-weight: 700;
          vertical-align: 2px; }
/* 전체 폭 카드(옵션·추가정보)와 접힌 카드가 서로 붙어 있었다 */
.pe > .card { margin-top: 16px; }
.pe-sec-head { display: flex; align-items: baseline; justify-content: space-between;
               gap: 12px; flex-wrap: wrap; margin-bottom: 10px; }
.pe-sec-head .card-title { margin-bottom: 0; }

/* 라디오는 한 줄로 — `.pe-form label` 의 grid 를 덮는다 */
.pe-radios { display: flex; flex-wrap: wrap; gap: 14px; align-items: center; min-height: 36px; }
.pe-form .pe-radio { display: inline-flex; align-items: center; gap: 5px;
                     color: var(--text); font-size: var(--fs-7); }
.pe-form .pe-radio input { accent-color: var(--accent); }
/* 마스터 소유 값(상품명·코드·단가·재고)은 못 고친다는 걸 색으로 */
.pe-form .text-input[readonly] { background: var(--surface-strong); color: var(--text-muted); }
.pe-count { display: block; text-align: right; font-size: var(--fs-8); color: var(--text-subtle); }
.pe-lbl-quiet { color: var(--text-muted); }
.pe-cat { margin-bottom: 14px; padding-bottom: 14px; border-bottom: 1px solid var(--border); }
.pe-group-pick { display: flex; align-items: center; gap: 6px; }
.pe-group-pick select { min-width: 0; }

/* 이미지: 대표 미리보기 + 올리는 자리를 나란히 */
.pe-img-row { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; align-items: start; }
.pe-img-cell { min-width: 0; }
.pe-img-cap { margin: 6px 0 0; text-align: center; font-size: var(--fs-8); color: var(--text-muted); }
.pe-drop label { display: flex; flex-direction: column; align-items: center; justify-content: center;
                 gap: 4px; aspect-ratio: 1 / 1; padding: 8px; text-align: center; cursor: pointer;
                 border: 1px dashed var(--border-strong); border-radius: var(--radius);
                 color: var(--text-muted); font-size: var(--fs-8); }
.pe-drop label:hover { border-color: var(--accent); color: var(--accent); background: var(--accent-soft); }
.pe-drop label b { font-size: var(--fs-7); color: var(--text); }
.pe-drop label:hover b { color: var(--accent); }
.pe-drop-ico { font-size: var(--fs-1); line-height: 1; }
.pe-sub-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.pe-sub-head h3.card-sub { margin-bottom: 8px; }
.pe-sub-head .pe-count { text-align: right; }
/* 사진 모서리 ⓧ 로 지운다 (시안) */
.pe-img-grid figure { position: relative; }
.pe-thumb-x { position: absolute; right: 4px; top: 4px; z-index: 1; }
.pe-thumb-x button { width: 20px; height: 20px; padding: 0; line-height: 1; cursor: pointer;
                     border: 1px solid var(--border); border-radius: 999px;
                     background: var(--surface); color: var(--text-muted); }
.pe-thumb-x button:hover { background: var(--danger); border-color: var(--danger); color: #fff; }

/* 옵션값을 적으면 고객이 보는 모양으로 옆에 그려 준다 */
.pe-preview { line-height: 1.9; }
.pe-chip { display: inline-block; margin: 0 4px 2px 0; padding: 2px 8px; border-radius: 999px;
           background: var(--surface-strong); color: var(--text); font-size: var(--fs-8); }
@media (max-width: 640px) {
  .pe-img-row { grid-template-columns: 1fr; }
  .pe-head { flex-wrap: wrap; }
  .pe-head-actions { width: 100%; }
}

/* 이카운트에서 자동으로 오는 값 안내 (상품 등록 화면, 2026-09-18) */
.pe-erp { margin: 4px 0 0; padding: 10px 12px; border-radius: var(--radius-sm);
          background: var(--surface-strong); color: var(--text-muted); font-size: var(--fs-8);
          line-height: 1.7; }
.pe-erp b { color: var(--text); }
.pe-erp-when { display: inline-block; margin-right: 6px; }

/* Unified editor: stable local drafts, responsive direct-input options. */
.pe [hidden] { display: none !important; }
.pe-save-status { padding: 10px 14px; border: 1px solid var(--border); border-radius: 8px;
  background: var(--surface); color: var(--text-muted); margin: 0 0 16px; }
.pe-save-status.err { color: var(--danger); border-color: var(--danger); }
.pe-opt-scroll { overflow-x: auto; margin-bottom: 12px; }
.pe-opt { min-width: 640px; width: 100%; }
.pe-opt td:nth-child(1) { width: 20%; }
.pe-opt td:nth-child(2) { width: 32%; }
.pe-opt td:nth-child(3) { width: 28%; white-space: normal; }
.pe-opt .text-input { width: 100%; min-width: 0; }
.pe-opt textarea { resize: vertical; }
.pe-img-main { position: relative; }
.pe #pe-images > .pe-img-add label { aspect-ratio: auto; min-height: 72px; padding: 12px; gap: 4px; }
.pe-drop label:focus-visible, .pe-img-add label:focus-visible { outline: 2px solid var(--accent); }
#pe-group-edit { padding: 8px 0; }
#pe-group-edit label { margin-top: 8px; }
.pe-head-actions { flex-wrap: wrap; }
@media (max-width: 640px) {
  .pe-group-pick { flex-wrap: wrap; }
  .pe-group-pick select { width: 100%; }
  .pe-opt { min-width: 0; }
  .pe-opt thead { display: none; }
  .pe-opt tbody, .pe-opt tr { display: block; }
  .pe-opt tr { padding: 10px 0; border-bottom: 1px solid var(--border); }
  .pe-opt td:nth-child(n) { display: block; width: 100%; border: 0; padding: 5px 0; }
  .pe-opt td:nth-child(1)::before { content: '옵션명'; display: block; margin-bottom: 4px; }
  .pe-opt td:nth-child(2)::before { content: '옵션값'; display: block; margin-bottom: 4px; }
  .pe-opt td:nth-child(4), .pe-opt td:nth-child(5), .pe-opt td:nth-child(6) { display: inline-block; width: auto; margin-right: 14px; }
  .pe-opt td:nth-child(4)::after { content: ' 필수'; }
  .pe-opt td:nth-child(5)::after { content: ' 사용'; }
}
