refactor(512-4 700 줄 나눔 CSS): App.css · B01 · B06 횡단 · B03 스타일 각 둘로 나눔 — 규칙 차례 그대로 · 부르는 곳 이어 부름 · 시험은 두 파일 이어 읽음

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-22 19:49:43 +09:00
co-authored by Claude Sonnet 5.5
parent 35a8ac9bac
commit cbfc006834
22 changed files with 1659 additions and 1648 deletions
@@ -10,6 +10,7 @@ import "../../B06_Section/B06_Section_UI_Style.css";
// SVG 차트 색상(.b06-chart__*)의 정의처는 _Style_Cross.css다. 이걸 빼면 B05로 바로 진입했을 때
// 배경 rect가 브라우저 기본 fill(검정)로 그려진다 — B06을 먼저 방문해야 정상으로 보이던 원인.
import "../../B06_Section/B06_Section_UI_Style_Cross.css";
import "../../B06_Section/B06_Section_UI_Style_Cross_Chart.css";
import "../../B06_Section/B06_Section_UI_Style_Cross_Areas.css";
export function createProfileFrame(view: string) {
+1
View File
@@ -64,6 +64,7 @@ import {
} from "../../B06_Section/B06_Section_UI_Page_Structures_Selection";
import "../../B06_Section/B06_Section_UI_Style.css";
import "../../B06_Section/B06_Section_UI_Style_Cross.css";
import "../../B06_Section/B06_Section_UI_Style_Cross_Chart.css";
import "../../B06_Section/B06_Section_UI_Style_Cross_Controls.css";
import "../../B06_Section/B06_Section_UI_Style_Cross_Areas.css";
import { loadSectionDetail } from "../../B06_Section/B06_Section_Section_Store";
+1
View File
@@ -49,6 +49,7 @@ import { buildResourcePanel } from "./B01_Dashboard_UI_Resources";
import { buildTempUploadSection } from "./B01_Dashboard_UI_TempUpload";
import { buildKnowledgeChat } from "./B01_Dashboard_UI_Knowledge_Chat";
import "./B01_Dashboard_UI_Style.css";
import "./B01_Dashboard_UI_Style_Company.css";
export interface DashboardState {
user: DashboardUser;
-425
View File
@@ -385,428 +385,3 @@
grid-template-columns: 1fr;
}
}
/* 회사 주소 입력 — 검색해서 고르는 칸 (2026-09-13).
라벨·입력·버튼을 한 줄에 세운다. ui-field 가 기본이 세로(라벨 위·입력 아래·오류 슬롯)라
그대로 두면 버튼이 오류 슬롯 높이만큼 밀려 수평이 어긋난다 — 이 칸에서만 가로로 눕힌다. */
.b01-dashboard__address {
display: flex;
flex-direction: column;
gap: var(--spacing-8, 8px);
}
.b01-dashboard__address-row {
display: flex;
align-items: center;
gap: var(--spacing-8, 8px);
}
.b01-dashboard__address-row > .ui-field {
display: flex;
flex: 1 1 auto;
flex-direction: row;
align-items: center;
gap: var(--spacing-8, 8px);
min-width: 0;
margin: 0;
}
.b01-dashboard__address .ui-field__label {
flex: 0 0 64px;
margin: 0;
white-space: nowrap;
}
.b01-dashboard__address .ui-input {
flex: 1 1 auto;
min-width: 0;
}
.b01-dashboard__address .ui-field__error {
display: none;
}
.b01-dashboard__address-row > .ui-btn {
flex: 0 0 auto;
}
.b01-dashboard__address-zip {
flex: 0 0 auto;
color: var(--color-text-muted, #666);
font-size: 0.85rem;
white-space: nowrap;
}
.b01-dashboard__address-list {
display: flex;
flex-direction: column;
max-height: 220px;
overflow-y: auto;
overscroll-behavior: contain;
border: 1px solid var(--color-border);
border-radius: var(--radius-8, 8px);
}
.b01-dashboard__address-item {
display: flex;
flex-direction: column;
gap: 2px;
padding: var(--spacing-8, 8px);
border: 0;
border-bottom: 1px solid var(--color-border);
background: transparent;
color: inherit;
text-align: left;
cursor: pointer;
}
.b01-dashboard__address-item:last-child {
border-bottom: 0;
}
.b01-dashboard__address-item:hover,
.b01-dashboard__address-item:focus-visible {
background: var(--color-surface-hover, rgba(0, 0, 0, 0.04));
}
.b01-dashboard__address-item small {
color: var(--color-text-muted, #666);
}
.b01-dashboard__map-zoom {
display: flex;
gap: var(--spacing-8, 8px);
margin-bottom: var(--spacing-8, 8px);
}
/* 회사 주소 지도 미리보기 — 타일 3×3 을 붙이고 가운데 표식을 찍는다 (2026-09-06). */
.b01-dashboard__map-frame {
position: relative;
width: 100%;
max-width: 384px;
aspect-ratio: 1;
overflow: hidden;
border: 1px solid var(--color-border);
border-radius: var(--radius-8, 8px);
}
.b01-dashboard__map-grid {
display: grid;
grid-template-columns: repeat(3, 256px);
transform: scale(0.5);
transform-origin: top left;
}
.b01-dashboard__map-marker {
position: absolute;
width: 12px;
height: 12px;
margin: -6px 0 0 -6px;
border: 2px solid var(--color-surface, #fff);
border-radius: 50%;
background: var(--color-danger, #d33);
}
/* 프로젝트 참여자 고르기 (2026-09-06). */
.b01-dashboard__members {
display: flex;
flex-direction: column;
gap: var(--spacing-4, 4px);
max-height: 160px;
overflow-y: auto;
}
.b01-dashboard__member-row {
display: flex;
align-items: center;
gap: var(--spacing-8);
}
.b01-knowledge-chat {
position: fixed;
right: 24px;
bottom: 24px;
z-index: 100;
display: flex;
flex-direction: column-reverse;
align-items: flex-end;
gap: 8px;
}
.b01-knowledge-chat__toggle,
.b01-knowledge-chat__form button {
border: 0;
background: var(--color-primary);
color: var(--color-primary-text);
font: inherit;
cursor: pointer;
}
.b01-knowledge-chat__toggle {
display: grid;
width: 58px;
height: 58px;
place-items: center;
border-radius: 50%;
box-shadow: 0 4px 16px #0004;
}
.b01-knowledge-chat__toggle svg {
width: 30px;
height: 30px;
}
.b01-knowledge-chat__panel {
display: flex;
flex-direction: column;
width: min(380px, calc(100vw - 32px));
height: min(680px, calc(100dvh - 104px));
border: 1px solid var(--color-border);
border-radius: 12px;
background: var(--color-surface, #fff);
box-shadow: 0 8px 28px #0003;
color: var(--color-text-body);
overflow: hidden;
overscroll-behavior: contain;
}
.b01-knowledge-chat__panel[hidden] {
display: none;
}
.b01-knowledge-chat__panel header {
display: flex;
align-items: center;
gap: 10px;
padding: 10px 14px;
border-bottom: 1px solid var(--color-border);
}
.b01-knowledge-chat__avatar {
display: grid;
width: 34px;
height: 34px;
place-items: center;
border-radius: 50%;
background: var(--color-primary);
color: var(--color-primary-text);
}
.b01-knowledge-chat__avatar svg {
width: 21px;
height: 21px;
}
.b01-knowledge-chat__close {
margin-left: auto;
border: 0;
background: transparent;
color: inherit;
font: inherit;
font-size: 26px;
cursor: pointer;
}
.b01-knowledge-chat__messages {
display: flex;
flex: 1;
flex-direction: column;
gap: 12px;
min-height: 0;
padding: 16px 12px;
overflow-y: auto;
overscroll-behavior: contain;
}
.b01-knowledge-chat__user,
.b01-knowledge-chat__reply {
max-width: 88%;
margin: 0;
padding: 10px 12px;
border-radius: 14px;
overflow-wrap: anywhere;
white-space: pre-wrap;
}
.b01-knowledge-chat__user {
align-self: flex-end;
border-bottom-right-radius: 4px;
background: var(--color-primary);
color: var(--color-primary-text);
}
.b01-knowledge-chat__reply {
align-self: flex-start;
border: 1px solid var(--color-border);
border-bottom-left-radius: 4px;
background: var(--color-surface-raised);
}
.b01-knowledge-chat__reply details {
margin-top: 8px;
font-size: 0.9em;
}
.b01-knowledge-chat__reply summary {
cursor: pointer;
overflow-wrap: anywhere;
}
.b01-knowledge-chat__reply pre {
max-height: 220px;
overflow: auto;
white-space: pre-wrap;
font: inherit;
}
.b01-knowledge-chat__sources {
display: grid;
gap: 6px;
margin-top: 12px;
padding-top: 10px;
border-top: 1px solid var(--color-border);
}
.b01-knowledge-chat__sources > summary {
margin-bottom: 3px;
color: var(--color-text-secondary, #666);
font-size: 0.85em;
}
.b01-knowledge-chat__source {
display: grid;
gap: 3px;
width: 100%;
padding: 8px 10px;
border: 1px solid var(--color-border);
border-radius: 8px;
background: var(--color-surface, #fff);
color: inherit;
text-align: left;
cursor: pointer;
}
.b01-knowledge-chat__source span {
color: var(--color-text-secondary, #666);
font-size: 0.8em;
overflow-wrap: anywhere;
}
.b01-knowledge-source-modal.ui-modal {
width: min(900px, 94vw);
--modal-max: 88vh;
}
.b01-knowledge-source-modal__content {
max-height: calc(88vh - 100px);
overflow: auto;
overscroll-behavior: contain;
padding: 8px 16px;
line-height: 1.75;
overflow-wrap: anywhere;
}
.b01-knowledge-source-modal__content h2,
.b01-knowledge-source-modal__content h3,
.b01-knowledge-source-modal__content h4,
.b01-knowledge-source-modal__content h5 {
margin: 1.4em 0 0.5em;
line-height: 1.4;
}
.b01-knowledge-source-modal__content p,
.b01-knowledge-source-modal__content ul,
.b01-knowledge-source-modal__content ol {
margin: 0.6em 0 1em;
}
.b01-knowledge-source-modal__content code {
padding: 0.1em 0.35em;
border-radius: 4px;
background: var(--color-surface);
}
.b01-knowledge-source-modal__content .ui-markdown-table {
max-width: 100%;
overflow-x: auto;
overscroll-behavior: contain;
}
.b01-knowledge-source-modal__content table {
width: 100%;
border-collapse: collapse;
font-size: 0.92em;
}
.b01-knowledge-source-modal__content th,
.b01-knowledge-source-modal__content td {
padding: 8px 10px;
border: 1px solid var(--color-border);
text-align: left;
vertical-align: top;
}
.b01-knowledge-source-modal__content th {
background: var(--color-surface);
}
.b01-knowledge-chat__form {
display: flex;
align-items: flex-end;
gap: 8px;
padding: 8px;
border-top: 1px solid var(--color-border);
}
.b01-knowledge-chat__form textarea {
min-width: 0;
flex: 1;
min-height: 56px;
max-height: 140px;
padding: 8px;
border: 1px solid var(--color-border);
border-radius: 6px;
background: var(--color-canvas);
color: var(--color-text-body);
font: inherit;
resize: vertical;
overflow-y: auto;
}
.b01-knowledge-chat__form textarea::placeholder {
color: var(--color-text-muted);
}
.b01-knowledge-chat__form button {
padding: 9px 14px;
border-radius: 8px;
}
.b01-knowledge-chat button:focus-visible,
.b01-knowledge-chat textarea:focus-visible {
outline: 2px solid var(--color-royal-amethyst, #6843a7);
outline-offset: 2px;
}
/* 계산 자리 창(504-2) — 묶음 · 까닭 글은 줄바꿈 · 체크 칸은 가운데 */
.b01-dashboard__calc-sites .b01-dashboard__table td {
white-space: normal;
}
.b01-dashboard__calc-sites .b01-dashboard__table td:nth-child(2),
.b01-dashboard__calc-sites .b01-dashboard__table td:nth-child(3) {
text-align: center;
}
.b01-dashboard__calc-sites .b01-dashboard__calc-group td {
background: var(--color-surface);
font-weight: var(--font-weight-medium);
}
.b01-dashboard__calc-sites .b01-dashboard__calc-name {
padding-left: var(--spacing-16);
}
.b01-dashboard__calc-sites .b01-dashboard__calc-group .b01-dashboard__calc-name {
padding-left: 0;
}
.b01-dashboard__calc-count,
.b01-dashboard__calc-note {
margin: 0 0 0.5rem;
}
@@ -0,0 +1,424 @@
/* 회사 주소 입력 — 검색해서 고르는 칸 (2026-09-13).
라벨·입력·버튼을 한 줄에 세운다. ui-field 가 기본이 세로(라벨 위·입력 아래·오류 슬롯)라
그대로 두면 버튼이 오류 슬롯 높이만큼 밀려 수평이 어긋난다 — 이 칸에서만 가로로 눕힌다. */
.b01-dashboard__address {
display: flex;
flex-direction: column;
gap: var(--spacing-8, 8px);
}
.b01-dashboard__address-row {
display: flex;
align-items: center;
gap: var(--spacing-8, 8px);
}
.b01-dashboard__address-row > .ui-field {
display: flex;
flex: 1 1 auto;
flex-direction: row;
align-items: center;
gap: var(--spacing-8, 8px);
min-width: 0;
margin: 0;
}
.b01-dashboard__address .ui-field__label {
flex: 0 0 64px;
margin: 0;
white-space: nowrap;
}
.b01-dashboard__address .ui-input {
flex: 1 1 auto;
min-width: 0;
}
.b01-dashboard__address .ui-field__error {
display: none;
}
.b01-dashboard__address-row > .ui-btn {
flex: 0 0 auto;
}
.b01-dashboard__address-zip {
flex: 0 0 auto;
color: var(--color-text-muted, #666);
font-size: 0.85rem;
white-space: nowrap;
}
.b01-dashboard__address-list {
display: flex;
flex-direction: column;
max-height: 220px;
overflow-y: auto;
overscroll-behavior: contain;
border: 1px solid var(--color-border);
border-radius: var(--radius-8, 8px);
}
.b01-dashboard__address-item {
display: flex;
flex-direction: column;
gap: 2px;
padding: var(--spacing-8, 8px);
border: 0;
border-bottom: 1px solid var(--color-border);
background: transparent;
color: inherit;
text-align: left;
cursor: pointer;
}
.b01-dashboard__address-item:last-child {
border-bottom: 0;
}
.b01-dashboard__address-item:hover,
.b01-dashboard__address-item:focus-visible {
background: var(--color-surface-hover, rgba(0, 0, 0, 0.04));
}
.b01-dashboard__address-item small {
color: var(--color-text-muted, #666);
}
.b01-dashboard__map-zoom {
display: flex;
gap: var(--spacing-8, 8px);
margin-bottom: var(--spacing-8, 8px);
}
/* 회사 주소 지도 미리보기 — 타일 3×3 을 붙이고 가운데 표식을 찍는다 (2026-09-06). */
.b01-dashboard__map-frame {
position: relative;
width: 100%;
max-width: 384px;
aspect-ratio: 1;
overflow: hidden;
border: 1px solid var(--color-border);
border-radius: var(--radius-8, 8px);
}
.b01-dashboard__map-grid {
display: grid;
grid-template-columns: repeat(3, 256px);
transform: scale(0.5);
transform-origin: top left;
}
.b01-dashboard__map-marker {
position: absolute;
width: 12px;
height: 12px;
margin: -6px 0 0 -6px;
border: 2px solid var(--color-surface, #fff);
border-radius: 50%;
background: var(--color-danger, #d33);
}
/* 프로젝트 참여자 고르기 (2026-09-06). */
.b01-dashboard__members {
display: flex;
flex-direction: column;
gap: var(--spacing-4, 4px);
max-height: 160px;
overflow-y: auto;
}
.b01-dashboard__member-row {
display: flex;
align-items: center;
gap: var(--spacing-8);
}
.b01-knowledge-chat {
position: fixed;
right: 24px;
bottom: 24px;
z-index: 100;
display: flex;
flex-direction: column-reverse;
align-items: flex-end;
gap: 8px;
}
.b01-knowledge-chat__toggle,
.b01-knowledge-chat__form button {
border: 0;
background: var(--color-primary);
color: var(--color-primary-text);
font: inherit;
cursor: pointer;
}
.b01-knowledge-chat__toggle {
display: grid;
width: 58px;
height: 58px;
place-items: center;
border-radius: 50%;
box-shadow: 0 4px 16px #0004;
}
.b01-knowledge-chat__toggle svg {
width: 30px;
height: 30px;
}
.b01-knowledge-chat__panel {
display: flex;
flex-direction: column;
width: min(380px, calc(100vw - 32px));
height: min(680px, calc(100dvh - 104px));
border: 1px solid var(--color-border);
border-radius: 12px;
background: var(--color-surface, #fff);
box-shadow: 0 8px 28px #0003;
color: var(--color-text-body);
overflow: hidden;
overscroll-behavior: contain;
}
.b01-knowledge-chat__panel[hidden] {
display: none;
}
.b01-knowledge-chat__panel header {
display: flex;
align-items: center;
gap: 10px;
padding: 10px 14px;
border-bottom: 1px solid var(--color-border);
}
.b01-knowledge-chat__avatar {
display: grid;
width: 34px;
height: 34px;
place-items: center;
border-radius: 50%;
background: var(--color-primary);
color: var(--color-primary-text);
}
.b01-knowledge-chat__avatar svg {
width: 21px;
height: 21px;
}
.b01-knowledge-chat__close {
margin-left: auto;
border: 0;
background: transparent;
color: inherit;
font: inherit;
font-size: 26px;
cursor: pointer;
}
.b01-knowledge-chat__messages {
display: flex;
flex: 1;
flex-direction: column;
gap: 12px;
min-height: 0;
padding: 16px 12px;
overflow-y: auto;
overscroll-behavior: contain;
}
.b01-knowledge-chat__user,
.b01-knowledge-chat__reply {
max-width: 88%;
margin: 0;
padding: 10px 12px;
border-radius: 14px;
overflow-wrap: anywhere;
white-space: pre-wrap;
}
.b01-knowledge-chat__user {
align-self: flex-end;
border-bottom-right-radius: 4px;
background: var(--color-primary);
color: var(--color-primary-text);
}
.b01-knowledge-chat__reply {
align-self: flex-start;
border: 1px solid var(--color-border);
border-bottom-left-radius: 4px;
background: var(--color-surface-raised);
}
.b01-knowledge-chat__reply details {
margin-top: 8px;
font-size: 0.9em;
}
.b01-knowledge-chat__reply summary {
cursor: pointer;
overflow-wrap: anywhere;
}
.b01-knowledge-chat__reply pre {
max-height: 220px;
overflow: auto;
white-space: pre-wrap;
font: inherit;
}
.b01-knowledge-chat__sources {
display: grid;
gap: 6px;
margin-top: 12px;
padding-top: 10px;
border-top: 1px solid var(--color-border);
}
.b01-knowledge-chat__sources > summary {
margin-bottom: 3px;
color: var(--color-text-secondary, #666);
font-size: 0.85em;
}
.b01-knowledge-chat__source {
display: grid;
gap: 3px;
width: 100%;
padding: 8px 10px;
border: 1px solid var(--color-border);
border-radius: 8px;
background: var(--color-surface, #fff);
color: inherit;
text-align: left;
cursor: pointer;
}
.b01-knowledge-chat__source span {
color: var(--color-text-secondary, #666);
font-size: 0.8em;
overflow-wrap: anywhere;
}
.b01-knowledge-source-modal.ui-modal {
width: min(900px, 94vw);
--modal-max: 88vh;
}
.b01-knowledge-source-modal__content {
max-height: calc(88vh - 100px);
overflow: auto;
overscroll-behavior: contain;
padding: 8px 16px;
line-height: 1.75;
overflow-wrap: anywhere;
}
.b01-knowledge-source-modal__content h2,
.b01-knowledge-source-modal__content h3,
.b01-knowledge-source-modal__content h4,
.b01-knowledge-source-modal__content h5 {
margin: 1.4em 0 0.5em;
line-height: 1.4;
}
.b01-knowledge-source-modal__content p,
.b01-knowledge-source-modal__content ul,
.b01-knowledge-source-modal__content ol {
margin: 0.6em 0 1em;
}
.b01-knowledge-source-modal__content code {
padding: 0.1em 0.35em;
border-radius: 4px;
background: var(--color-surface);
}
.b01-knowledge-source-modal__content .ui-markdown-table {
max-width: 100%;
overflow-x: auto;
overscroll-behavior: contain;
}
.b01-knowledge-source-modal__content table {
width: 100%;
border-collapse: collapse;
font-size: 0.92em;
}
.b01-knowledge-source-modal__content th,
.b01-knowledge-source-modal__content td {
padding: 8px 10px;
border: 1px solid var(--color-border);
text-align: left;
vertical-align: top;
}
.b01-knowledge-source-modal__content th {
background: var(--color-surface);
}
.b01-knowledge-chat__form {
display: flex;
align-items: flex-end;
gap: 8px;
padding: 8px;
border-top: 1px solid var(--color-border);
}
.b01-knowledge-chat__form textarea {
min-width: 0;
flex: 1;
min-height: 56px;
max-height: 140px;
padding: 8px;
border: 1px solid var(--color-border);
border-radius: 6px;
background: var(--color-canvas);
color: var(--color-text-body);
font: inherit;
resize: vertical;
overflow-y: auto;
}
.b01-knowledge-chat__form textarea::placeholder {
color: var(--color-text-muted);
}
.b01-knowledge-chat__form button {
padding: 9px 14px;
border-radius: 8px;
}
.b01-knowledge-chat button:focus-visible,
.b01-knowledge-chat textarea:focus-visible {
outline: 2px solid var(--color-royal-amethyst, #6843a7);
outline-offset: 2px;
}
/* 계산 자리 창(504-2) — 묶음 · 까닭 글은 줄바꿈 · 체크 칸은 가운데 */
.b01-dashboard__calc-sites .b01-dashboard__table td {
white-space: normal;
}
.b01-dashboard__calc-sites .b01-dashboard__table td:nth-child(2),
.b01-dashboard__calc-sites .b01-dashboard__table td:nth-child(3) {
text-align: center;
}
.b01-dashboard__calc-sites .b01-dashboard__calc-group td {
background: var(--color-surface);
font-weight: var(--font-weight-medium);
}
.b01-dashboard__calc-sites .b01-dashboard__calc-name {
padding-left: var(--spacing-16);
}
.b01-dashboard__calc-sites .b01-dashboard__calc-group .b01-dashboard__calc-name {
padding-left: 0;
}
.b01-dashboard__calc-count,
.b01-dashboard__calc-note {
margin: 0 0 0.5rem;
}
+1
View File
@@ -48,6 +48,7 @@ import {
type UploadStatus,
} from "./B03_FileInput_UI_Support";
import "./B03_FileInput_UI_Style.css";
import "./B03_FileInput_UI_Style_Card.css";
function L(key: keyof typeof ui_locales): string {
return ui_locales[key][currentLanguageIndex];
-364
View File
@@ -348,367 +348,3 @@
grid-template-columns: repeat(auto-fill, minmax(min(260px, 100%), 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). */
/* ⚠ 좁은 폭에서 배지·[선택]·[×] 가 밀려 나가지 않게 **줄 자체가 넘치지 않도록** 막는다
(2026-09-08). 제목은 이미 말줄임이라, 넘치는 것은 늘 오른쪽 붙박이들이었다. */
.b03-file__card-header {
display: flex;
flex-wrap: nowrap;
gap: var(--spacing-8);
align-items: center;
min-width: 0;
max-width: 100%;
}
.b03-file__card-header > * {
min-width: 0;
}
.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;
/* 계획노선 선 색 — 녹색(2026-09-04 사용자 지시). 지형 범위를 벗어나면 아래에서
붉은색으로 덮어써 경고로 쓴다. */
stroke: var(--color-success, #16a34a);
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;
}
/* 올리는 중에만 [파일 선택]을 감춘다. 끝난 카드에도 남겨 두어야 파일 하나를 갈아
끼우고 [파일 업로드]로 다시 돌릴 수 있다(2026-09-04 사용자 지시). */
.b03-file__card--uploading .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;
}
@@ -0,0 +1,363 @@
/* 업로드 중에는 화면 조작을 막는다 — 중복 업로드·단계 이동 방지(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). */
/* ⚠ 좁은 폭에서 배지·[선택]·[×] 가 밀려 나가지 않게 **줄 자체가 넘치지 않도록** 막는다
(2026-09-08). 제목은 이미 말줄임이라, 넘치는 것은 늘 오른쪽 붙박이들이었다. */
.b03-file__card-header {
display: flex;
flex-wrap: nowrap;
gap: var(--spacing-8);
align-items: center;
min-width: 0;
max-width: 100%;
}
.b03-file__card-header > * {
min-width: 0;
}
.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;
/* 계획노선 선 색 — 녹색(2026-09-04 사용자 지시). 지형 범위를 벗어나면 아래에서
붉은색으로 덮어써 경고로 쓴다. */
stroke: var(--color-success, #16a34a);
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;
}
/* 올리는 중에만 [파일 선택]을 감춘다. 끝난 카드에도 남겨 두어야 파일 하나를 갈아
끼우고 [파일 업로드]로 다시 돌릴 수 있다(2026-09-04 사용자 지시). */
.b03-file__card--uploading .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;
}
-374
View File
@@ -367,377 +367,3 @@ html.is-bm-route .b06-section__notice-bar {
color: var(--color-text-muted);
background: var(--color-surface);
}
/* SVG 차트 색상은 테마 토큰만 사용한다. */
.b06-chart__bg {
fill: var(--color-surface-raised);
}
/* 세로 창을 변환으로 옮기는 겹(2026-09-04) — 세로로 눌리거나 늘어나도 선 굵기·점선 간격은
그대로여야 한다. 변환이 걸려 있을 때만 적용해 B06 종단·횡단은 예전 그대로 그려진다. */
.b06-chart__ywindow[transform] * {
vector-effect: non-scaling-stroke;
}
.b06-chart__grid {
stroke: var(--color-border);
stroke-width: 1;
}
.b06-chart__axis {
stroke: var(--color-text-secondary);
stroke-width: 1;
}
.b06-chart__tick,
.b06-chart__station-label,
.b06-chart__axis-label {
fill: var(--color-text-secondary);
font-family: var(--font-body);
}
.b06-chart__tick,
.b06-chart__station-label {
font-size: 10px;
}
/* MC(곡선 가운데) 측점 = 사용자가 고칠 자리(507-3) — 한 단계 크게 · 굵게 · 경고색. 고름 빨강은 아래가 이김. */
.b06-chart__station-label--mc {
font-size: 12px;
font-weight: var(--font-weight-bold);
fill: var(--color-warning);
}
.b06-station--mc {
font-size: 1.15em;
font-weight: var(--font-weight-bold);
color: var(--color-warning);
}
/* 중심고 Y축 라벨(318-2) — 눈금과 같은 10px · 둥근 상자 · 축선 앞에서 멈춤 ·
바탕 = 불투명 섞음(겹친 눈금 글을 위에서 가림 · 319-1) · 색 = 원지반선 · 설계선(379-3 · `--b06-tag` = _Cross_Areas.css) */
.b06-chart__center-box {
fill: color-mix(in srgb, var(--b06-tag) 14%, var(--color-surface-raised));
stroke: var(--b06-tag);
stroke-width: 1;
}
.b06-chart__center-text {
fill: var(--b06-tag);
font-weight: var(--font-weight-medium);
}
/* 겹쳐 위 단으로 올린 측점 이름(407-4) — 선 · 지반선 위라 바탕색 테두리로 읽히게. */
.b06-chart__station-label--lifted {
paint-order: stroke;
stroke: var(--color-surface-raised);
stroke-width: 3px;
stroke-linejoin: round;
pointer-events: none;
}
/* 구조물(비정규) 측점 이름 — 종단면도 측점선 상단 표기. */
.b06-chart__structure-label {
font-size: 9px;
font-weight: var(--font-weight-medium);
fill: rgb(180 83 9);
}
.b06-chart__axis-label {
fill: var(--color-text-body);
font-size: var(--text-caption);
font-weight: var(--font-weight-medium);
}
.b06-chart__profile {
fill: none;
stroke: var(--color-chart-0);
stroke-width: 2.5;
}
/* 지반선 · 계획선은 누름을 통과 — 겹친 측점선 누름이 측점 고름 · 임시 횡단으로 감(505-3) */
.b06-chart__profile,
.b06-chart__design-profile {
pointer-events: none;
}
.b06-chart__cross-profile {
fill: none;
stroke: var(--color-chart-1);
stroke-width: 2.4;
}
/* 종단 계획선(시공계획고): 지반선과 구분되도록 파선 + 강조색 */
.b06-chart__design-profile {
fill: none;
stroke: var(--color-royal-amethyst);
stroke-width: 2.2;
stroke-dasharray: 8 4;
}
/* 절토(계획고가 지반고보다 낮음) / 성토 구간 음영 */
.b06-chart__band {
stroke: none;
}
.b06-chart__band--cut {
fill: rgb(220 38 38 / 14%);
}
.b06-chart__band--fill {
fill: rgb(37 99 235 / 14%);
}
.b06-chart__balance-boundary {
stroke: var(--color-royal-amethyst);
stroke-width: 1.2;
stroke-dasharray: 3 3;
opacity: 0.55;
}
.b06-chart__station {
cursor: pointer;
}
/* 구조물 측점선은 끌어 옮길 수 있다 — 커서로 그 사실을 알린다(2026-08-01 사용자 지시). */
.b06-chart__station--draggable {
cursor: ew-resize;
touch-action: none;
}
.b06-chart__station-line {
stroke-width: 1.2;
}
.b06-chart__station-hit {
stroke: transparent;
stroke-width: 14;
pointer-events: stroke;
}
.b06-chart__station-line--bp,
.b06-chart__station-line--regular,
.b06-chart__station-line--curve {
stroke: var(--color-warning);
}
.b06-chart__station-line--ep {
stroke: var(--color-accent);
stroke-dasharray: 4 3;
}
/* 비정규 측점(구조물)은 종단면도에서도 자수정색 파선으로 구분한다(B05 종단 규칙과 정합).
미선택 시 stroke 미정의로 세로선이 안 그려지던 문제 해소. */
.b06-chart__station-line--irregular {
stroke: var(--color-royal-amethyst, rgb(139 92 246));
stroke-width: 1.4;
stroke-dasharray: 5 3;
}
/* 추가 측점(368-3) = 일반측점 색 점선 */
.b06-chart__station-line--plus {
stroke: var(--color-warning);
stroke-dasharray: 5 3;
}
.b06-chart__station-line--selected,
.b06-chart__center-marker {
stroke: var(--color-danger);
stroke-width: 2.5;
}
/* 십자선이 계획 노선(계획고) 위치를 가리킬 때: 종단 계획선과 동일 색으로 대응시킨다 */
.b06-chart__center-marker--design {
stroke: var(--color-royal-amethyst);
}
.b06-chart__station--selected .b06-chart__station-label,
.b06-chart__station-label--selected {
fill: var(--color-danger);
font-weight: var(--font-weight-bold);
}
/* 측점 표준횡단 설계 지정 컨트롤 (카드 헤더 아래) — 좌측 여유 추가(2번).
한 행 고정(nowrap): 넘치는 컨트롤은 다음 행으로 밀지 않고 "⋯" 드롭다운으로 이동(N-2-2). */
.b06-design {
display: flex;
flex-wrap: nowrap;
align-items: center;
gap: var(--spacing-8) var(--spacing-16);
padding: var(--spacing-8) 0 var(--spacing-8) var(--spacing-16);
border-bottom: 1px solid var(--color-border);
margin-bottom: var(--spacing-8);
}
/* 오버플로 드롭다운(N-2-2): 넘친 컨트롤을 담는 우측 맞춤 "⋯" 메뉴. 세로 배치. */
.b06-design__more {
position: relative;
flex: 0 0 auto;
margin-left: auto;
}
.b06-design__more-summary {
display: inline-flex;
align-items: center;
justify-content: center;
width: 24px;
height: 22px;
border: 1px solid var(--color-border);
border-radius: var(--radius-inputs);
background: var(--color-surface);
color: var(--color-text-secondary);
font-size: 0.9rem;
line-height: 1;
cursor: pointer;
list-style: none;
}
.b06-design__more-summary::-webkit-details-marker {
display: none;
}
.b06-design__more[open] .b06-design__more-summary {
color: var(--color-surface);
background: var(--color-royal-amethyst);
border-color: var(--color-royal-amethyst);
}
.b06-design__more-panel {
position: absolute;
right: 0;
top: calc(100% + 4px);
z-index: 3;
display: flex;
flex-direction: column;
gap: var(--spacing-8);
padding: var(--spacing-8);
border: 1px solid var(--color-border);
border-radius: var(--radius-inputs);
background: var(--color-surface-raised);
box-shadow: var(--shadow-sm);
}
.b06-design__seg {
display: flex;
align-items: center;
gap: var(--spacing-8);
}
.b06-design__seg-legend {
font-size: 0.72rem;
color: var(--color-text-secondary);
white-space: nowrap;
}
/* 선행 조건 미충족 옵션 — 숨김(179-2 · 옛 E-6 「흐리게 늘 보임」 폐기 · 쪽은 단면유형 알약에). */
.b06-design__seg--disabled {
display: none;
}
.b06-design__seg-buttons {
display: inline-flex;
border: 1px solid var(--color-border);
border-radius: var(--radius-inputs);
overflow: hidden;
}
.b06-design__btn {
padding: 3px 8px;
font-size: 0.72rem;
color: var(--color-text-secondary);
background: var(--color-surface);
border: none;
border-left: 1px solid var(--color-border);
cursor: pointer;
}
.b06-design__btn:first-child {
border-left: none;
}
.b06-design__btn--active {
color: var(--color-surface);
background: var(--color-royal-amethyst);
font-weight: var(--font-weight-medium);
}
.b06-design__areas {
display: inline-flex;
gap: var(--spacing-8);
margin-left: auto;
font-size: 0.72rem;
font-family: var(--font-mono);
}
/* 암 경계선 제어(E-7) — 하단 정보 행 **왼쪽 맞춤**(318-2 · 중심고는 그래프 Y축 라벨 상자로 옮김). */
.b06-cross-card__rockb {
flex: 0 0 auto;
border-radius: var(--radius-inputs);
padding: 1px 4px;
}
/* 선 공용 칸(370-3) — 고른 선 제목 · 버튼 · 값 한 줄(넘치면 말줄임) · 빈 칸도 자리(띠 높이) 그대로. */
.b06-cross-card__linecell {
flex: 0 1 auto;
min-width: 0;
}
.b06-cross-card__linecell.is-empty {
visibility: hidden;
}
.b06-cross-card__linecell .b06-design__seg-buttons {
min-width: 0;
}
.b06-cross-card__linecell .b06-design__rockb-readout {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.b06-cross-card__linecell .b06-design__rockb-btn {
flex: 0 0 auto;
border-left: none;
}
.b06-cross-card__linecell
.b06-design__rockb-btn:not([hidden])
~ .b06-design__rockb-btn:not([hidden]) {
border-left: 1px solid var(--color-border);
}
/* 측점별 암 절토 경사(2026-09-07) — 행의 **오른쪽 끝**(암 경계 = 왼쪽). */
.b06-cross-card__cutslope {
margin-left: auto;
flex: 0 0 auto;
border-radius: var(--radius-inputs);
padding: 1px 4px;
}
.b06-design__cutslope-input {
width: 44px;
padding: 0 2px;
font-size: 0.72rem;
font-family: var(--font-mono);
text-align: right;
color: var(--color-text);
background: var(--color-surface);
border: 1px solid var(--color-border);
border-radius: var(--radius-inputs);
}
/* 화살표(스피너)는 칸이 좁아 지운다 — 값은 직접 넣거나 ↺ 로 되돌린다. */
.b06-design__cutslope-input::-webkit-outer-spin-button,
.b06-design__cutslope-input::-webkit-inner-spin-button {
margin: 0;
appearance: none;
}
.b06-design__cutslope-unit {
padding: 0 2px 0 1px;
font-size: 0.72rem;
color: var(--color-text-secondary);
align-self: center;
}
@@ -0,0 +1,373 @@
/* SVG 차트 색상은 테마 토큰만 사용한다. */
.b06-chart__bg {
fill: var(--color-surface-raised);
}
/* 세로 창을 변환으로 옮기는 겹(2026-09-04) — 세로로 눌리거나 늘어나도 선 굵기·점선 간격은
그대로여야 한다. 변환이 걸려 있을 때만 적용해 B06 종단·횡단은 예전 그대로 그려진다. */
.b06-chart__ywindow[transform] * {
vector-effect: non-scaling-stroke;
}
.b06-chart__grid {
stroke: var(--color-border);
stroke-width: 1;
}
.b06-chart__axis {
stroke: var(--color-text-secondary);
stroke-width: 1;
}
.b06-chart__tick,
.b06-chart__station-label,
.b06-chart__axis-label {
fill: var(--color-text-secondary);
font-family: var(--font-body);
}
.b06-chart__tick,
.b06-chart__station-label {
font-size: 10px;
}
/* MC(곡선 가운데) 측점 = 사용자가 고칠 자리(507-3) — 한 단계 크게 · 굵게 · 경고색. 고름 빨강은 아래가 이김. */
.b06-chart__station-label--mc {
font-size: 12px;
font-weight: var(--font-weight-bold);
fill: var(--color-warning);
}
.b06-station--mc {
font-size: 1.15em;
font-weight: var(--font-weight-bold);
color: var(--color-warning);
}
/* 중심고 Y축 라벨(318-2) — 눈금과 같은 10px · 둥근 상자 · 축선 앞에서 멈춤 ·
바탕 = 불투명 섞음(겹친 눈금 글을 위에서 가림 · 319-1) · 색 = 원지반선 · 설계선(379-3 · `--b06-tag` = _Cross_Areas.css) */
.b06-chart__center-box {
fill: color-mix(in srgb, var(--b06-tag) 14%, var(--color-surface-raised));
stroke: var(--b06-tag);
stroke-width: 1;
}
.b06-chart__center-text {
fill: var(--b06-tag);
font-weight: var(--font-weight-medium);
}
/* 겹쳐 위 단으로 올린 측점 이름(407-4) — 선 · 지반선 위라 바탕색 테두리로 읽히게. */
.b06-chart__station-label--lifted {
paint-order: stroke;
stroke: var(--color-surface-raised);
stroke-width: 3px;
stroke-linejoin: round;
pointer-events: none;
}
/* 구조물(비정규) 측점 이름 — 종단면도 측점선 상단 표기. */
.b06-chart__structure-label {
font-size: 9px;
font-weight: var(--font-weight-medium);
fill: rgb(180 83 9);
}
.b06-chart__axis-label {
fill: var(--color-text-body);
font-size: var(--text-caption);
font-weight: var(--font-weight-medium);
}
.b06-chart__profile {
fill: none;
stroke: var(--color-chart-0);
stroke-width: 2.5;
}
/* 지반선 · 계획선은 누름을 통과 — 겹친 측점선 누름이 측점 고름 · 임시 횡단으로 감(505-3) */
.b06-chart__profile,
.b06-chart__design-profile {
pointer-events: none;
}
.b06-chart__cross-profile {
fill: none;
stroke: var(--color-chart-1);
stroke-width: 2.4;
}
/* 종단 계획선(시공계획고): 지반선과 구분되도록 파선 + 강조색 */
.b06-chart__design-profile {
fill: none;
stroke: var(--color-royal-amethyst);
stroke-width: 2.2;
stroke-dasharray: 8 4;
}
/* 절토(계획고가 지반고보다 낮음) / 성토 구간 음영 */
.b06-chart__band {
stroke: none;
}
.b06-chart__band--cut {
fill: rgb(220 38 38 / 14%);
}
.b06-chart__band--fill {
fill: rgb(37 99 235 / 14%);
}
.b06-chart__balance-boundary {
stroke: var(--color-royal-amethyst);
stroke-width: 1.2;
stroke-dasharray: 3 3;
opacity: 0.55;
}
.b06-chart__station {
cursor: pointer;
}
/* 구조물 측점선은 끌어 옮길 수 있다 — 커서로 그 사실을 알린다(2026-08-01 사용자 지시). */
.b06-chart__station--draggable {
cursor: ew-resize;
touch-action: none;
}
.b06-chart__station-line {
stroke-width: 1.2;
}
.b06-chart__station-hit {
stroke: transparent;
stroke-width: 14;
pointer-events: stroke;
}
.b06-chart__station-line--bp,
.b06-chart__station-line--regular,
.b06-chart__station-line--curve {
stroke: var(--color-warning);
}
.b06-chart__station-line--ep {
stroke: var(--color-accent);
stroke-dasharray: 4 3;
}
/* 비정규 측점(구조물)은 종단면도에서도 자수정색 파선으로 구분한다(B05 종단 규칙과 정합).
미선택 시 stroke 미정의로 세로선이 안 그려지던 문제 해소. */
.b06-chart__station-line--irregular {
stroke: var(--color-royal-amethyst, rgb(139 92 246));
stroke-width: 1.4;
stroke-dasharray: 5 3;
}
/* 추가 측점(368-3) = 일반측점 색 점선 */
.b06-chart__station-line--plus {
stroke: var(--color-warning);
stroke-dasharray: 5 3;
}
.b06-chart__station-line--selected,
.b06-chart__center-marker {
stroke: var(--color-danger);
stroke-width: 2.5;
}
/* 십자선이 계획 노선(계획고) 위치를 가리킬 때: 종단 계획선과 동일 색으로 대응시킨다 */
.b06-chart__center-marker--design {
stroke: var(--color-royal-amethyst);
}
.b06-chart__station--selected .b06-chart__station-label,
.b06-chart__station-label--selected {
fill: var(--color-danger);
font-weight: var(--font-weight-bold);
}
/* 측점 표준횡단 설계 지정 컨트롤 (카드 헤더 아래) — 좌측 여유 추가(2번).
한 행 고정(nowrap): 넘치는 컨트롤은 다음 행으로 밀지 않고 "⋯" 드롭다운으로 이동(N-2-2). */
.b06-design {
display: flex;
flex-wrap: nowrap;
align-items: center;
gap: var(--spacing-8) var(--spacing-16);
padding: var(--spacing-8) 0 var(--spacing-8) var(--spacing-16);
border-bottom: 1px solid var(--color-border);
margin-bottom: var(--spacing-8);
}
/* 오버플로 드롭다운(N-2-2): 넘친 컨트롤을 담는 우측 맞춤 "⋯" 메뉴. 세로 배치. */
.b06-design__more {
position: relative;
flex: 0 0 auto;
margin-left: auto;
}
.b06-design__more-summary {
display: inline-flex;
align-items: center;
justify-content: center;
width: 24px;
height: 22px;
border: 1px solid var(--color-border);
border-radius: var(--radius-inputs);
background: var(--color-surface);
color: var(--color-text-secondary);
font-size: 0.9rem;
line-height: 1;
cursor: pointer;
list-style: none;
}
.b06-design__more-summary::-webkit-details-marker {
display: none;
}
.b06-design__more[open] .b06-design__more-summary {
color: var(--color-surface);
background: var(--color-royal-amethyst);
border-color: var(--color-royal-amethyst);
}
.b06-design__more-panel {
position: absolute;
right: 0;
top: calc(100% + 4px);
z-index: 3;
display: flex;
flex-direction: column;
gap: var(--spacing-8);
padding: var(--spacing-8);
border: 1px solid var(--color-border);
border-radius: var(--radius-inputs);
background: var(--color-surface-raised);
box-shadow: var(--shadow-sm);
}
.b06-design__seg {
display: flex;
align-items: center;
gap: var(--spacing-8);
}
.b06-design__seg-legend {
font-size: 0.72rem;
color: var(--color-text-secondary);
white-space: nowrap;
}
/* 선행 조건 미충족 옵션 — 숨김(179-2 · 옛 E-6 「흐리게 늘 보임」 폐기 · 쪽은 단면유형 알약에). */
.b06-design__seg--disabled {
display: none;
}
.b06-design__seg-buttons {
display: inline-flex;
border: 1px solid var(--color-border);
border-radius: var(--radius-inputs);
overflow: hidden;
}
.b06-design__btn {
padding: 3px 8px;
font-size: 0.72rem;
color: var(--color-text-secondary);
background: var(--color-surface);
border: none;
border-left: 1px solid var(--color-border);
cursor: pointer;
}
.b06-design__btn:first-child {
border-left: none;
}
.b06-design__btn--active {
color: var(--color-surface);
background: var(--color-royal-amethyst);
font-weight: var(--font-weight-medium);
}
.b06-design__areas {
display: inline-flex;
gap: var(--spacing-8);
margin-left: auto;
font-size: 0.72rem;
font-family: var(--font-mono);
}
/* 암 경계선 제어(E-7) — 하단 정보 행 **왼쪽 맞춤**(318-2 · 중심고는 그래프 Y축 라벨 상자로 옮김). */
.b06-cross-card__rockb {
flex: 0 0 auto;
border-radius: var(--radius-inputs);
padding: 1px 4px;
}
/* 선 공용 칸(370-3) — 고른 선 제목 · 버튼 · 값 한 줄(넘치면 말줄임) · 빈 칸도 자리(띠 높이) 그대로. */
.b06-cross-card__linecell {
flex: 0 1 auto;
min-width: 0;
}
.b06-cross-card__linecell.is-empty {
visibility: hidden;
}
.b06-cross-card__linecell .b06-design__seg-buttons {
min-width: 0;
}
.b06-cross-card__linecell .b06-design__rockb-readout {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.b06-cross-card__linecell .b06-design__rockb-btn {
flex: 0 0 auto;
border-left: none;
}
.b06-cross-card__linecell
.b06-design__rockb-btn:not([hidden])
~ .b06-design__rockb-btn:not([hidden]) {
border-left: 1px solid var(--color-border);
}
/* 측점별 암 절토 경사(2026-09-07) — 행의 **오른쪽 끝**(암 경계 = 왼쪽). */
.b06-cross-card__cutslope {
margin-left: auto;
flex: 0 0 auto;
border-radius: var(--radius-inputs);
padding: 1px 4px;
}
.b06-design__cutslope-input {
width: 44px;
padding: 0 2px;
font-size: 0.72rem;
font-family: var(--font-mono);
text-align: right;
color: var(--color-text);
background: var(--color-surface);
border: 1px solid var(--color-border);
border-radius: var(--radius-inputs);
}
/* 화살표(스피너)는 칸이 좁아 지운다 — 값은 직접 넣거나 ↺ 로 되돌린다. */
.b06-design__cutslope-input::-webkit-outer-spin-button,
.b06-design__cutslope-input::-webkit-inner-spin-button {
margin: 0;
appearance: none;
}
.b06-design__cutslope-unit {
padding: 0 2px 0 1px;
font-size: 0.72rem;
color: var(--color-text-secondary);
align-self: center;
}
-477
View File
@@ -431,480 +431,3 @@ input[type="color"][data-mixed="true"]::-webkit-color-swatch { background: trans
padding-top: 6px;
padding-bottom: 6px;
}
/* 도면층 행: 이름은 줄여 담고 아이콘은 줄이지 않는다. 이름이 안 줄면 오른쪽 아이콘이
행 밖으로 밀려 잘린다 (2026-09-01 실측: 내용 237~286px / 보이는 폭 229px). */
.cad-layer-manager .layer > button > span {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
}
.cad-layer-manager .layer > button > div {
flex-shrink: 0;
}
/* 행 안의 아이콘 버튼은 여백을 줄여 이름 몫을 남긴다 — 아이콘 6개가 한 행을 다 먹었다. */
.cad-layer-manager .layer > button [data-size="small"] {
padding-left: 2px;
padding-right: 2px;
min-width: 0;
}
/* 도면층 버튼 — 색은 토큰으로만, 상태는 Button이 붙이는 data-* 속성으로 가른다. */
.cad-layer-manager button[data-type="regular"] {
background: var(--cad-chrome-sunken);
color: var(--cad-accent);
}
.cad-layer-manager button[data-type="transparent"] {
background: transparent;
color: var(--cad-accent);
}
.cad-layer-manager button:hover {
background: var(--cad-hover);
color: var(--color-text);
}
.cad-layer-manager button[data-active="true"] {
background: var(--color-primary);
color: var(--color-primary-text);
}
.cad-view-controls {
position: fixed;
z-index: 3;
right: 14px;
bottom: calc(var(--cad-command-height) + var(--cad-status-height) + 14px);
display: flex;
align-items: center;
overflow: hidden;
border: 1px solid var(--cad-line);
border-radius: 4px;
background: var(--cad-chrome-raised);
box-shadow: var(--shadow-lg);
}
/* 오토캐드 파일 끌어다 놓기 안내 — 캔버스 오른쪽 위 흐린 글씨(빠른 특성 창이 뜨면 그 아래로 가려짐) */
.cad-drop-hint {
position: fixed;
z-index: 2;
top: calc(var(--cad-title-height) + var(--cad-ribbon-height) + 8px);
right: 14px;
display: flex;
flex-direction: column;
align-items: flex-end;
gap: 2px;
white-space: nowrap;
padding: 2px 4px;
border: 0;
background: transparent;
color: var(--cad-text-muted);
font-size: 11px;
text-align: right;
opacity: 0.55;
cursor: pointer;
}
.cad-drop-hint:hover {
opacity: 1;
}
.cad-drop-hint__steps {
display: flex;
flex-direction: column;
align-items: flex-end;
color: var(--cad-text-dim);
font-size: 10px;
}
/* 파일을 끄는 동안 — 화면 가장자리 흐린 테두리(`dxf-clip-paste.ts`) */
body.cad-file-dragging::after {
content: '';
position: fixed;
z-index: 50;
inset: 6px;
border: 2px dashed var(--cad-accent);
border-radius: 6px;
opacity: 0.6;
pointer-events: none;
}
.cad-view-controls button {
width: 34px;
height: 32px;
border: 0;
border-right: 1px solid var(--cad-line);
background: transparent;
font-size: 17px;
}
.cad-view-controls button:hover {
background: var(--cad-hover);
}
.cad-view-controls__fit {
color: var(--cad-accent);
font-size: 15px;
}
.cad-view-controls span {
min-width: 48px;
color: var(--cad-text-dim);
font-size: 10px;
text-align: center;
}
/* 하단 명령어 입력창은 숨김 처리 (마우스 커서 단축키 입력으로 대체) */
.cad-command-area {
position: fixed;
z-index: 3;
right: 0;
bottom: var(--cad-status-height);
left: var(--cad-panel-width);
height: var(--cad-command-height);
display: flex;
flex-direction: column;
gap: 4px;
padding: 6px 10px;
background: var(--cad-chrome);
border-top: 1px solid var(--cad-line);
}
.cad-command-history {
display: flex;
flex-direction: column;
flex: 1;
justify-content: flex-end;
overflow: hidden;
color: var(--cad-text-muted);
font: 11px Consolas, monospace;
}
.cad-command-suggestions {
position: absolute;
z-index: 6;
bottom: 100%;
left: 10px;
display: flex;
flex-direction: column;
min-width: 220px;
padding: 4px;
background: var(--cad-chrome-raised);
border: 1px solid var(--cad-line);
border-radius: 4px;
box-shadow: var(--shadow-lg);
}
.cad-command-suggestions button {
padding: 4px 8px;
border: 0;
border-radius: 3px;
background: transparent;
font: 11px Consolas, monospace;
text-align: left;
}
.cad-command-suggestions button:hover {
background: var(--cad-hover);
}
.cad-prop--wide select {
min-width: 132px;
}
.cad-command-prompt {
max-width: 42%;
overflow: hidden;
color: var(--cad-text-dim);
font-size: 11px;
white-space: nowrap;
text-overflow: ellipsis;
}
.cad-command-area form {
display: flex;
align-items: center;
gap: 7px;
height: 28px;
}
.cad-command-area label {
color: var(--color-text);
font-size: 11px;
font-weight: 600;
}
.cad-command-area input {
flex: 1;
height: 26px;
padding: 0 8px;
border: 1px solid var(--cad-line);
border-radius: 2px;
outline: none;
background: var(--cad-chrome-sunken);
color: var(--cad-text);
font: 11px Consolas, monospace;
}
.cad-command-area input:focus {
border-color: var(--color-focus-ring);
box-shadow: 0 0 0 1px var(--color-focus-ring);
}
.cad-statusbar {
position: fixed;
z-index: 3;
right: 0;
bottom: 0;
left: 0;
height: var(--cad-status-height);
display: flex;
align-items: center;
gap: 2px;
padding: 0 8px;
background: var(--cad-chrome);
border-top: 1px solid var(--cad-line);
}
.cad-statusbar button {
height: 21px;
padding: 0 8px;
border: 1px solid transparent;
border-radius: 2px;
background: transparent;
color: var(--cad-text-dim);
font-size: 10px;
}
.cad-statusbar button:hover {
background: var(--cad-hover);
}
.cad-statusbar button[data-active="true"] {
border-color: var(--cad-accent);
background: var(--color-primary);
color: var(--color-primary-text);
}
.cad-statusbar__hint {
margin-left: auto;
color: var(--cad-text-muted);
font-size: 10px;
}
@media (max-width: 800px) {
:root {
--cad-panel-width: 200px;
}
.cad-statusbar__hint {
display: none;
}
}
/* 특성 팔레트 — 값을 바로 고치는 입력들 */
.cad-properties-editor {
display: flex;
flex-direction: column;
gap: 7px;
}
.cad-properties-editor__title {
color: var(--color-text);
font-size: 13px;
font-weight: 600;
}
.cad-properties-editor label {
display: grid;
grid-template-columns: 72px 1fr;
align-items: center;
gap: 8px;
font-size: 11px;
color: var(--cad-text-dim);
}
.cad-properties-editor select,
.cad-properties-editor input {
height: 24px;
min-width: 0;
padding: 0 4px;
border: 1px solid var(--cad-line);
border-radius: 3px;
background: var(--cad-chrome-sunken);
color: var(--cad-text);
font-size: 11px;
}
.cad-properties-editor__readout {
margin: 6px 0 0;
border-top: 1px solid var(--cad-line);
}
.cad-properties-editor__readout div {
display: grid;
grid-template-columns: 72px 1fr;
padding: 5px 0;
border-bottom: 1px solid var(--cad-line);
font-size: 11px;
}
.cad-properties-editor__readout dt {
color: var(--cad-text-dim);
}
.cad-properties-editor__readout dd {
margin: 0;
overflow: hidden;
color: var(--cad-text);
text-overflow: ellipsis;
}
.cad-properties__empty {
margin: 0;
color: var(--cad-text-muted);
font-size: 11px;
}
/* 빠른 특성 — 화면 위에 뜨는 작은 상자 */
.cad-quick-properties {
position: fixed;
z-index: 5;
top: calc(var(--cad-title-height) + var(--cad-ribbon-height) + 12px);
right: 14px;
width: 240px;
padding: 8px 10px 10px;
background: var(--cad-chrome-raised);
border: 1px solid var(--cad-line);
border-radius: 5px;
box-shadow: var(--shadow-lg);
}
.cad-quick-properties__header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 6px;
color: var(--cad-text-dim);
font-size: 11px;
}
.cad-quick-properties__header button {
border: 0;
background: transparent;
color: var(--cad-text-muted);
font-size: 12px;
}
/* 블록 라이브러리 팔레트 (INSERT/BLOCK) */
.cad-block-library {
position: fixed;
z-index: 5;
top: calc(var(--cad-title-height) + var(--cad-ribbon-height) + 12px);
right: 14px;
width: 240px;
padding: 8px 10px 10px;
background: var(--cad-chrome-raised);
border: 1px solid var(--cad-line);
border-radius: 5px;
box-shadow: var(--shadow-lg);
}
.cad-block-library__empty {
margin: 0;
color: var(--cad-text-muted);
font-size: 11px;
line-height: 1.5;
}
.cad-block-library__list {
max-height: 220px;
margin: 0;
padding: 0;
overflow-y: auto;
list-style: none;
}
.cad-block-library__list li {
display: flex;
align-items: center;
gap: 4px;
}
.cad-block-library__list li button {
border: 0;
background: transparent;
color: var(--cad-text);
font-size: 12px;
}
.cad-block-library__name {
flex: 1;
overflow: hidden;
padding: 3px 4px;
text-align: left;
text-overflow: ellipsis;
white-space: nowrap;
}
.cad-block-library__name:hover {
background: var(--cad-chrome-sunken);
}
.cad-block-library__actions {
display: flex;
gap: 6px;
margin-top: 8px;
}
.cad-block-library__actions button {
flex: 1;
padding: 4px 0;
border: 1px solid var(--cad-line);
border-radius: 3px;
background: transparent;
color: var(--cad-text-dim);
font-size: 11px;
}
/* 도각 자리표 패널 — 도각 편집으로 도면을 실었을 때만 뜬다 (2026-09-06 사용자 지시로
부모 사이드바에서 캐드 안으로 옮김). 도면 오른쪽 위, 리본 아래에 붙는다. */
.cad-frame-tokens {
position: fixed;
/* 오른쪽 위는 진행단계 패널이 쓴다 — 아래쪽(상태막대·명령행 위)에 붙인다. */
right: 12px;
bottom: calc(var(--cad-status-height) + var(--cad-command-height) + 8px);
z-index: 3;
max-height: 46vh;
overflow-y: auto;
display: flex;
flex-direction: column;
gap: 6px;
width: 236px;
padding: 8px;
border: 1px solid var(--cad-line);
border-radius: 6px;
background: var(--cad-chrome-raised);
box-shadow: var(--shadow-lg);
color: var(--cad-text);
}
.cad-frame-tokens__header {
display: flex;
justify-content: space-between;
align-items: flex-start;
gap: 6px;
color: var(--cad-text-dim);
font-size: 11px;
line-height: 1.4;
}
.cad-frame-tokens__fold {
flex: none;
border: 1px solid var(--cad-line);
border-radius: 4px;
background: transparent;
color: var(--cad-text);
cursor: pointer;
}
.cad-frame-tokens__group {
display: flex;
flex-wrap: wrap;
gap: 4px;
align-items: center;
}
.cad-frame-tokens__title {
width: 100%;
color: var(--cad-text-dim);
font-size: 11px;
}
.cad-frame-tokens__button {
padding: 3px 7px;
border: 1px solid var(--cad-line);
border-radius: 4px;
background: var(--cad-chrome);
color: var(--cad-text);
font-size: 11px;
cursor: pointer;
}
.cad-frame-tokens__button:hover {
background: var(--cad-accent-soft, var(--cad-chrome-raised));
}
/* 자리표 칸 크기 입력 (2026-09-06) */
.cad-frame-tokens__size {
display: flex;
align-items: center;
gap: 4px;
color: var(--cad-text-dim);
font-size: 11px;
}
.cad-frame-tokens__size input {
width: 64px;
padding: 2px 4px;
border: 1px solid var(--cad-line);
border-radius: 4px;
background: var(--cad-chrome);
color: var(--cad-text);
font-size: 11px;
}
+1
View File
@@ -1,4 +1,5 @@
import './App.css';
import './App_Layers.css';
import { ToastContainer } from 'react-toastify';
import { FramePlaceholderPanel } from './components/FramePlaceholderPanel.tsx';
import { Toolbar } from './components/Toolbar.tsx';
@@ -0,0 +1,477 @@
/* 도면층 행: 이름은 줄여 담고 아이콘은 줄이지 않는다. 이름이 안 줄면 오른쪽 아이콘이
행 밖으로 밀려 잘린다 (2026-09-01 실측: 내용 237~286px / 보이는 폭 229px). */
.cad-layer-manager .layer > button > span {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
}
.cad-layer-manager .layer > button > div {
flex-shrink: 0;
}
/* 행 안의 아이콘 버튼은 여백을 줄여 이름 몫을 남긴다 — 아이콘 6개가 한 행을 다 먹었다. */
.cad-layer-manager .layer > button [data-size="small"] {
padding-left: 2px;
padding-right: 2px;
min-width: 0;
}
/* 도면층 버튼 — 색은 토큰으로만, 상태는 Button이 붙이는 data-* 속성으로 가른다. */
.cad-layer-manager button[data-type="regular"] {
background: var(--cad-chrome-sunken);
color: var(--cad-accent);
}
.cad-layer-manager button[data-type="transparent"] {
background: transparent;
color: var(--cad-accent);
}
.cad-layer-manager button:hover {
background: var(--cad-hover);
color: var(--color-text);
}
.cad-layer-manager button[data-active="true"] {
background: var(--color-primary);
color: var(--color-primary-text);
}
.cad-view-controls {
position: fixed;
z-index: 3;
right: 14px;
bottom: calc(var(--cad-command-height) + var(--cad-status-height) + 14px);
display: flex;
align-items: center;
overflow: hidden;
border: 1px solid var(--cad-line);
border-radius: 4px;
background: var(--cad-chrome-raised);
box-shadow: var(--shadow-lg);
}
/* 오토캐드 파일 끌어다 놓기 안내 — 캔버스 오른쪽 위 흐린 글씨(빠른 특성 창이 뜨면 그 아래로 가려짐) */
.cad-drop-hint {
position: fixed;
z-index: 2;
top: calc(var(--cad-title-height) + var(--cad-ribbon-height) + 8px);
right: 14px;
display: flex;
flex-direction: column;
align-items: flex-end;
gap: 2px;
white-space: nowrap;
padding: 2px 4px;
border: 0;
background: transparent;
color: var(--cad-text-muted);
font-size: 11px;
text-align: right;
opacity: 0.55;
cursor: pointer;
}
.cad-drop-hint:hover {
opacity: 1;
}
.cad-drop-hint__steps {
display: flex;
flex-direction: column;
align-items: flex-end;
color: var(--cad-text-dim);
font-size: 10px;
}
/* 파일을 끄는 동안 — 화면 가장자리 흐린 테두리(`dxf-clip-paste.ts`) */
body.cad-file-dragging::after {
content: '';
position: fixed;
z-index: 50;
inset: 6px;
border: 2px dashed var(--cad-accent);
border-radius: 6px;
opacity: 0.6;
pointer-events: none;
}
.cad-view-controls button {
width: 34px;
height: 32px;
border: 0;
border-right: 1px solid var(--cad-line);
background: transparent;
font-size: 17px;
}
.cad-view-controls button:hover {
background: var(--cad-hover);
}
.cad-view-controls__fit {
color: var(--cad-accent);
font-size: 15px;
}
.cad-view-controls span {
min-width: 48px;
color: var(--cad-text-dim);
font-size: 10px;
text-align: center;
}
/* 하단 명령어 입력창은 숨김 처리 (마우스 커서 단축키 입력으로 대체) */
.cad-command-area {
position: fixed;
z-index: 3;
right: 0;
bottom: var(--cad-status-height);
left: var(--cad-panel-width);
height: var(--cad-command-height);
display: flex;
flex-direction: column;
gap: 4px;
padding: 6px 10px;
background: var(--cad-chrome);
border-top: 1px solid var(--cad-line);
}
.cad-command-history {
display: flex;
flex-direction: column;
flex: 1;
justify-content: flex-end;
overflow: hidden;
color: var(--cad-text-muted);
font: 11px Consolas, monospace;
}
.cad-command-suggestions {
position: absolute;
z-index: 6;
bottom: 100%;
left: 10px;
display: flex;
flex-direction: column;
min-width: 220px;
padding: 4px;
background: var(--cad-chrome-raised);
border: 1px solid var(--cad-line);
border-radius: 4px;
box-shadow: var(--shadow-lg);
}
.cad-command-suggestions button {
padding: 4px 8px;
border: 0;
border-radius: 3px;
background: transparent;
font: 11px Consolas, monospace;
text-align: left;
}
.cad-command-suggestions button:hover {
background: var(--cad-hover);
}
.cad-prop--wide select {
min-width: 132px;
}
.cad-command-prompt {
max-width: 42%;
overflow: hidden;
color: var(--cad-text-dim);
font-size: 11px;
white-space: nowrap;
text-overflow: ellipsis;
}
.cad-command-area form {
display: flex;
align-items: center;
gap: 7px;
height: 28px;
}
.cad-command-area label {
color: var(--color-text);
font-size: 11px;
font-weight: 600;
}
.cad-command-area input {
flex: 1;
height: 26px;
padding: 0 8px;
border: 1px solid var(--cad-line);
border-radius: 2px;
outline: none;
background: var(--cad-chrome-sunken);
color: var(--cad-text);
font: 11px Consolas, monospace;
}
.cad-command-area input:focus {
border-color: var(--color-focus-ring);
box-shadow: 0 0 0 1px var(--color-focus-ring);
}
.cad-statusbar {
position: fixed;
z-index: 3;
right: 0;
bottom: 0;
left: 0;
height: var(--cad-status-height);
display: flex;
align-items: center;
gap: 2px;
padding: 0 8px;
background: var(--cad-chrome);
border-top: 1px solid var(--cad-line);
}
.cad-statusbar button {
height: 21px;
padding: 0 8px;
border: 1px solid transparent;
border-radius: 2px;
background: transparent;
color: var(--cad-text-dim);
font-size: 10px;
}
.cad-statusbar button:hover {
background: var(--cad-hover);
}
.cad-statusbar button[data-active="true"] {
border-color: var(--cad-accent);
background: var(--color-primary);
color: var(--color-primary-text);
}
.cad-statusbar__hint {
margin-left: auto;
color: var(--cad-text-muted);
font-size: 10px;
}
@media (max-width: 800px) {
:root {
--cad-panel-width: 200px;
}
.cad-statusbar__hint {
display: none;
}
}
/* 특성 팔레트 — 값을 바로 고치는 입력들 */
.cad-properties-editor {
display: flex;
flex-direction: column;
gap: 7px;
}
.cad-properties-editor__title {
color: var(--color-text);
font-size: 13px;
font-weight: 600;
}
.cad-properties-editor label {
display: grid;
grid-template-columns: 72px 1fr;
align-items: center;
gap: 8px;
font-size: 11px;
color: var(--cad-text-dim);
}
.cad-properties-editor select,
.cad-properties-editor input {
height: 24px;
min-width: 0;
padding: 0 4px;
border: 1px solid var(--cad-line);
border-radius: 3px;
background: var(--cad-chrome-sunken);
color: var(--cad-text);
font-size: 11px;
}
.cad-properties-editor__readout {
margin: 6px 0 0;
border-top: 1px solid var(--cad-line);
}
.cad-properties-editor__readout div {
display: grid;
grid-template-columns: 72px 1fr;
padding: 5px 0;
border-bottom: 1px solid var(--cad-line);
font-size: 11px;
}
.cad-properties-editor__readout dt {
color: var(--cad-text-dim);
}
.cad-properties-editor__readout dd {
margin: 0;
overflow: hidden;
color: var(--cad-text);
text-overflow: ellipsis;
}
.cad-properties__empty {
margin: 0;
color: var(--cad-text-muted);
font-size: 11px;
}
/* 빠른 특성 — 화면 위에 뜨는 작은 상자 */
.cad-quick-properties {
position: fixed;
z-index: 5;
top: calc(var(--cad-title-height) + var(--cad-ribbon-height) + 12px);
right: 14px;
width: 240px;
padding: 8px 10px 10px;
background: var(--cad-chrome-raised);
border: 1px solid var(--cad-line);
border-radius: 5px;
box-shadow: var(--shadow-lg);
}
.cad-quick-properties__header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 6px;
color: var(--cad-text-dim);
font-size: 11px;
}
.cad-quick-properties__header button {
border: 0;
background: transparent;
color: var(--cad-text-muted);
font-size: 12px;
}
/* 블록 라이브러리 팔레트 (INSERT/BLOCK) */
.cad-block-library {
position: fixed;
z-index: 5;
top: calc(var(--cad-title-height) + var(--cad-ribbon-height) + 12px);
right: 14px;
width: 240px;
padding: 8px 10px 10px;
background: var(--cad-chrome-raised);
border: 1px solid var(--cad-line);
border-radius: 5px;
box-shadow: var(--shadow-lg);
}
.cad-block-library__empty {
margin: 0;
color: var(--cad-text-muted);
font-size: 11px;
line-height: 1.5;
}
.cad-block-library__list {
max-height: 220px;
margin: 0;
padding: 0;
overflow-y: auto;
list-style: none;
}
.cad-block-library__list li {
display: flex;
align-items: center;
gap: 4px;
}
.cad-block-library__list li button {
border: 0;
background: transparent;
color: var(--cad-text);
font-size: 12px;
}
.cad-block-library__name {
flex: 1;
overflow: hidden;
padding: 3px 4px;
text-align: left;
text-overflow: ellipsis;
white-space: nowrap;
}
.cad-block-library__name:hover {
background: var(--cad-chrome-sunken);
}
.cad-block-library__actions {
display: flex;
gap: 6px;
margin-top: 8px;
}
.cad-block-library__actions button {
flex: 1;
padding: 4px 0;
border: 1px solid var(--cad-line);
border-radius: 3px;
background: transparent;
color: var(--cad-text-dim);
font-size: 11px;
}
/* 도각 자리표 패널 — 도각 편집으로 도면을 실었을 때만 뜬다 (2026-09-06 사용자 지시로
부모 사이드바에서 캐드 안으로 옮김). 도면 오른쪽 위, 리본 아래에 붙는다. */
.cad-frame-tokens {
position: fixed;
/* 오른쪽 위는 진행단계 패널이 쓴다 — 아래쪽(상태막대·명령행 위)에 붙인다. */
right: 12px;
bottom: calc(var(--cad-status-height) + var(--cad-command-height) + 8px);
z-index: 3;
max-height: 46vh;
overflow-y: auto;
display: flex;
flex-direction: column;
gap: 6px;
width: 236px;
padding: 8px;
border: 1px solid var(--cad-line);
border-radius: 6px;
background: var(--cad-chrome-raised);
box-shadow: var(--shadow-lg);
color: var(--cad-text);
}
.cad-frame-tokens__header {
display: flex;
justify-content: space-between;
align-items: flex-start;
gap: 6px;
color: var(--cad-text-dim);
font-size: 11px;
line-height: 1.4;
}
.cad-frame-tokens__fold {
flex: none;
border: 1px solid var(--cad-line);
border-radius: 4px;
background: transparent;
color: var(--cad-text);
cursor: pointer;
}
.cad-frame-tokens__group {
display: flex;
flex-wrap: wrap;
gap: 4px;
align-items: center;
}
.cad-frame-tokens__title {
width: 100%;
color: var(--cad-text-dim);
font-size: 11px;
}
.cad-frame-tokens__button {
padding: 3px 7px;
border: 1px solid var(--cad-line);
border-radius: 4px;
background: var(--cad-chrome);
color: var(--cad-text);
font-size: 11px;
cursor: pointer;
}
.cad-frame-tokens__button:hover {
background: var(--cad-accent-soft, var(--cad-chrome-raised));
}
/* 자리표 칸 크기 입력 (2026-09-06) */
.cad-frame-tokens__size {
display: flex;
align-items: center;
gap: 4px;
color: var(--cad-text-dim);
font-size: 11px;
}
.cad-frame-tokens__size input {
width: 64px;
padding: 2px 4px;
border: 1px solid var(--cad-line);
border-radius: 4px;
background: var(--cad-chrome);
color: var(--cad-text);
font-size: 11px;
}
@@ -16,6 +16,7 @@
* ========================================================================== */
import "../B01_Dashboard/B01_Dashboard_UI_Style.css";
import "../B01_Dashboard/B01_Dashboard_UI_Style_Company.css";
import {
createButton,
createInputField,
@@ -12,7 +12,7 @@ def _src(rel: str) -> str:
def test_막힌_묶음은_숨김():
css = _src("B06_Section/B06_Section_UI_Style_Cross.css")
css = _src("B06_Section/B06_Section_UI_Style_Cross.css") + _src("B06_Section/B06_Section_UI_Style_Cross_Chart.css")
body = re.search(r"\.b06-design__seg--disabled\s*\{([^}]*)\}", css).group(1)
assert "display: none;" in body
assert "opacity" not in body
+3 -1
View File
@@ -182,7 +182,9 @@ def _rule(css: str, selector: str) -> str:
def test_css_layout() -> None:
css = _src("B06_Section", "B06_Section_UI_Style_Cross.css")
css = _src("B06_Section", "B06_Section_UI_Style_Cross.css") + _src(
"B06_Section", "B06_Section_UI_Style_Cross_Chart.css"
)
assert "align-items: start" in _rule(css, ".b06-section__grid") # 카드 = 내용 높이
rock = _rule(css, ".b06-cross-card__rockb")
assert "position: absolute" not in rock and "translateX" not in rock # 왼쪽 맞춤
+1 -1
View File
@@ -16,7 +16,7 @@ def test_추가_측점_선_점선_끌기_없음() -> None:
graph = _read("B06_Section/B06_Section_UI_Longitudinal.ts")
assert 'station.kind === "irregular" && !station.plus' in graph
assert 'station.plus ? "plus" : station.kind' in graph
css = _read("B06_Section/B06_Section_UI_Style_Cross.css")
css = _read("B06_Section/B06_Section_UI_Style_Cross.css") + _read("B06_Section/B06_Section_UI_Style_Cross_Chart.css")
rule = css[css.index(".b06-chart__station-line--plus") :].split("}")[0]
assert "var(--color-warning)" in rule and "stroke-dasharray: 5 3" in rule
assert "PLUS_OWNER_PREFIX" in _read("B05_Profile/B05_Profile_UI_Profile_Layout.ts")
+3 -1
View File
@@ -91,5 +91,7 @@ def test_배선_떠_있는_선_조정창_걷음() -> None:
assert "buildRockBoundaryControl" not in chrome # 479 — 그림 없는 암 카드도 빈 칸
detail = (B06 / "B06_Section_UI_Cross_Detail_Pick.ts").read_text(encoding="utf-8")
assert ".b06-chart__design-hit:not(.b06-chart__rock-hit)" in detail # 상세 표 강조에 안 섞임
css = (B06 / "B06_Section_UI_Style_Cross.css").read_text(encoding="utf-8")
css = (B06 / "B06_Section_UI_Style_Cross.css").read_text(encoding="utf-8") + (
B06 / "B06_Section_UI_Style_Cross_Chart.css"
).read_text(encoding="utf-8")
assert ".b06-cross-card__linecell.is-empty {" in css and "text-overflow: ellipsis;" in css
@@ -71,7 +71,9 @@ def test_곡선_판_가둠_도구줄_횡단판_종단판() -> None:
def test_지반선_계획선_누름_통과() -> None:
css = _read("B06_Section", "B06_Section_UI_Style_Cross.css")
css = _read("B06_Section", "B06_Section_UI_Style_Cross.css") + _read(
"B06_Section", "B06_Section_UI_Style_Cross_Chart.css"
)
assert ".b06-chart__profile,\n.b06-chart__design-profile {\n pointer-events: none;" in css
+1 -1
View File
@@ -65,7 +65,7 @@ def test_b08_b09_earthwork_station_mc() -> None:
def test_b05_b06_screen_mc_emphasis() -> None:
css = _src("B06_Section/B06_Section_UI_Style_Cross.css")
css = _src("B06_Section/B06_Section_UI_Style_Cross.css") + _src("B06_Section/B06_Section_UI_Style_Cross_Chart.css")
assert "header strong.b06-station--mc {" in css # 카드 머리 strong 규칙을 이김
for rule in ("\n.b06-chart__station-label--mc {", "\n.b06-station--mc {"):
body = css[css.index(rule) : css.index("}", css.index(rule))]
+1 -1
View File
@@ -225,7 +225,7 @@ def test_CAD_머리줄_없음_탭줄_빈자리_변수():
src = ROOT / "B07_DesignDetail/openwebcad/src"
ribbon = (src / "ribbon/Ribbon.tsx").read_text("utf-8")
quick = (src / "components/QuickAccessBar.tsx").read_text("utf-8")
css = (src / "App.css").read_text("utf-8")
css = (src / "App.css").read_text("utf-8") + (src / "App_Layers.css").read_text("utf-8")
assert '<span ref={slotRef} className="cad-ribbon-tabs__slot" />' in ribbon
assert ribbon.index("cad-ribbon-tabs__slot") < ribbon.index("<QuickAccessBar />")
flat = " ".join(ribbon.split()) # 줄바꿈 · 들여쓰기 무관
@@ -53,7 +53,9 @@ def test_따로_둔_모달도_위_고정():
m01 = _text("M01_MasterData/M01_MasterData_UI_Style.css")
assert "align-items: flex-start;" in _block(m01, ".m01-procure")
assert "margin-top: 10vh;" in _block(m01, ".m01-procure__box")
b01 = _text("B01_Dashboard/B01_Dashboard_UI_Style.css")
b01 = _text("B01_Dashboard/B01_Dashboard_UI_Style.css") + _text(
"B01_Dashboard/B01_Dashboard_UI_Style_Company.css"
)
assert "align-items: flex-start;" in _block(b01, ".b01-dashboard__modal")