Files
Aislo/B05_wf2_Route/B05_wf2_Route_UI_Style.css
T
2026-07-23 19:31:52 +09:00

551 lines
13 KiB
CSS

.b05-route-layout {
height: calc(100vh - var(--spacing-64));
height: calc(100dvh - var(--spacing-64));
min-height: 0;
overflow: hidden;
}
.b05-route-layout .ui-workflow-layout__body,
.b05-route-layout .ui-workflow-layout__main {
height: 100%;
min-height: 0;
}
.b05-route-layout .ui-workflow-layout__main {
overflow: hidden;
}
.b05-route__main {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
min-height: 0;
overflow: hidden;
}
.b05-route__viewport {
position: relative;
width: 100%;
flex: 1 1 auto;
height: auto;
min-height: 0;
overflow: hidden;
background: var(--color-surface);
}
/* 하단 종단 패널: 그래프 + 12행 도면 테이블을 담기 위해 화면 높이의 60%를 차지한다.
접기 핸들로 언제든 내릴 수 있어 3D 뷰를 전체 영역으로 볼 수 있다. */
.b05-route-profile {
position: relative;
display: flex;
flex: 0 0 60vh;
flex: 0 0 60dvh;
flex-direction: column;
min-height: 0;
overflow: visible;
border-top: 1px solid var(--color-border);
background: var(--color-surface-raised);
transition: flex-basis var(--transition-fast);
}
.b05-route-profile.is-collapsed {
flex-basis: 0;
min-height: 0;
}
.b05-route-profile__body {
box-sizing: border-box;
flex: 1 1 auto;
min-height: 0;
overflow-x: scroll;
overflow-y: hidden;
padding-inline: 15px;
}
/* 종단면도는 노선 전체 길이만큼 가로로 길어 스크롤바가 유일한 이동 수단이다.
전역 스크롤바(8px, thumb 불투명도 12%)는 가로로 쓰기엔 너무 옅어 잡히지 않으므로
이 패널에서만 더 두껍고 대비가 분명한 막대로 덮어쓴다. */
.b05-route-profile__body {
scrollbar-color: var(--color-text-muted, var(--color-plum-velvet)) var(--color-surface);
scrollbar-width: auto;
}
.b05-route-profile__body::-webkit-scrollbar {
height: 12px;
}
.b05-route-profile__body::-webkit-scrollbar-track {
border-top: 1px solid var(--color-border);
background-color: var(--color-surface);
}
.b05-route-profile__body::-webkit-scrollbar-thumb {
border: 2px solid transparent;
border-radius: var(--radius-pills);
background-color: color-mix(in srgb, var(--color-text) 45%, transparent);
background-clip: padding-box;
}
.b05-route-profile__body::-webkit-scrollbar-thumb:hover {
background-color: color-mix(in srgb, var(--color-text) 65%, transparent);
}
/* 그래프와 테이블을 같은 폭으로 쌓아 X축이 저절로 맞물리게 한다. */
.b05-profile__canvas {
display: flex;
flex-direction: column;
}
.b05-profile__chart {
position: relative;
flex: 0 0 auto;
min-height: 0;
}
.b05-route-profile.is-collapsed .b05-route-profile__body,
.b05-route-profile.is-collapsed .b05-route-profile__balance {
display: none;
}
.b05-route-profile__empty {
margin: 0;
padding: var(--spacing-24);
color: var(--color-text-muted);
font-size: var(--text-body-sm);
}
.b05-route-profile .b06-section__chart-wrap {
height: 100%;
}
.b05-route__viewport canvas {
display: block;
width: 100%;
height: 100%;
}
.b05-route__viewer-status {
position: absolute;
inset: var(--spacing-16) auto auto var(--spacing-16);
max-width: 420px;
padding: var(--spacing-8) var(--spacing-16);
border: 1px solid var(--color-border);
border-radius: var(--radius-inputs);
background: var(--color-surface-raised);
color: var(--color-text-body);
font-size: var(--text-caption);
pointer-events: none;
}
.b05-route__view-controls {
position: absolute;
z-index: 2;
top: 58px;
left: var(--spacing-16);
display: flex;
align-items: center;
gap: var(--spacing-8);
}
.b05-route__view-group {
display: flex;
gap: var(--spacing-4);
}
.b05-route__view-controls .ui-btn {
height: 34px;
padding: 0 var(--spacing-8);
}
.b05-route__view-separator {
width: 1px;
height: 24px;
background: color-mix(in srgb, var(--color-border) 75%, transparent);
}
.b05-route__panel {
display: flex;
flex-direction: column;
width: 100%;
min-width: 0;
gap: var(--spacing-16);
padding-bottom: var(--spacing-24);
}
.b05-route__panel-section {
display: flex;
flex-direction: column;
width: 100%;
min-width: 0;
gap: var(--spacing-8);
padding: calc(var(--spacing-8) + var(--spacing-4));
border: 1px solid var(--color-border);
border-radius: var(--radius-cards);
background: var(--color-surface-raised);
}
.b05-route__panel-section h3 {
margin: 0;
color: var(--color-text);
font-size: var(--text-body-sm);
}
.b05-route__panel-body,
.b05-route__field,
.b05-route__metrics {
display: flex;
flex-direction: column;
min-width: 0;
gap: var(--spacing-8);
}
.b05-route__contour-row {
display: flex;
align-items: end;
gap: var(--spacing-8);
}
.b05-route__contour-row .b05-route__field {
flex: 1;
}
.b05-route__contour-row .ui-btn {
flex: 0 0 auto;
}
.b05-route__field,
.b05-route__check,
.b05-route__metrics {
color: var(--color-text-body);
font-size: var(--text-caption);
}
.b05-route__field input,
.b05-route__field select,
.b05-route__panel-section > select {
width: 100%;
min-width: 0;
padding: var(--spacing-8);
border: 1px solid var(--color-border);
border-radius: var(--radius-inputs);
background: var(--color-surface);
color: var(--color-text-body);
}
.b05-route__check {
display: flex;
align-items: center;
gap: var(--spacing-8);
}
.b05-route__button-grid,
.b05-route__palette {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
min-width: 0;
gap: var(--spacing-8);
}
.b05-route__chip {
padding: var(--spacing-8);
border: 1px solid var(--color-border);
border-radius: var(--radius-inputs);
background: var(--color-surface);
color: var(--color-text-body);
font-size: var(--text-caption);
cursor: pointer;
}
.b05-route__chip.is-ep,
.b05-route__chip.is-fp {
color: var(--color-danger);
}
.b05-route__chip.is-bp {
color: var(--color-success);
}
.b05-route__chip.is-cp,
.b05-route__stale {
color: var(--color-warning);
}
.b05-route__actions {
display: flex;
gap: var(--spacing-8);
}
.b05-route__actions > * {
flex: 1;
}
.b05-route__stale {
font-size: var(--text-caption);
font-weight: var(--font-weight-medium);
}
.b05-route__panel details {
color: var(--color-text-body);
font-size: var(--text-caption);
}
/* 계획선 설계 폼 안내문 */
.b05-route__note {
margin: 0;
color: var(--color-text-muted, var(--color-plum-velvet));
font-size: var(--text-caption);
line-height: 1.4;
}
/* 종단면도 상단 절·성토 균형 지표 바 */
.b05-route-profile__balance {
display: flex;
flex: 0 0 auto;
flex-wrap: nowrap;
gap: var(--spacing-16);
align-items: center;
height: 24px;
padding: 0 var(--spacing-8);
overflow-x: auto;
overflow-y: hidden;
font-size: var(--text-caption);
white-space: nowrap;
}
.b05-route-profile__balance-item {
display: inline-flex;
gap: var(--spacing-8);
align-items: center;
}
.b05-route-profile__balance-item em {
color: var(--color-text-muted, var(--color-plum-velvet));
font-style: normal;
}
.b05-route-profile__balance-item.is-cut em {
color: rgb(220 38 38);
}
.b05-route-profile__balance-item.is-fill em {
color: rgb(37 99 235);
}
.b05-route-profile__balance-item.is-over,
.b05-route-profile__balance-item.is-unsaved {
color: rgb(180 83 9);
font-weight: var(--font-weight-medium);
}
.b05-route-profile__balance-item.is-edited em {
color: var(--color-royal-amethyst, rgb(109 40 217));
}
.b05-route-profile__balance-warning {
overflow: hidden;
color: rgb(180 83 9);
text-overflow: ellipsis;
}
.b05-route-profile__balance-reset {
flex: 0 0 auto;
padding: 1px var(--spacing-8);
border: 1px solid var(--color-border);
border-radius: var(--radius-inputs);
background: var(--color-surface);
color: var(--color-text-body);
font-size: var(--text-caption);
cursor: pointer;
}
/* ─── 도면 테이블 (구배 ~ 곡선 9행) ───────────────────────────────────────
셀은 종단면도와 같은 X 매핑으로 절대 배치되어 측점 수직선과 맞물린다.
행 이름표만 sticky로 좌측에 고정되어 가로 스크롤에도 계속 보인다. */
.b05-profile-table {
position: relative;
display: flex;
flex: 0 0 auto;
flex-direction: column;
min-height: 0;
border-top: 2px solid var(--color-text-muted, var(--color-plum-velvet));
color: var(--color-text-body);
/* 행 높이와 셀 폭에 맞춰 렌더러가 계산해 넣는다 (createProfileTable). */
font-size: var(--b05-table-font, 11px);
line-height: 1.1;
user-select: none;
}
/* 12개 행이 테이블 세로를 균등하게 나눠 갖는다 (패널을 키우면 행이 두꺼워진다). */
.b05-profile-table__row {
position: relative;
flex: 1 1 0;
min-height: 12px;
border-bottom: 1px solid var(--color-border);
white-space: nowrap;
}
/* 구배 / 측점값 / 곡선 묶음의 시작 행은 굵은 선으로 그룹을 구분한다. */
.b05-profile-table__row.is-group-start {
border-top: 2px solid var(--color-text-muted, var(--color-plum-velvet));
}
.b05-profile-table__row--grade {
background: color-mix(in srgb, var(--color-surface) 55%, transparent);
}
.b05-profile-table__row:last-child {
border-bottom: 0;
}
.b05-profile-table__label {
position: sticky;
z-index: 3;
left: 0;
display: inline-flex;
align-items: center;
box-sizing: border-box;
width: var(--b05-table-label-width, 60px);
height: 100%;
padding-inline: var(--spacing-4);
border-right: 2px solid var(--color-text-muted, var(--color-plum-velvet));
background: var(--color-surface-raised);
color: var(--color-text);
font-weight: var(--font-weight-medium);
}
.b05-profile-table__cell,
.b05-profile-table__segment,
.b05-profile-table__curve {
position: absolute;
top: 0;
display: flex;
align-items: center;
justify-content: center;
height: 100%;
overflow: hidden;
}
/* 측점 값 셀은 측점 수직선을 중심으로 좌우 대칭 배치된다. */
.b05-profile-table__cell,
.b05-profile-table__curve {
width: var(--b05-table-cell-width, 56px);
transform: translateX(-50%);
}
.b05-profile-table__row.is-cut .b05-profile-table__cell {
color: rgb(220 38 38);
}
.b05-profile-table__row.is-fill .b05-profile-table__cell {
color: rgb(37 99 235);
}
.b05-profile-table__row.is-plan .b05-profile-table__cell {
color: var(--color-royal-amethyst, rgb(109 40 217));
font-weight: var(--font-weight-medium);
}
/* 구간 블록: 변화점 사이 직선 전체를 덮어 어느 구간의 값인지 한눈에 보이게 한다. */
.b05-profile-table__segment {
box-sizing: border-box;
border-left: 1px solid var(--color-border);
border-right: 1px solid var(--color-border);
}
.b05-profile-table__segment.is-violation {
background: color-mix(in srgb, rgb(220 38 38) 12%, transparent);
color: rgb(180 83 9);
}
.b05-profile-table__curve {
z-index: 2;
background: var(--color-surface-raised);
}
.b05-profile-table__curve.is-optional {
opacity: 0.75;
}
.b05-profile-table__curve.is-omitted {
text-decoration: line-through;
}
.b05-profile-table__radius {
box-sizing: border-box;
width: 100%;
height: 90%;
padding: 0 1px;
border: 1px solid var(--color-border);
border-radius: 2px;
background: var(--color-surface);
color: var(--color-text-body);
font-size: inherit;
text-align: center;
}
/* ─── 계획고 편집 버튼 (평시 투명, 패널 hover 시 노출) ───────────────────── */
.b05-profile-edit {
position: absolute;
z-index: 4;
inset: 0;
pointer-events: none;
}
.b05-profile-edit__btn {
position: absolute;
width: 18px;
height: 15px;
padding: 0;
border: 1px solid transparent;
border-radius: 3px;
background: transparent;
color: transparent;
font-size: 9px;
line-height: 1;
cursor: pointer;
opacity: 0;
pointer-events: auto;
transition: opacity var(--transition-fast);
}
.b05-route-profile:hover .b05-profile-edit__btn {
border-color: color-mix(in srgb, var(--color-border) 60%, transparent);
background: color-mix(in srgb, var(--color-surface) 70%, transparent);
color: var(--color-text-muted, var(--color-plum-velvet));
opacity: 0.45;
}
.b05-route-profile .b05-profile-edit__btn:hover,
.b05-route-profile .b05-profile-edit__btn:focus-visible {
border-color: var(--color-border);
background: var(--color-surface-raised);
color: var(--color-text);
opacity: 1;
}
.b05-profile-edit__btn.is-up {
top: 2px;
}
.b05-profile-edit__btn.is-down {
bottom: 2px;
}
.b05-profile-edit__btn.is-segment.is-up {
top: 19px;
}
.b05-profile-edit__btn.is-segment.is-down {
bottom: 19px;
}
.b05-profile-edit__btn.is-reset,
.b05-route-profile:hover .b05-profile-edit__btn.is-reset {
top: 36px;
border-color: color-mix(in srgb, var(--color-royal-amethyst, rgb(109 40 217)) 45%, transparent);
background: var(--color-surface-raised);
color: var(--color-royal-amethyst, rgb(109 40 217));
opacity: 0.9;
}