diff --git a/B05_Profile/B05_Profile_UI_Panel.ts b/B05_Profile/B05_Profile_UI_Panel.ts
index decab2cc..e0c9b812 100644
--- a/B05_Profile/B05_Profile_UI_Panel.ts
+++ b/B05_Profile/B05_Profile_UI_Panel.ts
@@ -387,10 +387,18 @@ export function createRoutePanel(callbacks: PanelCallbacks) {
const tempSaveButton = button(L("B05_Route_Btn_TempSave"), callbacks.onTempSave);
const goCrossButton = button(L("B05_Route_Btn_GoCross"), callbacks.onGoCross, "filled");
const actionRow = document.createElement("div");
- // 사이드 최하단 고정(공용 ui-sidebar-actions) — 스크롤에서 제외(2026-08-05 사용자 지시).
- actionRow.className = "b05-route__actions ui-sidebar-actions";
+ actionRow.className = "b05-route__actions";
actionRow.append(resetButton, tempSaveButton, goCrossButton);
+ // 사이드 최하단 고정 영역(2026-08-05 사용자 지시) — 위 구분선(dock 상단 테두리) →
+ // 구조물 목록 → 중간 구분선 → 액션 버튼 순. 목록을 「구조물 배치」 본문에 두면
+ // 고른 구조물의 폼 길이에 밀려 화면 밖으로 나갔다(2026-08-18 사용자 지시).
+ const dockDivider = document.createElement("hr");
+ dockDivider.className = "b05-structure__divider";
+ const actionDock = document.createElement("div");
+ actionDock.className = "b05-route__dock ui-sidebar-actions";
+ actionDock.append(structures.listRoot, dockDivider, actionRow);
+
const inputElements = [
algorithm,
gradeClass,
@@ -419,7 +427,7 @@ export function createRoutePanel(callbacks: PanelCallbacks) {
structures.root,
routeCalc.root,
selected.root,
- actionRow,
+ actionDock,
);
// 컨테이너 제목 행 전체 클릭 시 본문을 접거나 편다(공용 collapsible). 내부 details 등 별도
diff --git a/B05_Profile/B05_Profile_UI_Structures_Panel.ts b/B05_Profile/B05_Profile_UI_Structures_Panel.ts
index 34bb76ee..2eba70cf 100644
--- a/B05_Profile/B05_Profile_UI_Structures_Panel.ts
+++ b/B05_Profile/B05_Profile_UI_Structures_Panel.ts
@@ -60,6 +60,9 @@ export interface PipeFacilityItem {
export interface StructuresSection {
root: HTMLElement;
+ /** 배치된 구조물 목록(
) — 섹션 본문이 아니라 사이드 하단 고정 영역에 붙인다
+ * (2026-08-18 사용자 지시: 폼 길이에 밀려 목록이 화면 밖으로 나가던 문제). */
+ listRoot: HTMLElement;
/** 서버에서 받은 타입 목록을 채운다(최초 1회). */
setTypes: (types: StructureType[]) => void;
/** 서버 정본으로 목록을 교체한다(진입·복원·저장 후). */
@@ -165,6 +168,8 @@ export function createStructuresSection(callbacks: StructuresCallbacks): Structu
actions.className = "b05-route__irregular-actions";
actions.append(primary, removeButton, resetButton);
+ // 목록은 이 섹션 본문에 붙이지 않는다 — 폼이 길어지면 스크롤 밖으로 밀려 안 보였다.
+ // 패널(B05_Profile_UI_Panel)이 하단 고정 영역에 배치한다(2026-08-18 사용자 지시).
const list = document.createElement("ul");
list.className = "b05-route__irregular-list";
// 사용법 설명 문단은 두지 않는다 — 공간 대비 의미 없음(2026-08-17 사용자 지시,
@@ -174,15 +179,7 @@ export function createStructuresSection(callbacks: StructuresCallbacks): Structu
const positionDivider = document.createElement("hr");
positionDivider.className = "b05-structure__divider";
- body.append(
- typeRow,
- positionRow,
- positionDivider,
- optionRow,
- facilityOptions.root,
- actions,
- list,
- );
+ body.append(typeRow, positionRow, positionDivider, optionRow, facilityOptions.root, actions);
let types: StructureType[] = [];
let structures: StructureInstance[] = [];
@@ -529,6 +526,7 @@ export function createStructuresSection(callbacks: StructuresCallbacks): Structu
return {
root,
+ listRoot: list,
setTypes(next) {
types = next;
const groups = [...new Set(next.map((t) => t.group))];
diff --git a/B05_Profile/B05_Profile_UI_Style.css b/B05_Profile/B05_Profile_UI_Style.css
index b0c4e00a..f3976aa7 100644
--- a/B05_Profile/B05_Profile_UI_Style.css
+++ b/B05_Profile/B05_Profile_UI_Style.css
@@ -413,6 +413,19 @@
color: var(--color-warning);
}
+/* 사이드 최하단 고정 영역 — 공용 ui-sidebar-actions(sticky·배경·상단 구분선)를 그대로
+ 쓰되, 안쪽은 [구조물 목록][중간 구분선][액션 버튼 행] 세로 배치로 되돌린다
+ (2026-08-18 사용자 지시). */
+.b05-route__dock.ui-sidebar-actions {
+ flex-direction: column;
+}
+
+/* 공용 규칙(.ui-sidebar-actions > * { flex: 1 })이 목록·구분선까지 늘리지 않도록
+ 같은 자리에서 되돌린다 — 로드 순서에 기대지 않게 선택자를 한 단계 더 좁혔다. */
+.b05-route__dock.ui-sidebar-actions > * {
+ flex: none;
+}
+
.b05-route__actions {
display: flex;
gap: var(--spacing-8);