사용자 지적(2026-09-03) — 선택 항목이 너무 크고 대중없이 놓임. 안내는 B04·B05 와 같은 공용 좌측 패널로 빼고 본문은 고르는 자리만 남김. - `B03_FileInput_UI_Guide.ts` 신설 — 필요한 파일 / 고르는 방법 / 알아 둘 것 3묶음을 공용 오버레이 `optionsContent` 에 실음. 문단 구획은 공용 `ui-sidebar-section`. - 선택 영역 160px 블록 → 한 줄 바. 긴 문구는 패널로 옮기고 힌트는 한 줄로 교체. - 카드 `min-height: 220px` 폐지, [선택]을 제목 줄 오른쪽 끝 작은 버튼으로 이동, 빈 칸은 제목 줄만 남김. 진행바·속도·예상완료는 올라가는 동안만 표시. - 여백 정리 — 컨테이너 패딩 32 → 20, 그룹 제목 24 → 16px, 격자 간격 24 → 12. - 좌측 패널이 열리면 본문을 밀어내는 규칙 추가 — B03 은 일반 레이아웃이라 공용 워크플로 레이아웃의 padding 규칙이 없어 패널이 카드를 덮었음. 검증: 카드 높이 232 → 66px(빈 칸)·117px(파일 있음), 선택 영역 160 → 47px, 문서 높이 1408px 로 한 화면 남짓. typecheck·prettier 통과. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
589 lines
16 KiB
CSS
589 lines
16 KiB
CSS
.b03-file {
|
||
min-height: calc(100vh - var(--app-header-height, 0px));
|
||
background: linear-gradient(
|
||
180deg,
|
||
var(--color-canvas, #ffffff) 0%,
|
||
var(--color-mist-violet, #edecff) 100%
|
||
);
|
||
padding: 0 var(--spacing-24) var(--spacing-48) var(--spacing-24); /* 상단 여백은 main-layout 마진으로 조정하므로 padding-top은 0 */
|
||
}
|
||
|
||
.b03-file__main-layout {
|
||
max-width: var(--page-max-width, 1200px);
|
||
margin: var(--spacing-40) auto 0 auto; /* 상단 구분선(헤더)과의 간격을 확실하게 40px 벌림 */
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: var(--spacing-32);
|
||
}
|
||
|
||
.b03-file__control-panel {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: var(--spacing-16);
|
||
background: var(--color-canvas, #ffffff);
|
||
/* 여백 32 → 20 (2026-09-03) — 고르는 자리만 남기고 안내를 좌측 패널로 뺐다. */
|
||
padding: var(--spacing-20);
|
||
border-radius: var(--radius-large, 24px); /* Wiza 24px 대형 둥글기 */
|
||
border: 1px solid var(--color-mist, #e6e2e3);
|
||
box-shadow: var(--shadow-lg);
|
||
}
|
||
|
||
.b03-file__cards-container-panel {
|
||
margin-top: 0; /* 단일 layout gap에 의해 제어되도록 설정 */
|
||
}
|
||
|
||
.b03-file__subtitle {
|
||
font-size: var(--text-body-sm, 14px);
|
||
color: var(--color-slate, #615e6e);
|
||
margin: 0 0 var(--spacing-8) 0;
|
||
}
|
||
|
||
.b03-file__native-input,
|
||
.b03-file__slot-input {
|
||
display: none;
|
||
}
|
||
|
||
/* Wiza 스타일 가이드의 Lavender Glow 그라데이션 및 soft purple border hover */
|
||
/* 한 줄 바(2026-09-03) — 종전 160px 블록은 안내 문구를 담느라 컸다. 문구는 좌측
|
||
패널로 갔으므로 여기는 「끌어 놓거나 눌러서 고르는 자리」 표시만 한다. */
|
||
.b03-file__dropzone {
|
||
padding: var(--spacing-12) var(--spacing-16);
|
||
border: 1px dashed var(--color-mist, #e6e2e3);
|
||
border-radius: var(--radius-cards, 8px);
|
||
background: var(--color-paper, #f6f7fa);
|
||
display: flex;
|
||
flex-direction: row;
|
||
flex-wrap: wrap;
|
||
align-items: baseline;
|
||
justify-content: center;
|
||
gap: var(--spacing-8);
|
||
cursor: pointer;
|
||
text-align: center;
|
||
transition:
|
||
background var(--transition-base, 0.2s),
|
||
border-color var(--transition-base, 0.2s),
|
||
box-shadow var(--transition-base, 0.2s);
|
||
}
|
||
|
||
.b03-file__dropzone:hover {
|
||
background: var(--color-mist-violet, #edecff);
|
||
border-color: var(--color-royal-amethyst, #3e0079);
|
||
}
|
||
|
||
.b03-file__dropzone:focus-visible,
|
||
.b03-file__dropzone.is-dragging {
|
||
outline: none;
|
||
background: var(--color-mist-violet, #edecff);
|
||
border-color: var(--color-royal-amethyst, #3e0079);
|
||
box-shadow: 0 0 0 4px rgba(62, 0, 121, 0.15);
|
||
}
|
||
|
||
.b03-file__dropzone strong {
|
||
color: var(--color-deep-iris, #26114a);
|
||
font-size: var(--text-body-sm, 14px);
|
||
font-weight: var(--font-weight-medium, 500);
|
||
}
|
||
|
||
.b03-file__dropzone span {
|
||
font-size: var(--text-body-sm, 14px);
|
||
color: var(--color-slate, #615e6e);
|
||
}
|
||
|
||
.b03-file__error {
|
||
min-height: var(--spacing-16);
|
||
color: var(--color-danger, #dc2626);
|
||
font-size: var(--text-body-sm, 14px);
|
||
margin: var(--spacing-8) 0;
|
||
}
|
||
|
||
.b03-file__resume {
|
||
display: none;
|
||
align-items: center;
|
||
gap: var(--spacing-8);
|
||
flex-wrap: wrap;
|
||
padding: var(--spacing-12) var(--spacing-16);
|
||
border: 1px solid var(--color-mist, #e6e2e3);
|
||
border-radius: var(--radius-cards, 8px);
|
||
background: var(--color-paper, #f6f7fa);
|
||
color: var(--color-deep-iris, #26114a);
|
||
font-size: var(--text-body-sm, 14px);
|
||
margin-top: var(--spacing-8);
|
||
}
|
||
|
||
.b03-file__resume.is-visible {
|
||
display: flex;
|
||
}
|
||
|
||
/* 재접속 현황(서버 정본) 배너 — 완료 안내와 중단 세션 이어올리기 안내를 담는다. */
|
||
.b03-file__overview {
|
||
display: none;
|
||
flex-direction: column;
|
||
gap: var(--spacing-4);
|
||
margin-top: var(--spacing-8);
|
||
padding: var(--spacing-12) var(--spacing-16);
|
||
border: 1px solid var(--color-border);
|
||
border-radius: var(--radius-cards, 8px);
|
||
background: var(--color-surface);
|
||
font-size: var(--text-body-sm, 14px);
|
||
}
|
||
|
||
.b03-file__overview.is-visible {
|
||
display: flex;
|
||
}
|
||
|
||
.b03-file__overview-complete {
|
||
margin: 0;
|
||
color: var(--color-success, #3fbb6f);
|
||
font-weight: 600;
|
||
}
|
||
|
||
.b03-file__overview-pending {
|
||
margin: 0;
|
||
color: var(--color-text-secondary);
|
||
}
|
||
|
||
/* 완료 슬롯 재업로드 확인 모달 — 페이지 위를 덮는 단순 확인창. */
|
||
.b03-file__modal-backdrop {
|
||
position: fixed;
|
||
inset: 0;
|
||
z-index: 1000;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
background: rgb(0 0 0 / 45%);
|
||
}
|
||
|
||
.b03-file__modal {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: var(--spacing-12);
|
||
max-width: 420px;
|
||
padding: var(--spacing-24);
|
||
border: 1px solid var(--color-border);
|
||
border-radius: var(--radius-cards, 8px);
|
||
background: var(--color-surface-raised);
|
||
box-shadow: 0 12px 32px rgb(0 0 0 / 30%);
|
||
}
|
||
|
||
.b03-file__modal p {
|
||
margin: 0;
|
||
color: var(--color-text-secondary);
|
||
white-space: pre-line;
|
||
}
|
||
|
||
.b03-file__modal-actions {
|
||
display: flex;
|
||
gap: var(--spacing-8);
|
||
justify-content: flex-end;
|
||
}
|
||
|
||
.b03-file__cards-grid {
|
||
display: grid;
|
||
grid-template-columns: 1fr;
|
||
gap: var(--spacing-32);
|
||
}
|
||
|
||
/* 계획노선 | 지형(LAS) — 컨테이너를 둘로 나눈다(2026-08-31 사용자 지시).
|
||
노선은 카드 5장(shapefile 한 벌), 지형은 4장이라 폭을 5:4 비슷하게 준다. */
|
||
.b03-file__columns {
|
||
display: grid;
|
||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||
gap: var(--spacing-16);
|
||
align-items: start;
|
||
}
|
||
|
||
/* 좌측 안내 패널이 열리면 본문을 그만큼 밀어낸다 — 공용 워크플로 레이아웃(B04·B05)의
|
||
`.ui-workflow-layout__body` 규칙과 같은 값. 접히면 손잡이 폭만 남긴다. */
|
||
.b03-file__main-layout {
|
||
transition: padding-left var(--transition-base);
|
||
}
|
||
|
||
.b03-file.is-options-open .b03-file__main-layout {
|
||
padding-left: min(var(--wf-left-panel-width), calc(100vw - var(--spacing-48)));
|
||
}
|
||
|
||
.b03-file:not(.is-options-open) .b03-file__main-layout {
|
||
padding-left: var(--spacing-24);
|
||
}
|
||
|
||
@media (max-width: 860px) {
|
||
.b03-file.is-options-open .b03-file__main-layout {
|
||
padding-left: 0;
|
||
}
|
||
}
|
||
|
||
/* --- 좌측 안내 패널 (2026-09-03) — 본문에서 뺀 설명이 사는 자리. --- */
|
||
.b03-file__guide {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: var(--spacing-12);
|
||
padding: var(--spacing-12);
|
||
}
|
||
|
||
.b03-file__guide-group {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: var(--spacing-8);
|
||
padding: var(--spacing-12);
|
||
}
|
||
|
||
.b03-file__guide-title {
|
||
margin: 0;
|
||
font-size: var(--text-body-sm, 14px);
|
||
font-weight: var(--font-weight-medium, 500);
|
||
color: var(--color-text, #26114a);
|
||
}
|
||
|
||
.b03-file__guide-list {
|
||
margin: 0;
|
||
padding-left: var(--spacing-16);
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: var(--spacing-4);
|
||
font-size: var(--text-caption, 12px);
|
||
line-height: 1.55;
|
||
color: var(--color-text-secondary, #615e6e);
|
||
}
|
||
|
||
.b03-file__group {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: var(--spacing-12);
|
||
}
|
||
|
||
.b03-file__group-hint {
|
||
font-size: var(--text-body-sm, 14px);
|
||
color: var(--color-slate, #615e6e);
|
||
margin: calc(var(--spacing-8) * -1) 0 0 0;
|
||
}
|
||
|
||
/* 제목 24px → 본문 크기(2026-09-03) — 컨테이너가 둘뿐이라 큰 제목이 자리만 먹었다. */
|
||
.b03-file__group-title {
|
||
font-size: var(--text-body, 16px);
|
||
color: var(--color-deep-iris, #26114a);
|
||
font-family: var(--font-britti-sans, inherit);
|
||
margin: 0;
|
||
}
|
||
|
||
.b03-file__group-content {
|
||
display: grid;
|
||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||
gap: var(--spacing-12);
|
||
}
|
||
|
||
/* 업로드 중에는 화면 조작을 막는다 — 중복 업로드·단계 이동 방지(2026-08-08 사용자 지시). */
|
||
.b03-file--busy {
|
||
pointer-events: none;
|
||
}
|
||
|
||
.b03-file--busy .b03-file__card-select,
|
||
.b03-file--busy .b03-file__card-remove,
|
||
.b03-file--busy .b03-file__dropzone {
|
||
opacity: 0.5;
|
||
}
|
||
|
||
/* 업로드 버튼 안에서 도는 원 — 공용 스피너를 버튼 글자 크기에 맞춰 줄인다. */
|
||
.b03-file__upload-spinner {
|
||
width: 14px;
|
||
height: 14px;
|
||
border-width: 2px;
|
||
border-color: rgb(255 255 255 / 40%);
|
||
border-top-color: var(--color-primary-text);
|
||
}
|
||
|
||
/* Wiza 8px radius 카드 */
|
||
/* 카드 한 장 = 파일 한 칸. 빈 칸은 **한 줄**로 끝난다(2026-09-03 사용자 지시) —
|
||
파일이 붙거나 올라가는 중에만 아래 내용(파일명·진행바)이 펼쳐진다. */
|
||
.b03-file__card {
|
||
padding: var(--spacing-12) var(--spacing-16);
|
||
border: 1px solid var(--color-mist, #e6e2e3);
|
||
border-radius: var(--radius-cards, 8px);
|
||
background: var(--color-canvas, #ffffff);
|
||
box-shadow: var(--shadow-sm);
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: var(--spacing-8);
|
||
transition:
|
||
transform var(--transition-base, 0.2s),
|
||
border-color var(--transition-base, 0.2s),
|
||
box-shadow var(--transition-base, 0.2s);
|
||
}
|
||
|
||
.b03-file__card:hover {
|
||
transform: translateY(-2px);
|
||
box-shadow: var(--shadow-lg);
|
||
border-color: var(--color-royal-amethyst, #3e0079);
|
||
}
|
||
|
||
.b03-file__card--selected {
|
||
border-color: var(--color-royal-amethyst, #3e0079);
|
||
background: var(--color-paper, #f6f7fa);
|
||
}
|
||
|
||
.b03-file__card--uploading {
|
||
border-color: var(--color-royal-amethyst, #3e0079);
|
||
box-shadow: var(--shadow-lg-2);
|
||
}
|
||
|
||
.b03-file__card--completed {
|
||
border-color: #10b981; /* Success Green */
|
||
}
|
||
|
||
.b03-file__card--error {
|
||
border-color: var(--color-danger, #dc2626);
|
||
}
|
||
|
||
/* 카드가 좁아졌다(컨테이너 2열 × 카드 2열, 2026-08-31). 격자로 고정하면 제목이
|
||
글자 단위로 접히므로, 자리가 모자라면 배지·삭제 버튼이 다음 줄로 내려가게 한다. */
|
||
/* 제목·상태·[선택]이 **한 줄**에 선다(2026-09-03) — 줄바꿈을 허용하면 [선택]이 아래로
|
||
내려가 카드가 두 줄이 됐다. 자리가 모자라면 제목이 줄어든다(min-width: 0). */
|
||
.b03-file__card-header {
|
||
display: flex;
|
||
flex-wrap: nowrap;
|
||
gap: var(--spacing-8);
|
||
align-items: center;
|
||
}
|
||
|
||
.b03-file__card-icon {
|
||
flex: 0 0 auto;
|
||
width: 28px;
|
||
height: 28px;
|
||
border-radius: var(--radius-icons, 8px);
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
color: var(--color-royal-amethyst, #3e0079);
|
||
background: var(--color-mist-violet, #edecff);
|
||
font-size: var(--text-body-sm, 14px);
|
||
margin-right: var(--spacing-8); /* 아이콘 우측 마진 추가 (아이콘 좌측 여유 확대 효과) */
|
||
}
|
||
|
||
.b03-file__card-heading {
|
||
min-width: 0;
|
||
flex: 1 1 auto;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 1px;
|
||
}
|
||
|
||
.b03-file__card-label {
|
||
color: var(--color-deep-iris, #26114a);
|
||
font-size: var(--text-body-sm, 14px);
|
||
font-weight: var(--font-weight-medium, 500);
|
||
/* 한글은 글자 단위로 끊기므로 어절을 지켜 준다 — "계획
|
||
노선
|
||
도형" 방지. */
|
||
word-break: keep-all;
|
||
overflow-wrap: break-word;
|
||
}
|
||
|
||
.b03-file__card-ext,
|
||
.b03-file__file-size,
|
||
.b03-file__progress-info {
|
||
color: var(--color-slate, #615e6e);
|
||
font-size: var(--text-caption, 12px);
|
||
}
|
||
|
||
.b03-file__card-badge-container {
|
||
display: flex;
|
||
align-items: center;
|
||
margin-left: auto;
|
||
margin-right: var(--spacing-4);
|
||
}
|
||
|
||
.b03-file__card-remove {
|
||
width: 24px;
|
||
height: 24px;
|
||
border: 1px solid var(--color-mist, #e6e2e3);
|
||
border-radius: var(--radius-buttons, 8px);
|
||
color: var(--color-slate, #615e6e);
|
||
background: var(--color-canvas, #ffffff);
|
||
cursor: pointer;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: var(--text-body-sm, 14px);
|
||
line-height: 1;
|
||
padding: 0;
|
||
margin-left: var(--spacing-8); /* 취소 버튼 좌측 여유 추가 (취소 버튼 우측 여유 확보) */
|
||
transition: all var(--transition-base, 0.2s);
|
||
}
|
||
|
||
.b03-file__card-remove:hover {
|
||
color: var(--color-danger, #dc2626);
|
||
border-color: var(--color-danger, #dc2626);
|
||
background: #fef2f2;
|
||
}
|
||
|
||
.b03-file__card-content {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: var(--spacing-8);
|
||
}
|
||
|
||
/* 빈 칸은 제목 줄만 남긴다 — 파일이 붙으면 이름·크기가, 올라가는 중에는 진행바가 선다. */
|
||
.b03-file__card--empty .b03-file__card-content {
|
||
display: none;
|
||
}
|
||
|
||
/* [선택]은 제목 줄 오른쪽 끝의 작은 버튼 — 종전 전폭 40px 버튼이 카드 높이를 키웠다. */
|
||
.b03-file__card-select {
|
||
flex: 0 0 auto;
|
||
min-height: 26px;
|
||
padding: 0 var(--spacing-8);
|
||
border: 1px solid var(--color-mist, #e6e2e3);
|
||
border-radius: var(--radius-buttons, 8px);
|
||
color: var(--color-deep-iris, #26114a);
|
||
background: var(--color-canvas, #ffffff);
|
||
font-weight: var(--font-weight-medium, 500);
|
||
font-size: var(--text-caption, 12px);
|
||
white-space: nowrap;
|
||
cursor: pointer;
|
||
transition:
|
||
background var(--transition-base, 0.2s),
|
||
border-color var(--transition-base, 0.2s);
|
||
}
|
||
|
||
.b03-file__file-info {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 4px;
|
||
min-width: 0;
|
||
}
|
||
|
||
.b03-file__file-name {
|
||
color: var(--color-deep-iris, #26114a);
|
||
font-size: var(--text-body-sm, 14px);
|
||
font-weight: var(--font-weight-medium, 500);
|
||
overflow-wrap: anywhere;
|
||
}
|
||
|
||
/* 진행바·속도·예상완료는 **올라가는 동안만** 보인다(2026-09-03) — 끝난 카드에 남겨 두면
|
||
읽을 일 없는 세 줄이 카드 높이를 그대로 차지했다. */
|
||
.b03-file__progress-section {
|
||
display: none;
|
||
flex-direction: column;
|
||
gap: var(--spacing-8);
|
||
}
|
||
|
||
.b03-file__card--uploading .b03-file__progress-section {
|
||
display: flex;
|
||
}
|
||
|
||
.b03-file__progress-bar-container {
|
||
width: 100%;
|
||
height: 6px;
|
||
overflow: hidden;
|
||
border-radius: var(--radius-pills, 1440px);
|
||
background: var(--color-mist, #e6e2e3);
|
||
}
|
||
|
||
.b03-file__progress-bar {
|
||
width: 0;
|
||
height: 100%;
|
||
border-radius: var(--radius-pills, 1440px);
|
||
background: var(--color-royal-amethyst, #3e0079);
|
||
transition: width var(--transition-base, 0.2s);
|
||
}
|
||
|
||
.b03-file__progress-info {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 2px;
|
||
}
|
||
|
||
.b03-file__error-message {
|
||
display: none;
|
||
padding: var(--spacing-8) var(--spacing-12);
|
||
border-radius: var(--radius-cards, 8px);
|
||
color: var(--color-danger, #dc2626);
|
||
background: #fef2f2;
|
||
font-size: var(--text-caption, 12px);
|
||
border: 1px solid rgba(220, 38, 38, 0.15);
|
||
}
|
||
|
||
.b03-file__card--empty .b03-file__file-info,
|
||
.b03-file__card--empty .b03-file__progress-section,
|
||
.b03-file__card--empty .b03-file__error-message {
|
||
display: none;
|
||
}
|
||
|
||
.b03-file__card--selected .b03-file__progress-section {
|
||
display: none;
|
||
}
|
||
|
||
.b03-file__card--uploading .b03-file__card-select,
|
||
.b03-file__card--completed .b03-file__card-select {
|
||
display: none;
|
||
}
|
||
|
||
.b03-file__card--error .b03-file__error-message {
|
||
display: block;
|
||
}
|
||
|
||
.b03-file__card--error .b03-file__progress-section {
|
||
display: none;
|
||
}
|
||
|
||
.b03-file__results {
|
||
margin: var(--spacing-8) 0 0 0;
|
||
padding: 0;
|
||
list-style: none;
|
||
border: 1px solid var(--color-mist, #e6e2e3);
|
||
border-radius: var(--radius-cards, 8px);
|
||
overflow: hidden;
|
||
background: var(--color-canvas, #ffffff);
|
||
}
|
||
|
||
.b03-file__results:empty {
|
||
display: none;
|
||
}
|
||
|
||
.b03-file__results li {
|
||
padding: var(--spacing-12) var(--spacing-16);
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 2px;
|
||
border-bottom: 1px solid var(--color-mist, #e6e2e3);
|
||
color: var(--color-deep-iris, #26114a);
|
||
font-size: var(--text-body-sm, 14px);
|
||
}
|
||
|
||
.b03-file__results li:last-child {
|
||
border-bottom: 0;
|
||
}
|
||
|
||
@media (max-width: 1440px) {
|
||
/* 좁아지면 두 컨테이너를 위아래로 쌓는다 — 카드가 눌려 글자가 접히는 것을 막는다. */
|
||
.b03-file__columns {
|
||
grid-template-columns: 1fr;
|
||
}
|
||
}
|
||
|
||
@media (max-width: 720px) {
|
||
.b03-file {
|
||
padding: var(--spacing-16) var(--spacing-12);
|
||
}
|
||
|
||
.b03-file__group-content {
|
||
grid-template-columns: 1fr; /* 모바일에서는 1행 1열 구조 */
|
||
}
|
||
}
|
||
|
||
/* LAS 없는 설계(도엽등고선 기반) 토글 — 2026-08-30 */
|
||
.b03-file__lasfree {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
padding: 4px 2px;
|
||
font-size: var(--text-body);
|
||
color: var(--color-text-body);
|
||
cursor: pointer;
|
||
user-select: none;
|
||
}
|
||
|
||
.b03-file__card--disabled {
|
||
opacity: 0.45;
|
||
pointer-events: none;
|
||
}
|