8125a59366
- 옵션 1개 상품은 한 행에 썸네일·옵션값 이름·품목코드(복사)·자체코드· 추가금액·진열·판매를 두고 「저장」 한 번으로 옵션 PUT → 품목 PUT. - 옵션 없는 상품: 행 추가/삭제 후 저장 → 옵션 생성 → 카페24가 부여한 품목코드를 재시도 조회(products.wait_for_variants)로 받아 자체코드· 추가금액·썸네일까지 이어서 반영. - 순서 드래그는 품목 display_order 로 저장(옵션값 재배열 PUT 은 위치 짝맞춤 때문에 품목코드↔이름이 뒤바뀔 수 있어 사용하지 않음). - 「옵션값 불러오기」: 탭/공백 구분 텍스트(이름·판매가·추가금액·자체코드) 붙여넣기 → 행 자동 채움. 기존 옵션은 이름으로 짝지어 코드/금액만. - 옵션 2개 이상(조합) 상품은 기존 2열 화면 유지. - 모달 JS 를 app/static/cafe24-options.js 로 분리. 유닛테스트 90 통과, 통합 하네스 통과, 헤드리스 크롬 렌더 확인. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
1470 lines
37 KiB
CSS
1470 lines
37 KiB
CSS
/* 카페24 상품관리 모듈 전용 스타일.
|
|
전역(erp.css) 은 건드리지 않는다. 클래스 접두사: cf24-
|
|
색상은 erp.css 의 :root 토큰을 재사용한다. */
|
|
|
|
/* .erp-page 는 flex column + overflow-y:auto 다. 자식의 flex-shrink 기본값이
|
|
1 이라 내용이 화면보다 길면 카드가 눌려 잘리고(스크롤도 안 생긴다),
|
|
시스템 화면의 [카페24 연결] 버튼처럼 카드 아래쪽이 사라진다.
|
|
축소를 막아 넘친 만큼 .erp-page 가 스크롤하게 한다.
|
|
이 파일은 카페24 템플릿에서만 로드되므로 다른 모듈에는 영향이 없다. */
|
|
.erp-page > * {
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
/* 분할 화면은 편집 영역을 최대한 넓게 쓴다 — 이 페이지에서만 폭 제한을 푼다.
|
|
box-sizing 을 함께 바꿔야 한다: .erp-page 는 width:100% + padding:24px 라서
|
|
max-width 를 풀면 padding 이 폭에 더해져 문서 전체에 가로 스크롤이 생긴다. */
|
|
.erp-page {
|
|
max-width: none;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.cf24-card {
|
|
margin-bottom: var(--sp-16, 16px);
|
|
}
|
|
|
|
/* ════════════════════════════════════════════════════════════
|
|
좌우 분할: 왼쪽 목록(좁게) | 가운데 상세페이지 편집(넓게) | 오른쪽 정보 패널
|
|
(.cf24-split-3 — 아래 3분할 절). 각 칸이 따로 스크롤되고, 전체 높이는 화면에 맞춘다.
|
|
════════════════════════════════════════════════════════════ */
|
|
.cf24-split {
|
|
display: grid;
|
|
grid-template-columns: 550px minmax(0, 1fr);
|
|
gap: var(--sp-12, 12px);
|
|
align-items: stretch;
|
|
}
|
|
|
|
/* .erp-page 는 flex column 이다. 위 flex-shrink:0 규칙의 예외로, 분할 영역만은
|
|
남은 높이를 모두 차지하고 안에서 스크롤되게 한다(휴가/쿠팡 모듈과 같은 방식). */
|
|
.erp-page > .cf24-split {
|
|
flex: 1 1 auto;
|
|
min-height: 0;
|
|
}
|
|
|
|
.cf24-pane {
|
|
min-height: 0;
|
|
overflow: auto;
|
|
margin-bottom: 0;
|
|
padding: var(--sp-12, 12px);
|
|
}
|
|
|
|
.cf24-pane-list {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--sp-8, 8px);
|
|
overflow: hidden; /* 표만 스크롤 — 검색/필터는 고정 */
|
|
}
|
|
|
|
.cf24-pane-editor {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--sp-8, 8px);
|
|
padding: var(--sp-16, 16px);
|
|
}
|
|
|
|
@media (max-width: 1100px) {
|
|
.cf24-split {
|
|
grid-template-columns: minmax(0, 1fr);
|
|
}
|
|
.cf24-pane {
|
|
overflow: visible;
|
|
}
|
|
.cf24-pane-list {
|
|
max-height: 45vh;
|
|
}
|
|
}
|
|
|
|
/* ── 왼쪽: 검색·필터 ── */
|
|
.cf24-filters {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--sp-8, 8px);
|
|
flex: 0 0 auto;
|
|
}
|
|
|
|
.cf24-checks {
|
|
display: flex;
|
|
gap: var(--sp-12, 12px);
|
|
font-size: var(--text-caption, 12px);
|
|
}
|
|
|
|
.cf24-checks label {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 4px;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.cf24-list-count {
|
|
font-size: var(--text-caption, 12px);
|
|
color: var(--color-midtone-gray, #737373);
|
|
}
|
|
|
|
/* ── 왼쪽: 목록 표 (좁게) ── */
|
|
.cf24-list-scroll {
|
|
flex: 1 1 auto;
|
|
min-height: 0;
|
|
overflow-y: auto;
|
|
}
|
|
|
|
.cf24-list-table {
|
|
font-size: 12px;
|
|
table-layout: fixed;
|
|
width: 100%;
|
|
}
|
|
|
|
.cf24-list-table thead th {
|
|
position: sticky;
|
|
top: 0;
|
|
z-index: 1;
|
|
padding: 6px 4px;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.cf24-list-table tbody td {
|
|
padding: 6px 4px;
|
|
vertical-align: top;
|
|
}
|
|
|
|
/* 목록 폭 550px 기준. 고정폭을 뺀 나머지(약 290px)가 상품명 몫이다.
|
|
진열/판매 칸은 제목(2글자) + 정렬 화살표가 들어갈 만큼만. */
|
|
.cf24-col-no { width: 40px; text-align: right; color: var(--color-midtone-gray, #737373); }
|
|
.cf24-col-flag { width: 40px; text-align: center; }
|
|
.cf24-col-date { width: 78px; white-space: nowrap; color: var(--color-midtone-gray, #737373); }
|
|
.cf24-col-name { word-break: break-word; }
|
|
|
|
/* 긴 상품명은 2줄까지만 — 행 높이를 고르게 유지해 목록을 훑기 쉽게 한다.
|
|
전체 이름은 title 툴팁과 편집기 제목에서 확인한다. */
|
|
.cf24-col-name a {
|
|
color: inherit;
|
|
text-decoration: none;
|
|
display: -webkit-box;
|
|
-webkit-line-clamp: 2;
|
|
-webkit-box-orient: vertical;
|
|
overflow: hidden;
|
|
line-height: 1.4;
|
|
}
|
|
|
|
.cf24-row {
|
|
cursor: pointer;
|
|
}
|
|
|
|
.cf24-row:hover {
|
|
background: var(--color-ghost-gray, #f2f2f2);
|
|
}
|
|
|
|
.cf24-row.is-active {
|
|
background: var(--color-rich-black, #0a0a0a);
|
|
}
|
|
|
|
/* 선택된 행은 마우스를 올려도 그대로 둔다. erp-shell.css 의
|
|
`.erp-table tbody tr:hover` 가 특이도가 더 높아 검은 배경을 덮어쓰므로
|
|
여기서 더 구체적인 선택자로 되돌린다. */
|
|
.cf24-list-table tbody tr.cf24-row.is-active:hover {
|
|
background: var(--color-rich-black, #0a0a0a);
|
|
}
|
|
|
|
.cf24-row.is-active td,
|
|
.cf24-row.is-active .cf24-col-name a {
|
|
color: #fff;
|
|
}
|
|
|
|
/* 진열/판매 표시는 좁은 칸이라 배지 대신 점으로 */
|
|
.cf24-dot {
|
|
display: inline-block;
|
|
width: 8px;
|
|
height: 8px;
|
|
border-radius: 50%;
|
|
background: var(--color-subtle-ash, #e5e5e5);
|
|
}
|
|
|
|
.cf24-dot-on {
|
|
background: var(--color-success-green, #10c22b);
|
|
}
|
|
|
|
/* 제목행 클릭 정렬 */
|
|
.cf24-sortable {
|
|
cursor: pointer;
|
|
user-select: none;
|
|
}
|
|
|
|
.cf24-sortable::after {
|
|
content: "↕";
|
|
opacity: 0.35;
|
|
margin-left: 2px;
|
|
}
|
|
|
|
.cf24-sortable.is-asc::after { content: "▲"; opacity: 1; }
|
|
.cf24-sortable.is-desc::after { content: "▼"; opacity: 1; }
|
|
|
|
/* ── 오른쪽: 편집기 ── */
|
|
.cf24-editor-head {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: flex-start;
|
|
gap: var(--sp-12, 12px);
|
|
flex: 0 0 auto;
|
|
}
|
|
|
|
.cf24-editor-title {
|
|
margin: 0;
|
|
font-size: var(--text-heading, 18px);
|
|
letter-spacing: -0.45px;
|
|
}
|
|
|
|
/* 상품명 수정 — 평소엔 제목, 연필을 누르면 입력칸으로 바뀐다 */
|
|
/* 입력칸이 남는 폭을 다 쓰게 한다(min-width:0 이 없으면 긴 이름이 배지를 밀어낸다) */
|
|
.cf24-name-box {
|
|
flex: 1 1 auto;
|
|
min-width: 0;
|
|
}
|
|
|
|
.cf24-name-box .is-hidden {
|
|
display: none;
|
|
}
|
|
|
|
.cf24-name-edit {
|
|
margin-left: var(--sp-6, 6px);
|
|
padding: 0 4px;
|
|
border: 0;
|
|
border-radius: var(--r-sm, 4px);
|
|
background: transparent;
|
|
color: var(--color-midtone-gray, #737373);
|
|
font-size: var(--text-body, 14px);
|
|
line-height: 1.4;
|
|
cursor: pointer;
|
|
vertical-align: middle;
|
|
}
|
|
|
|
.cf24-name-edit:hover {
|
|
background: var(--color-ghost-gray, #f2f2f2);
|
|
color: var(--color-rich-black, #0a0a0a);
|
|
}
|
|
|
|
.cf24-name-form {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--sp-6, 6px);
|
|
}
|
|
|
|
.cf24-name-input {
|
|
flex: 1 1 auto;
|
|
min-width: 200px;
|
|
padding: var(--sp-6, 6px) var(--sp-8, 8px);
|
|
border: 1px solid var(--color-subtle-ash, #e5e5e5);
|
|
border-radius: var(--r-md, 6px);
|
|
font-size: var(--text-heading, 18px);
|
|
letter-spacing: -0.45px;
|
|
}
|
|
|
|
.cf24-name-input:focus {
|
|
outline: none;
|
|
border-color: var(--color-rich-black, #0a0a0a);
|
|
}
|
|
|
|
.cf24-editor-sub {
|
|
margin: 4px 0 0;
|
|
font-size: var(--text-caption, 12px);
|
|
color: var(--color-midtone-gray, #737373);
|
|
}
|
|
|
|
.cf24-editor-badges {
|
|
display: flex;
|
|
gap: 4px;
|
|
flex: 0 0 auto;
|
|
}
|
|
|
|
/* 편집기 단축키 안내 — 옅은 파랑으로 본문과 구분한다 */
|
|
.cf24-shortcuts {
|
|
font-size: var(--text-caption, 12px);
|
|
color: #79a6dd;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
/* 편집 폼과 코드 칸은 **줄어들지 않는다.** 아래 「예약 적용」·「버전 이력」을 펼치면
|
|
코드 칸이 눌리는 대신 내용이 아래로 밀리고 오른쪽 칸(.cf24-pane-editor)이 스크롤된다.
|
|
flex: 1 1 auto 였을 때는 펼칠 때마다 편집기가 작아져 작업하던 위치를 잃었다. */
|
|
.cf24-editor-form {
|
|
display: flex;
|
|
flex-direction: column;
|
|
flex: 0 0 auto;
|
|
gap: var(--sp-8, 8px);
|
|
}
|
|
|
|
.cf24-editor-bar {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
gap: var(--sp-8, 8px);
|
|
flex-wrap: wrap;
|
|
flex: 0 0 auto;
|
|
}
|
|
|
|
.cf24-editor-bar-right {
|
|
display: flex;
|
|
gap: var(--sp-8, 8px);
|
|
align-items: center;
|
|
}
|
|
|
|
.cf24-check-inline {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 4px;
|
|
margin-left: var(--sp-12, 12px);
|
|
cursor: pointer;
|
|
color: var(--color-rich-black, #0a0a0a);
|
|
}
|
|
|
|
.cf24-memo {
|
|
width: 260px;
|
|
padding: 6px var(--sp-10, 10px);
|
|
border: 1px solid var(--color-subtle-ash, #e5e5e5);
|
|
border-radius: var(--r-lg, 10px);
|
|
font-size: 12px;
|
|
}
|
|
|
|
.cf24-html-main {
|
|
flex: 1 1 auto;
|
|
min-height: 340px;
|
|
}
|
|
|
|
/* ════════════════════════════════════════════════════════════
|
|
문법 강조 편집기
|
|
투명한 <textarea> 를 색칠된 <pre> 위에 정확히 겹쳐 놓는 방식이다.
|
|
두 요소의 폰트·줄높이·여백·줄바꿈 규칙이 **완전히 같아야** 글자가 어긋나지
|
|
않는다. 아래 두 선택자에 붙은 속성을 바꿀 때는 반드시 함께 바꿀 것.
|
|
외부 라이브러리를 쓰지 않는다(자체 호스팅 원칙 + CDN 의존 제거).
|
|
════════════════════════════════════════════════════════════ */
|
|
/* 스크롤은 **textarea 가** 담당하고, 색칠 층과 줄 번호가 transform 으로 따라간다.
|
|
폭·높이를 계산해 맞추는 방식은 flex 안에서 `width: max-content` 가 기대대로
|
|
동작하지 않아 실패했다 — 긴 줄이 있으면 textarea 만 내부 스크롤되고 색칠 층은
|
|
제자리에 남아, 커서 위치와 보이는 글자가 어긋났다(실측 706 vs 686).
|
|
스크롤 동기화 방식은 크기 계산이 아예 필요 없어 어긋날 여지가 없다. */
|
|
.cf24-code {
|
|
position: relative;
|
|
/* 화면 높이에 맞춰 크되(창 크기에 적응), 무엇을 펼쳐도 이 높이를 유지한다.
|
|
56vh 는 접힌 상태에서 「예약 적용」·「버전 이력」 요약줄까지 스크롤 없이
|
|
들어오는 값이다(실측: 62vh 는 51px 넘쳤고 56vh 는 0). */
|
|
flex: 0 0 auto;
|
|
height: 56vh;
|
|
min-height: 340px;
|
|
overflow: hidden;
|
|
border: 1px solid var(--color-subtle-ash, #e5e5e5);
|
|
border-radius: var(--r-lg, 10px);
|
|
background: var(--color-canvas-white, #fff);
|
|
}
|
|
|
|
/* 줄 번호 — 코드 영역 왼쪽에 고정된 별도 칸(가로 스크롤과 무관) */
|
|
.cf24-gutter {
|
|
position: absolute;
|
|
left: 0;
|
|
top: 0;
|
|
bottom: 0;
|
|
width: 42px;
|
|
overflow: hidden;
|
|
padding: var(--sp-12, 12px) var(--sp-8, 8px) 0 0;
|
|
text-align: right;
|
|
background: var(--color-ghost-gray, #f6f8fa);
|
|
border-right: 1px solid var(--color-subtle-ash, #e5e5e5);
|
|
color: #8c959f;
|
|
user-select: none;
|
|
white-space: pre;
|
|
}
|
|
|
|
.cf24-gutter-inner {
|
|
will-change: transform; /* 세로 스크롤을 따라 움직인다 */
|
|
}
|
|
|
|
.cf24-code-body {
|
|
position: absolute;
|
|
left: 43px; /* 줄 번호 칸 + 경계선 */
|
|
right: 0;
|
|
top: 0;
|
|
bottom: 0;
|
|
overflow: hidden;
|
|
}
|
|
|
|
/* 두 층의 글자가 정확히 겹치려면 아래 속성이 전부 같아야 한다.
|
|
줄 번호(.cf24-gutter)도 같은 글꼴 지표를 써야 줄이 맞는다. */
|
|
.cf24-gutter,
|
|
.cf24-code-hl,
|
|
.cf24-code-input {
|
|
margin: 0;
|
|
border: 0;
|
|
box-sizing: border-box;
|
|
font-family: var(--font-geist-mono, ui-monospace, "Consolas", monospace);
|
|
font-size: 12px;
|
|
line-height: 1.6;
|
|
tab-size: 2;
|
|
}
|
|
|
|
.cf24-code-hl,
|
|
.cf24-code-input {
|
|
padding: var(--sp-12, 12px);
|
|
white-space: pre; /* 줄바꿈하지 않는다 — 줄 번호가 어긋나지 않게 */
|
|
overflow-wrap: normal;
|
|
}
|
|
|
|
/* 색칠 층 — textarea 의 스크롤량만큼 transform 으로 이동한다. */
|
|
.cf24-code-hl {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
width: max-content;
|
|
min-width: 100%;
|
|
pointer-events: none;
|
|
color: var(--color-rich-black, #0a0a0a);
|
|
will-change: transform;
|
|
}
|
|
|
|
/* textarea 가 실제 스크롤 주체다. */
|
|
.cf24-code-input {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
display: block;
|
|
background: transparent;
|
|
color: transparent;
|
|
caret-color: var(--color-rich-black, #0a0a0a);
|
|
resize: none;
|
|
overflow: auto;
|
|
}
|
|
|
|
.cf24-code-input:focus {
|
|
outline: none;
|
|
}
|
|
|
|
.cf24-code:focus-within {
|
|
border-color: var(--color-rich-black, #0a0a0a);
|
|
}
|
|
|
|
/* 선택 영역은 **반투명**이어야 한다.
|
|
textarea 의 글자는 투명이고 실제 글자는 아래 <pre> 가 그린다. 선택 배경은
|
|
textarea(위층)가 칠하므로 불투명하면 아래 글자를 덮어 "선택하면 글자가 사라지는"
|
|
현상이 생긴다. 알파를 줘서 색칠된 글자가 비쳐 보이게 한다. */
|
|
.cf24-code-input::selection {
|
|
background: rgba(51, 122, 226, 0.28);
|
|
}
|
|
|
|
.cf24-code-input::-moz-selection {
|
|
background: rgba(51, 122, 226, 0.28);
|
|
}
|
|
|
|
/* 토큰 색 — GitHub 라이트 계열 */
|
|
.cf24-t-tag { color: #116329; } /* 태그 이름 */
|
|
.cf24-t-attr { color: #953800; } /* 속성 이름 */
|
|
.cf24-t-val { color: #0a3069; } /* 속성 값 */
|
|
.cf24-t-pun { color: #57606a; } /* < > / = */
|
|
.cf24-t-com { color: #6e7781; font-style: italic; } /* 주석 */
|
|
.cf24-t-doc { color: #6639ba; } /* DOCTYPE 등 선언 */
|
|
|
|
.cf24-code-hint {
|
|
font-size: var(--text-caption, 12px);
|
|
color: var(--color-midtone-gray, #737373);
|
|
}
|
|
|
|
.cf24-details {
|
|
flex: 0 0 auto;
|
|
border-top: 1px solid var(--color-subtle-ash, #e5e5e5);
|
|
padding-top: var(--sp-8, 8px);
|
|
}
|
|
|
|
.cf24-details > summary {
|
|
cursor: pointer;
|
|
font-size: var(--text-caption, 12px);
|
|
color: var(--color-midtone-gray, #737373);
|
|
}
|
|
|
|
.cf24-compact {
|
|
font-size: 12px;
|
|
}
|
|
|
|
.cf24-compact tbody td,
|
|
.cf24-compact thead th {
|
|
padding: 6px 8px;
|
|
}
|
|
|
|
.cf24-empty-pane {
|
|
margin: auto;
|
|
text-align: center;
|
|
padding: var(--sp-24, 24px);
|
|
}
|
|
|
|
.cf24-empty-pane h3 {
|
|
margin: 0 0 var(--sp-8, 8px);
|
|
}
|
|
|
|
.cf24-card-head {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--sp-8, 8px);
|
|
margin-bottom: var(--sp-12, 12px);
|
|
}
|
|
|
|
.cf24-card-head h3 {
|
|
margin: 0;
|
|
font-size: var(--text-heading, 18px);
|
|
letter-spacing: -0.45px;
|
|
}
|
|
|
|
.cf24-muted {
|
|
color: var(--color-midtone-gray, #737373);
|
|
font-size: var(--text-caption, 12px);
|
|
}
|
|
|
|
.cf24-err {
|
|
color: var(--color-callout-red, #c22b10);
|
|
}
|
|
|
|
.cf24-nowrap {
|
|
white-space: nowrap;
|
|
}
|
|
|
|
/* 상태 배지 */
|
|
.cf24-badge-ok {
|
|
background: var(--color-success-green, #10c22b);
|
|
color: #fff;
|
|
}
|
|
|
|
.cf24-badge-off {
|
|
background: var(--color-ghost-gray, #f2f2f2);
|
|
color: var(--color-rich-black, #0a0a0a);
|
|
}
|
|
|
|
/* 클릭으로 진열/판매를 토글하는 배지. 눌리는 것임을 커서·테두리로 알린다. */
|
|
.cf24-badge-btn {
|
|
border: 1px solid transparent;
|
|
font: inherit;
|
|
font-size: var(--text-caption, 12px);
|
|
cursor: pointer;
|
|
transition: filter 0.12s ease, box-shadow 0.12s ease;
|
|
}
|
|
|
|
.cf24-badge-btn:hover:not(:disabled) {
|
|
filter: brightness(0.94);
|
|
box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.08);
|
|
}
|
|
|
|
.cf24-badge-btn:disabled {
|
|
opacity: 0.55;
|
|
cursor: progress;
|
|
}
|
|
|
|
/* 안내/오류 배너 */
|
|
.cf24-flash {
|
|
padding: var(--sp-10, 10px) var(--sp-12, 12px);
|
|
border-radius: var(--r-lg, 10px);
|
|
margin-bottom: var(--sp-12, 12px);
|
|
font-size: var(--text-body, 14px);
|
|
}
|
|
|
|
.cf24-flash-ok {
|
|
background: #eefaf0;
|
|
border: 1px solid var(--color-success-green, #10c22b);
|
|
}
|
|
|
|
.cf24-flash-err {
|
|
background: #fdefec;
|
|
border: 1px solid var(--color-callout-red, #c22b10);
|
|
}
|
|
|
|
/* 키-값 표 */
|
|
.cf24-kv th {
|
|
width: 180px;
|
|
text-align: left;
|
|
color: var(--color-midtone-gray, #737373);
|
|
font-weight: 500;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.cf24-actions {
|
|
display: flex;
|
|
gap: var(--sp-8, 8px);
|
|
align-items: center;
|
|
margin-top: var(--sp-12, 12px);
|
|
}
|
|
|
|
.cf24-warn {
|
|
color: var(--color-callout-red, #c22b10);
|
|
font-size: var(--text-caption, 12px);
|
|
font-weight: 500;
|
|
}
|
|
|
|
/* 검색 도구모음 / 페이지 이동 */
|
|
.cf24-toolbar {
|
|
display: flex;
|
|
gap: var(--sp-8, 8px);
|
|
align-items: center;
|
|
flex-wrap: wrap;
|
|
margin-bottom: var(--sp-12, 12px);
|
|
}
|
|
|
|
/* 한 줄 높이로 고정한다. 세로 flex 안에서 flex-basis 를 주면 그 값이 '높이'로
|
|
적용돼 입력란이 거대해진다(실제로 그랬다 — flex 방향을 항상 확인할 것). */
|
|
.cf24-search {
|
|
flex: 0 0 auto;
|
|
width: 100%;
|
|
box-sizing: border-box;
|
|
height: 32px;
|
|
padding: 0 var(--sp-10, 10px);
|
|
border: 1px solid var(--color-subtle-ash, #e5e5e5);
|
|
border-radius: var(--r-lg, 10px);
|
|
font-size: var(--text-body, 14px);
|
|
}
|
|
|
|
.cf24-pager {
|
|
display: flex;
|
|
gap: var(--sp-12, 12px);
|
|
align-items: center;
|
|
justify-content: center;
|
|
margin-top: var(--sp-16, 16px);
|
|
}
|
|
|
|
/* 상세설명 HTML 원문 */
|
|
.cf24-label {
|
|
display: block;
|
|
margin: var(--sp-16, 16px) 0 var(--sp-8, 8px);
|
|
font-size: var(--text-caption, 12px);
|
|
font-weight: 500;
|
|
color: var(--color-midtone-gray, #737373);
|
|
}
|
|
|
|
.cf24-html {
|
|
width: 100%;
|
|
box-sizing: border-box;
|
|
padding: var(--sp-12, 12px);
|
|
border: 1px solid var(--color-subtle-ash, #e5e5e5);
|
|
border-radius: var(--r-lg, 10px);
|
|
background: var(--color-canvas-white, #fff);
|
|
font-family: var(--font-geist-mono, ui-monospace, monospace);
|
|
font-size: 12px;
|
|
line-height: 1.6;
|
|
white-space: pre;
|
|
overflow: auto;
|
|
resize: vertical;
|
|
}
|
|
|
|
/* 읽기 전용은 배경으로 구분 — 편집 가능한 칸과 헷갈리지 않게 */
|
|
.cf24-html[readonly] {
|
|
background: var(--color-ghost-gray, #f2f2f2);
|
|
}
|
|
|
|
.cf24-note {
|
|
margin: var(--sp-12, 12px) 0 0;
|
|
padding: var(--sp-10, 10px) var(--sp-12, 12px);
|
|
border-left: 3px solid var(--color-subtle-ash, #e5e5e5);
|
|
background: var(--color-ghost-gray, #f2f2f2);
|
|
border-radius: var(--r-sm, 6px);
|
|
color: var(--color-midtone-gray, #737373);
|
|
font-size: var(--text-caption, 12px);
|
|
line-height: 1.7;
|
|
}
|
|
|
|
/* 넓은 로그 표는 카드 안에서만 가로 스크롤 */
|
|
.cf24-scroll {
|
|
overflow-x: auto;
|
|
}
|
|
|
|
.cf24-scroll code {
|
|
font-family: var(--font-geist-mono, ui-monospace, monospace);
|
|
font-size: 12px;
|
|
}
|
|
|
|
.cf24-empty {
|
|
padding: var(--sp-24, 24px);
|
|
}
|
|
|
|
.cf24-empty h3 {
|
|
margin: 0 0 var(--sp-8, 8px);
|
|
}
|
|
|
|
/* ── 예약 폼 ── */
|
|
.cf24-schedule-form {
|
|
padding-top: var(--sp-8, 8px);
|
|
}
|
|
|
|
.cf24-schedule-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
|
|
gap: var(--sp-8, 8px);
|
|
}
|
|
|
|
.cf24-schedule-grid label {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 4px;
|
|
font-size: var(--text-caption, 12px);
|
|
color: var(--color-midtone-gray, #737373);
|
|
}
|
|
|
|
.cf24-schedule-wide {
|
|
grid-column: 1 / -1;
|
|
}
|
|
|
|
/* 날짜/시간을 별도 input 으로 나눈다 — datetime-local 은 한국어 로캘에서
|
|
"2026. 08. 14. 오후 07:00" 형태로 길어져 auto-fit minmax(160px, 1fr) 칸에
|
|
잘렸다(실측). 지금은 표시 텍스트를 우리가 직접 그리므로(아래 .cf24-dt-*) 폭을
|
|
내용에 맞춰 조절한다. */
|
|
.cf24-schedule-datetime {
|
|
grid-column: span 2;
|
|
max-width: 300px;
|
|
}
|
|
|
|
.cf24-schedule-datetime-row {
|
|
display: flex;
|
|
gap: 6px;
|
|
}
|
|
|
|
/* ── 날짜/시간 표시 형식을 직접 그리는 오버레이 ──
|
|
네이티브 date/time input 은 표시 형식을 CSS 로 바꿀 수 없다(브라우저·로캘가
|
|
강제). 코드 편집기(.cf24-code-input 위 .cf24-code-hl)와 같은 원리로, 투명한
|
|
네이티브 input 을 우리가 그린 텍스트 위에 완전히 겹쳐 클릭·키보드·달력 팝업은
|
|
네이티브 그대로 쓰고 보이는 글자만 형식화한다. */
|
|
.cf24-dt-field {
|
|
position: relative;
|
|
min-width: 0;
|
|
height: 32px;
|
|
}
|
|
|
|
/* 날짜 칸에 요일까지 표시("2026년 08월 20일 (목)")하므로 시간 칸보다 넓게 잡는다. */
|
|
.cf24-dt-field-date {
|
|
flex: 1.7 1 0;
|
|
}
|
|
|
|
.cf24-dt-field-time {
|
|
flex: 1 1 0;
|
|
}
|
|
|
|
.cf24-dt-display {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 100%;
|
|
height: 100%;
|
|
box-sizing: border-box;
|
|
padding: 0 6px;
|
|
border: 1px solid var(--color-subtle-ash, #e5e5e5);
|
|
border-radius: var(--r-lg, 10px);
|
|
background: var(--color-canvas-white, #fff);
|
|
color: var(--color-rich-black, #0a0a0a);
|
|
/* 12px 는 실측으로 고른 값 — 날짜 칸에 요일까지 들어가도 잘리지 않는 폭·글자크기
|
|
조합이다. */
|
|
font-size: 12px;
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
pointer-events: none; /* 클릭은 위에 겹친 네이티브 input 이 받는다 */
|
|
}
|
|
|
|
.cf24-dt-native {
|
|
position: absolute;
|
|
inset: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
margin: 0;
|
|
padding: 0;
|
|
border: 0;
|
|
background: transparent;
|
|
opacity: 0; /* 완전히 투명 — 아래 .cf24-dt-display 가 그대로 비쳐 보인다 */
|
|
cursor: pointer;
|
|
}
|
|
|
|
.cf24-schedule-input {
|
|
height: 32px;
|
|
box-sizing: border-box;
|
|
padding: 0 var(--sp-8, 8px);
|
|
border: 1px solid var(--color-subtle-ash, #e5e5e5);
|
|
border-radius: var(--r-lg, 10px);
|
|
font-size: var(--text-body, 14px);
|
|
color: var(--color-rich-black, #0a0a0a);
|
|
background: var(--color-canvas-white, #fff);
|
|
}
|
|
|
|
/* ── 상품 다이렉트 주소 ── */
|
|
.cf24-url-row {
|
|
display: flex;
|
|
gap: var(--sp-8, 8px);
|
|
align-items: center;
|
|
flex: 0 0 auto;
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.cf24-url {
|
|
flex: 1 1 260px;
|
|
min-width: 0;
|
|
height: 30px;
|
|
box-sizing: border-box;
|
|
padding: 0 var(--sp-10, 10px);
|
|
border: 1px solid var(--color-subtle-ash, #e5e5e5);
|
|
border-radius: var(--r-lg, 10px);
|
|
background: var(--color-ghost-gray, #f6f8fa);
|
|
color: var(--color-midtone-gray, #737373);
|
|
font-family: var(--font-geist-mono, ui-monospace, monospace);
|
|
font-size: 12px;
|
|
}
|
|
|
|
/* ════════════════════════════════════════════════════════════
|
|
3분할 — 목록 | 편집기 | 상품 정보 패널
|
|
왼쪽 목록은 좁게, 가운데 편집기가 남는 폭을, 오른쪽 패널은 고정폭.
|
|
════════════════════════════════════════════════════════════ */
|
|
.cf24-split.cf24-split-3 {
|
|
/* 목록은 320~460px 사이에서 줄어들고, 편집기가 남는 폭을, 패널은 380px 고정.
|
|
1920px: 460 + 380 → 편집기 약 1000px. 1400px: 320 + 380 → 편집기 약 640px. */
|
|
grid-template-columns: minmax(320px, 460px) minmax(0, 1fr) 380px;
|
|
}
|
|
|
|
@media (max-width: 1360px) {
|
|
/* 폭이 모자라면 정보 패널을 편집기 아래로 내린다(목록은 그대로 왼쪽).
|
|
아래 칸은 높이를 제한해 편집기가 너무 눌리지 않게 한다(패널 안에서 스크롤). */
|
|
.cf24-split.cf24-split-3 {
|
|
grid-template-columns: minmax(300px, 380px) minmax(0, 1fr);
|
|
grid-template-areas: "list editor" "list side";
|
|
grid-template-rows: minmax(0, 1fr) auto;
|
|
}
|
|
.cf24-split-3 > .cf24-pane-list { grid-area: list; }
|
|
.cf24-split-3 > .cf24-pane-editor { grid-area: editor; }
|
|
.cf24-split-3 > .cf24-pane-side { grid-area: side; max-height: 38vh; }
|
|
}
|
|
|
|
@media (max-width: 1100px) {
|
|
.cf24-split.cf24-split-3 {
|
|
grid-template-columns: minmax(0, 1fr);
|
|
grid-template-areas: none;
|
|
}
|
|
.cf24-split-3 > .cf24-pane-list,
|
|
.cf24-split-3 > .cf24-pane-editor,
|
|
.cf24-split-3 > .cf24-pane-side { grid-area: auto; max-height: none; }
|
|
}
|
|
|
|
.cf24-pane-side {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--sp-12, 12px);
|
|
padding: var(--sp-12, 12px);
|
|
}
|
|
|
|
/* 읽기 지연 안내 배너 */
|
|
.cf24-flash-warn {
|
|
background: #fff8e6;
|
|
border: 1px solid #f0b429;
|
|
}
|
|
|
|
.cf24-btn-inline {
|
|
margin-left: var(--sp-8, 8px);
|
|
padding: 2px 8px;
|
|
font-size: 12px;
|
|
}
|
|
|
|
/* ── 정보 패널 공통 ── */
|
|
.cf24-side {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--sp-12, 12px);
|
|
}
|
|
|
|
.cf24-side-sec {
|
|
border: 1px solid var(--color-subtle-ash, #e5e5e5);
|
|
border-radius: var(--r-lg, 10px);
|
|
padding: var(--sp-10, 10px) var(--sp-12, 12px);
|
|
background: var(--color-canvas-white, #fff);
|
|
}
|
|
|
|
.cf24-side-title {
|
|
margin: 0 0 var(--sp-8, 8px);
|
|
font-size: var(--text-body, 14px);
|
|
font-weight: 600;
|
|
letter-spacing: -0.3px;
|
|
}
|
|
|
|
.cf24-side-details > summary.cf24-side-title {
|
|
cursor: pointer;
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
.cf24-side-details[open] > summary.cf24-side-title {
|
|
margin-bottom: var(--sp-8, 8px);
|
|
}
|
|
|
|
.cf24-side-note {
|
|
margin: 0 0 var(--sp-8, 8px);
|
|
font-size: var(--text-caption, 12px);
|
|
color: var(--color-midtone-gray, #737373);
|
|
}
|
|
|
|
.cf24-side-note-warn {
|
|
color: #9a6700;
|
|
}
|
|
|
|
.cf24-side-form {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--sp-8, 8px);
|
|
}
|
|
|
|
.cf24-side-field {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 4px;
|
|
font-size: var(--text-caption, 12px);
|
|
color: var(--color-midtone-gray, #737373);
|
|
min-width: 0;
|
|
}
|
|
|
|
.cf24-side-field input[type="text"],
|
|
.cf24-side-field select {
|
|
height: 32px;
|
|
box-sizing: border-box;
|
|
width: 100%;
|
|
padding: 0 var(--sp-8, 8px);
|
|
border: 1px solid var(--color-subtle-ash, #e5e5e5);
|
|
border-radius: var(--r-md, 6px);
|
|
font-size: var(--text-body, 14px);
|
|
color: var(--color-rich-black, #0a0a0a);
|
|
background: var(--color-canvas-white, #fff);
|
|
}
|
|
|
|
.cf24-side-field input:focus,
|
|
.cf24-side-field select:focus {
|
|
outline: none;
|
|
border-color: var(--color-rich-black, #0a0a0a);
|
|
}
|
|
|
|
/* 값이 바뀐 입력칸은 테두리로 표시 — 무엇이 저장될지 보이게 */
|
|
.cf24-side input.is-dirty,
|
|
.cf24-side select.is-dirty {
|
|
border-color: #f0b429;
|
|
background: #fffbea;
|
|
}
|
|
|
|
.cf24-side-grid3 {
|
|
display: grid;
|
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
gap: var(--sp-8, 8px);
|
|
}
|
|
|
|
.cf24-side-actions {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
gap: var(--sp-8, 8px);
|
|
}
|
|
|
|
.cf24-side-actions .cf24-muted {
|
|
min-width: 0;
|
|
flex: 1 1 auto;
|
|
}
|
|
|
|
.cf24-side-actions .is-ok { color: var(--color-success-green, #10c22b); }
|
|
.cf24-side-actions .is-err { color: var(--color-callout-red, #c22b10); }
|
|
|
|
/* ── 대표 이미지 ── */
|
|
.cf24-image-box {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
min-height: 160px;
|
|
border: 1px dashed var(--color-subtle-ash, #e5e5e5);
|
|
border-radius: var(--r-md, 6px);
|
|
background: var(--color-ghost-gray, #f6f8fa);
|
|
margin-bottom: var(--sp-8, 8px);
|
|
overflow: hidden;
|
|
}
|
|
|
|
.cf24-image-main {
|
|
display: block;
|
|
max-width: 100%;
|
|
max-height: 260px;
|
|
object-fit: contain;
|
|
}
|
|
|
|
.cf24-image-empty {
|
|
font-size: var(--text-caption, 12px);
|
|
color: var(--color-midtone-gray, #737373);
|
|
padding: var(--sp-16, 16px);
|
|
}
|
|
|
|
.cf24-image-thumbs {
|
|
display: flex;
|
|
gap: var(--sp-8, 8px);
|
|
margin-bottom: var(--sp-8, 8px);
|
|
}
|
|
|
|
.cf24-image-thumb {
|
|
margin: 0;
|
|
flex: 1 1 0;
|
|
min-width: 0;
|
|
text-align: center;
|
|
font-size: 11px;
|
|
color: var(--color-midtone-gray, #737373);
|
|
}
|
|
|
|
.cf24-image-thumb img {
|
|
display: block;
|
|
width: 100%;
|
|
height: 64px;
|
|
object-fit: contain;
|
|
border: 1px solid var(--color-subtle-ash, #e5e5e5);
|
|
border-radius: var(--r-sm, 4px);
|
|
background: #fff;
|
|
}
|
|
|
|
.cf24-image-thumb img.is-hidden,
|
|
.cf24-side .is-hidden {
|
|
display: none;
|
|
}
|
|
|
|
.cf24-file-pick {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--sp-8, 8px);
|
|
cursor: pointer;
|
|
min-width: 0;
|
|
}
|
|
|
|
.cf24-file-pick input[type="file"] {
|
|
position: absolute;
|
|
width: 1px;
|
|
height: 1px;
|
|
opacity: 0;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.cf24-file-name {
|
|
font-size: var(--text-caption, 12px);
|
|
color: var(--color-midtone-gray, #737373);
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
min-width: 0;
|
|
}
|
|
|
|
/* ── 옵션 / 품목 ── */
|
|
.cf24-options-body {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--sp-10, 10px);
|
|
}
|
|
|
|
.cf24-opt-group {
|
|
border-top: 1px solid var(--color-subtle-ash, #e5e5e5);
|
|
padding-top: var(--sp-8, 8px);
|
|
}
|
|
|
|
.cf24-opt-head {
|
|
display: flex;
|
|
gap: var(--sp-8, 8px);
|
|
align-items: flex-end;
|
|
margin-bottom: var(--sp-8, 8px);
|
|
}
|
|
|
|
.cf24-opt-head .cf24-side-field { flex: 1 1 auto; }
|
|
.cf24-opt-head .cf24-side-field-type { flex: 0 0 140px; }
|
|
|
|
.cf24-opt-value {
|
|
display: grid;
|
|
grid-template-columns: 44px minmax(0, 1fr) auto;
|
|
gap: var(--sp-8, 8px);
|
|
align-items: center;
|
|
padding: 4px 0;
|
|
}
|
|
|
|
.cf24-opt-thumb {
|
|
width: 44px;
|
|
height: 44px;
|
|
border: 1px solid var(--color-subtle-ash, #e5e5e5);
|
|
border-radius: var(--r-sm, 4px);
|
|
background: var(--color-ghost-gray, #f6f8fa);
|
|
object-fit: cover;
|
|
display: block;
|
|
}
|
|
|
|
.cf24-opt-thumb-empty {
|
|
width: 44px;
|
|
height: 44px;
|
|
border: 1px dashed var(--color-subtle-ash, #e5e5e5);
|
|
border-radius: var(--r-sm, 4px);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 10px;
|
|
color: var(--color-midtone-gray, #737373);
|
|
}
|
|
|
|
.cf24-opt-value input[type="text"] {
|
|
height: 30px;
|
|
box-sizing: border-box;
|
|
width: 100%;
|
|
padding: 0 var(--sp-8, 8px);
|
|
border: 1px solid var(--color-subtle-ash, #e5e5e5);
|
|
border-radius: var(--r-md, 6px);
|
|
font-size: 13px;
|
|
}
|
|
|
|
.cf24-opt-value .cf24-file-pick .erp-btn {
|
|
padding: 3px 8px;
|
|
font-size: 12px;
|
|
}
|
|
|
|
/* ── 옵션/품목 모달 — 380px 패널은 품목 표를 담기에 좁아(실측: 옵션값 이름이
|
|
아이콘 아래로 꺾여 잘렸다) 넓은 창에서 편집한다. 왼쪽 옵션 정의 / 오른쪽 품목 표. */
|
|
.cf24-modal {
|
|
position: fixed;
|
|
inset: 0;
|
|
z-index: 1000;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
padding: 24px;
|
|
background: rgba(10, 10, 10, 0.45);
|
|
}
|
|
|
|
.cf24-modal[hidden] {
|
|
display: none;
|
|
}
|
|
|
|
body.cf24-modal-open {
|
|
overflow: hidden; /* 뒤 화면 스크롤 잠금 */
|
|
}
|
|
|
|
.cf24-modal-box {
|
|
display: flex;
|
|
flex-direction: column;
|
|
width: min(1280px, 96vw);
|
|
/* max-height 가 아니라 height 고정 — 두 열이 창 바닥까지 늘어나고 각 열 안에서
|
|
스크롤한다(품목이 많을 때 표만 스크롤, 저장 버튼은 항상 보임). */
|
|
height: 90vh;
|
|
background: var(--color-canvas-white, #fff);
|
|
border-radius: var(--r-xl, 14px);
|
|
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
|
|
overflow: hidden;
|
|
}
|
|
|
|
.cf24-modal-head {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
gap: var(--sp-12, 12px);
|
|
padding: 14px 18px;
|
|
border-bottom: 1px solid var(--color-subtle-ash, #e5e5e5);
|
|
flex: 0 0 auto;
|
|
}
|
|
|
|
.cf24-modal-title {
|
|
margin: 0;
|
|
font-size: var(--text-heading, 18px);
|
|
letter-spacing: -0.45px;
|
|
min-width: 0;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.cf24-modal-close {
|
|
flex: 0 0 auto;
|
|
width: 32px;
|
|
height: 32px;
|
|
border: 0;
|
|
border-radius: 50%;
|
|
background: transparent;
|
|
font-size: 16px;
|
|
cursor: pointer;
|
|
color: var(--color-midtone-gray, #737373);
|
|
}
|
|
|
|
.cf24-modal-close:hover {
|
|
background: var(--color-ghost-gray, #f2f2f2);
|
|
color: var(--color-rich-black, #0a0a0a);
|
|
}
|
|
|
|
.cf24-modal-body {
|
|
padding: 16px 18px 18px;
|
|
flex: 1 1 auto;
|
|
min-height: 0;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
/* 옵션 정의(왼쪽, 좁게) | 품목 표(오른쪽, 남는 폭 전부). 두 열 모두 창 바닥까지. */
|
|
.cf24-modal-grid {
|
|
flex: 1 1 auto;
|
|
min-height: 0;
|
|
display: grid;
|
|
grid-template-columns: 340px minmax(0, 1fr);
|
|
grid-template-rows: minmax(0, 1fr);
|
|
gap: 24px;
|
|
align-items: stretch;
|
|
}
|
|
|
|
@media (max-width: 960px) {
|
|
.cf24-modal-grid {
|
|
grid-template-columns: minmax(0, 1fr);
|
|
grid-template-rows: auto;
|
|
}
|
|
}
|
|
|
|
.cf24-modal-col {
|
|
min-width: 0;
|
|
min-height: 0;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
/* 왼쪽 열은 통째로 스크롤, 오른쪽 열은 표만 스크롤(제목·저장 버튼 고정) */
|
|
.cf24-modal-col-options {
|
|
overflow: auto;
|
|
}
|
|
|
|
.cf24-modal-col-variants > .cf24-variants-wrap {
|
|
flex: 1 1 auto;
|
|
min-height: 0;
|
|
overflow: auto;
|
|
border-bottom: 1px solid var(--color-subtle-ash, #e5e5e5);
|
|
}
|
|
|
|
.cf24-modal-col-variants > .cf24-side-actions {
|
|
flex: 0 0 auto;
|
|
}
|
|
|
|
/* 옵션이 없는 상품의 생성 폼 — 넓은 모달에서 끝까지 늘어나지 않게 */
|
|
.cf24-modal-body .cf24-opt-create {
|
|
max-width: 560px;
|
|
}
|
|
|
|
/* 품목 표 — 모달의 오른쪽 열(약 700px)에 맞춘다 */
|
|
.cf24-variants {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
font-size: 13px;
|
|
}
|
|
|
|
.cf24-variants th,
|
|
.cf24-variants td {
|
|
padding: 6px 6px;
|
|
border-bottom: 1px solid var(--color-subtle-ash, #e5e5e5);
|
|
vertical-align: middle;
|
|
text-align: left;
|
|
}
|
|
|
|
.cf24-variants th {
|
|
font-weight: 500;
|
|
font-size: 12px;
|
|
color: var(--color-midtone-gray, #737373);
|
|
white-space: nowrap;
|
|
position: sticky;
|
|
top: 0;
|
|
background: var(--color-canvas-white, #fff);
|
|
}
|
|
|
|
/* 열 폭 — 옵션 이름이 한 줄에 들어가도록 나머지를 좁게 잡는다
|
|
(1280px 모달: 340 옵션 + 24 간격 → 표 약 880px, 이름 칸 약 420px). */
|
|
.cf24-v-imgcol { width: 40px; }
|
|
.cf24-v-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 0; }
|
|
.cf24-v-syscode { width: 104px; }
|
|
.cf24-v-code { width: 132px; }
|
|
.cf24-v-amount { width: 90px; }
|
|
.cf24-v-amount input { text-align: right; }
|
|
.cf24-v-flag { width: 56px; text-align: center; }
|
|
|
|
/* 품목코드 — 클릭하면 클립보드로. 눌리는 것임을 커서·밑줄로 알린다. */
|
|
.cf24-v-copy {
|
|
font-family: var(--font-geist-mono, ui-monospace, monospace);
|
|
font-size: 11px;
|
|
color: var(--color-midtone-gray, #737373);
|
|
background: transparent;
|
|
border: 0;
|
|
padding: 2px 4px;
|
|
border-radius: var(--r-sm, 4px);
|
|
cursor: copy;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.cf24-v-copy:hover {
|
|
background: var(--color-ghost-gray, #f2f2f2);
|
|
color: var(--color-rich-black, #0a0a0a);
|
|
}
|
|
|
|
.cf24-v-copy.is-copied {
|
|
color: var(--color-success-green, #10c22b);
|
|
}
|
|
|
|
/* ── 통합 목록(옵션값 1 : 품목 1) — 모달 전체 폭 사용, 표만 스크롤 ── */
|
|
.cf24-u-wrap {
|
|
display: flex;
|
|
flex-direction: column;
|
|
flex: 1 1 auto;
|
|
min-height: 0;
|
|
gap: var(--sp-10, 10px);
|
|
}
|
|
|
|
.cf24-u-head {
|
|
display: flex;
|
|
align-items: flex-end;
|
|
gap: var(--sp-10, 10px);
|
|
flex: 0 0 auto;
|
|
}
|
|
|
|
.cf24-u-optname { flex: 0 1 320px; }
|
|
|
|
.cf24-u-head-actions {
|
|
margin-left: auto;
|
|
display: flex;
|
|
gap: var(--sp-8, 8px);
|
|
align-items: flex-end;
|
|
}
|
|
|
|
.cf24-u-tablewrap {
|
|
flex: 1 1 auto;
|
|
min-height: 0;
|
|
overflow: auto;
|
|
border-top: 1px solid var(--color-subtle-ash, #e5e5e5);
|
|
border-bottom: 1px solid var(--color-subtle-ash, #e5e5e5);
|
|
}
|
|
|
|
.cf24-u-note { flex: 0 0 auto; margin: 0; }
|
|
.cf24-u-actions { flex: 0 0 auto; }
|
|
|
|
.cf24-u-table .cf24-u-drag { width: 26px; text-align: center; }
|
|
.cf24-u-table .cf24-u-thumb { width: 118px; }
|
|
.cf24-u-table .cf24-u-del { width: 30px; text-align: center; }
|
|
.cf24-u-table .cf24-u-name input[type="text"] { font-weight: 500; }
|
|
|
|
.cf24-u-thumb .cf24-opt-thumb-slot { display: inline-block; vertical-align: middle; margin-right: 6px; }
|
|
.cf24-u-thumb .cf24-opt-thumb,
|
|
.cf24-u-thumb .cf24-opt-thumb-empty { width: 40px; height: 40px; }
|
|
.cf24-u-pick { display: inline-flex; vertical-align: middle; }
|
|
.cf24-u-pick .erp-btn { padding: 3px 8px; font-size: 12px; }
|
|
|
|
.cf24-drag-handle {
|
|
cursor: grab;
|
|
color: var(--color-midtone-gray, #737373);
|
|
font-size: 14px;
|
|
user-select: none;
|
|
padding: 4px 2px;
|
|
letter-spacing: -1px;
|
|
}
|
|
|
|
.cf24-drag-handle:active { cursor: grabbing; }
|
|
.cf24-drag-handle.is-dirty { color: #f0b429; }
|
|
|
|
tr.cf24-u-row.is-dragging {
|
|
opacity: 0.45;
|
|
background: #fffbea;
|
|
}
|
|
|
|
.cf24-u-remove {
|
|
border: 0;
|
|
background: transparent;
|
|
color: var(--color-midtone-gray, #737373);
|
|
cursor: pointer;
|
|
font-size: 13px;
|
|
padding: 4px;
|
|
border-radius: var(--r-sm, 4px);
|
|
}
|
|
|
|
.cf24-u-remove:hover {
|
|
background: #fdefec;
|
|
color: var(--color-callout-red, #c22b10);
|
|
}
|
|
|
|
.cf24-btn-danger {
|
|
color: var(--color-callout-red, #c22b10);
|
|
border-color: var(--color-callout-red, #c22b10);
|
|
}
|
|
|
|
/* 옵션값 불러오기 대화상자 — 옵션 모달 위에 한 겹 더 */
|
|
.cf24-import { z-index: 1100; }
|
|
|
|
.cf24-import-box {
|
|
width: min(720px, 94vw);
|
|
height: auto;
|
|
max-height: 80vh;
|
|
}
|
|
|
|
.cf24-import-text {
|
|
width: 100%;
|
|
box-sizing: border-box;
|
|
min-height: 220px;
|
|
padding: var(--sp-10, 10px);
|
|
border: 1px solid var(--color-subtle-ash, #e5e5e5);
|
|
border-radius: var(--r-md, 6px);
|
|
font-family: var(--font-geist-mono, ui-monospace, monospace);
|
|
font-size: 12px;
|
|
line-height: 1.6;
|
|
white-space: pre;
|
|
resize: vertical;
|
|
}
|
|
|
|
.cf24-import-preview { margin: 6px 0 10px; min-height: 16px; }
|
|
|
|
.cf24-v-img {
|
|
width: 32px;
|
|
height: 32px;
|
|
object-fit: cover;
|
|
border: 1px solid var(--color-subtle-ash, #e5e5e5);
|
|
border-radius: var(--r-sm, 4px);
|
|
background: var(--color-ghost-gray, #f6f8fa);
|
|
display: block;
|
|
}
|
|
|
|
.cf24-v-img-empty {
|
|
border-style: dashed;
|
|
}
|
|
|
|
.cf24-v-name {
|
|
font-weight: 500;
|
|
}
|
|
|
|
.cf24-variants input[type="text"] {
|
|
height: 30px;
|
|
box-sizing: border-box;
|
|
width: 100%;
|
|
padding: 0 8px;
|
|
border: 1px solid var(--color-subtle-ash, #e5e5e5);
|
|
border-radius: var(--r-sm, 4px);
|
|
font-size: 13px;
|
|
}
|
|
|
|
/* 진열/판매 토글 — 저장 전까지는 화면만 바뀐다(배지와 같은 색 규칙) */
|
|
.cf24-v-toggle {
|
|
border: 1px solid transparent;
|
|
border-radius: 999px;
|
|
padding: 2px 6px;
|
|
font-size: 11px;
|
|
white-space: nowrap;
|
|
cursor: pointer;
|
|
background: var(--color-ghost-gray, #f2f2f2);
|
|
color: var(--color-rich-black, #0a0a0a);
|
|
}
|
|
|
|
.cf24-v-toggle.is-on {
|
|
background: var(--color-success-green, #10c22b);
|
|
color: #fff;
|
|
}
|
|
|
|
.cf24-v-toggle.is-dirty {
|
|
box-shadow: 0 0 0 2px #f0b429;
|
|
}
|
|
|
|
.cf24-opt-danger {
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
padding-top: var(--sp-8, 8px);
|
|
}
|
|
|
|
.cf24-opt-danger .erp-btn {
|
|
color: var(--color-callout-red, #c22b10);
|
|
border-color: var(--color-callout-red, #c22b10);
|
|
}
|
|
|
|
.cf24-opt-create textarea {
|
|
width: 100%;
|
|
box-sizing: border-box;
|
|
min-height: 64px;
|
|
padding: var(--sp-8, 8px);
|
|
border: 1px solid var(--color-subtle-ash, #e5e5e5);
|
|
border-radius: var(--r-md, 6px);
|
|
font-size: 13px;
|
|
resize: vertical;
|
|
}
|