Files
Aislo/B03_FileInput/B03_FileInput_UI_Style.css
T
eomsangdonandClaude Opus 5 41c1771fad feat(B03): 부속 파일 카드에 파일 속 값 표시·래스터 썸네일 점선 테두리
개수만 보이던 부속 파일 카드에 파일 안의 중요한 값을 함께 보임.

- .shx — 도형 종류(폴리라인 등)와 범위 크기를 머리글에서 읽음.
- .dbf — 속성 이름 목록을 머리글 서술자에서 읽음(앞 4개).
- .cpg — 같은 세트 .dbf 의 첫 글자 속성을 그 인코딩으로 읽어 견본으로 보임.
- .prj — 중앙자오선(투영 매개변수)과 길이 단위. proj 문자열 변환을 쓰지 않아
  정보 손실 경고가 나지 않음.
- 카드 표시 줄 수를 2 → 3 으로 늘리고, 길이 단위 표기를 m 으로 통일.
- GeoTIFF 썸네일에 다른 미리보기와 같은 점선 테두리.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-04 22:16:14 +09:00

714 lines
20 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
.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 → 16 (2026-09-03) — 고르는 자리만 남기고 안내를 좌측 패널로 뺐다.
`--spacing-20`은 테마에 없는 토큰이라 선언째 무효가 된다(패딩이 통째로 사라짐). */
padding: var(--spacing-16);
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).
좁아지면 아래로 접히되, 선택 영역이 남는 폭을 먹는다. */
/* 셋을 같은 폭·같은 높이로 나눈다 — 열 1:1:1(2026-09-03 사용자 지시).
flex 로는 버튼·드롭존의 내용 폭이 배분에 섞여 288·254·288 로 어긋났다. 격자는
칸을 먼저 나누므로 내용과 무관하게 정확히 1:1:1 이 된다. 좁아지면 칸이 접힌다. */
.b03-file__pick-row {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
align-items: stretch;
gap: var(--spacing-8);
}
.b03-file__pick-row > * {
min-width: 0;
}
/* 칸을 꽉 채워야 세 칸의 높이가 같아진다 — 버튼은 기본이 내용 크기다. */
.b03-file__pick-row .b03-file__temp-picker > .ui-btn,
.b03-file__pick-row > .ui-btn {
width: 100%;
height: 100%;
}
/* 한 줄 바(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);
}
/* 빈 오류 줄이 자리를 잡고 있으면 토글 아래가 통째로 비어 보인다 — 글자가 있을 때만
자리를 차지한다(2026-09-03 사용자 지시). */
.b03-file__error {
color: var(--color-danger, #dc2626);
font-size: var(--text-body-sm, 14px);
margin: 0;
}
.b03-file__error:empty {
display: none;
}
.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;
}
/* LAS 없이 설계 토글 — 파일 입력 컨테이너의 스위치(2026-09-03 사용자 지시).
B04 좌측 패널의 체크 줄(`b04-surface__check`)과 같은 서식이다. */
.b03-file__lasfree {
display: flex;
align-items: center;
gap: var(--spacing-8);
align-self: flex-start;
padding: var(--spacing-8) var(--spacing-12);
border: 1px solid var(--color-mist, #e6e2e3);
border-radius: var(--radius-buttons, 8px);
font-size: var(--text-body-sm, 14px);
color: var(--color-deep-iris, #26114a);
cursor: pointer;
transition: border-color var(--transition-base, 0.2s);
}
.b03-file__lasfree:hover {
border-color: var(--color-royal-amethyst, #3e0079);
}
.b03-file__lasfree input {
width: 16px;
height: 16px;
margin: 0;
accent-color: var(--color-royal-amethyst, #3e0079);
cursor: pointer;
}
/* 켜져 있으면 스위치 자신도 켜진 티를 낸다 — 지형 컨테이너가 왜 잠겼는지의 근거. */
.b03-file__lasfree:has(input:checked) {
border-color: var(--color-royal-amethyst, #3e0079);
background: var(--color-mist-violet, #edecff);
font-weight: var(--font-weight-medium, 500);
}
/* LAS 없이 설계를 켜면 지형 컨테이너는 받지 않는다 — 잠긴 것이 보이게 흐린다. */
.b03-file__group--disabled {
opacity: 0.55;
}
.b03-file__card--disabled {
background: var(--color-paper, #f6f7fa);
border-style: dashed;
}
.b03-file__card--disabled .b03-file__card-select {
cursor: not-allowed;
}
/* 좌측 안내 패널이 열리면 본문을 그만큼 밀어낸다 — 공용 워크플로 레이아웃(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) — 본문에서 뺀 설명이 사는 자리.
양식은 B04~B07 좌측 패널과 **같은 공용 양식**이다: 루트 `__form`, 문단은
`ui-collapsible ui-sidebar-section`(외곽선·접힘·캐럿은 공용 CSS 몫), 제목은
`__group-legend` 크기. 여기서는 값만 맞추고 새로 만들지 않는다. --- */
.b03-file__form {
display: flex;
flex-direction: column;
gap: var(--spacing-16);
padding: var(--spacing-16);
}
.b03-file__guide-group {
display: flex;
flex-direction: column;
gap: var(--spacing-8);
margin: 0;
padding: var(--spacing-16);
border-radius: var(--radius-cards);
background-color: var(--color-surface-raised);
}
.b03-file__guide-legend {
margin: 0;
padding: 0 var(--spacing-8);
font-size: var(--text-caption);
font-weight: var(--font-weight-medium);
color: var(--color-text-secondary);
}
/* 글자 크기·색도 공용 양식 그대로 — B04 좌측 패널 본문(`b04-surface__check`)과 같은
`--text-body-sm` · `--color-text-body`(2026-09-03 사용자 지시: 양식 = 글자 크기 포함). */
.b03-file__guide-list {
margin: 0;
padding-left: var(--spacing-16);
display: flex;
flex-direction: column;
gap: var(--spacing-4);
font-size: var(--text-body-sm);
color: var(--color-text-body);
}
.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;
}
/* 카드가 좁아지면 한 줄에 제목·상태·[선택]이 못 들어가 제목이 글자 단위로 접힌다
(2026-09-03 실측: 안내 패널을 연 상태에서 카드 폭 210px). 폭이 모자라면 열을 줄인다. */
.b03-file__group-content {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(260px, 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);
/* 제목은 한 줄로 두고 모자라면 말줄임 — 접히면 카드가 세로로 길어진다(2026-09-03). */
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.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__preview,
.b03-file__card--empty .b03-file__progress-section,
.b03-file__card--empty .b03-file__error-message {
display: none;
}
/* 업로드 자료 미리보기(2026-09-04) — 분석 메타데이터의 범위만으로 그리는 작은 도형.
값이 없으면 `is-visible` 이 안 붙어 자리를 차지하지 않는다. */
.b03-file__preview {
display: none;
margin-top: 6px;
}
/* 카드 한 행을 전부 쓰고 높이는 고정한다 (2026-09-04 사용자 지시) — 카드 높이가
파일마다 들쭉날쭉하지 않게. 그림·썸네일·값 표시가 모두 같은 상자를 쓴다. */
.b03-file__preview.is-visible {
display: flex;
grid-column: 1 / -1;
align-items: center;
justify-content: center;
width: 100%;
height: 120px;
overflow: hidden;
border: 1px solid var(--color-border, #dcdce6);
border-radius: var(--radius-cards, 8px);
background: var(--color-surface, #fff);
}
.b03-file__preview svg {
display: block;
width: 100%;
height: 100%;
}
/* 라이다 탑뷰 점 그림 — 점이 5천 개라 선 하나로 묶어 그린다. */
.b03-file__preview-cloud {
fill: none;
stroke: var(--color-text-muted, #5a5a72);
stroke-linecap: round;
stroke-opacity: 0.55;
stroke-width: 0.7;
}
/* GeoTIFF 저해상 썸네일 — 원본 비율을 지켜 상자 안에 맞춘다. 썸네일이 곧 자료 범위라
다른 그림의 점선 사각형과 같은 테두리를 둘러 셋이 같은 모양으로 보이게 한다
(2026-09-04 사용자 지적). */
.b03-file__preview-thumb {
max-width: 100%;
max-height: 100%;
border: 1px dashed var(--color-border, #9aa);
image-rendering: pixelated;
object-fit: contain;
}
/* 그릴 도형이 없는 부속 파일 — 구분되는 값을 큰 글씨로. */
.b03-file__preview-facts {
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
padding: 8px;
text-align: center;
}
.b03-file__preview-fact {
color: var(--color-text, #1c1c28);
font-size: var(--text-body, 15px);
font-weight: 600;
}
.b03-file__preview-fact-sub {
color: var(--color-text-muted, #5a5a72);
font-size: var(--text-caption, 12px);
}
.b03-file__preview-empty {
color: var(--color-text-muted, #8a8aa0);
font-size: var(--text-caption, 12px);
}
.b03-file__preview-extent {
fill: color-mix(in srgb, var(--color-border, #9aa) 12%, transparent);
stroke: var(--color-border, #9aa);
stroke-dasharray: 4 3;
stroke-width: 1;
}
.b03-file__preview-route {
fill: none;
stroke: var(--color-primary, #4a3aff);
stroke-linecap: round;
stroke-linejoin: round;
stroke-width: 1.5;
}
/* 계획노선이 지형 자료 범위를 벗어난 경우 — 눈으로 바로 잡히게 경고색. */
.b03-file__preview.is-warning .b03-file__preview-route {
stroke: var(--color-danger, #d33);
}
.b03-file__preview.is-warning .b03-file__preview-extent {
stroke: var(--color-danger, #d33);
stroke-dasharray: 3 2;
}
.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;
}