/* ============================================================================= * B05_Profile_UI_Style_Table.css * 종단면도 하단 **도면 테이블**과 그 위에 얹히는 것들 — * 표(구배~곡선) · 선택 측점 값 열 오버레이 · 그래프 우클릭 메뉴 · * 계획고 편집 버튼 · 줌/Y레인지 조작구. * * `B05_Profile_UI_Style.css` 가 700줄을 넘겨 **잘라낸 조각**이다(2026-09-04). * 규칙은 원본 순서 그대로 옮겼고 값은 하나도 바꾸지 않았다 — 진입 TS 가 * 본체 다음에 이 파일을 불러오므로 캐스케이드 순서도 같다. * ========================================================================== */ /* ─── 도면 테이블 (구배 ~ 곡선 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: 5; left: 0; display: inline-flex; align-items: center; /* 행제목이 좌측 편집 버튼 층에 걸린다 — 글자를 우측으로 맞추고 좌측 여백을 더 민다 (2026-08-05 사용자 지시). */ justify-content: flex-end; box-sizing: border-box; width: var(--b05-table-label-width, 60px); height: 100%; padding-inline: var(--spacing-16) 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-size: var(--b05-table-label-font, inherit); font-weight: var(--font-weight-medium); white-space: nowrap; } .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; } /* 이웃 곡선 셀과 겹치는 좁은 자리(배관 측점 등) — 셀을 얇게 줄이고 입력을 세로쓰기로 세운다. 자리는 측점 수직선 그대로다(옆으로 비키면 다른 열 값으로 오해, 2026-08-04). */ .b05-profile-table__curve.is-rotated input { writing-mode: vertical-rl; width: 100%; height: 100%; padding: 0; text-align: center; } /* 측점 값 셀은 측점 수직선을 중심으로 좌우 대칭 배치된다. 셀 경계(= 이웃 측점과의 중간)에 세로 구분선을 둬 구배 행과 같은 격자를 만든다. */ .b05-profile-table__cell, .b05-profile-table__curve { box-sizing: border-box; width: var(--b05-table-cell-width, 56px); border-left: 1px solid var(--color-border); transform: translateX(-50%); } .b05-profile-table__cell:last-child, .b05-profile-table__curve:last-child { border-right: 1px solid var(--color-border); } /* 구조물 측점 빈 칸의 세로선은 이웃 규칙 측점의 값 한가운데를 지나고, 곡선 L/R 칸 경계와 x가 겹쳐 곡선 행 구분선이 위 행들까지 이어진 것처럼 보인다. 곡선 행에만 남기고 값 행에서는 지운다(2026-08-30 사용자 지시). */ .b05-profile-table__cell.is-structure { border-left-color: transparent; } .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); } /* 구간 블록: 변화점 사이를 빈틈없이 채운다. 구분선은 변화점(= 생성된 R의 중심, 측점 수직선) 위에 놓이므로 왼쪽 테두리 하나면 충분하다. 양쪽에 다 주면 맞닿는 자리가 2px로 두꺼워진다. */ .b05-profile-table__segment { box-sizing: border-box; border-left: 1px solid var(--color-border); } .b05-profile-table__segment:last-child { 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); } /* 구배 블록 값. 가로로 안 들어가면 90도 회전해 좁은 블록에도 값을 표기한다. */ .b05-profile-table__segment-value { line-height: 1; white-space: nowrap; } .b05-profile-table__segment-value.is-rotated { transform: rotate(-90deg); } .b05-profile-table__curve { z-index: 2; } .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; } /* 숫자 입력의 상·하 토글(스피너) 제거 — 항상 사용자가 값 직접 입력. */ .b05-profile-table__no-spin::-webkit-outer-spin-button, .b05-profile-table__no-spin::-webkit-inner-spin-button { margin: 0; -webkit-appearance: none; appearance: none; } .b05-profile-table__no-spin { -moz-appearance: textfield; appearance: textfield; } /* ─── 선택된 비정규 측점 값 열 오버레이 (규칙 열과 같은 12행) ────────────── 세로 점선·구조물 태그 없이, 선택 시에만 값 열을 테이블 위에 겹쳐 보여준다. */ /* ── 구조물 우클릭 메뉴 (그래프 위 — 배관 추가 · 구조물 삭제) ─────────────── */ .b05-profile-chart__context-menu { position: absolute; z-index: 7; display: flex; flex-direction: column; min-width: 120px; padding: var(--spacing-4); border: 1px solid var(--color-border); border-radius: var(--radius-cards); background: var(--color-surface-raised); box-shadow: 0 4px 16px rgb(0 0 0 / 25%); } .b05-profile-chart__context-menu[hidden] { display: none; } .b05-profile-chart__context-menu-item { padding: var(--spacing-4) var(--spacing-8); border: 0; border-radius: var(--radius-cards); background: transparent; color: var(--color-text-body); font-size: 12px; text-align: left; cursor: pointer; } .b05-profile-chart__context-menu-item:hover { background: var(--color-surface-sunken); } /* 구조물군 하위 메뉴(아코디언, 2026-08-18 메뉴 일원화) — 머리글 굵게, 종류는 들여쓰기. 종류가 많은 군이 펼쳐지면 메뉴가 화면을 넘을 수 있어 최대 높이에서 안쪽 스크롤. */ .b05-profile-chart__context-menu, .b05-drainage__context-menu { max-height: 320px; overflow-y: auto; } .b05-profile-chart__context-menu-item.is-group, .b05-drainage__context-menu-item.is-group { font-weight: var(--font-weight-medium); } .b05-profile-chart__context-menu-sub, .b05-drainage__context-menu-sub { display: flex; flex-direction: column; } .b05-profile-chart__context-menu-item.is-sub, .b05-drainage__context-menu-item.is-sub { padding-left: var(--spacing-24); } .b05-profile-table__irregular-col { position: absolute; /* 값 셀(0)·곡선(2) 위, sticky 행 이름표(5) **아래**로 둔다 — 스크롤로 값 열이 이름표까지 와도 행 제목이 가려지지 않는다. */ z-index: 4; top: 0; bottom: 0; display: flex; flex-direction: column; box-sizing: border-box; border-inline: 1px solid var(--color-royal-amethyst, rgb(109 40 217)); background: color-mix( in srgb, var(--color-royal-amethyst, rgb(109 40 217)) 14%, var(--color-surface) ); transform: translateX(-50%); /* 열 자체는 클릭을 통과시키고, 입력 셀만 pointer-events를 되살린다(작업6). */ pointer-events: none; } /* 비정규(구조물) 측점은 측점 격자와 무관한 위치에 떠서, 이웃 셀을 가린 자리에 뜬다. 떠 있는 창임이 드러나게 그림자·굵은 테두리로 구분한다(규칙 측점은 격자와 일치해 불필요). */ .b05-profile-table__irregular-col.is-floating { border-inline-width: 2px; box-shadow: 0 0 0 1px var(--color-surface-raised), 0 4px 12px rgb(0 0 0 / 28%); } .b05-profile-table__irregular-col-cell { display: flex; flex: 1 1 0; align-items: center; justify-content: center; min-height: 0; overflow: hidden; border-bottom: 1px solid color-mix(in srgb, var(--color-border) 70%, transparent); color: var(--color-text); font-variant-numeric: tabular-nums; white-space: nowrap; } /* 변화점에서 좌/우로 갈린 값: 세로 구분선으로 반씩 나누고 각 반쪽은 폰트를 줄여 셀에 맞춘다. */ .b05-profile-table__irregular-col-cell.is-split { gap: 0; } .b05-profile-table__irregular-col-half { display: flex; flex: 1 1 0; align-items: center; justify-content: center; min-width: 0; height: 100%; overflow: hidden; font-size: 0.72em; } .b05-profile-table__irregular-col-half:first-child { border-right: 1px solid color-mix(in srgb, var(--color-border) 85%, transparent); } .b05-profile-table__irregular-col-cell:last-child { border-bottom: 0; } .b05-profile-table__irregular-col-cell.is-cut { color: rgb(220 38 38); } .b05-profile-table__irregular-col-cell.is-fill { color: rgb(37 99 235); } /* 계획고(is-plan)는 오버레이에서 별도 강조 없이 다른 값과 동일한 스타일을 쓴다(작업 C-2). */ /* 값 열의 계획고 직접 입력 셀 — 열은 pointer-events:none이라 입력만 되살린다. */ .b05-profile-table__irregular-input { box-sizing: border-box; width: 92%; height: 88%; padding: 0; /* 계획고만 테두리·색으로 따로 강조하지 않는다 — 같은 열의 다른 값과 같아 보여야 한다 (2026-08-02 사용자 지시). 고칠 수 있다는 표시는 커서와 포커스 테두리로 충분하다. */ border: 1px solid transparent; border-radius: 2px; background: transparent; color: inherit; font: inherit; text-align: center; pointer-events: auto; } .b05-profile-table__irregular-input:focus, .b05-profile-table__irregular-input:hover { border-color: var(--color-royal-amethyst, rgb(109 40 217)); background: var(--color-surface); } /* ─── 계획고 편집 버튼 (크기 유지·상시 표시·밝은 글자) ───────────────────── */ /* [쉬프트]로 고른 직선 구간 강조 — 직선과 **양 끝 라운드**를 함께 빨갛게 덧그린다 (2026-09-03 사용자 지시). 편집 버튼층(z-index 4)보다 아래에 깔아 버튼을 가리지 않는다. */ .b05-profile-runmark { position: absolute; z-index: 3; inset: 0; pointer-events: none; } .b05-profile-runmark__line { fill: none; stroke: var(--color-danger, #d64545); stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; opacity: 0.85; } /* 구간 경계(라운드 시·종점) 세로 표식 — 어디까지 함께 움직이는지 알린다. */ .b05-profile-runmark__edge { stroke: var(--color-danger, #d64545); stroke-width: 1; stroke-dasharray: 3 3; opacity: 0.5; } .b05-profile-edit { position: absolute; z-index: 4; inset: 0; pointer-events: none; } /* 상시 보이게 둔다(예전엔 패널 hover 시에만 노출). 크기는 ▲▼·↺·⬆⬇ 전부 21×17로 키웠다(2026-08-04 사용자 지시 — 18×15는 누르기도 읽기도 작았다). */ .b05-profile-edit__btn { position: absolute; width: 21px; height: 17px; padding: 0; font-size: 12px; line-height: 1; border: 1px solid color-mix(in srgb, var(--color-border) 75%, transparent); border-radius: 3px; background: color-mix(in srgb, var(--color-surface-raised) 80%, transparent); color: var(--color-text); font-size: 9px; line-height: 1; cursor: pointer; opacity: 0.9; pointer-events: auto; transition: opacity var(--transition-fast), background var(--transition-fast); } .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; } /* 구간 시프트 버튼은 측점 버튼과 같은 줄(is-up/is-down)에 놓이고, 겹치는 자리에서만 렌더러가 좌우로 비켜 배치한다. 글리프(⇧⇩ vs ▲▼)로 구분한다. */ /* 방향별 색 — 올림은 빨강, 내림은 파랑(2026-08-04 사용자 지시). 무채색이던 버튼이 배경에 묻혀 잘 안 보였다. --color-danger는 테마별로 정의돼 있고(라이트 #c0392b / 다크 #e8695a), 파랑 #5b8def(--color-chart-0)는 두 테마 모두에서 대비가 나온다. is-segment(⇧⇩)에도 같은 방향색을 적용한다 — 구분은 글리프가 맡는다. */ .b05-profile-edit__btn.is-up { border-color: color-mix(in srgb, var(--color-danger) 65%, transparent); color: var(--color-danger); } /* 구간 이동(⬆⬇)은 속 찬 화살표가 잘 읽히도록 굵게(크기는 공통 21×17). */ .b05-profile-edit__btn.is-segment { font-weight: 700; } .b05-profile-edit__btn.is-down { border-color: color-mix(in srgb, var(--color-chart-0, #5b8def) 65%, transparent); color: var(--color-chart-0, #5b8def); } .b05-route-profile .b05-profile-edit__btn.is-up:hover, .b05-route-profile .b05-profile-edit__btn.is-up:focus-visible { border-color: var(--color-danger); background: color-mix(in srgb, var(--color-danger) 14%, var(--color-surface-raised)); color: var(--color-danger); } .b05-route-profile .b05-profile-edit__btn.is-down:hover, .b05-route-profile .b05-profile-edit__btn.is-down:focus-visible { border-color: var(--color-chart-0, #5b8def); background: color-mix(in srgb, var(--color-chart-0, #5b8def) 14%, var(--color-surface-raised)); color: var(--color-chart-0, #5b8def); } .b05-profile-edit__btn.is-reset { top: 22px; border-color: color-mix(in srgb, var(--color-royal-amethyst, rgb(109 40 217)) 55%, transparent); background: var(--color-surface-raised); color: color-mix(in srgb, var(--color-royal-amethyst, rgb(139 92 246)) 85%, var(--color-text)); opacity: 0.95; } .b05-profile-table__segment.is-structure { opacity: 0.55; } .b05-profile-table__segment.is-structure.is-highlight { opacity: 1; background: color-mix(in srgb, var(--color-primary) 14%, transparent); outline: 1px solid var(--color-primary); } /* ── 종단도 줌·Y레인지 조작구 (2026-09-04) ───────────────────────────── * 요약줄 오른쪽 끝(= 그래프 우측 상단)에 붙는다. 양식은 횡단도 줌 버튼세트 * (.b06-cross-card__zoom-btn)와 같게 맞췄다 — 그쪽 CSS는 B06 페이지 전용이라 * 여기서 같은 값으로 다시 적는다. */ .b05-profile__zoom { display: flex; flex: 0 0 auto; margin-left: auto; overflow: hidden; border: 1px solid var(--color-border); border-radius: var(--radius-inputs); background: color-mix(in srgb, var(--color-surface-raised) 88%, transparent); } .b05-profile__zoom-btn { width: 22px; height: 22px; padding: 0; border: none; border-left: 1px solid var(--color-border); background: none; color: var(--color-text-secondary); font-size: 0.8rem; line-height: 1; cursor: pointer; } .b05-profile__zoom-btn:first-child { border-left: none; } .b05-profile__zoom-btn:hover:not(:disabled) { color: var(--color-text); background: var(--color-surface); } /* 배율 한계(축소는 폭맞춤, 확대는 8배)에 닿은 버튼 — 눌러도 변화가 없으니 흐리게 죽인다. */ .b05-profile__zoom-btn:disabled { opacity: 0.35; cursor: default; }